diff --git a/.github/infrastructure/conformance/hashicorp/setup-hashicorp-vault-secrets.sh b/.github/infrastructure/conformance/hashicorp/setup-hashicorp-vault-secrets.sh
index 35ad267d0..00c004528 100755
--- a/.github/infrastructure/conformance/hashicorp/setup-hashicorp-vault-secrets.sh
+++ b/.github/infrastructure/conformance/hashicorp/setup-hashicorp-vault-secrets.sh
@@ -16,6 +16,8 @@ for attempt in `seq $MAX_ATTEMPTS`; do
if vault status &&
vault kv put secret/dapr/conftestsecret conftestsecret=abcd &&
vault kv put secret/dapr/secondsecret secondsecret=efgh &&
+ vault kv put secret/secretWithNoPrefix noPrefixKey=noProblem &&
+ vault kv put secret/alternativePrefix/secretUnderAlternativePrefix altPrefixKey=altPrefixValue &&
vault kv put secret/dapr/multiplekeyvaluessecret first=1 second=2 third=3;
then
echo ✅ secrets set;
diff --git a/.github/infrastructure/conformance/temporal/worker/go.mod b/.github/infrastructure/conformance/temporal/worker/go.mod
index 8274a2983..a376bf660 100644
--- a/.github/infrastructure/conformance/temporal/worker/go.mod
+++ b/.github/infrastructure/conformance/temporal/worker/go.mod
@@ -33,3 +33,5 @@ require (
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+
+replace github.com/dapr/dapr => github.com/1046102779/dapr v0.0.0-20221021130037-635b70c24259
diff --git a/.github/infrastructure/docker-compose-hashicorp-vault.yml b/.github/infrastructure/docker-compose-hashicorp-vault.yml
index 7d5cc7de0..eafd2cef8 100644
--- a/.github/infrastructure/docker-compose-hashicorp-vault.yml
+++ b/.github/infrastructure/docker-compose-hashicorp-vault.yml
@@ -1,8 +1,9 @@
version: '3.9'
# Use a YAML reference to define VAULT_TOKEN and DOCKER_IMAGE only once
-x-common-vaues:
+x-common-values:
# This should match tests/config/secrestore/hashicorp/vault/hashicorp-vault.yaml
+ # This should match .github/infrastructure/conformance/hashicorp/vault_token_file.txt
vault_token: &VAULT_TOKEN "vault-dev-root-token-id"
# Reuse the same docker image to save on resources and because the base vault image
# has everything we need for seeding the initial key values too.
diff --git a/.github/infrastructure/docker-compose-kubemq.yml b/.github/infrastructure/docker-compose-kubemq.yml
new file mode 100644
index 000000000..8aa740fe7
--- /dev/null
+++ b/.github/infrastructure/docker-compose-kubemq.yml
@@ -0,0 +1,8 @@
+version: '2'
+services:
+ rabbitmq:
+ image: kubemq/kubemq-community:latest
+ ports:
+ - 8080:8080
+ - 9090:9090
+ - 50000:50000
diff --git a/.github/scripts/dapr_bot.js b/.github/scripts/dapr_bot.js
new file mode 100644
index 000000000..32e335c7f
--- /dev/null
+++ b/.github/scripts/dapr_bot.js
@@ -0,0 +1,224 @@
+// list of owner who can control dapr-bot workflow
+// TODO: Read owners from OWNERS file.
+const owners = [
+ "yaron2",
+ "berndverst",
+ "artursouza",
+ "mukundansundar",
+ "halspang",
+ "tanvigour",
+ "pkedy",
+ "amuluyavarote",
+ "daixiang0",
+ "ItalyPaleAle",
+ "jjcollinge",
+ "pravinpushkar",
+ "shivamkm07",
+ "shubham1172",
+ "skyao",
+ "msfussell",
+ "Taction",
+ "RyanLettieri",
+ "DeepanshuA",
+ "yash-nisar",
+ "addjuarez",
+ "tmacam",
+];
+
+const docsIssueBodyTpl = (issueNumber) => `This issue was automatically created by \
+[Dapr Bot](https://github.com/dapr/dapr/blob/master/.github/workflows/dapr-bot.yml) because a \"documentation required\" label \
+was added to dapr/components-contrib#${issueNumber}. \n\n\
+TODO: Add more details as per [this template](.github/ISSUE_TEMPLATE/new-content-needed.md).`;
+
+const newComponentBodyTpl = (issueNumber) => `This issue was automatically created by \
+[Dapr Bot](https://github.com/dapr/dapr/blob/master/.github/workflows/dapr-bot.yml) because a \"new component\" label \
+was added to dapr/components-contrib#${issueNumber}. \n\n\
+
+Please register the component in [cmd/daprd/components](https://github.com/dapr/dapr/tree/master/cmd/daprd/components), \
+similar to the ones in the folder (one file per component).`;
+
+module.exports = async ({ github, context }) => {
+ if (context.eventName == "issue_comment" && context.payload.action == "created") {
+ await handleIssueCommentCreate({ github, context });
+ } else if ((context.eventName == "issues" || context.eventName == "pull_request") && context.payload.action == "labeled") {
+ await handleIssueOrPrLabeled({ github, context });
+ } else {
+ console.log(`[main] event ${context.eventName} not supported, exiting.`);
+ }
+}
+
+/**
+ * Handle issue comment create event.
+ */
+async function handleIssueCommentCreate({ github, context }) {
+ const payload = context.payload;
+ const issue = context.issue;
+ const username = context.actor;
+ const isFromPulls = !!payload.issue.pull_request;
+ const commentBody = payload.comment.body;
+
+ if (!commentBody) {
+ console.log("[handleIssueCommentCreate] comment body not found, exiting.");
+ return;
+ }
+ const command = commentBody.split(" ")[0];
+
+ // Commands that can be executed by anyone.
+ if (command === "/assign") {
+ await cmdAssign(github, issue, username, isFromPulls);
+ return;
+ }
+
+ // Commands that can only be executed by owners.
+ if (owners.indexOf(username) < 0) {
+ console.log(`[handleIssueCommentCreate] user ${username} is not an owner, exiting.`);
+ return;
+ }
+
+ switch (command) {
+ case "/make-me-laugh":
+ await cmdMakeMeLaugh(github, issue);
+ break;
+ case "/ok-to-test":
+ await cmdOkToTest(github, issue, isFromPulls);
+ break;
+ default:
+ console.log(`[handleIssueCommentCreate] command ${command} not found, exiting.`);
+ break;
+ }
+}
+
+
+
+/**
+ * Handle issue or PR labeled event.
+ */
+async function handleIssueOrPrLabeled({ github, context }) {
+ const payload = context.payload;
+ const label = payload.label.name;
+ const issueNumber = payload.issue.number;
+
+ // This should not run in forks.
+ if (context.repo.owner !== "dapr") {
+ console.log("[handleIssueOrPrLabeled] not running in dapr repo, exiting.");
+ return;
+ }
+
+ // Authorization is not required here because it's triggered by an issue label event.
+ // Only authorized users can add labels to issues.
+ if (label == "documentation required") {
+ // Open a new docs issue
+ await github.issues.create({
+ owner: "dapr",
+ repo: "docs",
+ title: `New content needed for dapr/components-contrib#${issueNumber}`,
+ labels: ["content/missing-information", "created-by/dapr-bot"],
+ body: docsIssueBodyTpl(issueNumber),
+ });
+ } else if (label == "new component") {
+ // Open a new dapr issue
+ await github.issues.create({
+ owner: "dapr",
+ repo: "dapr",
+ title: `Component registration for dapr/components-contrib#${issueNumber}`,
+ labels: ["area/components", "created-by/dapr-bot"],
+ body: newComponentBodyTpl(issueNumber),
+ });
+ } else {
+ console.log(`[handleIssueOrPrLabeled] label ${label} not supported, exiting.`);
+ }
+}
+
+/**
+ * Assign the issue to the user who commented.
+ * @param {*} github GitHub object reference
+ * @param {*} issue GitHub issue object
+ * @param {*} username GitHub user who commented
+ * @param {boolean} isFromPulls is the workflow triggered by a pull request?
+ */
+async function cmdAssign(github, issue, username, isFromPulls) {
+ if (isFromPulls) {
+ console.log("[cmdAssign] pull requests unsupported, skipping command execution.");
+ return;
+ } else if (issue.assignees && issue.assignees.length !== 0) {
+ console.log("[cmdAssign] issue already has assignees, skipping command execution.");
+ return;
+ }
+
+ await github.issues.addAssignees({
+ owner: issue.owner,
+ repo: issue.repo,
+ issue_number: issue.number,
+ assignees: [username],
+ });
+}
+
+/**
+ * Comment a funny joke.
+ * @param {*} github GitHub object reference
+ * @param {*} issue GitHub issue object
+ */
+async function cmdMakeMeLaugh(github, issue) {
+ const result = await github.request("https://official-joke-api.appspot.com/random_joke");
+ jokedata = result.data;
+ joke = "I have a bad feeling about this.";
+ if (jokedata && jokedata.setup && jokedata.punchline) {
+ joke = `${jokedata.setup} - ${jokedata.punchline}`;
+ }
+
+ await github.issues.createComment({
+ owner: issue.owner,
+ repo: issue.repo,
+ issue_number: issue.number,
+ body: joke,
+ });
+}
+
+
+/**
+ * Trigger e2e test for the pull request.
+ * @param {*} github GitHub object reference
+ * @param {*} issue GitHub issue object
+ * @param {boolean} isFromPulls is the workflow triggered by a pull request?
+ */
+async function cmdOkToTest(github, issue, isFromPulls) {
+ if (!isFromPulls) {
+ console.log("[cmdOkToTest] only pull requests supported, skipping command execution.");
+ return;
+ }
+
+ // Get pull request
+ const pull = await github.pulls.get({
+ owner: issue.owner,
+ repo: issue.repo,
+ pull_number: issue.number
+ });
+
+ if (pull && pull.data) {
+ // Get commit id and repo from pull head
+ const testPayload = {
+ pull_head_ref: pull.data.head.sha,
+ pull_head_repo: pull.data.head.repo.full_name,
+ command: "ok-to-test",
+ issue: issue,
+ };
+
+ // Fire repository_dispatch event to trigger certification test
+ await github.repos.createDispatchEvent({
+ owner: issue.owner,
+ repo: issue.repo,
+ event_type: "certification-test",
+ client_payload: testPayload,
+ });
+
+ // Fire repository_dispatch event to trigger conformance test
+ await github.repos.createDispatchEvent({
+ owner: issue.owner,
+ repo: issue.repo,
+ event_type: "conformance-test",
+ client_payload: testPayload,
+ });
+
+ console.log(`[cmdOkToTest] triggered certification and conformance tests for ${JSON.stringify(testPayload)}`);
+ }
+}
diff --git a/.github/workflows/certification.yml b/.github/workflows/certification.yml
index 2ceb16d95..1265cb398 100644
--- a/.github/workflows/certification.yml
+++ b/.github/workflows/certification.yml
@@ -53,6 +53,7 @@ jobs:
- pubsub.mqtt
- state.mongodb
- state.redis
+ - state.cockroachdb
- state.postgresql
- state.cassandra
- state.memcached
@@ -60,6 +61,7 @@ jobs:
- bindings.alicloud.dubbo
- bindings.kafka
- bindings.redis
+ - bindings.cron
- secretstores.local.env
- secretstores.local.file
- secretstores.hashicorp.vault
@@ -245,7 +247,7 @@ jobs:
working-directory: ${{ env.TEST_PATH }}
run: |
echo "Running certification tests for ${{ matrix.component }} ... "
- export GOLANG_PROTOBUF_REGISTRATION_CONFLICT=warn
+ export GOLANG_PROTOBUF_REGISTRATION_CONFLICT=ignore
set +e
gotestsum --jsonfile ${{ env.TEST_OUTPUT_FILE_PREFIX }}_certification.json \
--junitfile ${{ env.TEST_OUTPUT_FILE_PREFIX }}_certification.xml --format standard-quiet -- \
diff --git a/.github/workflows/components-contrib.yml b/.github/workflows/components-contrib.yml
index c4185e2bf..9871ff236 100644
--- a/.github/workflows/components-contrib.yml
+++ b/.github/workflows/components-contrib.yml
@@ -35,7 +35,7 @@ jobs:
GOOS: ${{ matrix.target_os }}
GOARCH: ${{ matrix.target_arch }}
GOPROXY: https://proxy.golang.org
- GOLANGCI_LINT_VER: "v1.48.0"
+ GOLANGCI_LINT_VER: "v1.50.1"
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml
index 6fa698b36..7a898acbb 100644
--- a/.github/workflows/conformance.yml
+++ b/.github/workflows/conformance.yml
@@ -48,6 +48,7 @@ jobs:
id: pr-components
run: |
PR_COMPONENTS=$(yq -I0 --tojson eval - << EOF
+ - bindings.cron
- bindings.http
- bindings.influx
- bindings.kafka-wurstmeister
@@ -57,6 +58,7 @@ jobs:
- bindings.mqtt-vernemq
- bindings.postgres
- bindings.redis
+ - bindings.kubemq
- bindings.rabbitmq
- pubsub.aws.snssqs
- pubsub.hazelcast
@@ -70,6 +72,7 @@ jobs:
- pubsub.redis
- pubsub.kafka-wurstmeister
- pubsub.kafka-confluent
+ - pubsub.kubemq
- secretstores.kubernetes
- secretstores.localenv
- secretstores.localfile
@@ -82,6 +85,7 @@ jobs:
- state.postgresql
- state.redis
- state.sqlserver
+ - state.in-memory
- state.cockroachdb
- workflows.temporal
- state.rethinkdb
@@ -292,7 +296,7 @@ jobs:
- name: Start Eclipse Mosquitto (MQTT)
run: docker-compose -f ./.github/infrastructure/docker-compose-mosquitto.yml -p mosquitto up -d
if: contains(matrix.component, 'mqtt-mosquitto')
-
+
- name: Start EMQ X (MQTT)
run: docker-compose -f ./.github/infrastructure/docker-compose-emqx.yml -p emqx up -d
if: contains(matrix.component, 'mqtt-emqx')
@@ -331,7 +335,7 @@ jobs:
if: contains(matrix.component, 'mysql.mariadb')
- name: Start KinD
- uses: helm/kind-action@v1.0.0
+ uses: helm/kind-action@v1.4.0
if: contains(matrix.component, 'kubernetes')
- name: Start postgresql
@@ -348,7 +352,7 @@ jobs:
run: |
docker-compose -f ./.github/infrastructure/docker-compose-cockroachdb.yml -p cockroachdb up -d
if: contains(matrix.component, 'cockroachdb')
-
+
- name: Start vault
run: |
docker-compose -f ./.github/infrastructure/docker-compose-hashicorp-vault.yml -p vault up -d
@@ -359,6 +363,10 @@ jobs:
docker-compose -f ./.github/infrastructure/docker-compose-rethinkdb.yml -p rethinkdb up -d
if: contains(matrix.component, 'rethinkdb')
+ - name: Start kubemq
+ run: docker-compose -f ./.github/infrastructure/docker-compose-kubemq.yml -p kubemq up -d
+ if: contains(matrix.component, 'kubemq')
+
- name: Setup KinD test data
if: contains(matrix.component, 'kubernetes')
run: |
@@ -369,7 +377,7 @@ jobs:
uses: actions/setup-go@v3
with:
go-version: '^1.19'
-
+
- name: Download Go dependencies
run: |
go mod download
diff --git a/.github/workflows/dapr-bot.yml b/.github/workflows/dapr-bot.yml
index c4ef5d1a1..feead1f9c 100644
--- a/.github/workflows/dapr-bot.yml
+++ b/.github/workflows/dapr-bot.yml
@@ -14,99 +14,24 @@
name: dapr-bot
on:
- issue_comment: {types: created}
+ issue_comment:
+ types: [created]
+ issues:
+ types: [labeled]
+ pull_request:
+ types: [labeled]
jobs:
daprbot:
name: bot-processor
runs-on: ubuntu-latest
steps:
- - name: Comment analyzer
- uses: actions/github-script@v1
+ - name: Checkout code
+ uses: actions/checkout@v2 # required to make the script available for next step
+ - name: Issue analyzer
+ uses: actions/github-script@v4
with:
github-token: ${{secrets.DAPR_BOT_TOKEN}}
script: |
- // list of owner who can control dapr-bot workflow
- // TODO: Read owners from OWNERS file.
- const owners = [
- "yaron2",
- "berndverst",
- "artursouza",
- "mukundansundar",
- "halspang",
- "tanvigour",
- "pkedy",
- "amuluyavarote",
- "daixiang0",
- "ItalyPaleAle",
- "jjcollinge",
- "pravinpushkar",
- "shivamkm07",
- "shubham1172",
- "skyao",
- "msfussell",
- "Taction",
- "RyanLettieri",
- "DeepanshuA",
- "yash-nisar",
- "addjuarez",
- "tmacam",
- ];
- const payload = context.payload;
- const issue = context.issue;
- const isFromPulls = !!payload.issue.pull_request;
- const commentBody = payload.comment.body;
-
- if (!isFromPulls && commentBody && commentBody.indexOf("/assign") == 0) {
- if (!issue.assignees || issue.assignees.length === 0) {
- await github.issues.addAssignees({
- owner: issue.owner,
- repo: issue.repo,
- issue_number: issue.number,
- assignees: [context.actor],
- })
- }
-
- return;
- }
-
- // actions above this check are enabled for everyone.
- if (owners.indexOf(context.actor) < 0) {
- return;
- }
-
- if (isFromPulls && commentBody) {
- if (commentBody.indexOf("/ok-to-test") == 0) {
- // Get pull request
- const pull = await github.pulls.get({
- owner: issue.owner,
- repo: issue.repo,
- pull_number: issue.number
- });
- if (pull && pull.data) {
- // Get commit id and repo from pull head
- const testPayload = {
- pull_head_ref: pull.data.head.sha,
- pull_head_repo: pull.data.head.repo.full_name,
- command: "ok-to-test",
- issue: issue,
- };
-
- // Fire repository_dispatch event to trigger certification test
- await github.repos.createDispatchEvent({
- owner: issue.owner,
- repo: issue.repo,
- event_type: "certification-test",
- client_payload: testPayload,
- });
-
- // Fire repository_dispatch event to trigger conformance test
- await github.repos.createDispatchEvent({
- owner: issue.owner,
- repo: issue.repo,
- event_type: "conformance-test",
- client_payload: testPayload,
- });
- }
- }
- }
+ const script = require('./.github/scripts/dapr_bot.js')
+ await script({github, context})
diff --git a/.golangci.yml b/.golangci.yml
index 26ea4cffa..f3df9740d 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -31,7 +31,7 @@ run:
# skip-files:
# - ".*\\.my\\.go$"
# - lib/bad.go
-
+
# output configuration options
output:
# colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number"
@@ -116,13 +116,14 @@ linters-settings:
# minimal occurrences count to trigger, 3 by default
min-occurrences: 5
depguard:
- list-type: blacklist
+ list-type: denylist
include-go-root: false
- packages:
- - github.com/Sirupsen/logrus
- packages-with-error-messages:
- # specify an error message to output when a blacklisted package is used
- github.com/Sirupsen/logrus: "must use github.com/dapr/kit/logger"
+ packages-with-error-message:
+ - "github.com/Sirupsen/logrus": "must use github.com/dapr/kit/logger"
+ - "github.com/agrea/ptr": "must use github.com/dapr/kit/ptr"
+ - "github.com/cenkalti/backoff": "must use github.com/cenkalti/backoff/v4"
+ - "github.com/cenkalti/backoff/v2": "must use github.com/cenkalti/backoff/v4"
+ - "github.com/cenkalti/backoff/v3": "must use github.com/cenkalti/backoff/v4"
misspell:
# Correct spellings using locale preferences for US or UK.
# Default is to use a neutral variety of English.
@@ -276,3 +277,6 @@ linters:
- rowserrcheck
- sqlclosecheck
- structcheck
+ - deadcode
+ - nosnakecase
+ - varcheck
diff --git a/bindings/alicloud/dingtalk/webhook/webhook_test.go b/bindings/alicloud/dingtalk/webhook/webhook_test.go
index 895ad2b36..b527171af 100644
--- a/bindings/alicloud/dingtalk/webhook/webhook_test.go
+++ b/bindings/alicloud/dingtalk/webhook/webhook_test.go
@@ -37,7 +37,7 @@ func TestPublishMsg(t *testing.T) { //nolint:paralleltest
w.WriteHeader(http.StatusOK)
_, err := w.Write([]byte("{\"errcode\":0}"))
require.NoError(t, err)
- if r.Method != "POST" {
+ if r.Method != http.MethodPost {
t.Errorf("Expected 'POST' request, got '%s'", r.Method)
}
if r.URL.EscapedPath() != "/test" {
diff --git a/bindings/azure/blobstorage/blobstorage.go b/bindings/azure/blobstorage/blobstorage.go
index ddcd2f8e0..3724a7e0f 100644
--- a/bindings/azure/blobstorage/blobstorage.go
+++ b/bindings/azure/blobstorage/blobstorage.go
@@ -20,18 +20,18 @@ import (
"errors"
"fmt"
"io"
- "net/url"
"strconv"
- "strings"
- "time"
- "github.com/Azure/azure-storage-blob-go/azblob"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container"
"github.com/google/uuid"
"github.com/dapr/components-contrib/bindings"
- azauth "github.com/dapr/components-contrib/internal/authentication/azure"
- mdutils "github.com/dapr/components-contrib/metadata"
+ storageinternal "github.com/dapr/components-contrib/internal/component/azure/blobstorage"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
const (
@@ -49,41 +49,23 @@ const (
// Defines the delete snapshots option for the delete operation.
// See: https://docs.microsoft.com/en-us/rest/api/storageservices/delete-blob#request-headers
metadataKeyDeleteSnapshots = "deleteSnapshots"
- // HTTP headers to be associated with the blob.
- // See: https://docs.microsoft.com/en-us/rest/api/storageservices/put-blob#request-headers-all-blob-types
- metadataKeyContentType = "contentType"
- metadataKeyContentMD5 = "contentMD5"
- metadataKeyContentEncoding = "contentEncoding"
- metadataKeyContentLanguage = "contentLanguage"
- metadataKeyContentDisposition = "contentDisposition"
- metadataKeyCacheControl = "cacheControl"
- // Specifies the maximum number of HTTP GET requests that will be made while reading from a RetryReader. A value
- // of zero means that no additional HTTP GET requests will be made.
- defaultGetBlobRetryCount = 10
// Specifies the maximum number of blobs to return, including all BlobPrefix elements. If the request does not
// specify maxresults the server will return up to 5,000 items.
// See: https://docs.microsoft.com/en-us/rest/api/storageservices/list-blobs#uri-parameters
- maxResults = 5000
+ maxResults int32 = 5000
+ endpointKey = "endpoint"
)
var ErrMissingBlobName = errors.New("blobName is a required attribute")
// AzureBlobStorage allows saving blobs to an Azure Blob Storage account.
type AzureBlobStorage struct {
- metadata *blobStorageMetadata
- containerURL azblob.ContainerURL
+ metadata *storageinternal.BlobStorageMetadata
+ containerClient *container.Client
logger logger.Logger
}
-type blobStorageMetadata struct {
- AccountName string
- Container string
- GetBlobRetryCount int
- DecodeBase64 bool
- PublicAccessLevel azblob.PublicAccessType
-}
-
type createResponse struct {
BlobURL string `json:"blobURL"`
BlobName string `json:"blobName"`
@@ -111,90 +93,14 @@ func NewAzureBlobStorage(logger logger.Logger) bindings.OutputBinding {
// Init performs metadata parsing.
func (a *AzureBlobStorage) Init(metadata bindings.Metadata) error {
- m, err := a.parseMetadata(metadata)
+ var err error
+ a.containerClient, a.metadata, err = storageinternal.CreateContainerStorageClient(a.logger, metadata.Properties)
if err != nil {
return err
}
- a.metadata = m
-
- credential, env, err := azauth.GetAzureStorageBlobCredentials(a.logger, m.AccountName, metadata.Properties)
- if err != nil {
- return fmt.Errorf("invalid credentials with error: %s", err.Error())
- }
-
- userAgent := "dapr-" + logger.DaprVersion
- options := azblob.PipelineOptions{
- Telemetry: azblob.TelemetryOptions{Value: userAgent},
- }
- p := azblob.NewPipeline(credential, options)
-
- var containerURL azblob.ContainerURL
- customEndpoint, ok := mdutils.GetMetadataProperty(metadata.Properties, azauth.StorageEndpointKeys...)
- if ok && customEndpoint != "" {
- URL, parseErr := url.Parse(fmt.Sprintf("%s/%s/%s", customEndpoint, m.AccountName, m.Container))
- if parseErr != nil {
- return parseErr
- }
- containerURL = azblob.NewContainerURL(*URL, p)
- } else {
- URL, _ := url.Parse(fmt.Sprintf("https://%s.blob.%s/%s", m.AccountName, env.StorageEndpointSuffix, m.Container))
- containerURL = azblob.NewContainerURL(*URL, p)
- }
-
- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
- _, err = containerURL.Create(ctx, azblob.Metadata{}, m.PublicAccessLevel)
- cancel()
- // Don't return error, container might already exist
- a.logger.Debugf("error creating container: %w", err)
- a.containerURL = containerURL
-
return nil
}
-func (a *AzureBlobStorage) parseMetadata(metadata bindings.Metadata) (*blobStorageMetadata, error) {
- var m blobStorageMetadata
- if val, ok := mdutils.GetMetadataProperty(metadata.Properties, azauth.StorageAccountNameKeys...); ok && val != "" {
- m.AccountName = val
- } else {
- return nil, fmt.Errorf("missing or empty %s field from metadata", azauth.StorageAccountNameKeys[0])
- }
-
- if val, ok := mdutils.GetMetadataProperty(metadata.Properties, azauth.StorageContainerNameKeys...); ok && val != "" {
- m.Container = val
- } else {
- return nil, fmt.Errorf("missing or empty %s field from metadata", azauth.StorageContainerNameKeys[0])
- }
-
- m.GetBlobRetryCount = defaultGetBlobRetryCount
- if val, ok := metadata.Properties["getBlobRetryCount"]; ok {
- n, err := strconv.Atoi(val)
- if err != nil || n == 0 {
- return nil, fmt.Errorf("invalid getBlobRetryCount field from metadata")
- }
- m.GetBlobRetryCount = n
- }
-
- m.DecodeBase64 = false
- if val, ok := metadata.Properties["decodeBase64"]; ok {
- n, err := strconv.ParseBool(val)
- if err != nil {
- return nil, fmt.Errorf("invalid decodeBase64 field from metadata")
- }
- m.DecodeBase64 = n
- }
-
- m.PublicAccessLevel = azblob.PublicAccessType(strings.ToLower(metadata.Properties["publicAccessLevel"]))
- // per the Dapr documentation "none" is a valid value
- if m.PublicAccessLevel == "none" {
- m.PublicAccessLevel = ""
- }
- if !a.isValidPublicAccessType(m.PublicAccessLevel) {
- return nil, fmt.Errorf("invalid public access level: %s; allowed: %s", m.PublicAccessLevel, azblob.PossiblePublicAccessTypeValues())
- }
-
- return &m, nil
-}
-
func (a *AzureBlobStorage) Operations() []bindings.OperationKind {
return []bindings.OperationKind{
bindings.CreateOperation,
@@ -205,44 +111,21 @@ func (a *AzureBlobStorage) Operations() []bindings.OperationKind {
}
func (a *AzureBlobStorage) create(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
- var blobHTTPHeaders azblob.BlobHTTPHeaders
- var blobURL azblob.BlockBlobURL
var blobName string
if val, ok := req.Metadata[metadataKeyBlobName]; ok && val != "" {
blobName = val
delete(req.Metadata, metadataKeyBlobName)
} else {
- blobName = uuid.New().String()
- }
- blobURL = a.getBlobURL(blobName)
-
- if val, ok := req.Metadata[metadataKeyContentType]; ok && val != "" {
- blobHTTPHeaders.ContentType = val
- delete(req.Metadata, metadataKeyContentType)
- }
- if val, ok := req.Metadata[metadataKeyContentMD5]; ok && val != "" {
- sDec, err := b64.StdEncoding.DecodeString(val)
- if err != nil || len(sDec) != 16 {
- return nil, fmt.Errorf("the MD5 value specified in Content MD5 is invalid, MD5 value must be 128 bits and base64 encoded")
+ id, err := uuid.NewRandom()
+ if err != nil {
+ return nil, err
}
- blobHTTPHeaders.ContentMD5 = sDec
- delete(req.Metadata, metadataKeyContentMD5)
+ blobName = id.String()
}
- if val, ok := req.Metadata[metadataKeyContentEncoding]; ok && val != "" {
- blobHTTPHeaders.ContentEncoding = val
- delete(req.Metadata, metadataKeyContentEncoding)
- }
- if val, ok := req.Metadata[metadataKeyContentLanguage]; ok && val != "" {
- blobHTTPHeaders.ContentLanguage = val
- delete(req.Metadata, metadataKeyContentLanguage)
- }
- if val, ok := req.Metadata[metadataKeyContentDisposition]; ok && val != "" {
- blobHTTPHeaders.ContentDisposition = val
- delete(req.Metadata, metadataKeyContentDisposition)
- }
- if val, ok := req.Metadata[metadataKeyCacheControl]; ok && val != "" {
- blobHTTPHeaders.CacheControl = val
- delete(req.Metadata, metadataKeyCacheControl)
+
+ blobHTTPHeaders, err := storageinternal.CreateBlobHTTPHeadersFromRequest(req.Metadata, nil, a.logger)
+ if err != nil {
+ return nil, err
}
d, err := strconv.Unquote(string(req.Data))
@@ -258,17 +141,21 @@ func (a *AzureBlobStorage) create(ctx context.Context, req *bindings.InvokeReque
req.Data = decoded
}
- _, err = azblob.UploadBufferToBlockBlob(ctx, req.Data, blobURL, azblob.UploadToBlockBlobOptions{
- Parallelism: 16,
- Metadata: a.sanitizeMetadata(req.Metadata),
- BlobHTTPHeaders: blobHTTPHeaders,
- })
+ uploadOptions := azblob.UploadBufferOptions{
+ Metadata: storageinternal.SanitizeMetadata(a.logger, req.Metadata),
+ HTTPHeaders: &blobHTTPHeaders,
+ TransactionalContentMD5: &blobHTTPHeaders.BlobContentMD5,
+ }
+
+ blockBlobClient := a.containerClient.NewBlockBlobClient(blobName)
+ _, err = blockBlobClient.UploadBuffer(ctx, req.Data, &uploadOptions)
+
if err != nil {
return nil, fmt.Errorf("error uploading az blob: %w", err)
}
resp := createResponse{
- BlobURL: blobURL.String(),
+ BlobURL: blockBlobClient.URL(),
}
b, err := json.Marshal(resp)
if err != nil {
@@ -286,23 +173,26 @@ func (a *AzureBlobStorage) create(ctx context.Context, req *bindings.InvokeReque
}
func (a *AzureBlobStorage) get(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
- var blobURL azblob.BlockBlobURL
+ var blockBlobClient *blockblob.Client
if val, ok := req.Metadata[metadataKeyBlobName]; ok && val != "" {
- blobURL = a.getBlobURL(val)
+ blockBlobClient = a.containerClient.NewBlockBlobClient(val)
} else {
return nil, ErrMissingBlobName
}
- resp, err := blobURL.Download(ctx, 0, azblob.CountToEnd, azblob.BlobAccessConditions{}, false)
+ downloadOptions := azblob.DownloadStreamOptions{
+ AccessConditions: &blob.AccessConditions{},
+ }
+
+ blobDownloadResponse, err := blockBlobClient.DownloadStream(ctx, &downloadOptions)
if err != nil {
return nil, fmt.Errorf("error downloading az blob: %w", err)
}
-
- bodyStream := resp.Body(azblob.RetryReaderOptions{MaxRetryRequests: a.metadata.GetBlobRetryCount})
-
- data, err := io.ReadAll(bodyStream)
+ reader := blobDownloadResponse.Body
+ defer reader.Close()
+ blobData, err := io.ReadAll(reader)
if err != nil {
- return nil, fmt.Errorf("error reading az blob body: %w", err)
+ return nil, fmt.Errorf("error reading az blob: %w", err)
}
var metadata map[string]string
@@ -311,45 +201,54 @@ func (a *AzureBlobStorage) get(ctx context.Context, req *bindings.InvokeRequest)
return nil, fmt.Errorf("error parsing metadata: %w", err)
}
+ getPropertiesOptions := blob.GetPropertiesOptions{
+ AccessConditions: &blob.AccessConditions{},
+ }
+
if fetchMetadata {
- props, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
+ props, err := blockBlobClient.GetProperties(ctx, &getPropertiesOptions)
if err != nil {
return nil, fmt.Errorf("error reading blob metadata: %w", err)
}
- metadata = props.NewMetadata()
+ metadata = props.Metadata
}
return &bindings.InvokeResponse{
- Data: data,
+ Data: blobData,
Metadata: metadata,
}, nil
}
func (a *AzureBlobStorage) delete(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
- var blobURL azblob.BlockBlobURL
- if val, ok := req.Metadata[metadataKeyBlobName]; ok && val != "" {
- blobURL = a.getBlobURL(val)
- } else {
+ var blockBlobClient *blockblob.Client
+ val, ok := req.Metadata[metadataKeyBlobName]
+ if !ok || val == "" {
return nil, ErrMissingBlobName
}
- deleteSnapshotsOptions := azblob.DeleteSnapshotsOptionNone
- if val, ok := req.Metadata[metadataKeyDeleteSnapshots]; ok && val != "" {
- deleteSnapshotsOptions = azblob.DeleteSnapshotsOptionType(val)
+ var deleteSnapshotsOptions blob.DeleteSnapshotsOptionType
+ if deleteSnapShotOption, ok := req.Metadata[metadataKeyDeleteSnapshots]; ok && val != "" {
+ deleteSnapshotsOptions = azblob.DeleteSnapshotsOptionType(deleteSnapShotOption)
if !a.isValidDeleteSnapshotsOptionType(deleteSnapshotsOptions) {
return nil, fmt.Errorf("invalid delete snapshot option type: %s; allowed: %s",
deleteSnapshotsOptions, azblob.PossibleDeleteSnapshotsOptionTypeValues())
}
}
- _, err := blobURL.Delete(ctx, deleteSnapshotsOptions, azblob.BlobAccessConditions{})
+ deleteOptions := blob.DeleteOptions{
+ DeleteSnapshots: &deleteSnapshotsOptions,
+ AccessConditions: &blob.AccessConditions{},
+ }
+
+ blockBlobClient = a.containerClient.NewBlockBlobClient(val)
+ _, err := blockBlobClient.Delete(ctx, &deleteOptions)
return nil, err
}
func (a *AzureBlobStorage) list(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
- options := azblob.ListBlobsSegmentOptions{}
+ options := container.ListBlobsFlatOptions{}
hasPayload := false
var payload listPayload
@@ -360,50 +259,52 @@ func (a *AzureBlobStorage) list(ctx context.Context, req *bindings.InvokeRequest
}
hasPayload = true
}
-
if hasPayload {
- options.Details.Copy = payload.Include.Copy
- options.Details.Metadata = payload.Include.Metadata
- options.Details.Snapshots = payload.Include.Snapshots
- options.Details.UncommittedBlobs = payload.Include.UncommittedBlobs
- options.Details.Deleted = payload.Include.Deleted
+ options.Include.Copy = payload.Include.Copy
+ options.Include.Metadata = payload.Include.Metadata
+ options.Include.Snapshots = payload.Include.Snapshots
+ options.Include.UncommittedBlobs = payload.Include.UncommittedBlobs
+ options.Include.Deleted = payload.Include.Deleted
}
- if hasPayload && payload.MaxResults != int32(0) {
- options.MaxResults = payload.MaxResults
+ if hasPayload && payload.MaxResults > 0 {
+ options.MaxResults = &payload.MaxResults
} else {
- options.MaxResults = maxResults
+ options.MaxResults = ptr.Of(maxResults) // cannot get address of constant directly
}
if hasPayload && payload.Prefix != "" {
- options.Prefix = payload.Prefix
+ options.Prefix = &payload.Prefix
}
- var initialMarker azblob.Marker
+ var initialMarker string
if hasPayload && payload.Marker != "" {
- initialMarker = azblob.Marker{Val: &payload.Marker}
+ initialMarker = payload.Marker
} else {
- initialMarker = azblob.Marker{}
+ initialMarker = ""
}
+ options.Marker = &initialMarker
- var blobs []azblob.BlobItem
metadata := map[string]string{}
- for currentMaker := initialMarker; currentMaker.NotDone(); {
- var listBlob *azblob.ListBlobsFlatSegmentResponse
- listBlob, err := a.containerURL.ListBlobsFlatSegment(ctx, currentMaker, options)
+ blobs := []*container.BlobItem{}
+ pager := a.containerClient.NewListBlobsFlatPager(&options)
+
+ for pager.More() {
+ resp, err := pager.NextPage(ctx)
if err != nil {
return nil, fmt.Errorf("error listing blobs: %w", err)
}
- blobs = append(blobs, listBlob.Segment.BlobItems...)
-
+ blobs = append(blobs, resp.Segment.BlobItems...)
numBlobs := len(blobs)
- currentMaker = listBlob.NextMarker
- metadata[metadataKeyMarker] = *currentMaker.Val
metadata[metadataKeyNumber] = strconv.FormatInt(int64(numBlobs), 10)
+ metadata[metadataKeyMarker] = ""
+ if resp.Marker != nil {
+ metadata[metadataKeyMarker] = *resp.Marker
+ }
- if options.MaxResults-maxResults > 0 {
- options.MaxResults -= maxResults
+ if *options.MaxResults-maxResults > 0 {
+ *options.MaxResults -= maxResults
} else {
break
}
@@ -435,23 +336,6 @@ func (a *AzureBlobStorage) Invoke(ctx context.Context, req *bindings.InvokeReque
}
}
-func (a *AzureBlobStorage) getBlobURL(name string) azblob.BlockBlobURL {
- blobURL := a.containerURL.NewBlockBlobURL(name)
-
- return blobURL
-}
-
-func (a *AzureBlobStorage) isValidPublicAccessType(accessType azblob.PublicAccessType) bool {
- validTypes := azblob.PossiblePublicAccessTypeValues()
- for _, item := range validTypes {
- if item == accessType {
- return true
- }
- }
-
- return false
-}
-
func (a *AzureBlobStorage) isValidDeleteSnapshotsOptionType(accessType azblob.DeleteSnapshotsOptionType) bool {
validTypes := azblob.PossibleDeleteSnapshotsOptionTypeValues()
for _, item := range validTypes {
@@ -462,41 +346,3 @@ func (a *AzureBlobStorage) isValidDeleteSnapshotsOptionType(accessType azblob.De
return false
}
-
-func (a *AzureBlobStorage) sanitizeMetadata(metadata map[string]string) map[string]string {
- for key, val := range metadata {
- // Keep only letters and digits
- n := 0
- newKey := make([]byte, len(key))
- for i := 0; i < len(key); i++ {
- if (key[i] >= 'A' && key[i] <= 'Z') ||
- (key[i] >= 'a' && key[i] <= 'z') ||
- (key[i] >= '0' && key[i] <= '9') {
- newKey[n] = key[i]
- n++
- }
- }
-
- if n != len(key) {
- nks := string(newKey[:n])
- a.logger.Warnf("metadata key %s contains disallowed characters, sanitized to %s", key, nks)
- delete(metadata, key)
- metadata[nks] = val
- key = nks
- }
-
- // Remove all non-ascii characters
- n = 0
- newVal := make([]byte, len(val))
- for i := 0; i < len(val); i++ {
- if val[i] > 127 {
- continue
- }
- newVal[n] = val[i]
- n++
- }
- metadata[key] = string(newVal[:n])
- }
-
- return metadata
-}
diff --git a/bindings/azure/blobstorage/blobstorage_test.go b/bindings/azure/blobstorage/blobstorage_test.go
index d0a459141..fbcb6e54e 100644
--- a/bindings/azure/blobstorage/blobstorage_test.go
+++ b/bindings/azure/blobstorage/blobstorage_test.go
@@ -17,83 +17,12 @@ import (
"context"
"testing"
- "github.com/Azure/azure-storage-blob-go/azblob"
"github.com/stretchr/testify/assert"
"github.com/dapr/components-contrib/bindings"
"github.com/dapr/kit/logger"
)
-func TestParseMetadata(t *testing.T) {
- m := bindings.Metadata{}
- blobStorage := NewAzureBlobStorage(logger.NewLogger("test")).(*AzureBlobStorage)
-
- t.Run("parse all metadata", func(t *testing.T) {
- m.Properties = map[string]string{
- "storageAccount": "account",
- "storageAccessKey": "key",
- "container": "test",
- "getBlobRetryCount": "5",
- "decodeBase64": "true",
- }
- meta, err := blobStorage.parseMetadata(m)
- assert.Nil(t, err)
- assert.Equal(t, "test", meta.Container)
- assert.Equal(t, "account", meta.AccountName)
- // storageAccessKey is parsed in the azauth package
- assert.Equal(t, true, meta.DecodeBase64)
- assert.Equal(t, 5, meta.GetBlobRetryCount)
- assert.Equal(t, azblob.PublicAccessNone, meta.PublicAccessLevel)
- })
-
- t.Run("parse metadata with publicAccessLevel = blob", func(t *testing.T) {
- m.Properties = map[string]string{
- "storageAccount": "account",
- "storageAccessKey": "key",
- "container": "test",
- "publicAccessLevel": "blob",
- }
- meta, err := blobStorage.parseMetadata(m)
- assert.Nil(t, err)
- assert.Equal(t, azblob.PublicAccessBlob, meta.PublicAccessLevel)
- })
-
- t.Run("parse metadata with publicAccessLevel = container", func(t *testing.T) {
- m.Properties = map[string]string{
- "storageAccount": "account",
- "storageAccessKey": "key",
- "container": "test",
- "publicAccessLevel": "container",
- }
- meta, err := blobStorage.parseMetadata(m)
- assert.Nil(t, err)
- assert.Equal(t, azblob.PublicAccessContainer, meta.PublicAccessLevel)
- })
-
- t.Run("parse metadata with invalid publicAccessLevel", func(t *testing.T) {
- m.Properties = map[string]string{
- "storageAccount": "account",
- "storageAccessKey": "key",
- "container": "test",
- "publicAccessLevel": "invalid",
- }
- _, err := blobStorage.parseMetadata(m)
- assert.Error(t, err)
- })
-
- t.Run("sanitize metadata if necessary", func(t *testing.T) {
- m.Properties = map[string]string{
- "somecustomfield": "some-custom-value",
- "specialfield": "special:valueÜ",
- "not-allowed:": "not-allowed",
- }
- meta := blobStorage.sanitizeMetadata(m.Properties)
- assert.Equal(t, meta["somecustomfield"], "some-custom-value")
- assert.Equal(t, meta["specialfield"], "special:value")
- assert.Equal(t, meta["notallowed"], "not-allowed")
- })
-}
-
func TestGetOption(t *testing.T) {
blobStorage := NewAzureBlobStorage(logger.NewLogger("test")).(*AzureBlobStorage)
diff --git a/bindings/azure/cosmosdb/cosmosdb.go b/bindings/azure/cosmosdb/cosmosdb.go
index d4efb802b..4a3cbaf8b 100644
--- a/bindings/azure/cosmosdb/cosmosdb.go
+++ b/bindings/azure/cosmosdb/cosmosdb.go
@@ -20,6 +20,7 @@ import (
"strings"
"time"
+ "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos"
"github.com/dapr/components-contrib/bindings"
@@ -60,6 +61,14 @@ func (c *CosmosDB) Init(metadata bindings.Metadata) error {
c.partitionKey = m.PartitionKey
+ opts := azcosmos.ClientOptions{
+ ClientOptions: policy.ClientOptions{
+ Telemetry: policy.TelemetryOptions{
+ ApplicationID: "dapr-" + logger.DaprVersion,
+ },
+ },
+ }
+
// Create the client; first, try authenticating with a master key, if present
var client *azcosmos.Client
if m.MasterKey != "" {
@@ -67,7 +76,7 @@ func (c *CosmosDB) Init(metadata bindings.Metadata) error {
if keyErr != nil {
return keyErr
}
- client, err = azcosmos.NewClientWithKey(m.URL, cred, nil)
+ client, err = azcosmos.NewClientWithKey(m.URL, cred, &opts)
if err != nil {
return err
}
@@ -81,7 +90,7 @@ func (c *CosmosDB) Init(metadata bindings.Metadata) error {
if errToken != nil {
return errToken
}
- client, err = azcosmos.NewClient(m.URL, token, nil)
+ client, err = azcosmos.NewClient(m.URL, token, &opts)
if err != nil {
return err
}
diff --git a/bindings/azure/storagequeues/storagequeues.go b/bindings/azure/storagequeues/storagequeues.go
index 51da3427f..048e9a359 100644
--- a/bindings/azure/storagequeues/storagequeues.go
+++ b/bindings/azure/storagequeues/storagequeues.go
@@ -25,9 +25,9 @@ import (
"github.com/dapr/components-contrib/bindings"
azauth "github.com/dapr/components-contrib/internal/authentication/azure"
- "github.com/dapr/components-contrib/internal/utils"
contribMetadata "github.com/dapr/components-contrib/metadata"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
const (
@@ -47,9 +47,11 @@ type QueueHelper interface {
// AzureQueueHelper concrete impl of queue helper.
type AzureQueueHelper struct {
- queueURL azqueue.QueueURL
- logger logger.Logger
- decodeBase64 bool
+ queueURL azqueue.QueueURL
+ logger logger.Logger
+ decodeBase64 bool
+ encodeBase64 bool
+ visibilityTimeout time.Duration
}
// Init sets up this helper.
@@ -73,6 +75,8 @@ func (d *AzureQueueHelper) Init(metadata bindings.Metadata) (*storageQueuesMetad
p := azqueue.NewPipeline(credential, pipelineOptions)
d.decodeBase64 = m.DecodeBase64
+ d.encodeBase64 = m.EncodeBase64
+ d.visibilityTimeout = *m.VisibilityTimeout
if m.QueueEndpoint != "" {
URL, parseErr := url.Parse(fmt.Sprintf("%s/%s/%s", m.QueueEndpoint, m.AccountName, m.QueueName))
@@ -103,6 +107,10 @@ func (d *AzureQueueHelper) Write(ctx context.Context, data []byte, ttl *time.Dur
s = string(data)
}
+ if d.encodeBase64 {
+ s = base64.StdEncoding.EncodeToString([]byte(s))
+ }
+
if ttl == nil {
ttlToUse := defaultTTL
ttl = &ttlToUse
@@ -114,7 +122,7 @@ func (d *AzureQueueHelper) Write(ctx context.Context, data []byte, ttl *time.Dur
func (d *AzureQueueHelper) Read(ctx context.Context, consumer *consumer) error {
messagesURL := d.queueURL.NewMessagesURL()
- res, err := messagesURL.Dequeue(ctx, 1, time.Second*30)
+ res, err := messagesURL.Dequeue(ctx, 1, d.visibilityTimeout)
if err != nil {
return err
}
@@ -170,11 +178,13 @@ type AzureStorageQueues struct {
}
type storageQueuesMetadata struct {
- QueueName string
- QueueEndpoint string
- AccountName string
- DecodeBase64 bool
- ttl *time.Duration
+ QueueName string
+ QueueEndpoint string
+ AccountName string
+ DecodeBase64 bool
+ EncodeBase64 bool
+ ttl *time.Duration
+ VisibilityTimeout *time.Duration
}
// NewAzureStorageQueues returns a new AzureStorageQueues instance.
@@ -192,29 +202,31 @@ func (a *AzureStorageQueues) Init(metadata bindings.Metadata) (err error) {
return nil
}
-func parseMetadata(metadata bindings.Metadata) (*storageQueuesMetadata, error) {
- var m storageQueuesMetadata
+func parseMetadata(meta bindings.Metadata) (*storageQueuesMetadata, error) {
+ m := storageQueuesMetadata{
+ VisibilityTimeout: ptr.Of(time.Second * 30),
+ }
// AccountKey is parsed in azauth
- if val, ok := contribMetadata.GetMetadataProperty(metadata.Properties, azauth.StorageAccountNameKeys...); ok && val != "" {
+ contribMetadata.DecodeMetadata(meta.Properties, &m)
+
+ if val, ok := contribMetadata.GetMetadataProperty(meta.Properties, azauth.StorageAccountNameKeys...); ok && val != "" {
m.AccountName = val
} else {
return nil, fmt.Errorf("missing or empty %s field from metadata", azauth.StorageAccountNameKeys[0])
}
- if val, ok := contribMetadata.GetMetadataProperty(metadata.Properties, azauth.StorageQueueNameKeys...); ok && val != "" {
+ if val, ok := contribMetadata.GetMetadataProperty(meta.Properties, azauth.StorageQueueNameKeys...); ok && val != "" {
m.QueueName = val
} else {
return nil, fmt.Errorf("missing or empty %s field from metadata", azauth.StorageQueueNameKeys[0])
}
- if val, ok := contribMetadata.GetMetadataProperty(metadata.Properties, azauth.StorageEndpointKeys...); ok && val != "" {
+ if val, ok := contribMetadata.GetMetadataProperty(meta.Properties, azauth.StorageEndpointKeys...); ok && val != "" {
m.QueueEndpoint = val
}
- m.DecodeBase64 = utils.IsTruthy(metadata.Properties["decodeBase64"])
-
- ttl, ok, err := contribMetadata.TryGetTTL(metadata.Properties)
+ ttl, ok, err := contribMetadata.TryGetTTL(meta.Properties)
if err != nil {
return nil, err
}
diff --git a/bindings/azure/storagequeues/storagequeues_test.go b/bindings/azure/storagequeues/storagequeues_test.go
index 77c0903cb..678ba388d 100644
--- a/bindings/azure/storagequeues/storagequeues_test.go
+++ b/bindings/azure/storagequeues/storagequeues_test.go
@@ -25,6 +25,7 @@ import (
"github.com/dapr/components-contrib/bindings"
"github.com/dapr/components-contrib/metadata"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
type MockHelper struct {
@@ -294,38 +295,49 @@ func TestParseMetadata(t *testing.T) {
properties map[string]string
// Account key is parsed in azauth
// expectedAccountKey string
- expectedQueueName string
- expectedQueueEndpointURL string
- expectedTTL *time.Duration
+ expectedQueueName string
+ expectedQueueEndpointURL string
+ expectedTTL *time.Duration
+ expectedVisibilityTimeout *time.Duration
}{
{
name: "Account and key",
properties: map[string]string{"storageAccessKey": "myKey", "queue": "queue1", "storageAccount": "devstoreaccount1"},
// expectedAccountKey: "myKey",
- expectedQueueName: "queue1",
- expectedQueueEndpointURL: "",
+ expectedQueueName: "queue1",
+ expectedQueueEndpointURL: "",
+ expectedVisibilityTimeout: ptr.Of(30 * time.Second),
},
{
name: "Accout, key, and endpoint",
properties: map[string]string{"accountKey": "myKey", "queueName": "queue1", "storageAccount": "someAccount", "queueEndpointUrl": "https://foo.example.com:10001"},
// expectedAccountKey: "myKey",
- expectedQueueName: "queue1",
- expectedQueueEndpointURL: "https://foo.example.com:10001",
+ expectedQueueName: "queue1",
+ expectedQueueEndpointURL: "https://foo.example.com:10001",
+ expectedVisibilityTimeout: ptr.Of(30 * time.Second),
},
{
name: "Empty TTL",
properties: map[string]string{"storageAccessKey": "myKey", "queue": "queue1", "storageAccount": "devstoreaccount1", metadata.TTLMetadataKey: ""},
// expectedAccountKey: "myKey",
- expectedQueueName: "queue1",
- expectedQueueEndpointURL: "",
+ expectedQueueName: "queue1",
+ expectedQueueEndpointURL: "",
+ expectedVisibilityTimeout: ptr.Of(30 * time.Second),
},
{
name: "With TTL",
properties: map[string]string{"accessKey": "myKey", "storageAccountQueue": "queue1", "storageAccount": "devstoreaccount1", metadata.TTLMetadataKey: "1"},
// expectedAccountKey: "myKey",
- expectedQueueName: "queue1",
- expectedTTL: &oneSecondDuration,
- expectedQueueEndpointURL: "",
+ expectedQueueName: "queue1",
+ expectedTTL: &oneSecondDuration,
+ expectedQueueEndpointURL: "",
+ expectedVisibilityTimeout: ptr.Of(30 * time.Second),
+ },
+ {
+ name: "With visibility timeout",
+ properties: map[string]string{"accessKey": "myKey", "storageAccountQueue": "queue1", "storageAccount": "devstoreaccount1", "visibilityTimeout": "5s"},
+ expectedQueueName: "queue1",
+ expectedVisibilityTimeout: ptr.Of(5 * time.Second),
},
}
@@ -341,6 +353,7 @@ func TestParseMetadata(t *testing.T) {
assert.Equal(t, tt.expectedQueueName, meta.QueueName)
assert.Equal(t, tt.expectedTTL, meta.ttl)
assert.Equal(t, tt.expectedQueueEndpointURL, meta.QueueEndpoint)
+ assert.Equal(t, tt.expectedVisibilityTimeout, meta.VisibilityTimeout)
})
}
}
diff --git a/bindings/cron/cron.go b/bindings/cron/cron.go
index 036c2b9f3..24549cdea 100644
--- a/bindings/cron/cron.go
+++ b/bindings/cron/cron.go
@@ -18,8 +18,10 @@ import (
"fmt"
"time"
+ "github.com/benbjohnson/clock"
"github.com/pkg/errors"
- cron "github.com/robfig/cron/v3"
+
+ cron "github.com/dapr/kit/cron"
"github.com/dapr/components-contrib/bindings"
"github.com/dapr/kit/logger"
@@ -27,18 +29,22 @@ import (
// Binding represents Cron input binding.
type Binding struct {
- logger logger.Logger
- name string
- schedule string
- parser cron.Parser
- runningCtx context.Context
- runningCancel context.CancelFunc
+ logger logger.Logger
+ name string
+ schedule string
+ parser cron.Parser
+ clk clock.Clock
}
// NewCron returns a new Cron event input binding.
-func NewCron(logger logger.Logger) bindings.InputOutputBinding {
+func NewCron(logger logger.Logger) bindings.InputBinding {
+ return NewCronWithClock(logger, clock.New())
+}
+
+func NewCronWithClock(logger logger.Logger, clk clock.Clock) bindings.InputBinding {
return &Binding{
logger: logger,
+ clk: clk,
parser: cron.NewParser(
cron.SecondOptional | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor,
),
@@ -62,14 +68,12 @@ func (b *Binding) Init(metadata bindings.Metadata) error {
}
b.schedule = s
- b.resetContext()
-
return nil
}
// Read triggers the Cron scheduler.
func (b *Binding) Read(ctx context.Context, handler bindings.Handler) error {
- c := cron.New(cron.WithParser(b.parser))
+ c := cron.New(cron.WithParser(b.parser), cron.WithClock(b.clk))
id, err := c.AddFunc(b.schedule, func() {
b.logger.Debugf("name: %s, schedule fired: %v", b.name, time.Now())
handler(ctx, &bindings.ReadResponse{
@@ -86,50 +90,11 @@ func (b *Binding) Read(ctx context.Context, handler bindings.Handler) error {
b.logger.Debugf("name: %s, next run: %v", b.name, time.Until(c.Entry(id).Next))
go func() {
- // Wait for a context to be canceled
- select {
- case <-b.runningCtx.Done():
- // Do nothing
- case <-ctx.Done():
- b.resetContext()
- }
+ // Wait for context to be canceled
+ <-ctx.Done()
b.logger.Debugf("name: %s, stopping schedule: %s", b.name, b.schedule)
c.Stop()
}()
return nil
}
-
-// Invoke exposes way to stop previously started cron.
-func (b *Binding) Invoke(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
- b.logger.Debugf("name: %s, operation: %v", b.name, req.Operation)
-
- switch req.Operation {
- case bindings.DeleteOperation:
- b.resetContext()
- return &bindings.InvokeResponse{
- Metadata: map[string]string{
- "schedule": b.schedule,
- "stopTimeUTC": time.Now().UTC().String(),
- },
- }, nil
- default:
- return nil, fmt.Errorf("invalid operation: '%v', only '%v' supported",
- req.Operation, bindings.DeleteOperation)
- }
-}
-
-// Operations method returns the supported operations by this binding.
-func (b *Binding) Operations() []bindings.OperationKind {
- return []bindings.OperationKind{
- bindings.DeleteOperation,
- }
-}
-
-// Resets the runningCtx
-func (b *Binding) resetContext() {
- if b.runningCancel != nil {
- b.runningCancel()
- }
- b.runningCtx, b.runningCancel = context.WithCancel(context.Background())
-}
diff --git a/bindings/cron/cron_test.go b/bindings/cron/cron_test.go
index 1a4ce5f71..f48fb8415 100644
--- a/bindings/cron/cron_test.go
+++ b/bindings/cron/cron_test.go
@@ -19,6 +19,7 @@ import (
"testing"
"time"
+ "github.com/benbjohnson/clock"
"github.com/stretchr/testify/assert"
"github.com/dapr/components-contrib/bindings"
@@ -35,90 +36,112 @@ func getTestMetadata(schedule string) bindings.Metadata {
}
func getNewCron() *Binding {
+ clk := clock.New()
+ return getNewCronWithClock(clk)
+}
+
+func getNewCronWithClock(clk clock.Clock) *Binding {
l := logger.NewLogger("cron")
if os.Getenv("DEBUG") != "" {
l.SetOutputLevel(logger.DebugLevel)
}
-
- return NewCron(l).(*Binding)
+ return NewCronWithClock(l, clk).(*Binding)
}
// go test -v -timeout 15s -count=1 ./bindings/cron/.
+//
+//nolint:dupword
func TestCronInitSuccess(t *testing.T) {
- c := getNewCron()
- err := c.Init(getTestMetadata("@every 1h"))
- assert.NoErrorf(t, err, "error initializing valid schedule")
-}
+ initTests := []struct {
+ schedule string
+ errorExpected bool
+ }{
+ {
+ schedule: "@every 1s", // macro cron format
+ errorExpected: false,
+ },
+ {
+ schedule: "*/3 * * * * *", // non standard cron format
+ errorExpected: false,
+ },
+ {
+ schedule: "*/15 * * * *", // standard cron format
+ errorExpected: false,
+ },
+ {
+ schedule: "0 0 1 * *", // standard cron format
+ errorExpected: false,
+ },
+ {
+ schedule: "0 0 */6 ? * *", // quartz cron format
+ errorExpected: false,
+ },
+ {
+ schedule: "INVALID_SCHEDULE", // invalid cron format
+ errorExpected: true,
+ },
+ }
-func TestCronInitWithSeconds(t *testing.T) {
- c := getNewCron()
- err := c.Init(getTestMetadata("15 * * * * *"))
- assert.NoErrorf(t, err, "error initializing schedule with seconds")
-}
-
-func TestCronInitFailure(t *testing.T) {
- c := getNewCron()
- err := c.Init(getTestMetadata("invalid schedule"))
- assert.Errorf(t, err, "no error while initializing invalid schedule")
+ for _, test := range initTests {
+ c := getNewCron()
+ err := c.Init(getTestMetadata(test.schedule))
+ if test.errorExpected {
+ assert.Errorf(t, err, "Got no error while initializing an invalid schedule: %s", test.schedule)
+ } else {
+ assert.NoErrorf(t, err, "error initializing valid schedule: %s", test.schedule)
+ }
+ }
}
// TestLongRead
// go test -v -count=1 -timeout 15s -run TestLongRead ./bindings/cron/.
-func TestCronReadWithDeleteInvoke(t *testing.T) {
- c := getNewCron()
+func TestCronRead(t *testing.T) {
+ clk := clock.NewMock()
+ c := getNewCronWithClock(clk)
schedule := "@every 1s"
assert.NoErrorf(t, c.Init(getTestMetadata(schedule)), "error initializing valid schedule")
- testsNum := 3
- i := 0
+ expectedCount := 5
+ observedCount := 0
err := c.Read(context.Background(), func(ctx context.Context, res *bindings.ReadResponse) ([]byte, error) {
assert.NotNil(t, res)
- assert.LessOrEqualf(t, i, testsNum, "Invoke didn't stop the schedule")
- i++
- if i == testsNum {
- resp, err := c.Invoke(context.Background(), &bindings.InvokeRequest{
- Operation: bindings.DeleteOperation,
- })
- assert.NoError(t, err)
- scheduleVal, exists := resp.Metadata["schedule"]
- assert.Truef(t, exists, "Response metadata doesn't include the expected 'schedule' key")
- assert.Equal(t, schedule, scheduleVal)
- }
-
+ observedCount++
return nil, nil
})
- time.Sleep(time.Duration(testsNum+3) * time.Second)
- assert.Equal(t, testsNum, i)
+ // Check if cron triggers 5 times in 5 seconds
+ for i := 0; i < expectedCount; i++ {
+ // Add time to mock clock in 1 second intervals using loop to allow cron go routine to run
+ clk.Add(time.Second)
+ }
+ // Wait for 1 second after adding the last second to mock clock to allow cron to finish triggering
+ time.Sleep(1 * time.Second)
+ assert.Equal(t, expectedCount, observedCount, "Cron did not trigger expected number of times, expected %d, got %d", expectedCount, observedCount)
assert.NoErrorf(t, err, "error on read")
}
func TestCronReadWithContextCancellation(t *testing.T) {
- c := getNewCron()
+ clk := clock.NewMock()
+ c := getNewCronWithClock(clk)
schedule := "@every 1s"
assert.NoErrorf(t, c.Init(getTestMetadata(schedule)), "error initializing valid schedule")
- testsNum := 3
- i := 0
+ expectedCount := 5
+ observedCount := 0
ctx, cancel := context.WithCancel(context.Background())
err := c.Read(ctx, func(ctx context.Context, res *bindings.ReadResponse) ([]byte, error) {
assert.NotNil(t, res)
- assert.LessOrEqualf(t, i, testsNum, "Invoke didn't stop the schedule")
- i++
- if i == testsNum {
+ assert.LessOrEqualf(t, observedCount, expectedCount, "Invoke didn't stop the schedule")
+ observedCount++
+ if observedCount == expectedCount {
+ // Cancel context after 5 triggers
cancel()
}
-
return nil, nil
})
- time.Sleep(time.Duration(testsNum+3) * time.Second)
- assert.Equal(t, testsNum, i)
+ // Check if cron triggers only 5 times in 10 seconds since context should be cancelled after 5 triggers
+ for i := 0; i < 10; i++ {
+ // Add time to mock clock in 1 second intervals using loop to allow cron go routine to run
+ clk.Add(time.Second)
+ }
+ time.Sleep(1 * time.Second)
+ assert.Equal(t, expectedCount, observedCount, "Cron did not trigger expected number of times, expected %d, got %d", expectedCount, observedCount)
assert.NoErrorf(t, err, "error on read")
}
-
-func TestCronInvokeInvalidOperation(t *testing.T) {
- c := getNewCron()
- initErr := c.Init(getTestMetadata("@every 1s"))
- assert.NoErrorf(t, initErr, "Error on Init")
- _, err := c.Invoke(context.Background(), &bindings.InvokeRequest{
- Operation: bindings.CreateOperation,
- })
- assert.Error(t, err)
-}
diff --git a/bindings/gcp/bucket/bucket.go b/bindings/gcp/bucket/bucket.go
index b1f80fb43..9a83b1e96 100644
--- a/bindings/gcp/bucket/bucket.go
+++ b/bindings/gcp/bucket/bucket.go
@@ -196,7 +196,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 binding error. error merge metadata : %w", err)
+ return nil, fmt.Errorf("gcp binding error. error merge metadata : %w", err)
}
var key string
diff --git a/bindings/http/http.go b/bindings/http/http.go
index fac33aacd..ccf629f6d 100644
--- a/bindings/http/http.go
+++ b/bindings/http/http.go
@@ -28,6 +28,7 @@ import (
"github.com/mitchellh/mapstructure"
"github.com/dapr/components-contrib/bindings"
+ "github.com/dapr/components-contrib/internal/utils"
"github.com/dapr/kit/logger"
)
@@ -35,10 +36,10 @@ import (
//
//revive:disable-next-line
type HTTPSource struct {
- metadata httpMetadata
- client *http.Client
-
- logger logger.Logger
+ metadata httpMetadata
+ client *http.Client
+ errorIfNot2XX bool
+ logger logger.Logger
}
type httpMetadata struct {
@@ -70,6 +71,13 @@ func (h *HTTPSource) Init(metadata bindings.Metadata) error {
Transport: netTransport,
}
+ if val, ok := metadata.Properties["errorIfNot2XX"]; ok {
+ h.errorIfNot2XX = utils.IsTruthy(val)
+ } else {
+ // Default behavior
+ h.errorIfNot2XX = true
+ }
+
return nil
}
@@ -91,6 +99,9 @@ func (h *HTTPSource) Operations() []bindings.OperationKind {
// Invoke performs an HTTP request to the configured HTTP endpoint.
func (h *HTTPSource) Invoke(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
u := h.metadata.URL
+
+ errorIfNot2XX := h.errorIfNot2XX // Default to the component config (default is true)
+
if req.Metadata != nil {
if path, ok := req.Metadata["path"]; ok {
// Simplicity and no "../../.." type exploits.
@@ -99,6 +110,13 @@ func (h *HTTPSource) Invoke(ctx context.Context, req *bindings.InvokeRequest) (*
return nil, fmt.Errorf("invalid path: %s", path)
}
}
+
+ if _, ok := req.Metadata["errorIfNot2XX"]; ok {
+ errorIfNot2XX = utils.IsTruthy(req.Metadata["errorIfNot2XX"])
+ }
+ } else {
+ // Prevent things below from failing if req.Metadata is nil.
+ req.Metadata = make(map[string]string)
}
var body io.Reader
@@ -164,8 +182,8 @@ func (h *HTTPSource) Invoke(ctx context.Context, req *bindings.InvokeRequest) (*
metadata[key] = strings.Join(values, ", ")
}
- // Create an error for non-200 status codes.
- if resp.StatusCode/100 != 2 {
+ // Create an error for non-200 status codes unless suppressed.
+ if errorIfNot2XX && resp.StatusCode/100 != 2 {
err = fmt.Errorf("received status code %d", resp.StatusCode)
}
diff --git a/bindings/http/http_test.go b/bindings/http/http_test.go
index 746fc052a..d88e8aad4 100644
--- a/bindings/http/http_test.go
+++ b/bindings/http/http_test.go
@@ -18,6 +18,7 @@ import (
"io"
"net/http"
"net/http/httptest"
+ "strconv"
"strings"
"testing"
@@ -45,146 +46,316 @@ func TestOperations(t *testing.T) {
}, opers)
}
-func TestInit(t *testing.T) {
- var path string
+type TestCase struct {
+ input string
+ operation string
+ metadata map[string]string
+ path string
+ err string
+ statusCode int
+}
- s := httptest.NewServer(
- http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- path = req.URL.Path
- input := req.Method
- if req.Body != nil {
- defer req.Body.Close()
- b, _ := io.ReadAll(req.Body)
- if len(b) > 0 {
- input = string(b)
- }
- }
- inputFromHeader := req.Header.Get("X-Input")
- if inputFromHeader != "" {
- input = inputFromHeader
- }
- w.Header().Set("Content-Type", "text/plain")
- if input == "internal server error" {
- w.WriteHeader(http.StatusInternalServerError)
- }
- w.Write([]byte(strings.ToUpper(input)))
- }),
- )
- defer s.Close()
+func (tc TestCase) ToInvokeRequest() bindings.InvokeRequest {
+ requestMetadata := tc.metadata
+ if requestMetadata == nil {
+ requestMetadata = map[string]string{}
+ }
+
+ requestMetadata["X-Status-Code"] = strconv.Itoa(tc.statusCode)
+
+ return bindings.InvokeRequest{
+ Data: []byte(tc.input),
+ Metadata: requestMetadata,
+ Operation: bindings.OperationKind(tc.operation),
+ }
+}
+
+type HTTPHandler struct {
+ Path string
+}
+
+func (h *HTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ h.Path = req.URL.Path
+
+ input := req.Method
+ if req.Body != nil {
+ defer req.Body.Close()
+ b, _ := io.ReadAll(req.Body)
+ if len(b) > 0 {
+ input = string(b)
+ }
+ }
+ inputFromHeader := req.Header.Get("X-Input")
+ if inputFromHeader != "" {
+ input = inputFromHeader
+ }
+
+ w.Header().Set("Content-Type", "text/plain")
+
+ statusCode := req.Header.Get("X-Status-Code")
+ if statusCode != "" {
+ code, _ := strconv.Atoi(statusCode)
+ w.WriteHeader(code)
+ }
+
+ w.Write([]byte(strings.ToUpper(input)))
+}
+
+func NewHTTPHandler() *HTTPHandler {
+ return &HTTPHandler{
+ Path: "/",
+ }
+}
+
+func InitBinding(s *httptest.Server, extraProps map[string]string) (bindings.OutputBinding, error) {
m := bindings.Metadata{Base: metadata.Base{
Properties: map[string]string{
"url": s.URL,
},
}}
+
+ if extraProps != nil {
+ for k, v := range extraProps {
+ m.Properties[k] = v
+ }
+ }
+
hs := bindingHttp.NewHTTP(logger.NewLogger("test"))
err := hs.Init(m)
+ return hs, err
+}
+
+func TestInit(t *testing.T) {
+ handler := NewHTTPHandler()
+ s := httptest.NewServer(handler)
+ defer s.Close()
+
+ _, err := InitBinding(s, nil)
+ require.NoError(t, err)
+}
+
+func TestDefaultBehavior(t *testing.T) {
+ handler := NewHTTPHandler()
+ s := httptest.NewServer(handler)
+ defer s.Close()
+
+ hs, err := InitBinding(s, nil)
require.NoError(t, err)
- tests := map[string]struct {
- input string
- operation string
- metadata map[string]string
- path string
- err string
- }{
+ tests := map[string]TestCase{
"get": {
- input: "GET",
- operation: "get",
- metadata: nil,
- path: "/",
- err: "",
+ input: "GET",
+ operation: "get",
+ metadata: nil,
+ path: "/",
+ err: "",
+ statusCode: 200,
},
"request headers": {
- input: "OVERRIDE",
- operation: "get",
- metadata: map[string]string{"X-Input": "override"},
- path: "/",
- err: "",
+ input: "OVERRIDE",
+ operation: "get",
+ metadata: map[string]string{"X-Input": "override"},
+ path: "/",
+ err: "",
+ statusCode: 200,
},
"post": {
- input: "expected",
- operation: "post",
- metadata: map[string]string{"path": "/test"},
- path: "/test",
- err: "",
+ input: "expected",
+ operation: "post",
+ metadata: map[string]string{"path": "/test"},
+ path: "/test",
+ err: "",
+ statusCode: 201,
},
"put": {
- input: "expected",
- operation: "put",
- metadata: map[string]string{"path": "/test"},
- path: "/test",
- err: "",
+ input: "expected",
+ operation: "put",
+ statusCode: 204,
+ metadata: map[string]string{"path": "/test"},
+ path: "/test",
+ err: "",
},
"patch": {
- input: "expected",
- operation: "patch",
- metadata: map[string]string{"path": "/test"},
- path: "/test",
- err: "",
+ input: "expected",
+ operation: "patch",
+ metadata: map[string]string{"path": "/test"},
+ path: "/test",
+ err: "",
+ statusCode: 206,
},
"delete": {
- input: "DELETE",
- operation: "delete",
- metadata: nil,
- path: "/",
- err: "",
+ input: "DELETE",
+ operation: "delete",
+ metadata: nil,
+ path: "/",
+ err: "",
+ statusCode: 200,
},
"options": {
- input: "OPTIONS",
- operation: "options",
- metadata: nil,
- path: "/",
- err: "",
+ input: "OPTIONS",
+ operation: "options",
+ metadata: nil,
+ path: "/",
+ err: "",
+ statusCode: 200,
},
"trace": {
- input: "TRACE",
- operation: "trace",
- metadata: nil,
- path: "/",
- err: "",
+ input: "TRACE",
+ operation: "trace",
+ metadata: nil,
+ path: "/",
+ err: "",
+ statusCode: 200,
},
"backward compatibility": {
- input: "expected",
- operation: "create",
- metadata: map[string]string{"path": "/test"},
- path: "/test",
- err: "",
+ input: "expected",
+ operation: "create",
+ metadata: map[string]string{"path": "/test"},
+ path: "/test",
+ err: "",
+ statusCode: 200,
},
"invalid path": {
- input: "expected",
- operation: "POST",
- metadata: map[string]string{"path": "/../test"},
- path: "",
- err: "invalid path: /../test",
+ input: "expected",
+ operation: "POST",
+ metadata: map[string]string{"path": "/../test"},
+ path: "",
+ err: "invalid path: /../test",
+ statusCode: 400,
},
"invalid operation": {
- input: "notvalid",
- operation: "notvalid",
- metadata: map[string]string{"path": "/test"},
- path: "/test",
- err: "invalid operation: notvalid",
+ input: "notvalid",
+ operation: "notvalid",
+ metadata: map[string]string{"path": "/test"},
+ path: "/test",
+ err: "invalid operation: notvalid",
+ statusCode: 400,
},
"internal server error": {
- input: "internal server error",
- operation: "post",
- metadata: map[string]string{"path": "/"},
- path: "/",
- err: "received status code 500",
+ input: "internal server error",
+ operation: "post",
+ metadata: map[string]string{"path": "/"},
+ path: "/",
+ err: "received status code 500",
+ statusCode: 500,
+ },
+ "internal server error suppressed": {
+ input: "internal server error", // trigger 500 downstream
+ operation: "post",
+ metadata: map[string]string{"path": "/", "errorIfNot2XX": "false"},
+ path: "/",
+ err: "",
+ statusCode: 500,
+ },
+ "redirect should not yield an error": {
+ input: "show me the treasure!",
+ operation: "post",
+ metadata: map[string]string{"path": "/", "errorIfNot2XX": "false"},
+ path: "/",
+ err: "",
+ statusCode: 302,
+ },
+ "redirect results in an error if not suppressed": {
+ input: "show me the treasure!",
+ operation: "post",
+ metadata: map[string]string{"path": "/"},
+ path: "/",
+ err: "received status code 302",
+ statusCode: 302,
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
- response, err := hs.Invoke(context.TODO(), &bindings.InvokeRequest{
- Data: []byte(tc.input),
- Metadata: tc.metadata,
- Operation: bindings.OperationKind(tc.operation),
- })
+ req := tc.ToInvokeRequest()
+ response, err := hs.Invoke(context.TODO(), &req)
if tc.err == "" {
require.NoError(t, err)
- assert.Equal(t, tc.path, path)
- assert.Equal(t, strings.ToUpper(tc.input), string(response.Data))
+ assert.Equal(t, tc.path, handler.Path)
+ if tc.statusCode != 204 {
+ // 204 will return no content, so we should skip checking
+ assert.Equal(t, strings.ToUpper(tc.input), string(response.Data))
+ }
+ assert.Equal(t, "text/plain", response.Metadata["Content-Type"])
+ } else {
+ require.Error(t, err)
+ assert.Equal(t, tc.err, err.Error())
+ }
+ })
+ }
+}
+
+func TestNon2XXErrorsSuppressed(t *testing.T) {
+ handler := NewHTTPHandler()
+ s := httptest.NewServer(handler)
+ defer s.Close()
+
+ hs, err := InitBinding(s, map[string]string{"errorIfNot2XX": "false"})
+ require.NoError(t, err)
+
+ tests := map[string]TestCase{
+ "internal server error": {
+ input: "internal server error",
+ operation: "post",
+ metadata: map[string]string{"path": "/"},
+ path: "/",
+ err: "",
+ statusCode: 500,
+ },
+ "internal server error overridden": {
+ input: "internal server error",
+ operation: "post",
+ metadata: map[string]string{"path": "/", "errorIfNot2XX": "true"},
+ path: "/",
+ err: "received status code 500",
+ statusCode: 500,
+ },
+ "internal server error suppressed by request and component": {
+ input: "internal server error", // trigger 500
+ operation: "post",
+ metadata: map[string]string{"path": "/", "errorIfNot2XX": "false"},
+ path: "/",
+ err: "",
+ statusCode: 500,
+ },
+ "trace": {
+ input: "TRACE",
+ operation: "trace",
+ metadata: nil,
+ path: "/",
+ err: "",
+ statusCode: 200,
+ },
+ "backward compatibility": {
+ input: "expected",
+ operation: "create",
+ metadata: map[string]string{"path": "/test"},
+ path: "/test",
+ err: "",
+ statusCode: 200,
+ },
+ "invalid path": {
+ input: "expected",
+ operation: "POST",
+ metadata: map[string]string{"path": "/../test"},
+ path: "",
+ err: "invalid path: /../test",
+ statusCode: 400,
+ },
+ }
+
+ for name, tc := range tests {
+ t.Run(name, func(t *testing.T) {
+ req := tc.ToInvokeRequest()
+ response, err := hs.Invoke(context.TODO(), &req)
+ if tc.err == "" {
+ require.NoError(t, err)
+ assert.Equal(t, tc.path, handler.Path)
+ if tc.statusCode != 204 {
+ // 204 will return no content, so we should skip checking
+ assert.Equal(t, strings.ToUpper(tc.input), string(response.Data))
+ }
assert.Equal(t, "text/plain", response.Metadata["Content-Type"])
} else {
require.Error(t, err)
diff --git a/bindings/kubemq/kubemq.go b/bindings/kubemq/kubemq.go
new file mode 100644
index 000000000..ca6c589ce
--- /dev/null
+++ b/bindings/kubemq/kubemq.go
@@ -0,0 +1,143 @@
+package kubemq
+
+import (
+ "context"
+ "fmt"
+ "strings"
+ "time"
+
+ qs "github.com/kubemq-io/kubemq-go/queues_stream"
+
+ "github.com/dapr/components-contrib/bindings"
+ "github.com/dapr/kit/logger"
+)
+
+// interface used to allow unit testing.
+type Kubemq interface {
+ bindings.InputBinding
+ bindings.OutputBinding
+}
+
+type kubeMQ struct {
+ client *qs.QueuesStreamClient
+ opts *options
+ logger logger.Logger
+ ctx context.Context
+ ctxCancel context.CancelFunc
+}
+
+func NewKubeMQ(logger logger.Logger) Kubemq {
+ return &kubeMQ{
+ client: nil,
+ opts: nil,
+ logger: logger,
+ ctx: nil,
+ ctxCancel: nil,
+ }
+}
+
+func (k *kubeMQ) Init(metadata bindings.Metadata) error {
+ opts, err := createOptions(metadata)
+ if err != nil {
+ return err
+ }
+ k.opts = opts
+ k.ctx, k.ctxCancel = context.WithCancel(context.Background())
+ client, err := qs.NewQueuesStreamClient(k.ctx,
+ qs.WithAddress(opts.host, opts.port),
+ qs.WithCheckConnection(true),
+ qs.WithAuthToken(opts.authToken),
+ qs.WithAutoReconnect(true),
+ qs.WithReconnectInterval(time.Second))
+ if err != nil {
+ k.logger.Errorf("error init kubemq client error: %s", err.Error())
+ return err
+ }
+ k.ctx, k.ctxCancel = context.WithCancel(context.Background())
+ k.client = client
+ return nil
+}
+
+func (k *kubeMQ) Read(ctx context.Context, handler bindings.Handler) error {
+ go func() {
+ for {
+ err := k.processQueueMessage(k.ctx, handler)
+ if err != nil {
+ k.logger.Error(err.Error())
+ time.Sleep(time.Second)
+ }
+ if k.ctx.Err() != nil {
+ return
+ }
+ }
+ }()
+ return nil
+}
+
+func (k *kubeMQ) Invoke(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
+ queueMessage := qs.NewQueueMessage().
+ SetChannel(k.opts.channel).
+ SetBody(req.Data).
+ SetPolicyDelaySeconds(parsePolicyDelaySeconds(req.Metadata)).
+ SetPolicyExpirationSeconds(parsePolicyExpirationSeconds(req.Metadata)).
+ SetPolicyMaxReceiveCount(parseSetPolicyMaxReceiveCount(req.Metadata)).
+ SetPolicyMaxReceiveQueue(parsePolicyMaxReceiveQueue(req.Metadata))
+ result, err := k.client.Send(k.ctx, queueMessage)
+ if err != nil {
+ return nil, err
+ }
+ if len(result.Results) > 0 {
+ if result.Results[0].IsError {
+ return nil, fmt.Errorf("error sending queue message: %s", result.Results[0].Error)
+ }
+ }
+ return &bindings.InvokeResponse{
+ Data: nil,
+ Metadata: nil,
+ }, nil
+}
+
+func (k *kubeMQ) Operations() []bindings.OperationKind {
+ return []bindings.OperationKind{bindings.CreateOperation}
+}
+
+func (k *kubeMQ) processQueueMessage(ctx context.Context, handler bindings.Handler) error {
+ pr := qs.NewPollRequest().
+ SetChannel(k.opts.channel).
+ SetMaxItems(k.opts.pollMaxItems).
+ SetWaitTimeout(k.opts.pollTimeoutSeconds).
+ SetAutoAck(k.opts.autoAcknowledged)
+
+ pollResp, err := k.client.Poll(ctx, pr)
+ if err != nil {
+ if strings.Contains(err.Error(), "timout waiting response") {
+ return nil
+ }
+ return err
+ }
+ if !pollResp.HasMessages() {
+ return nil
+ }
+
+ for _, message := range pollResp.Messages {
+ _, err := handler(ctx, &bindings.ReadResponse{
+ Data: message.Body,
+ })
+ if err != nil {
+ k.logger.Errorf("error received from response handler: %s", err.Error())
+ err := message.NAck()
+ if err != nil {
+ k.logger.Errorf("error processing nack message error: %s", err.Error())
+ }
+ time.Sleep(time.Second)
+ continue
+ } else {
+ err := message.Ack()
+ if err != nil {
+ k.logger.Errorf("error processing ack queue message error: %s", err.Error())
+ continue
+ }
+ }
+ }
+ return nil
+}
diff --git a/bindings/kubemq/kubemq_integration_test.go b/bindings/kubemq/kubemq_integration_test.go
new file mode 100644
index 000000000..d9ead92ee
--- /dev/null
+++ b/bindings/kubemq/kubemq_integration_test.go
@@ -0,0 +1,194 @@
+//go:build integration_test
+// +build integration_test
+
+package kubemq
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/dapr/components-contrib/bindings"
+ "github.com/dapr/components-contrib/metadata"
+ "github.com/dapr/kit/logger"
+)
+
+const (
+ // Environment variable containing the host name for KubeMQ integration tests
+ // To run using docker: docker run -d --hostname -kubemq --name test-kubemq -p 50000:50000 kubemq/kubemq-community:latest
+ // In that case the address string will be: "localhost:50000"
+ testKubeMQHostEnvKey = "DAPR_TEST_KUBEMQ_HOST"
+)
+
+func getTestKubeMQHost() string {
+ host := os.Getenv(testKubeMQHostEnvKey)
+ if host == "" {
+ host = "localhost:50000"
+ }
+ return host
+}
+
+func getDefaultMetadata(channel string) bindings.Metadata {
+ return bindings.Metadata{
+ Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": getTestKubeMQHost(),
+ "channel": channel,
+ "pollMaxItems": "1",
+ "autoAcknowledged": "true",
+ "pollTimeoutSeconds": "2",
+ },
+ },
+ }
+}
+
+func Test_kubeMQ_Init(t *testing.T) {
+ tests := []struct {
+ name string
+ meta bindings.Metadata
+ wantErr bool
+ }{
+ {
+ name: "init with valid options",
+ meta: bindings.Metadata{
+ Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": getTestKubeMQHost(),
+ "channel": "test",
+ "pollMaxItems": "1",
+ "autoAcknowledged": "true",
+ "pollTimeoutSeconds": "2",
+ },
+ },
+ },
+ wantErr: false,
+ },
+ {
+ name: "init with invalid options",
+ meta: bindings.Metadata{
+ Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": "localhost-bad:50000",
+ "channel": "test",
+ "pollMaxItems": "1",
+ "autoAcknowledged": "true",
+ "pollTimeoutSeconds": "2",
+ },
+ },
+ },
+ wantErr: true,
+ },
+ {
+ name: "init with invalid parsing options",
+ meta: bindings.Metadata{
+ Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": "bad",
+ "channel": "test",
+ "pollMaxItems": "1",
+ "autoAcknowledged": "true",
+ "pollTimeoutSeconds": "2",
+ },
+ },
+ },
+ wantErr: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ kubemq := NewKubeMQ(logger.NewLogger("test"))
+ err := kubemq.Init(tt.meta)
+ if tt.wantErr {
+ require.Error(t, err)
+ } else {
+ require.NoError(t, err)
+ }
+ })
+ }
+}
+
+func Test_kubeMQ_Invoke_Read_Single_Message(t *testing.T) {
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
+ defer cancel()
+ kubemq := NewKubeMQ(logger.NewLogger("test"))
+ err := kubemq.Init(getDefaultMetadata("test.read.single"))
+ require.NoError(t, err)
+ dataReadCh := make(chan []byte)
+ invokeRequest := &bindings.InvokeRequest{
+ Data: []byte("test"),
+ Metadata: map[string]string{},
+ }
+ _, err = kubemq.Invoke(ctx, invokeRequest)
+ require.NoError(t, err)
+ _ = kubemq.Read(ctx, func(ctx context.Context, req *bindings.ReadResponse) ([]byte, error) {
+ dataReadCh <- req.Data
+ return req.Data, nil
+ })
+ select {
+ case <-ctx.Done():
+ require.Fail(t, "timeout waiting for read response")
+ case data := <-dataReadCh:
+ require.Equal(t, invokeRequest.Data, data)
+ }
+}
+
+func Test_kubeMQ_Invoke_Read_Single_MessageWithHandlerError(t *testing.T) {
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
+ defer cancel()
+ kubemq := NewKubeMQ(logger.NewLogger("test"))
+ md := getDefaultMetadata("test.read.single.error")
+ md.Properties["autoAcknowledged"] = "false"
+ err := kubemq.Init(md)
+ require.NoError(t, err)
+ invokeRequest := &bindings.InvokeRequest{
+ Data: []byte("test"),
+ Metadata: map[string]string{},
+ }
+
+ _, err = kubemq.Invoke(ctx, invokeRequest)
+ require.NoError(t, err)
+ firstReadCtx, firstReadCancel := context.WithTimeout(context.Background(), time.Second*3)
+ defer firstReadCancel()
+ _ = kubemq.Read(firstReadCtx, func(ctx context.Context, req *bindings.ReadResponse) ([]byte, error) {
+ return nil, fmt.Errorf("handler error")
+ })
+
+ <-firstReadCtx.Done()
+ dataReadCh := make(chan []byte)
+ secondReadCtx, secondReadCancel := context.WithTimeout(context.Background(), time.Second*3)
+ defer secondReadCancel()
+ _ = kubemq.Read(secondReadCtx, func(ctx context.Context, req *bindings.ReadResponse) ([]byte, error) {
+ dataReadCh <- req.Data
+ return req.Data, nil
+ })
+ select {
+ case <-secondReadCtx.Done():
+ require.Fail(t, "timeout waiting for read response")
+ case data := <-dataReadCh:
+ require.Equal(t, invokeRequest.Data, data)
+ }
+}
+
+func Test_kubeMQ_Invoke_Error(t *testing.T) {
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
+ defer cancel()
+ kubemq := NewKubeMQ(logger.NewLogger("test"))
+ err := kubemq.Init(getDefaultMetadata("***test***"))
+ require.NoError(t, err)
+
+ invokeRequest := &bindings.InvokeRequest{
+ Data: []byte("test"),
+ Metadata: map[string]string{},
+ }
+ _, err = kubemq.Invoke(ctx, invokeRequest)
+ require.Error(t, err)
+}
diff --git a/bindings/kubemq/kubemq_test.go b/bindings/kubemq/kubemq_test.go
new file mode 100644
index 000000000..faa835d95
--- /dev/null
+++ b/bindings/kubemq/kubemq_test.go
@@ -0,0 +1,404 @@
+package kubemq
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/dapr/components-contrib/bindings"
+ "github.com/dapr/components-contrib/metadata"
+)
+
+func Test_createOptions(t *testing.T) {
+ tests := []struct {
+ name string
+ meta bindings.Metadata
+ want *options
+ wantErr bool
+ }{
+ {
+ name: "create valid opts",
+ meta: bindings.Metadata{
+ Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": "localhost:50000",
+ "channel": "test",
+ "authToken": "authToken",
+ "pollMaxItems": "10",
+ "autoAcknowledged": "true",
+ "pollTimeoutSeconds": "10",
+ },
+ },
+ },
+ want: &options{
+ host: "localhost",
+ port: 50000,
+ authToken: "authToken",
+ channel: "test",
+ autoAcknowledged: true,
+ pollMaxItems: 10,
+ pollTimeoutSeconds: 10,
+ },
+ wantErr: false,
+ },
+ {
+ name: "create invalid opts with bad host",
+ meta: bindings.Metadata{
+ Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": ":50000",
+ "clientId": "clientId",
+ },
+ },
+ },
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "create invalid opts with bad port",
+ meta: bindings.Metadata{
+ Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": "localhost:badport",
+ "clientId": "clientId",
+ },
+ },
+ },
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "create invalid opts with empty address",
+ meta: bindings.Metadata{
+ Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": "",
+ "clientId": "clientId",
+ },
+ },
+ },
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "create invalid opts with bad address format",
+ meta: bindings.Metadata{Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": "localhost50000",
+ },
+ }},
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "create invalid opts with no channel",
+ meta: bindings.Metadata{Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": "localhost:50000",
+ },
+ }},
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "create invalid opts with bad autoAcknowledged",
+ meta: bindings.Metadata{Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": "localhost:50000",
+ "channel": "test",
+ "autoAcknowledged": "bad",
+ },
+ }},
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "create invalid opts with invalid pollMaxItems",
+ meta: bindings.Metadata{Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": "localhost:50000",
+ "channel": "test",
+ "pollMaxItems": "0",
+ },
+ }},
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "create invalid opts with bad pollMaxItems format",
+ meta: bindings.Metadata{Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": "localhost:50000",
+ "channel": "test",
+ "pollMaxItems": "bad",
+ },
+ }},
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "create invalid opts with invalid pollTimeoutSeconds",
+ meta: bindings.Metadata{Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": "localhost:50000",
+ "channel": "test",
+ "pollTimeoutSeconds": "0",
+ },
+ }},
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "create invalid opts with bad format pollTimeoutSeconds",
+ meta: bindings.Metadata{Base: metadata.Base{
+ Name: "kubemq",
+ Properties: map[string]string{
+ "address": "localhost:50000",
+ "channel": "test",
+ "pollTimeoutSeconds": "bad",
+ },
+ }},
+ want: nil,
+ wantErr: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := createOptions(tt.meta)
+ if tt.wantErr {
+ assert.Error(t, err)
+ } else {
+ assert.NoError(t, err)
+ assert.Equal(t, tt.want, got)
+ }
+ })
+ }
+}
+
+func Test_parsePolicyDelaySeconds(t *testing.T) {
+ type args struct {
+ md map[string]string
+ }
+ tests := []struct {
+ name string
+ args args
+ want int
+ }{
+ {
+ name: "parse policy delay seconds - nil",
+ args: args{
+ md: nil,
+ },
+ want: 0,
+ },
+ {
+ name: "parse policy delay seconds - empty",
+ args: args{
+ md: map[string]string{},
+ },
+ want: 0,
+ },
+ {
+ name: "parse policy delay seconds",
+ args: args{
+ md: map[string]string{
+ "delaySeconds": "10",
+ },
+ },
+ want: 10,
+ },
+ {
+ name: "parse policy delay seconds with bad format",
+ args: args{
+ md: map[string]string{
+ "delaySeconds": "bad",
+ },
+ },
+ want: 0,
+ },
+ {
+ name: "parse policy delay seconds with negative value",
+ args: args{
+ md: map[string]string{
+ "delaySeconds": "-10",
+ },
+ },
+ want: 0,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ assert.Equalf(t, tt.want, parsePolicyDelaySeconds(tt.args.md), "parsePolicyDelaySeconds(%v)", tt.args.md)
+ })
+ }
+}
+
+func Test_parsePolicyExpirationSeconds(t *testing.T) {
+ type args struct {
+ md map[string]string
+ }
+ tests := []struct {
+ name string
+ args args
+ want int
+ }{
+ {
+ name: "parse policy expiration seconds - nil",
+ args: args{
+ md: nil,
+ },
+ want: 0,
+ },
+ {
+ name: "parse policy expiration seconds - empty",
+ args: args{
+ md: map[string]string{},
+ },
+ want: 0,
+ },
+ {
+ name: "parse policy expiration seconds",
+ args: args{
+ md: map[string]string{
+ "expirationSeconds": "10",
+ },
+ },
+ want: 10,
+ },
+ {
+ name: "parse policy expiration seconds with bad format",
+ args: args{
+ md: map[string]string{
+ "expirationSeconds": "bad",
+ },
+ },
+ want: 0,
+ },
+ {
+ name: "parse policy expiration seconds with negative value",
+ args: args{
+ md: map[string]string{
+ "expirationSeconds": "-10",
+ },
+ },
+ want: 0,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ assert.Equalf(t, tt.want, parsePolicyExpirationSeconds(tt.args.md), "parsePolicyExpirationSeconds(%v)", tt.args.md)
+ })
+ }
+}
+
+func Test_parseSetPolicyMaxReceiveCount(t *testing.T) {
+ type args struct {
+ md map[string]string
+ }
+ tests := []struct {
+ name string
+ args args
+ want int
+ }{
+ {
+ name: "parse policy max receive count nil",
+ args: args{
+ md: nil,
+ },
+ want: 0,
+ },
+ {
+ name: "parse policy max receive count empty",
+ args: args{
+ md: map[string]string{},
+ },
+ want: 0,
+ },
+ {
+ name: "parse policy max receive count",
+ args: args{
+ md: map[string]string{
+ "maxReceiveCount": "10",
+ },
+ },
+ want: 10,
+ },
+
+ {
+ name: "parse policy max receive count with bad format",
+ args: args{
+ md: map[string]string{
+ "maxReceiveCount": "bad",
+ },
+ },
+ want: 0,
+ },
+ {
+ name: "parse policy max receive count with negative value",
+ args: args{
+ md: map[string]string{
+ "maxReceiveCount": "-10",
+ },
+ },
+ want: 0,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ assert.Equalf(t, tt.want, parseSetPolicyMaxReceiveCount(tt.args.md), "parseSetPolicyMaxReceiveCount(%v)", tt.args.md)
+ })
+ }
+}
+
+func Test_parsePolicyMaxReceiveQueue(t *testing.T) {
+ type args struct {
+ md map[string]string
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {
+ name: "parse policy max receive queue nil",
+ args: args{
+ md: nil,
+ },
+ want: "",
+ },
+ {
+ name: "parse policy max receive queue empty",
+ args: args{
+ md: map[string]string{},
+ },
+ want: "",
+ },
+ {
+ name: "parse policy max receive queue",
+ args: args{
+ md: map[string]string{
+ "maxReceiveQueue": "some-queue",
+ },
+ },
+ want: "some-queue",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ assert.Equalf(t, tt.want, parsePolicyMaxReceiveQueue(tt.args.md), "parsePolicyMaxReceiveQueue(%v)", tt.args.md)
+ })
+ }
+}
diff --git a/bindings/kubemq/options.go b/bindings/kubemq/options.go
new file mode 100644
index 000000000..6abe4c9ed
--- /dev/null
+++ b/bindings/kubemq/options.go
@@ -0,0 +1,162 @@
+package kubemq
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/dapr/components-contrib/bindings"
+)
+
+type options struct {
+ host string
+ port int
+ channel string
+ authToken string
+ autoAcknowledged bool
+ pollMaxItems int
+ pollTimeoutSeconds int
+}
+
+func parseAddress(address string) (string, int, error) {
+ var host string
+ var port int
+ var err error
+ hostPort := strings.Split(address, ":")
+ if len(hostPort) != 2 {
+ return "", 0, fmt.Errorf("invalid kubemq address, address format is invalid")
+ }
+ host = hostPort[0]
+ if len(host) == 0 {
+ return "", 0, fmt.Errorf("invalid kubemq address, host is empty")
+ }
+ port, err = strconv.Atoi(hostPort[1])
+ if err != nil {
+ return "", 0, fmt.Errorf("invalid kubemq address, port is invalid")
+ }
+ return host, port, nil
+}
+
+// createOptions creates a new instance from the kubemq options
+func createOptions(md bindings.Metadata) (*options, error) {
+ result := &options{
+ host: "",
+ port: 0,
+ channel: "",
+ authToken: "",
+ autoAcknowledged: false,
+ pollMaxItems: 1,
+ pollTimeoutSeconds: 3600,
+ }
+ if val, found := md.Properties["address"]; found && val != "" {
+ var err error
+ result.host, result.port, err = parseAddress(val)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ return nil, fmt.Errorf("invalid kubemq address, address is empty")
+ }
+ if val, ok := md.Properties["channel"]; ok && val != "" {
+ result.channel = val
+ } else {
+ return nil, fmt.Errorf("invalid kubemq channel, channel is empty")
+ }
+
+ if val, found := md.Properties["authToken"]; found && val != "" {
+ if found && val != "" {
+ result.authToken = val
+ }
+ }
+
+ if val, found := md.Properties["autoAcknowledged"]; found && val != "" {
+ autoAcknowledged, err := strconv.ParseBool(val)
+ if err != nil {
+ return nil, fmt.Errorf("invalid kubemq autoAcknowledged value, %s", err.Error())
+ }
+ result.autoAcknowledged = autoAcknowledged
+ }
+ if val, found := md.Properties["pollMaxItems"]; found && val != "" {
+ pollMaxItems, err := strconv.Atoi(val)
+ if err != nil {
+ return nil, fmt.Errorf("invalid kubemq pollMaxItems value, %s", err.Error())
+ }
+ if pollMaxItems < 1 {
+ return nil, fmt.Errorf("invalid kubemq pollMaxItems value, value must be greater than 0")
+ }
+ result.pollMaxItems = pollMaxItems
+ }
+ if val, found := md.Properties["pollTimeoutSeconds"]; found && val != "" {
+ timeoutSecond, err := strconv.Atoi(val)
+ if err != nil {
+ return nil, fmt.Errorf("invalid kubemq pollTimeoutSeconds value, %s", err.Error())
+ } else {
+ if timeoutSecond < 1 {
+ return nil, fmt.Errorf("invalid kubemq pollTimeoutSeconds value, value must be greater than 0")
+ }
+ result.pollTimeoutSeconds = timeoutSecond
+ }
+ }
+ return result, nil
+}
+
+func parsePolicyDelaySeconds(md map[string]string) int {
+ if md == nil {
+ return 0
+ }
+ if val, found := md["delaySeconds"]; found && val != "" {
+ delaySeconds, err := strconv.Atoi(val)
+ if err != nil {
+ return 0
+ }
+ if delaySeconds < 0 {
+ return 0
+ }
+ return delaySeconds
+ }
+ return 0
+}
+
+func parsePolicyExpirationSeconds(md map[string]string) int {
+ if md == nil {
+ return 0
+ }
+ if val, found := md["expirationSeconds"]; found && val != "" {
+ expirationSeconds, err := strconv.Atoi(val)
+ if err != nil {
+ return 0
+ }
+ if expirationSeconds < 0 {
+ return 0
+ }
+ return expirationSeconds
+ }
+ return 0
+}
+
+func parseSetPolicyMaxReceiveCount(md map[string]string) int {
+ if md == nil {
+ return 0
+ }
+ if val, found := md["maxReceiveCount"]; found && val != "" {
+ maxReceiveCount, err := strconv.Atoi(val)
+ if err != nil {
+ return 0
+ }
+ if maxReceiveCount < 0 {
+ return 0
+ }
+ return maxReceiveCount
+ }
+ return 0
+}
+
+func parsePolicyMaxReceiveQueue(md map[string]string) string {
+ if md == nil {
+ return ""
+ }
+ if val, found := md["maxReceiveQueue"]; found && val != "" {
+ return val
+ }
+ return ""
+}
diff --git a/bindings/mysql/mysql.go b/bindings/mysql/mysql.go
index 3fb6d9976..9769ee7c6 100644
--- a/bindings/mysql/mysql.go
+++ b/bindings/mysql/mysql.go
@@ -20,6 +20,7 @@ import (
"database/sql"
"database/sql/driver"
"encoding/json"
+ "errors"
"fmt"
"os"
"reflect"
@@ -27,7 +28,6 @@ import (
"time"
"github.com/go-sql-driver/mysql"
- "github.com/pkg/errors"
"github.com/dapr/components-contrib/bindings"
"github.com/dapr/kit/logger"
@@ -117,7 +117,7 @@ func (m *Mysql) Init(metadata bindings.Metadata) error {
err = db.Ping()
if err != nil {
- return errors.Wrap(err, "unable to ping the DB")
+ return fmt.Errorf("unable to ping the DB: %w", err)
}
m.db = db
@@ -128,7 +128,7 @@ func (m *Mysql) Init(metadata bindings.Metadata) error {
// Invoke handles all invoke operations.
func (m *Mysql) Invoke(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
if req == nil {
- return nil, errors.Errorf("invoke request required")
+ return nil, errors.New("invoke request required")
}
if req.Operation == closeOperation {
@@ -136,13 +136,13 @@ func (m *Mysql) Invoke(ctx context.Context, req *bindings.InvokeRequest) (*bindi
}
if req.Metadata == nil {
- return nil, errors.Errorf("metadata required")
+ return nil, errors.New("metadata required")
}
m.logger.Debugf("operation: %v", req.Operation)
s, ok := req.Metadata[commandSQLKey]
if !ok || s == "" {
- return nil, errors.Errorf("required metadata not set: %s", commandSQLKey)
+ return nil, fmt.Errorf("required metadata not set: %s", commandSQLKey)
}
startTime := time.Now()
@@ -171,7 +171,7 @@ func (m *Mysql) Invoke(ctx context.Context, req *bindings.InvokeRequest) (*bindi
resp.Data = d
default:
- return nil, errors.Errorf("invalid operation type: %s. Expected %s, %s, or %s",
+ return nil, fmt.Errorf("invalid operation type: %s. Expected %s, %s, or %s",
req.Operation, execOperation, queryOperation, closeOperation)
}
@@ -201,11 +201,9 @@ func (m *Mysql) Close() error {
}
func (m *Mysql) query(ctx context.Context, sql string) ([]byte, error) {
- m.logger.Debugf("query: %s", sql)
-
rows, err := m.db.QueryContext(ctx, sql)
if err != nil {
- return nil, errors.Wrapf(err, "error executing %s", sql)
+ return nil, fmt.Errorf("error executing query: %w", err)
}
defer func() {
@@ -215,7 +213,7 @@ func (m *Mysql) query(ctx context.Context, sql string) ([]byte, error) {
result, err := m.jsonify(rows)
if err != nil {
- return nil, errors.Wrapf(err, "error marshalling query result for %s", sql)
+ return nil, fmt.Errorf("error marshalling query result for query: %w", err)
}
return result, nil
@@ -226,7 +224,7 @@ func (m *Mysql) exec(ctx context.Context, sql string) (int64, error) {
res, err := m.db.ExecContext(ctx, sql)
if err != nil {
- return 0, errors.Wrapf(err, "error executing %s", sql)
+ return 0, fmt.Errorf("error executing query: %w", err)
}
return res.RowsAffected()
@@ -237,7 +235,7 @@ func propertyToInt(props map[string]string, key string, setter func(int)) error
if i, err := strconv.Atoi(v); err == nil {
setter(i)
} else {
- return errors.Wrapf(err, "error converitng %s:%s to int", key, v)
+ return fmt.Errorf("error converting %s:%s to int: %w", key, v, err)
}
}
@@ -249,7 +247,7 @@ func propertyToDuration(props map[string]string, key string, setter func(time.Du
if d, err := time.ParseDuration(v); err == nil {
setter(d)
} else {
- return errors.Wrapf(err, "error converitng %s:%s to time duration", key, v)
+ return fmt.Errorf("error converting %s:%s to duration: %w", key, v, err)
}
}
@@ -258,14 +256,14 @@ func propertyToDuration(props map[string]string, key string, setter func(time.Du
func initDB(url, pemPath string) (*sql.DB, error) {
if _, err := mysql.ParseDSN(url); err != nil {
- return nil, errors.Wrapf(err, "illegal Data Source Name (DNS) specified by %s", connectionURLKey)
+ return nil, fmt.Errorf("illegal Data Source Name (DSN) specified by %s", connectionURLKey)
}
if pemPath != "" {
rootCertPool := x509.NewCertPool()
pem, err := os.ReadFile(pemPath)
if err != nil {
- return nil, errors.Wrapf(err, "Error reading PEM file from %s", pemPath)
+ return nil, fmt.Errorf("error reading PEM file from %s: %w", pemPath, err)
}
ok := rootCertPool.AppendCertsFromPEM(pem)
@@ -275,13 +273,13 @@ func initDB(url, pemPath string) (*sql.DB, error) {
err = mysql.RegisterTLSConfig("custom", &tls.Config{RootCAs: rootCertPool, MinVersion: tls.VersionTLS12})
if err != nil {
- return nil, errors.Wrap(err, "Error register TLS config")
+ return nil, fmt.Errorf("error register TLS config: %w", err)
}
}
db, err := sql.Open("mysql", url)
if err != nil {
- return nil, errors.Wrap(err, "error opening DB connection")
+ return nil, fmt.Errorf("error opening DB connection: %w", err)
}
return db, nil
diff --git a/bindings/rabbitmq/rabbitmq_integration_test.go b/bindings/rabbitmq/rabbitmq_integration_test.go
index e2714c9d3..e3939bbce 100644
--- a/bindings/rabbitmq/rabbitmq_integration_test.go
+++ b/bindings/rabbitmq/rabbitmq_integration_test.go
@@ -130,12 +130,14 @@ func TestPublishingWithTTL(t *testing.T) {
const maxGetDuration = ttlInSeconds * time.Second
metadata := bindings.Metadata{
- Name: "testQueue",
- Properties: map[string]string{
- "queueName": queueName,
- "host": rabbitmqHost,
- "deleteWhenUnused": strconv.FormatBool(exclusive),
- "durable": strconv.FormatBool(durable),
+ Base: contribMetadata.Base{
+ Name: "testQueue",
+ Properties: map[string]string{
+ "queueName": queueName,
+ "host": rabbitmqHost,
+ "deleteWhenUnused": strconv.FormatBool(exclusive),
+ "durable": strconv.FormatBool(durable),
+ },
},
}
@@ -162,7 +164,7 @@ func TestPublishingWithTTL(t *testing.T) {
},
}
- _, err = rabbitMQBinding1.Invoke(context.Backgound(), &writeRequest)
+ _, err = rabbitMQBinding1.Invoke(context.Background(), &writeRequest)
assert.Nil(t, err)
time.Sleep(time.Second + (ttlInSeconds * time.Second))
@@ -183,7 +185,7 @@ func TestPublishingWithTTL(t *testing.T) {
contribMetadata.TTLMetadataKey: strconv.Itoa(ttlInSeconds * 1000),
},
}
- _, err = rabbitMQBinding2.Invoke(context.Backgound(), &writeRequest)
+ _, err = rabbitMQBinding2.Invoke(context.Background(), &writeRequest)
assert.Nil(t, err)
msg, ok, err := getMessageWithRetries(ch, queueName, maxGetDuration)
@@ -204,14 +206,16 @@ func TestExclusiveQueue(t *testing.T) {
const maxGetDuration = ttlInSeconds * time.Second
metadata := bindings.Metadata{
- Name: "testQueue",
- Properties: map[string]string{
- "queueName": queueName,
- "host": rabbitmqHost,
- "deleteWhenUnused": strconv.FormatBool(exclusive),
- "durable": strconv.FormatBool(durable),
- "exclusive": strconv.FormatBool(exclusive),
- contribMetadata.TTLMetadataKey: strconv.FormatInt(ttlInSeconds, 10),
+ Base: contribMetadata.Base{
+ Name: "testQueue",
+ Properties: map[string]string{
+ "queueName": queueName,
+ "host": rabbitmqHost,
+ "deleteWhenUnused": strconv.FormatBool(exclusive),
+ "durable": strconv.FormatBool(durable),
+ "exclusive": strconv.FormatBool(exclusive),
+ contribMetadata.TTLMetadataKey: strconv.FormatInt(ttlInSeconds, 10),
+ },
},
}
@@ -257,13 +261,15 @@ func TestPublishWithPriority(t *testing.T) {
const maxPriority = 10
metadata := bindings.Metadata{
- Name: "testQueue",
- Properties: map[string]string{
- "queueName": queueName,
- "host": rabbitmqHost,
- "deleteWhenUnused": strconv.FormatBool(exclusive),
- "durable": strconv.FormatBool(durable),
- "maxPriority": strconv.FormatInt(maxPriority, 10),
+ Base: contribMetadata.Base{
+ Name: "testQueue",
+ Properties: map[string]string{
+ "queueName": queueName,
+ "host": rabbitmqHost,
+ "deleteWhenUnused": strconv.FormatBool(exclusive),
+ "durable": strconv.FormatBool(durable),
+ "maxPriority": strconv.FormatInt(maxPriority, 10),
+ },
},
}
@@ -283,7 +289,7 @@ func TestPublishWithPriority(t *testing.T) {
defer ch.Close()
const middlePriorityMsgContent = "middle"
- _, err = r.Invoke(context.Backgound(), &bindings.InvokeRequest{
+ _, err = r.Invoke(context.Background(), &bindings.InvokeRequest{
Metadata: map[string]string{
contribMetadata.PriorityMetadataKey: "5",
},
@@ -292,7 +298,7 @@ func TestPublishWithPriority(t *testing.T) {
assert.Nil(t, err)
const lowPriorityMsgContent = "low"
- _, err = r.Invoke(context.Backgound(), &bindings.InvokeRequest{
+ _, err = r.Invoke(context.Background(), &bindings.InvokeRequest{
Metadata: map[string]string{
contribMetadata.PriorityMetadataKey: "1",
},
@@ -301,7 +307,7 @@ func TestPublishWithPriority(t *testing.T) {
assert.Nil(t, err)
const highPriorityMsgContent = "high"
- _, err = r.Invoke(context.Backgound(), &bindings.InvokeRequest{
+ _, err = r.Invoke(context.Background(), &bindings.InvokeRequest{
Metadata: map[string]string{
contribMetadata.PriorityMetadataKey: "10",
},
diff --git a/bindings/redis/redis.go b/bindings/redis/redis.go
index aa70213ab..41b947d50 100644
--- a/bindings/redis/redis.go
+++ b/bindings/redis/redis.go
@@ -15,10 +15,10 @@ package redis
import (
"context"
- "errors"
"fmt"
"github.com/go-redis/redis/v8"
+ "github.com/pkg/errors"
"github.com/dapr/components-contrib/bindings"
rediscomponent "github.com/dapr/components-contrib/internal/component/redis"
@@ -66,21 +66,40 @@ func (r *Redis) Ping() error {
}
func (r *Redis) Operations() []bindings.OperationKind {
- return []bindings.OperationKind{bindings.CreateOperation}
+ return []bindings.OperationKind{
+ bindings.CreateOperation,
+ bindings.DeleteOperation,
+ bindings.GetOperation,
+ }
}
func (r *Redis) Invoke(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
- if val, ok := req.Metadata["key"]; ok && val != "" {
- key := val
- _, err := r.client.Do(ctx, "SET", key, req.Data).Result()
- if err != nil {
- return nil, err
+ if key, ok := req.Metadata["key"]; ok && key != "" {
+ switch req.Operation {
+ case bindings.DeleteOperation:
+ err := r.client.Del(ctx, key).Err()
+ if err != nil {
+ return nil, err
+ }
+ case bindings.GetOperation:
+ data, err := r.client.Get(ctx, key).Result()
+ if err != nil {
+ return nil, err
+ }
+ rep := &bindings.InvokeResponse{}
+ rep.Data = []byte(data)
+ return rep, nil
+ case bindings.CreateOperation:
+ _, err := r.client.Do(ctx, "SET", key, req.Data).Result()
+ if err != nil {
+ return nil, err
+ }
+ default:
+ return nil, fmt.Errorf("invalid operation type: %s", req.Operation)
}
-
return nil, nil
}
-
- return nil, errors.New("redis binding: missing key on write request metadata")
+ return nil, errors.New("redis binding: missing key in request metadata")
}
func (r *Redis) Close() error {
diff --git a/bindings/redis/redis_test.go b/bindings/redis/redis_test.go
index f57d81993..81fe68e92 100644
--- a/bindings/redis/redis_test.go
+++ b/bindings/redis/redis_test.go
@@ -30,7 +30,7 @@ const (
testKey = "test"
)
-func TestInvoke(t *testing.T) {
+func TestInvokeCreate(t *testing.T) {
s, c := setupMiniredis()
defer s.Close()
@@ -44,8 +44,9 @@ func TestInvoke(t *testing.T) {
assert.Equal(t, redis.Nil, err)
bindingRes, err := bind.Invoke(context.TODO(), &bindings.InvokeRequest{
- Data: []byte(testData),
- Metadata: map[string]string{"key": testKey},
+ Data: []byte(testData),
+ Metadata: map[string]string{"key": testKey},
+ Operation: bindings.CreateOperation,
})
assert.Equal(t, nil, err)
assert.Equal(t, true, bindingRes == nil)
@@ -55,6 +56,56 @@ func TestInvoke(t *testing.T) {
assert.Equal(t, true, getRes == testData)
}
+func TestInvokeGet(t *testing.T) {
+ s, c := setupMiniredis()
+ defer s.Close()
+
+ bind := &Redis{
+ client: c,
+ logger: logger.NewLogger("test"),
+ }
+ bind.ctx, bind.cancel = context.WithCancel(context.Background())
+
+ _, err := c.Do(context.Background(), "SET", testKey, testData).Result()
+ assert.Equal(t, nil, err)
+
+ bindingRes, err := bind.Invoke(context.TODO(), &bindings.InvokeRequest{
+ Metadata: map[string]string{"key": testKey},
+ Operation: bindings.GetOperation,
+ })
+ assert.Equal(t, nil, err)
+ assert.Equal(t, true, string(bindingRes.Data) == testData)
+}
+
+func TestInvokeDelete(t *testing.T) {
+ s, c := setupMiniredis()
+ defer s.Close()
+
+ bind := &Redis{
+ client: c,
+ logger: logger.NewLogger("test"),
+ }
+ bind.ctx, bind.cancel = context.WithCancel(context.Background())
+
+ _, err := c.Do(context.Background(), "SET", testKey, testData).Result()
+ assert.Equal(t, nil, err)
+
+ getRes, err := c.Do(context.Background(), "GET", testKey).Result()
+ assert.Equal(t, nil, err)
+ assert.Equal(t, true, getRes == testData)
+
+ _, err = bind.Invoke(context.TODO(), &bindings.InvokeRequest{
+ Metadata: map[string]string{"key": testKey},
+ Operation: bindings.DeleteOperation,
+ })
+
+ assert.Equal(t, nil, err)
+
+ rgetRep, err := c.Do(context.Background(), "GET", testKey).Result()
+ assert.Equal(t, redis.Nil, err)
+ assert.Equal(t, nil, rgetRep)
+}
+
func setupMiniredis() (*miniredis.Miniredis, *redis.Client) {
s, err := miniredis.Run()
if err != nil {
diff --git a/bindings/rethinkdb/statechange/statechange.go b/bindings/rethinkdb/statechange/statechange.go
index 9e642cf5c..c6203bfcf 100644
--- a/bindings/rethinkdb/statechange/statechange.go
+++ b/bindings/rethinkdb/statechange/statechange.go
@@ -28,7 +28,7 @@ import (
"github.com/dapr/kit/logger"
)
-// Binding represents RethinkDB change change state input binding which fires handler with
+// Binding represents RethinkDB change state input binding which fires handler with
// both the previous and current state store content each time there is a change.
type Binding struct {
logger logger.Logger
diff --git a/configuration/azure/appconfig/appconfig.go b/configuration/azure/appconfig/appconfig.go
index b91601ad6..849763c5c 100644
--- a/configuration/azure/appconfig/appconfig.go
+++ b/configuration/azure/appconfig/appconfig.go
@@ -15,6 +15,7 @@ package appconfig
import (
"context"
+ "errors"
"fmt"
"strconv"
"sync"
@@ -189,24 +190,19 @@ func parseMetadata(meta configuration.Metadata) (metadata, error) {
}
func (r *ConfigurationStore) Get(ctx context.Context, req *configuration.GetRequest) (*configuration.GetResponse, error) {
- timeoutContext, cancel := context.WithTimeout(ctx, r.metadata.requestTimeout)
- defer cancel()
-
keys := req.Keys
var items map[string]*configuration.Item
if len(keys) == 0 {
var err error
- if items, err = r.getAll(timeoutContext, req); err != nil {
+ if items, err = r.getAll(ctx, req); err != nil {
return &configuration.GetResponse{}, err
}
} else {
items = make(map[string]*configuration.Item, len(keys))
for _, key := range keys {
- // TODO: here contxt.TODO() is used because the SDK panics when a cancelled context is passed in GetSetting
- // Issue - https://github.com/Azure/azure-sdk-for-go/issues/19223 . Needs to be modified to use timeoutContext once the SDK is fixed
- resp, err := r.client.GetSetting(
- context.TODO(),
+ resp, err := r.getSettings(
+ ctx,
key,
&azappconfig.GetSettingOptions{
Label: r.getLabelFromMetadata(req.Metadata),
@@ -248,10 +244,10 @@ func (r *ConfigurationStore) getAll(ctx context.Context, req *configuration.GetR
},
nil)
- // TODO: here contxt.TODO() is used because the SDK panics when a cancelled context is passed in NextPage
- // Issue - https://github.com/Azure/azure-sdk-for-go/issues/19223 . It needs to be modified to use ctx once the SDK is fixed
for allSettingsPgr.More() {
- if revResp, err := allSettingsPgr.NextPage(context.TODO()); err == nil {
+ timeoutContext, cancel := context.WithTimeout(ctx, r.metadata.requestTimeout)
+ defer cancel()
+ if revResp, err := allSettingsPgr.NextPage(timeoutContext); err == nil {
for _, setting := range revResp.Settings {
item := &configuration.Item{
Metadata: map[string]string{},
@@ -295,20 +291,33 @@ func (r *ConfigurationStore) Subscribe(ctx context.Context, req *configuration.S
}
func (r *ConfigurationStore) doSubscribe(ctx context.Context, req *configuration.SubscribeRequest, handler configuration.UpdateHandler, sentinelKey string, id string) {
+ var etagVal *azcore.ETag
for {
- // get sentinel key changes
- _, err := r.Get(ctx, &configuration.GetRequest{
- Keys: []string{sentinelKey},
- Metadata: req.Metadata,
- })
+ // get sentinel key changes.
+ resp, err := r.getSettings(
+ ctx,
+ sentinelKey,
+ &azappconfig.GetSettingOptions{
+ Label: r.getLabelFromMetadata(req.Metadata),
+ OnlyIfChanged: etagVal,
+ },
+ )
if err != nil {
- r.logger.Debugf("azure appconfig error: fail to get sentinel key changes or sentinel key's value is unchanged: %s", err)
+ if errors.Is(err, context.Canceled) {
+ return
+ }
+ r.logger.Debugf("azure appconfig error: fail to get sentinel key or sentinel's key %s value is unchanged: %s", sentinelKey, err)
} else {
+ // if sentinel key has changed then update the Etag value.
+ etagVal = resp.ETag
items, err := r.Get(ctx, &configuration.GetRequest{
Keys: req.Keys,
Metadata: req.Metadata,
})
if err != nil {
+ if errors.Is(err, context.Canceled) {
+ return
+ }
r.logger.Errorf("azure appconfig error: fail to get configuration key changes: %s", err)
} else {
r.handleSubscribedChange(ctx, handler, items, id)
@@ -322,6 +331,13 @@ func (r *ConfigurationStore) doSubscribe(ctx context.Context, req *configuration
}
}
+func (r *ConfigurationStore) getSettings(ctx context.Context, key string, getSettingsOptions *azappconfig.GetSettingOptions) (azappconfig.GetSettingResponse, error) {
+ timeoutContext, cancel := context.WithTimeout(ctx, r.metadata.requestTimeout)
+ defer cancel()
+ resp, err := r.client.GetSetting(timeoutContext, key, getSettingsOptions)
+ return resp, err
+}
+
func (r *ConfigurationStore) handleSubscribedChange(ctx context.Context, handler configuration.UpdateHandler, items *configuration.GetResponse, id string) {
e := &configuration.UpdateEvent{
Items: items.Items,
diff --git a/configuration/redis/metadata.go b/configuration/redis/metadata.go
index d7d40a306..70d12036a 100644
--- a/configuration/redis/metadata.go
+++ b/configuration/redis/metadata.go
@@ -16,11 +16,11 @@ package redis
import "time"
type metadata struct {
- host string
- password string
- sentinelMasterName string
- maxRetries int
- maxRetryBackoff time.Duration
- enableTLS bool
- failover bool
+ Host string
+ Password string
+ SentinelMasterName string
+ MaxRetries int
+ MaxRetryBackoff time.Duration
+ EnableTLS bool
+ Failover bool
}
diff --git a/configuration/redis/redis.go b/configuration/redis/redis.go
index 53e2c73ed..4bb5e740c 100644
--- a/configuration/redis/redis.go
+++ b/configuration/redis/redis.go
@@ -78,40 +78,40 @@ func parseRedisMetadata(meta configuration.Metadata) (metadata, error) {
m := metadata{}
if val, ok := meta.Properties[host]; ok && val != "" {
- m.host = val
+ m.Host = val
} else {
return m, errors.New("redis store error: missing host address")
}
if val, ok := meta.Properties[password]; ok && val != "" {
- m.password = val
+ m.Password = val
}
- m.enableTLS = defaultEnableTLS
+ m.EnableTLS = defaultEnableTLS
if val, ok := meta.Properties[enableTLS]; ok && val != "" {
tls, err := strconv.ParseBool(val)
if err != nil {
return m, fmt.Errorf("redis store error: can't parse enableTLS field: %s", err)
}
- m.enableTLS = tls
+ m.EnableTLS = tls
}
- m.maxRetries = defaultMaxRetries
+ m.MaxRetries = defaultMaxRetries
if val, ok := meta.Properties[maxRetries]; ok && val != "" {
parsedVal, err := strconv.ParseInt(val, defaultBase, defaultBitSize)
if err != nil {
return m, fmt.Errorf("redis store error: can't parse maxRetries field: %s", err)
}
- m.maxRetries = int(parsedVal)
+ m.MaxRetries = int(parsedVal)
}
- m.maxRetryBackoff = defaultMaxRetryBackoff
+ m.MaxRetryBackoff = defaultMaxRetryBackoff
if val, ok := meta.Properties[maxRetryBackoff]; ok && val != "" {
parsedVal, err := strconv.ParseInt(val, defaultBase, defaultBitSize)
if err != nil {
return m, fmt.Errorf("redis store error: can't parse maxRetryBackoff field: %s", err)
}
- m.maxRetryBackoff = time.Duration(parsedVal)
+ m.MaxRetryBackoff = time.Duration(parsedVal)
}
if val, ok := meta.Properties[failover]; ok && val != "" {
@@ -119,13 +119,13 @@ func parseRedisMetadata(meta configuration.Metadata) (metadata, error) {
if err != nil {
return m, fmt.Errorf("redis store error: can't parse failover field: %s", err)
}
- m.failover = failover
+ m.Failover = failover
}
// set the sentinelMasterName only with failover == true.
- if m.failover {
+ if m.Failover {
if val, ok := meta.Properties[sentinelMasterName]; ok && val != "" {
- m.sentinelMasterName = val
+ m.SentinelMasterName = val
} else {
return m, errors.New("redis store error: missing sentinelMasterName")
}
@@ -142,14 +142,14 @@ func (r *ConfigurationStore) Init(metadata configuration.Metadata) error {
}
r.metadata = m
- if r.metadata.failover {
+ if r.metadata.Failover {
r.client = r.newFailoverClient(m)
} else {
r.client = r.newClient(m)
}
if _, err = r.client.Ping(context.TODO()).Result(); err != nil {
- return fmt.Errorf("redis store: error connecting to redis at %s: %s", m.host, err)
+ return fmt.Errorf("redis store: error connecting to redis at %s: %s", m.Host, err)
}
r.replicas, err = r.getConnectedSlaves()
@@ -159,18 +159,18 @@ func (r *ConfigurationStore) Init(metadata configuration.Metadata) error {
func (r *ConfigurationStore) newClient(m metadata) *redis.Client {
opts := &redis.Options{
- Addr: m.host,
- Password: m.password,
+ Addr: m.Host,
+ Password: m.Password,
DB: defaultDB,
- MaxRetries: m.maxRetries,
- MaxRetryBackoff: m.maxRetryBackoff,
+ MaxRetries: m.MaxRetries,
+ MaxRetryBackoff: m.MaxRetryBackoff,
}
// tell the linter to skip a check here.
/* #nosec */
- if m.enableTLS {
+ if m.EnableTLS {
opts.TLSConfig = &tls.Config{
- InsecureSkipVerify: m.enableTLS,
+ InsecureSkipVerify: m.EnableTLS,
}
}
@@ -179,17 +179,17 @@ func (r *ConfigurationStore) newClient(m metadata) *redis.Client {
func (r *ConfigurationStore) newFailoverClient(m metadata) *redis.Client {
opts := &redis.FailoverOptions{
- MasterName: r.metadata.sentinelMasterName,
- SentinelAddrs: []string{r.metadata.host},
+ MasterName: r.metadata.SentinelMasterName,
+ SentinelAddrs: []string{r.metadata.Host},
DB: defaultDB,
- MaxRetries: m.maxRetries,
- MaxRetryBackoff: m.maxRetryBackoff,
+ MaxRetries: m.MaxRetries,
+ MaxRetryBackoff: m.MaxRetryBackoff,
}
/* #nosec */
- if m.enableTLS {
+ if m.EnableTLS {
opts.TLSConfig = &tls.Config{
- InsecureSkipVerify: m.enableTLS,
+ InsecureSkipVerify: m.EnableTLS,
}
}
diff --git a/configuration/redis/redis_test.go b/configuration/redis/redis_test.go
index 10fa775ff..9975cdd66 100644
--- a/configuration/redis/redis_test.go
+++ b/configuration/redis/redis_test.go
@@ -264,13 +264,13 @@ func Test_parseRedisMetadata(t *testing.T) {
}},
},
want: metadata{
- host: "testHost",
- password: "testPassword",
- enableTLS: true,
- maxRetries: 10,
- maxRetryBackoff: time.Second,
- failover: true,
- sentinelMasterName: "tesSentinelMasterName",
+ Host: "testHost",
+ Password: "testPassword",
+ EnableTLS: true,
+ MaxRetries: 10,
+ MaxRetryBackoff: time.Second,
+ Failover: true,
+ SentinelMasterName: "tesSentinelMasterName",
},
},
}
diff --git a/go.mod b/go.mod
index fd60d9d64..8f7d4ef92 100644
--- a/go.mod
+++ b/go.mod
@@ -13,11 +13,12 @@ require (
github.com/Azure/azure-sdk-for-go v65.0.0+incompatible
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0
- github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v0.4.3
+ github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v0.5.0
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.2
github.com/Azure/azure-sdk-for-go/sdk/data/aztables v1.0.1
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.10.1
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.1
+ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.5.1
github.com/Azure/azure-storage-blob-go v0.10.0
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd
github.com/Azure/go-amqp v0.17.5
@@ -28,7 +29,6 @@ require (
github.com/DATA-DOG/go-sqlmock v1.5.0
github.com/Shopify/sarama v1.37.2
github.com/aerospike/aerospike-client-go v4.5.2+incompatible
- github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b
github.com/alibaba/sentinel-golang v1.0.4
github.com/alibabacloud-go/darabonba-openapi v0.2.1
github.com/alibabacloud-go/oos-20190601 v1.0.4
@@ -40,16 +40,17 @@ require (
github.com/aliyun/aliyun-tablestore-go-sdk v1.7.7
github.com/apache/dubbo-go-hessian2 v1.11.3
github.com/apache/pulsar-client-go v0.9.0
- github.com/apache/rocketmq-client-go/v2 v2.1.1-rc2
+ github.com/apache/rocketmq-client-go/v2 v2.1.0
github.com/aws/aws-sdk-go v1.44.128
+ github.com/benbjohnson/clock v1.3.0
github.com/bradfitz/gomemcache v0.0.0-20221031212613-62deef7fc822
github.com/camunda/zeebe/clients/go/v8 v8.1.3
- github.com/cenkalti/backoff/v4 v4.1.3
+ github.com/cenkalti/backoff/v4 v4.2.0
github.com/cinience/go_rocketmq v0.0.2
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/cyphar/filepath-securejoin v0.2.3
github.com/dancannon/gorethink v4.0.0+incompatible
- github.com/dapr/kit v0.0.2
+ github.com/dapr/kit v0.0.3
github.com/denisenkom/go-mssqldb v0.12.3
github.com/dghubble/go-twitter v0.0.0-20221024160433-0cc1e72ed6d8
github.com/dghubble/oauth1 v0.7.1
@@ -70,11 +71,13 @@ require (
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/golang-lru v0.5.4
github.com/hazelcast/hazelcast-go-client v0.0.0-20190530123621-6cf767c2f31a
+ github.com/http-wasm/http-wasm-host-go v0.2.0
github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.12+incompatible
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.6
github.com/influxdata/influxdb-client-go v1.4.0
github.com/jackc/pgx/v5 v5.0.4
github.com/json-iterator/go v1.1.12
+ github.com/kubemq-io/kubemq-go v1.7.6
github.com/labd/commercetools-go-sdk v1.1.0
github.com/machinebox/graphql v0.2.2
github.com/matoous/go-nanoid/v2 v2.0.0
@@ -82,7 +85,7 @@ require (
github.com/mrz1836/postmark v1.3.0
github.com/nacos-group/nacos-sdk-go/v2 v2.1.2
github.com/nats-io/nats-server/v2 v2.9.4
- github.com/nats-io/nats.go v1.19.0
+ github.com/nats-io/nats.go v1.19.1
github.com/nats-io/nkeys v0.3.0
github.com/nats-io/stan.go v0.10.3
github.com/open-policy-agent/opa v0.45.0
@@ -91,7 +94,6 @@ require (
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1
github.com/rabbitmq/amqp091-go v1.5.0
- github.com/robfig/cron/v3 v3.0.1
github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414
github.com/sendgrid/sendgrid-go v3.12.0+incompatible
github.com/sijms/go-ora/v2 v2.5.3
@@ -99,9 +101,9 @@ require (
github.com/supplyon/gremcos v0.1.38
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.527
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssm v1.0.527
+ github.com/tetratelabs/wazero v1.0.0-pre.4
github.com/valyala/fasthttp v1.41.0
github.com/vmware/vmware-go-kcl v1.5.0
- github.com/wapc/wapc-go v0.5.5
github.com/xdg-go/scram v1.1.1
go.mongodb.org/mongo-driver v1.10.3
go.temporal.io/api v1.12.0
@@ -132,7 +134,7 @@ require (
github.com/99designs/keyring v1.2.1 // indirect
github.com/AthenZ/athenz v1.10.39 // indirect
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
@@ -191,7 +193,7 @@ require (
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect
- github.com/fatih/color v1.9.0 // indirect
+ github.com/fatih/color v1.13.0 // indirect
github.com/gavv/httpexpect v2.0.0+incompatible // indirect
github.com/go-kit/kit v0.10.0 // indirect
github.com/go-kit/log v0.2.0 // indirect
@@ -205,6 +207,7 @@ require (
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.11.0 // indirect
+ github.com/go-resty/resty/v2 v2.7.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/gofrs/uuid v3.3.0+incompatible // indirect
@@ -225,12 +228,12 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
- github.com/gorilla/websocket v1.4.2 // indirect
+ github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
- github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v1.1.0 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
@@ -256,6 +259,7 @@ require (
github.com/kataras/go-serializer v0.0.4 // indirect
github.com/klauspost/compress v1.15.11 // indirect
github.com/knadh/koanf v1.4.1 // indirect
+ github.com/kubemq-io/protobuf v1.3.1 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/labstack/echo/v4 v4.9.0 // indirect
github.com/labstack/gommon v0.3.1 // indirect
@@ -264,7 +268,7 @@ require (
github.com/magiconair/properties v1.8.6 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/matryer/is v1.4.0 // indirect
- github.com/mattn/go-colorable v0.1.11 // indirect
+ github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-ieproxy v0.0.1 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
@@ -287,7 +291,7 @@ require (
github.com/nats-io/nuid v1.0.1 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pborman/uuid v1.2.1 // indirect
- github.com/pelletier/go-toml v1.9.3 // indirect
+ github.com/pelletier/go-toml v1.9.4 // indirect
github.com/pierrec/lz4 v2.6.0+incompatible // indirect
github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
@@ -309,12 +313,10 @@ require (
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/sony/gobreaker v0.4.2-0.20210216022020-dd874f9dd33b // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
- github.com/spf13/cast v1.3.1 // indirect
+ github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
- github.com/stathat/consistent v1.0.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
- github.com/tetratelabs/wazero v1.0.0-pre.3 // indirect
github.com/tidwall/gjson v1.13.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
@@ -364,6 +366,7 @@ require (
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
+ stathat.com/c/consistent v1.0.0 // indirect
)
replace github.com/gobwas/pool => github.com/gobwas/pool v0.2.1
diff --git a/go.sum b/go.sum
index cda69dc4d..d1ba277ba 100644
--- a/go.sum
+++ b/go.sum
@@ -51,6 +51,7 @@ cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1
cloud.google.com/go/datastore v1.8.0 h1:2qo2G7hABSeqswa+5Ga3+QB8/ZwKOJmDsCISM9scmsU=
cloud.google.com/go/datastore v1.8.0/go.mod h1:q1CpHVByTlXppdqTcu4LIhCsTn3fhtZ5R7+TajciO+M=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
+cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
cloud.google.com/go/iam v0.6.0 h1:nsqQC88kT5Iwlm4MeNGTpfMWddp6NB/UOLFTH6m1QfQ=
cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc=
@@ -102,21 +103,23 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4/go.mod h1:uGG2W01BaETf0Ozp+Q
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
-github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v0.4.3 h1:QzjiMJn/pBxOq1xA3F6ODUvO1agmt7+mI+DZEx6dPtc=
-github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v0.4.3/go.mod h1:p74+tP95m8830ypJk53L93+BEsjTKY4SKQ75J2NmS5U=
+github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v0.5.0 h1:OrKZybbyagpgJiREiIVzH5mV/z9oS4rXqdX7i31DSF0=
+github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v0.5.0/go.mod h1:p74+tP95m8830ypJk53L93+BEsjTKY4SKQ75J2NmS5U=
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.2 h1:yJegJqjhrMJ3Oe5s43jOTGL2AsE7pJyx+7Yqls/65tw=
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.2/go.mod h1:Fy3bbChFm4cZn6oIxYYqKB2FG3rBDxk3NZDLDJCHl+Q=
github.com/Azure/azure-sdk-for-go/sdk/data/aztables v1.0.1 h1:bFa9IcjvrCber6gGgDAUZ+I2bO8J7s8JxXmu9fhi2ss=
github.com/Azure/azure-sdk-for-go/sdk/data/aztables v1.0.1/go.mod h1:l3wvZkG9oW07GLBW5Cd0WwG5asOfJ8aqE8raUvNzLpk=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 h1:XUNQ4mw+zJmaA2KXzP9JlQiecy1SI+Eog7xVkPiqIbg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.10.1 h1:AhZnZn4kUKz36bHJ8AK/FH2tH/q3CAkG+Gme+2ibuak=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.10.1/go.mod h1:S78i9yTr4o/nXlH76bKjGUye9Z2wSxO5Tz7GoDr4vfI=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0 h1:Lg6BW0VPmCwcMlvOviL3ruHFO+H9tZNqscK0AeuFjGM=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA=
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.1 h1:Zm7A6yKHT3evC/0lquPWJ9hrkRGVIeZOmIvHPv6xV9Q=
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.1/go.mod h1:LH9XQnMr2ZYxQdVdCrzLO9mxeDyrDFa6wbSI3x5zCZk=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.5.1 h1:BMTdr+ib5ljLa9MxTJK8x/Ds0MbBb4MfuW5BL0zMJnI=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.5.1/go.mod h1:c6WvOhtmjNUWbLfOG1qxM/q0SPvQNSVJvolm+C52dIU=
github.com/Azure/azure-storage-blob-go v0.6.0/go.mod h1:oGfmITT1V6x//CswqY2gtAHND+xIP64/qL7a5QJix0Y=
github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs=
github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE=
@@ -208,8 +211,6 @@ github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia
github.com/agiledragon/gomonkey v2.0.2+incompatible/go.mod h1:2NGfXu1a80LLr2cmWXGBDaHEjb1idR6+FVlX5T3D9hw=
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
-github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b h1:WMhlIaJkDgEQSVJQM06YV+cYUl1r5OY5//ijMXJNqtA=
-github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b/go.mod h1:Tie46d3UWzXpj+Fh9+DQTyaUxEpFBPOLXrnx7nxlKRo=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
@@ -282,9 +283,8 @@ github.com/apache/pulsar-client-go v0.9.0 h1:L5jvGFXJm0JNA/PgUiJctTVHHttCe4wIEFD
github.com/apache/pulsar-client-go v0.9.0/go.mod h1:fSAcBipgz4KQ/VgwZEJtQ71cCXMKm8ezznstrozrngw=
github.com/apache/rocketmq-client-go v1.2.5 h1:2hPoLHpMJy1a57HDNmx7PZKgvlgVYO1Alz925oeqphQ=
github.com/apache/rocketmq-client-go v1.2.5/go.mod h1:Kap8oXIVLlHF50BGUbN9z97QUp1GaK1nOoCfsZnR2bw=
+github.com/apache/rocketmq-client-go/v2 v2.1.0 h1:3eABKfxc1WmS2lLTTbKMe1gZfZV6u1Sx9orFnOfABV0=
github.com/apache/rocketmq-client-go/v2 v2.1.0/go.mod h1:oEZKFDvS7sz/RWU0839+dQBupazyBV7WX5cP6nrio0Q=
-github.com/apache/rocketmq-client-go/v2 v2.1.1-rc2 h1:UQHWhwyw3tSLRhp0lVn/r/uNUzDnBZcDekGSzaXfz0M=
-github.com/apache/rocketmq-client-go/v2 v2.1.1-rc2/go.mod h1:DDYjQ9wxYmJLjgNK4+RqyFE8/13gLK/Bugz4U6zD5MI=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0 h1:5hryIiq9gtn+MiLVn0wP37kb/uTeRZgN08WoCsAhIhI=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
@@ -325,8 +325,9 @@ github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAm
github.com/awslabs/kinesis-aggregation/go v0.0.0-20210630091500-54e17340d32f h1:Pf0BjJDga7C98f0vhw+Ip5EaiE07S3lTKpIYPNS0nMo=
github.com/awslabs/kinesis-aggregation/go v0.0.0-20210630091500-54e17340d32f/go.mod h1:SghidfnxvX7ribW6nHI7T+IBbc9puZ9kk5Tx/88h8P4=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
-github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
+github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
+github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -353,9 +354,10 @@ github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n
github.com/cenkalti/backoff v2.0.0+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@@ -385,6 +387,7 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
@@ -416,8 +419,8 @@ github.com/dancannon/gorethink v4.0.0+incompatible h1:KFV7Gha3AuqT+gr0B/eKvGhbjm
github.com/dancannon/gorethink v4.0.0+incompatible/go.mod h1:BLvkat9KmZc1efyYwhz3WnybhRZtgF1K929FD8z1avU=
github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0=
github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0=
-github.com/dapr/kit v0.0.2 h1:VNg6RWrBMOdtY0/ZLztyAa/RjyFLaskdO9wt2HIREwk=
-github.com/dapr/kit v0.0.2/go.mod h1:Q4TWm9+vcPZFGehaJUZt2hvA805wJm7FIuoArytWJ8o=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/dave/jennifer v1.4.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -494,8 +497,10 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.0/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
+github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw=
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA=
@@ -506,8 +511,9 @@ github.com/fasthttp-contrib/sessions v0.0.0-20160905201309-74f6ac73d5d5/go.mod h
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
+github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
+github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
@@ -522,8 +528,9 @@ github.com/frankban/quicktest v1.10.2 h1:19ARM85nVi4xH7xPXuc5eM/udya5ieh7b/Sv+d8
github.com/frankban/quicktest v1.10.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
+github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
+github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU5kORdjhlA1yX8=
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
github.com/getkin/kin-openapi v0.2.0/go.mod h1:V1z9xl9oF5Wt7v32ne4FmiF1alpS4dM6mNzoywPOXlk=
@@ -578,6 +585,7 @@ github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2B
github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
+github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
@@ -764,8 +772,9 @@ github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
+github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE=
github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
@@ -785,6 +794,7 @@ github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
+github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0=
github.com/hashicorp/consul/api v1.13.0 h1:2hnLQ0GjQvw7f3O61jMO8gbasZviZTrt9R8WzgiirHc=
github.com/hashicorp/consul/api v1.13.0/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
@@ -795,14 +805,16 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
-github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
+github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.1.0 h1:QsGcniKx5/LuX2eYoeL+Np3UKYPNaN7YKpTh29h8rbw=
github.com/hashicorp/go-hclog v1.1.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
@@ -869,12 +881,15 @@ github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKe
github.com/hazelcast/hazelcast-go-client v0.0.0-20190530123621-6cf767c2f31a h1:j6SSiw7fWemWfrJL801xiQ6xRT7ZImika50xvmPN+tg=
github.com/hazelcast/hazelcast-go-client v0.0.0-20190530123621-6cf767c2f31a/go.mod h1:VhwtcZ7sg3xq7REqGzEy7ylSWGKz4jZd05eCJropNzI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/http-wasm/http-wasm-host-go v0.2.0 h1:BEu3SsCtx8JwVTCdITsvod5XlgjF9UQVJ8TxjFQJNs8=
+github.com/http-wasm/http-wasm-host-go v0.2.0/go.mod h1:OTNlRT3nkPc+WpuxZe1lgZ+X31GaoghBg01SQkPKMjs=
github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.12+incompatible h1:tANYIteuFrosKbRYUk1Yo/OGJjbt4x3OVg211Qc60M0=
github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.12+incompatible/go.mod h1:l7VUhRbTKCzdOacdT4oWCwATKyvZqUOlOqr0Ous3k4s=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.6 h1:18ZrfdnOMi2tx59TioYV5zFuCfD4YzoEz62ktQBOEeU=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.6/go.mod h1:QpZ96CRqyqd5fEODVmnzDNp3IWi5W95BFmWz1nfkq+s=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
+github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
@@ -979,6 +994,10 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/kubemq-io/kubemq-go v1.7.6 h1:AKQb6jbWzJRiNub/9wLHdkUnsBPtc8TImtiSNlKxug8=
+github.com/kubemq-io/kubemq-go v1.7.6/go.mod h1:oJVQFu794S9Df5AoEbaeM7s0knMjbKJs66PTLZzvk4g=
+github.com/kubemq-io/protobuf v1.3.1 h1:b4QcnpujV8U3go8pa2+FTESl6ygU6hY8APYibRtyemo=
+github.com/kubemq-io/protobuf v1.3.1/go.mod h1:mzbGBI05R+GhFLD520xweEIvDM+m4nI7ruJDhgEncas=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/labd/commercetools-go-sdk v1.1.0 h1:iX0JDkfAsZPXs0FUioYoFZ3Gm/GG9dEOqkv8vz439MM=
@@ -999,6 +1018,7 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/linkedin/goavro/v2 v2.9.8 h1:jN50elxBsGBDGVDEKqUlDuU1cFwJ11K/yrJCBMe/7Wg=
github.com/linkedin/goavro/v2 v2.9.8/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA=
+github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/machinebox/graphql v0.2.2 h1:dWKpJligYKhYKO5A2gvNhkJdQMNZeChZYyBbrZkBZfo=
github.com/machinebox/graphql v0.2.2/go.mod h1:F+kbVMHuwrQ5tYgU9JXlnskM8nOaFxCAEolaQybkjWA=
@@ -1021,8 +1041,10 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
-github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
+github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
+github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI=
github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
@@ -1068,6 +1090,7 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
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=
@@ -1116,8 +1139,8 @@ github.com/nats-io/nats-streaming-server v0.25.2/go.mod h1:bRbgx+iCG6EZEXpqVMroR
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
github.com/nats-io/nats.go v1.16.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
github.com/nats-io/nats.go v1.17.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
-github.com/nats-io/nats.go v1.19.0 h1:H6j8aBnTQFoVrTGB6Xjd903UMdE7jz6DS4YkmAqgZ9Q=
-github.com/nats-io/nats.go v1.19.0/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA=
+github.com/nats-io/nats.go v1.19.1 h1:pDQZthDfxRMSJ0ereExAM9ODf3JyS42Exk7iCMdbpec=
+github.com/nats-io/nats.go v1.19.1/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
@@ -1178,8 +1201,9 @@ github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
-github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
+github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
+github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
@@ -1268,7 +1292,6 @@ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqn
github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
-github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@@ -1287,6 +1310,7 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
+github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414 h1:AJNDS0kP60X8wwWFvbLPwDuojxubj9pbfK7pjHw0vKg=
github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
@@ -1332,11 +1356,13 @@ github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0b
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
+github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
+github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
@@ -1349,10 +1375,9 @@ 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/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
-github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
-github.com/stathat/consistent v1.0.0 h1:ZFJ1QTRn8npNBKW065raSZ8xfOqhpb8vLOkfp4CcL/U=
-github.com/stathat/consistent v1.0.0/go.mod h1:uajTPbgSygZBJ+V+0mY7meZ8i0XAcZs7AQ6V121XSxw=
+github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk=
+github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
@@ -1386,20 +1411,17 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.527 h1:hpZM
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.527/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssm v1.0.527 h1:WdSZURoWsFkpnMPyOZortjaL2z6jjk1erNPVdFB319o=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssm v1.0.527/go.mod h1:nzU/d/X/76YkHxzwfQY9+DtH53Wegy2ZZQ52W3nnMZE=
-github.com/tetratelabs/wazero v1.0.0-pre.3 h1:Z5fbogMUGcERzaQb9mQU8+yJSy0bVvv2ce3dfR4wcZg=
-github.com/tetratelabs/wazero v1.0.0-pre.3/go.mod h1:M8UDNECGm/HVjOfq0EOe4QfCY9Les1eq54IChMLETbc=
+github.com/tetratelabs/wazero v1.0.0-pre.4 h1:RBJQT5OzmORkSp6MmZDWoFEr0zXjk4pmvMKAdeUnsaI=
+github.com/tetratelabs/wazero v1.0.0-pre.4/go.mod h1:u8wrFmpdrykiFK0DFPiFm5a4+0RzsdmXYVtijBKqUVo=
github.com/tevid/gohamcrest v1.1.1/go.mod h1:3UvtWlqm8j5JbwYZh80D/PVBt0mJ1eJiYgZMibh0H/k=
github.com/tidwall/gjson v1.2.1/go.mod h1:c/nTNbUr0E0OrXEhq1pwa8iEgc2DOt4ZZqAt1HtCkPA=
-github.com/tidwall/gjson v1.8.1/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/gjson v1.13.0 h1:3TFY9yxOQShrvmjdM76K+jc66zJeT6D3/VFFYCGQf7M=
github.com/tidwall/gjson v1.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
-github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
-github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg=
@@ -1434,9 +1456,6 @@ github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/vmware/vmware-go-kcl v1.5.0 h1:lTptJptznhVOHS7CSuhd/2yDJa7deTBRHaj3zAvhJt8=
github.com/vmware/vmware-go-kcl v1.5.0/go.mod h1:P92YfaWfQyudNf62BNx+E2rJn9pd165MhHsRt8ajkpM=
-github.com/wapc/wapc-go v0.5.5 h1:FVMcscIUvARubkXS5hU2l7Z6k03cRE1mxc7Vpv56fIQ=
-github.com/wapc/wapc-go v0.5.5/go.mod h1:7hCuY3L3Kz0BHzqPzgnkf8tUDRqKP3rfh38jhx5ZI4g=
-github.com/wasmerio/wasmer-go v1.0.4 h1:MnqHoOGfiQ8MMq2RF6wyCeebKOe84G88h5yv+vmxJgs=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
@@ -1481,11 +1500,14 @@ go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.etcd.io/etcd/api/v3 v3.5.0-alpha.0/go.mod h1:mPcW6aZJukV6Aa81LSKpBjQXTWlXB5r74ymPoSWa3Sw=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
+go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
+go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.0-alpha.0/go.mod h1:kdV+xzCJ3luEBSIeQyB/OEKkWKd8Zkux4sbDeANrosU=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
+go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
go.etcd.io/etcd/client/v3 v3.5.0-alpha.0/go.mod h1:wKt7jgDgf/OfKiYmCq5WFGxOFAkVMLxiiXgLDFhECr8=
go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
go.etcd.io/etcd/pkg/v3 v3.5.0-alpha.0/go.mod h1:tV31atvwzcybuqejDoY3oaNRTtlD2l/Ot78Pc9w7DMY=
@@ -1564,6 +1586,7 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
@@ -1588,6 +1611,7 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@@ -1614,6 +1638,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1673,6 +1698,7 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@@ -1706,6 +1732,7 @@ golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
@@ -1816,10 +1843,12 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211106132015-ebca88c72f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1991,6 +2020,7 @@ google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
+google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
@@ -2078,6 +2108,8 @@ google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEc
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211104193956-4c6863e31247/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
@@ -2145,6 +2177,7 @@ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
+google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
diff --git a/internal/component/azure/blobstorage/client.go b/internal/component/azure/blobstorage/client.go
new file mode 100644
index 000000000..7a9250421
--- /dev/null
+++ b/internal/component/azure/blobstorage/client.go
@@ -0,0 +1,111 @@
+/*
+Copyright 2021 The Dapr Authors
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package blobstorage
+
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "time"
+
+ "github.com/Azure/azure-sdk-for-go/sdk/azcore"
+ "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container"
+
+ azauth "github.com/dapr/components-contrib/internal/authentication/azure"
+ mdutils "github.com/dapr/components-contrib/metadata"
+ "github.com/dapr/kit/logger"
+)
+
+const (
+ // Specifies the maximum number of HTTP requests that will be made to retry blob operations. A value
+ // of zero means that no additional HTTP requests will be made.
+ defaultBlobRetryCount = 3
+)
+
+func CreateContainerStorageClient(log logger.Logger, meta map[string]string) (*container.Client, *BlobStorageMetadata, error) {
+ m, err := parseMetadata(meta)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ userAgent := "dapr-" + logger.DaprVersion
+ options := container.ClientOptions{
+ ClientOptions: azcore.ClientOptions{
+ Retry: policy.RetryOptions{
+ MaxRetries: m.RetryCount,
+ },
+ Telemetry: policy.TelemetryOptions{
+ ApplicationID: userAgent,
+ },
+ },
+ }
+
+ settings, err := azauth.NewEnvironmentSettings("storage", meta)
+ if err != nil {
+ return nil, nil, err
+ }
+ var customEndpoint string
+ if val, ok := mdutils.GetMetadataProperty(meta, azauth.StorageEndpointKeys...); ok && val != "" {
+ customEndpoint = val
+ }
+ var URL *url.URL
+ if customEndpoint != "" {
+ var parseErr error
+ URL, parseErr = url.Parse(fmt.Sprintf("%s/%s/%s", customEndpoint, m.AccountName, m.ContainerName))
+ if parseErr != nil {
+ return nil, nil, parseErr
+ }
+ } else {
+ env := settings.AzureEnvironment
+ URL, _ = url.Parse(fmt.Sprintf("https://%s.blob.%s/%s", m.AccountName, env.StorageEndpointSuffix, m.ContainerName))
+ }
+
+ var clientErr error
+ var client *container.Client
+ // Try using shared key credentials first
+ if m.AccountKey != "" {
+ credential, newSharedKeyErr := azblob.NewSharedKeyCredential(m.AccountName, m.AccountKey)
+ if err != nil {
+ return nil, nil, fmt.Errorf("invalid shared key credentials with error: %w", newSharedKeyErr)
+ }
+ client, clientErr = container.NewClientWithSharedKeyCredential(URL.String(), credential, &options)
+ if clientErr != nil {
+ return nil, nil, fmt.Errorf("cannot init Blobstorage container client: %w", err)
+ }
+ } else {
+ // fallback to AAD
+ credential, tokenErr := settings.GetTokenCredential()
+ if err != nil {
+ return nil, nil, fmt.Errorf("invalid token credentials with error: %w", tokenErr)
+ }
+ client, clientErr = container.NewClient(URL.String(), credential, &options)
+ }
+ if clientErr != nil {
+ return nil, nil, fmt.Errorf("cannot init Blobstorage client: %w", clientErr)
+ }
+
+ createContainerOptions := container.CreateOptions{
+ Access: &m.PublicAccessLevel,
+ Metadata: map[string]string{},
+ }
+ timeoutCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+ _, err = client.Create(timeoutCtx, &createContainerOptions)
+ cancel()
+ // Don't return error, container might already exist
+ log.Debugf("error creating container: %v", err)
+
+ return client, m, nil
+}
diff --git a/internal/component/azure/blobstorage/client_test.go b/internal/component/azure/blobstorage/client_test.go
new file mode 100644
index 000000000..61ebe43ba
--- /dev/null
+++ b/internal/component/azure/blobstorage/client_test.go
@@ -0,0 +1,64 @@
+/*
+Copyright 2021 The Dapr Authors
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package blobstorage
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ azauth "github.com/dapr/components-contrib/internal/authentication/azure"
+ "github.com/dapr/kit/logger"
+)
+
+type scenario struct {
+ metadata map[string]string
+ expectedFailureSubString string
+}
+
+func TestClientInitFailures(t *testing.T) {
+ log := logger.NewLogger("test")
+
+ scenarios := map[string]scenario{
+ "missing accountName": {
+ metadata: createTestMetadata(false, true, true),
+ expectedFailureSubString: "missing or empty accountName field from metadata",
+ },
+ "missing container": {
+ metadata: createTestMetadata(true, true, false),
+ expectedFailureSubString: "missing or empty containerName field from metadata",
+ },
+ }
+
+ for name, s := range scenarios {
+ t.Run(name, func(t *testing.T) {
+ _, _, err := CreateContainerStorageClient(log, s.metadata)
+ assert.Contains(t, err.Error(), s.expectedFailureSubString)
+ })
+ }
+}
+
+func createTestMetadata(accountName bool, accountKey bool, container bool) map[string]string {
+ m := map[string]string{}
+ if accountName {
+ m[azauth.StorageAccountNameKeys[0]] = "account"
+ }
+ if accountKey {
+ m[azauth.StorageAccountKeyKeys[0]] = "key"
+ }
+ if container {
+ m[azauth.StorageContainerNameKeys[0]] = "test"
+ }
+ return m
+}
diff --git a/internal/component/azure/blobstorage/metadata.go b/internal/component/azure/blobstorage/metadata.go
new file mode 100644
index 000000000..af3db2061
--- /dev/null
+++ b/internal/component/azure/blobstorage/metadata.go
@@ -0,0 +1,88 @@
+/*
+Copyright 2021 The Dapr Authors
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package blobstorage
+
+import (
+ "fmt"
+ "strconv"
+
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
+
+ azauth "github.com/dapr/components-contrib/internal/authentication/azure"
+ mdutils "github.com/dapr/components-contrib/metadata"
+)
+
+type BlobStorageMetadata struct {
+ AccountName string
+ AccountKey string
+ ContainerName string
+ RetryCount int32 `json:"retryCount,string"`
+ DecodeBase64 bool `json:"decodeBase64,string"`
+ PublicAccessLevel azblob.PublicAccessType
+}
+
+func parseMetadata(meta map[string]string) (*BlobStorageMetadata, error) {
+ m := BlobStorageMetadata{
+ RetryCount: defaultBlobRetryCount,
+ }
+ mdutils.DecodeMetadata(meta, &m)
+
+ if val, ok := mdutils.GetMetadataProperty(meta, azauth.StorageAccountNameKeys...); ok && val != "" {
+ m.AccountName = val
+ } else {
+ return nil, fmt.Errorf("missing or empty %s field from metadata", azauth.StorageAccountNameKeys[0])
+ }
+
+ if val, ok := mdutils.GetMetadataProperty(meta, azauth.StorageContainerNameKeys...); ok && val != "" {
+ m.ContainerName = val
+ } else {
+ return nil, fmt.Errorf("missing or empty %s field from metadata", azauth.StorageContainerNameKeys[0])
+ }
+
+ if val, ok := mdutils.GetMetadataProperty(meta, azauth.StorageAccountKeyKeys...); ok && val != "" {
+ m.AccountKey = val
+ }
+
+ // per the Dapr documentation "none" is a valid value
+ if m.PublicAccessLevel == "none" {
+ m.PublicAccessLevel = ""
+ }
+ if m.PublicAccessLevel != "" && !isValidPublicAccessType(m.PublicAccessLevel) {
+ return nil, fmt.Errorf("invalid public access level: %s; allowed: %s",
+ m.PublicAccessLevel, azblob.PossiblePublicAccessTypeValues())
+ }
+
+ // we need this key for backwards compatibility
+ if val, ok := meta["getBlobRetryCount"]; ok && val != "" {
+ // convert val from string to int32
+ parseInt, err := strconv.ParseInt(val, 10, 32)
+ if err != nil {
+ return nil, err
+ }
+ m.RetryCount = int32(parseInt)
+ }
+
+ return &m, nil
+}
+
+func isValidPublicAccessType(accessType azblob.PublicAccessType) bool {
+ validTypes := azblob.PossiblePublicAccessTypeValues()
+ for _, item := range validTypes {
+ if item == accessType {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/internal/component/azure/blobstorage/metadata_test.go b/internal/component/azure/blobstorage/metadata_test.go
new file mode 100644
index 000000000..e0d648184
--- /dev/null
+++ b/internal/component/azure/blobstorage/metadata_test.go
@@ -0,0 +1,79 @@
+/*
+Copyright 2021 The Dapr Authors
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package blobstorage
+
+import (
+ "testing"
+
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestParseMetadata(t *testing.T) {
+ var m map[string]string
+
+ t.Run("parse all metadata", func(t *testing.T) {
+ m = map[string]string{
+ "storageAccount": "account",
+ "storageAccessKey": "key",
+ "container": "test",
+ "getBlobRetryCount": "5",
+ "decodeBase64": "true",
+ }
+ meta, err := parseMetadata(m)
+ assert.Nil(t, err)
+ assert.Equal(t, "test", meta.ContainerName)
+ assert.Equal(t, "account", meta.AccountName)
+ // storageAccessKey is parsed in the azauth package
+ assert.Equal(t, true, meta.DecodeBase64)
+ assert.Equal(t, int32(5), meta.RetryCount)
+ assert.Equal(t, "", string(meta.PublicAccessLevel))
+ })
+
+ t.Run("parse metadata with publicAccessLevel = blob", func(t *testing.T) {
+ m = map[string]string{
+ "storageAccount": "account",
+ "storageAccessKey": "key",
+ "container": "test",
+ "publicAccessLevel": "blob",
+ }
+ meta, err := parseMetadata(m)
+ assert.Nil(t, err)
+ assert.Equal(t, azblob.PublicAccessTypeBlob, meta.PublicAccessLevel)
+ })
+
+ t.Run("parse metadata with publicAccessLevel = container", func(t *testing.T) {
+ m = map[string]string{
+ "storageAccount": "account",
+ "storageAccessKey": "key",
+ "container": "test",
+ "publicAccessLevel": "container",
+ }
+ meta, err := parseMetadata(m)
+ assert.Nil(t, err)
+ assert.Equal(t, azblob.PublicAccessTypeContainer, meta.PublicAccessLevel)
+ })
+
+ t.Run("parse metadata with invalid publicAccessLevel", func(t *testing.T) {
+ m = map[string]string{
+ "storageAccount": "account",
+ "storageAccessKey": "key",
+ "container": "test",
+ "publicAccessLevel": "invalid",
+ }
+ _, err := parseMetadata(m)
+ assert.Error(t, err)
+ })
+}
diff --git a/internal/component/azure/blobstorage/request.go b/internal/component/azure/blobstorage/request.go
new file mode 100644
index 000000000..2d3dade3d
--- /dev/null
+++ b/internal/component/azure/blobstorage/request.go
@@ -0,0 +1,118 @@
+/*
+Copyright 2021 The Dapr Authors
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package blobstorage
+
+import (
+ b64 "encoding/base64"
+ "fmt"
+ "strings"
+
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
+
+ "github.com/dapr/kit/logger"
+)
+
+const (
+ contentTypeKey = "contenttype"
+ contentMD5Key = "contentmd5"
+ contentEncodingKey = "contentencoding"
+ contentLanguageKey = "contentlanguage"
+ contentDispositionKey = "contentdisposition"
+ cacheControlKey = "cachecontrol"
+)
+
+func CreateBlobHTTPHeadersFromRequest(meta map[string]string, contentType *string, log logger.Logger) (blob.HTTPHeaders, error) {
+ // build map to support arbitrary case
+ caseMap := make(map[string]string)
+ for k := range meta {
+ caseMap[strings.ToLower(k)] = k
+ }
+
+ blobHTTPHeaders := blob.HTTPHeaders{}
+ if val, ok := meta[caseMap[contentTypeKey]]; ok && val != "" {
+ blobHTTPHeaders.BlobContentType = &val
+ delete(meta, caseMap[contentTypeKey])
+ }
+
+ if contentType != nil {
+ if blobHTTPHeaders.BlobContentType != nil {
+ log.Warnf("ContentType received from request Metadata %s, as well as ContentType property %s, choosing value from contentType property", blobHTTPHeaders.BlobContentType, *contentType)
+ }
+ blobHTTPHeaders.BlobContentType = contentType
+ }
+
+ if val, ok := meta[caseMap[contentMD5Key]]; ok && val != "" {
+ sDec, err := b64.StdEncoding.DecodeString(val)
+ if err != nil || len(sDec) != 16 {
+ return blob.HTTPHeaders{}, fmt.Errorf("the MD5 value specified in Content MD5 is invalid, MD5 value must be 128 bits and base64 encoded")
+ }
+ blobHTTPHeaders.BlobContentMD5 = sDec
+ delete(meta, caseMap[contentMD5Key])
+ }
+ if val, ok := meta[caseMap[contentEncodingKey]]; ok && val != "" {
+ blobHTTPHeaders.BlobContentEncoding = &val
+ delete(meta, caseMap[contentEncodingKey])
+ }
+ if val, ok := meta[caseMap[contentLanguageKey]]; ok && val != "" {
+ blobHTTPHeaders.BlobContentLanguage = &val
+ delete(meta, caseMap[contentLanguageKey])
+ }
+ if val, ok := meta[caseMap[contentDispositionKey]]; ok && val != "" {
+ blobHTTPHeaders.BlobContentDisposition = &val
+ delete(meta, caseMap[contentDispositionKey])
+ }
+ if val, ok := meta[caseMap[cacheControlKey]]; ok && val != "" {
+ blobHTTPHeaders.BlobCacheControl = &val
+ delete(meta, caseMap[cacheControlKey])
+ }
+ return blobHTTPHeaders, nil
+}
+
+func SanitizeMetadata(log logger.Logger, metadata map[string]string) map[string]string {
+ for key, val := range metadata {
+ // Keep only letters and digits
+ n := 0
+ newKey := make([]byte, len(key))
+ for i := 0; i < len(key); i++ {
+ if (key[i] >= 'A' && key[i] <= 'Z') ||
+ (key[i] >= 'a' && key[i] <= 'z') ||
+ (key[i] >= '0' && key[i] <= '9') {
+ newKey[n] = key[i]
+ n++
+ }
+ }
+
+ if n != len(key) {
+ nks := string(newKey[:n])
+ log.Warnf("metadata key %s contains disallowed characters, sanitized to %s", key, nks)
+ delete(metadata, key)
+ metadata[nks] = val
+ key = nks
+ }
+
+ // Remove all non-ascii characters
+ n = 0
+ newVal := make([]byte, len(val))
+ for i := 0; i < len(val); i++ {
+ if val[i] > 127 {
+ continue
+ }
+ newVal[n] = val[i]
+ n++
+ }
+ metadata[key] = string(newVal[:n])
+ }
+
+ return metadata
+}
diff --git a/internal/component/azure/blobstorage/request_test.go b/internal/component/azure/blobstorage/request_test.go
new file mode 100644
index 000000000..74d92e7ed
--- /dev/null
+++ b/internal/component/azure/blobstorage/request_test.go
@@ -0,0 +1,68 @@
+/*
+Copyright 2021 The Dapr Authors
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package blobstorage
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/dapr/kit/logger"
+)
+
+func TestBlobHTTPHeaderGeneration(t *testing.T) {
+ log := logger.NewLogger("test")
+
+ t.Run("Content type is set from request, forward compatibility", func(t *testing.T) {
+ contentType := "application/json"
+ requestMetadata := map[string]string{}
+
+ blobHeaders, err := CreateBlobHTTPHeadersFromRequest(requestMetadata, &contentType, log)
+ assert.Nil(t, err)
+ assert.Equal(t, "application/json", *blobHeaders.BlobContentType)
+ })
+ t.Run("Content type and metadata provided (conflict), content type chosen", func(t *testing.T) {
+ contentType := "application/json"
+ requestMetadata := map[string]string{
+ contentTypeKey: "text/plain",
+ }
+
+ blobHeaders, err := CreateBlobHTTPHeadersFromRequest(requestMetadata, &contentType, log)
+ assert.Nil(t, err)
+ assert.Equal(t, "application/json", *blobHeaders.BlobContentType)
+ })
+ t.Run("ContentType not provided, metadata provided set backward compatibility", func(t *testing.T) {
+ requestMetadata := map[string]string{
+ contentTypeKey: "text/plain",
+ }
+ blobHeaders, err := CreateBlobHTTPHeadersFromRequest(requestMetadata, nil, log)
+ assert.Nil(t, err)
+ assert.Equal(t, "text/plain", *blobHeaders.BlobContentType)
+ })
+}
+
+func TestSanitizeRequestMetadata(t *testing.T) {
+ log := logger.NewLogger("test")
+ t.Run("sanitize metadata if necessary", func(t *testing.T) {
+ m := map[string]string{
+ "somecustomfield": "some-custom-value",
+ "specialfield": "special:valueÜ",
+ "not-allowed:": "not-allowed",
+ }
+ meta := SanitizeMetadata(log, m)
+ assert.Equal(t, meta["somecustomfield"], "some-custom-value")
+ assert.Equal(t, meta["specialfield"], "special:value")
+ assert.Equal(t, meta["notallowed"], "not-allowed")
+ })
+}
diff --git a/metadata/utils.go b/metadata/utils.go
index 3c18a34d2..65d66691b 100644
--- a/metadata/utils.go
+++ b/metadata/utils.go
@@ -16,11 +16,16 @@ package metadata
import (
"fmt"
"math"
+ "reflect"
"strconv"
+ "strings"
"time"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
+
+ "github.com/dapr/components-contrib/internal/utils"
+ "github.com/dapr/kit/ptr"
)
const (
@@ -140,7 +145,10 @@ func GetMetadataProperty(props map[string]string, keys ...string) (val string, o
func DecodeMetadata(input interface{}, result interface{}) error {
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
DecodeHook: mapstructure.ComposeDecodeHookFunc(
- toTimeDurationHookFunc()),
+ toTimeDurationHookFunc(),
+ toTruthyBoolHookFunc(),
+ toStringArrayHookFunc(),
+ ),
Metadata: nil,
Result: result,
WeaklyTypedInput: true,
@@ -151,3 +159,71 @@ func DecodeMetadata(input interface{}, result interface{}) error {
err = decoder.Decode(input)
return err
}
+
+func toTruthyBoolHookFunc() mapstructure.DecodeHookFunc {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data interface{},
+ ) (interface{}, error) {
+ if f == reflect.TypeOf("") && t == reflect.TypeOf(true) {
+ val := data.(string)
+ return utils.IsTruthy(val), nil
+ }
+ if f == reflect.TypeOf("") && t == reflect.TypeOf(reflect.TypeOf(ptr.Of(true))) {
+ val := data.(string)
+ return ptr.Of(utils.IsTruthy(val)), nil
+ }
+ return data, nil
+ }
+}
+
+func toStringArrayHookFunc() mapstructure.DecodeHookFunc {
+ return func(
+ f reflect.Type,
+ t reflect.Type,
+ data interface{},
+ ) (interface{}, error) {
+ if f == reflect.TypeOf("") && t == reflect.TypeOf([]string{}) {
+ val := data.(string)
+ return strings.Split(val, ","), nil
+ }
+ if f == reflect.TypeOf("") && t == reflect.TypeOf(ptr.Of([]string{})) {
+ val := data.(string)
+ return ptr.Of(strings.Split(val, ",")), nil
+ }
+ return data, nil
+ }
+}
+
+// GetMetadataInfoFromStructType converts a struct to a map of field name (or struct tag) to field type.
+// This is used to generate metadata documentation for components.
+func GetMetadataInfoFromStructType(t reflect.Type, metadataMap *map[string]string) error {
+ // Return if not struct or pointer to struct.
+ if t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ }
+ if t.Kind() != reflect.Struct {
+ return fmt.Errorf("not a struct: %s", t.Kind().String())
+ }
+
+ for i := 0; i < t.NumField(); i++ {
+ currentField := t.Field(i)
+ mapStructureTag := currentField.Tag.Get("mapstructure")
+ tags := strings.Split(mapStructureTag, ",")
+ numTags := len(tags)
+ if numTags > 1 && tags[numTags-1] == "squash" && currentField.Anonymous {
+ // traverse embedded struct
+ GetMetadataInfoFromStructType(currentField.Type, metadataMap)
+ continue
+ }
+ var fieldName string
+ if numTags > 0 && tags[0] != "" {
+ fieldName = tags[0]
+ } else {
+ fieldName = currentField.Name
+ }
+ (*metadataMap)[fieldName] = currentField.Type.String()
+ }
+ return nil
+}
diff --git a/metadata/utils_test.go b/metadata/utils_test.go
index 0e55b0f0f..21ce8dc42 100644
--- a/metadata/utils_test.go
+++ b/metadata/utils_test.go
@@ -14,6 +14,7 @@ limitations under the License.
package metadata
import (
+ "reflect"
"testing"
"time"
@@ -124,4 +125,116 @@ func TestMetadataDecode(t *testing.T) {
assert.Equal(t, 6*time.Minute, m.MyRegularDuration)
assert.Equal(t, Duration{Duration: 3 * time.Second}, m.Myduration)
})
+
+ t.Run("Test metadata decode hook for truthy values", func(t *testing.T) {
+ type testMetadata struct {
+ BoolPointer *bool
+ BoolPointerNotProvided *bool
+ BoolValueOn bool
+ BoolValue1 bool
+ BoolValueTrue bool
+ BoolValue0 bool
+ BoolValueFalse bool
+ BoolValueNonsense bool
+ }
+
+ var m testMetadata
+
+ testData := make(map[string]string)
+ testData["boolpointer"] = "on"
+ testData["boolvalueon"] = "on"
+ testData["boolvalue1"] = "1"
+ testData["boolvaluetrue"] = "true"
+ testData["boolvalue0"] = "0"
+ testData["boolvaluefalse"] = "false"
+ testData["boolvaluenonsense"] = "nonsense"
+
+ err := DecodeMetadata(testData, &m)
+ assert.NoError(t, err)
+ assert.True(t, *m.BoolPointer)
+ assert.True(t, m.BoolValueOn)
+ assert.True(t, m.BoolValue1)
+ assert.True(t, m.BoolValueTrue)
+ assert.False(t, m.BoolValue0)
+ assert.False(t, m.BoolValueFalse)
+ assert.False(t, m.BoolValueNonsense)
+ assert.Nil(t, m.BoolPointerNotProvided)
+ })
+
+ t.Run("Test metadata decode for string arrays", func(t *testing.T) {
+ type testMetadata struct {
+ StringArray []string
+ StringArrayPointer *[]string
+ EmptyStringArray []string
+ EmptyStringArrayPointer *[]string
+ EmptyStringArrayWithComma []string
+ EmptyStringArrayPointerWithComma *[]string
+ StringArrayOneElement []string
+ StringArrayOneElementPointer *[]string
+ StringArrayOneElementWithComma []string
+ StringArrayOneElementPointerWithComma *[]string
+ }
+
+ var m testMetadata
+
+ testData := make(map[string]string)
+ testData["stringarray"] = "one,two,three"
+ testData["stringarraypointer"] = "one,two,three"
+ testData["emptystringarray"] = ""
+ testData["emptystringarraypointer"] = ""
+ testData["stringarrayoneelement"] = "test"
+ testData["stringarrayoneelementpointer"] = "test"
+ testData["stringarrayoneelementwithcomma"] = "test,"
+ testData["stringarrayoneelementpointerwithcomma"] = "test,"
+ testData["emptystringarraywithcomma"] = ","
+ testData["emptystringarraypointerwithcomma"] = ","
+
+ err := DecodeMetadata(testData, &m)
+ assert.NoError(t, err)
+ assert.Equal(t, []string{"one", "two", "three"}, m.StringArray)
+ assert.Equal(t, []string{"one", "two", "three"}, *m.StringArrayPointer)
+ assert.Equal(t, []string{""}, m.EmptyStringArray)
+ assert.Equal(t, []string{""}, *m.EmptyStringArrayPointer)
+ assert.Equal(t, []string{"test"}, m.StringArrayOneElement)
+ assert.Equal(t, []string{"test"}, *m.StringArrayOneElementPointer)
+ assert.Equal(t, []string{"test", ""}, m.StringArrayOneElementWithComma)
+ assert.Equal(t, []string{"test", ""}, *m.StringArrayOneElementPointerWithComma)
+ assert.Equal(t, []string{"", ""}, m.EmptyStringArrayWithComma)
+ assert.Equal(t, []string{"", ""}, *m.EmptyStringArrayPointerWithComma)
+ })
+}
+
+func TestMetadataStructToStringMap(t *testing.T) {
+ t.Run("Test metadata struct to metadata info conversion", func(t *testing.T) {
+ type NestedStruct struct {
+ NestedStringCustom string `mapstructure:"nested_string_custom"`
+ NestedString string
+ }
+
+ type testMetadata struct {
+ NestedStruct `mapstructure:",squash"`
+ Mystring string
+ Myduration Duration
+ Myinteger int
+ Myfloat64 float64
+ Mybool *bool `json:",omitempty"`
+ MyRegularDuration time.Duration
+ SomethingWithCustomName string `mapstructure:"something_with_custom_name"`
+ }
+ m := testMetadata{}
+ metadatainfo := map[string]string{}
+ GetMetadataInfoFromStructType(reflect.TypeOf(m), &metadatainfo)
+
+ assert.Equal(t, "string", metadatainfo["Mystring"])
+ assert.Equal(t, "metadata.Duration", metadatainfo["Myduration"])
+ assert.Equal(t, "int", metadatainfo["Myinteger"])
+ assert.Equal(t, "float64", metadatainfo["Myfloat64"])
+ assert.Equal(t, "*bool", metadatainfo["Mybool"])
+ assert.Equal(t, "time.Duration", metadatainfo["MyRegularDuration"])
+ assert.Equal(t, "string", metadatainfo["something_with_custom_name"])
+ assert.NotContains(t, metadatainfo, "NestedStruct")
+ assert.NotContains(t, metadatainfo, "SomethingWithCustomName")
+ assert.Equal(t, "string", metadatainfo["nested_string_custom"])
+ assert.Equal(t, "string", metadatainfo["NestedString"])
+ })
}
diff --git a/middleware/http/wasm/basic/Makefile b/middleware/http/wasm/Makefile
similarity index 100%
rename from middleware/http/wasm/basic/Makefile
rename to middleware/http/wasm/Makefile
diff --git a/middleware/http/wasm/README.md b/middleware/http/wasm/README.md
index 034776157..6786e0078 100644
--- a/middleware/http/wasm/README.md
+++ b/middleware/http/wasm/README.md
@@ -1,5 +1,23 @@
-# WebAssembly Middleware
+## WebAssembly Middleware
-Middleware components in this directory load WebAssembly binaries (wasm) to
-modify requests and responses. Each middleware describes its features and
-constraints such as required function exports.
+This component lets you manipulate an incoming request or serve a response with custom logic compiled using the [htp-wasm](https://http-wasm.io/) Application Binary Interface (ABI). The `handle_request` function receives an incoming request and can manipulate it or serve a response as necessary.
+
+Please see the [documentation](https://github.com/dapr/docs/blob/v1.9/daprdocs/content/en/reference/components-reference/supported-middleware/middleware-wasm.md) for general configuration.
+
+### Generating Wasm
+
+To compile your wasm, you must compile source using an SDK such as [http-wasm-guest-tinygo](https://github.com/http-wasm/http-wasm-guest-tinygo). You can also make a copy of [hello.go](./example/example.go) and replace the `handler.HandleFn` function with your custom logic.
+
+If using TinyGo, compile like so and set the `path` attribute to the output:
+```bash
+tinygo build -o router.wasm -scheduler=none --no-debug -target=wasi router.go`
+```
+
+### Notes
+
+* This is an alpha feature, so configuration is subject to change.
+* This module implements the host side of the http-wasm handler protocol.
+* This uses [wazero](https://wazero.io) for the WebAssembly runtime as it has no dependencies,
+ nor relies on CGO. This allows installation without shared libraries.
+* Many WebAssembly compilers leave memory unbounded and/or set to 16MB. To
+ avoid resource exhaustion, assign [concurrency controls](https://docs.dapr.io/operations/configuration/control-concurrency/).
diff --git a/middleware/http/wasm/basic/README.md b/middleware/http/wasm/basic/README.md
deleted file mode 100644
index 11c0551d9..000000000
--- a/middleware/http/wasm/basic/README.md
+++ /dev/null
@@ -1,37 +0,0 @@
-## Basic WebAssembly Middleware
-
-WebAssembly is a way to safely run code compiled in other languages. Runtimes
-execute WebAssembly Modules (Wasm), which are most often binaries with a `.wasm`
-extension.
-
-This component allows you to rewrite a request URI with custom logic compiled
-to a Wasm using the [waPC protocol][1].
-
-Please see the [documentation][2] for general configuration.
-
-### Generating Wasm
-
-To compile your wasm, you must compile source using a wapc-go guest SDK such as
-[TinyGo][3]. You can also make a copy of [hello.go](./example/example.go) and
-replace the function `rewrite` with your custom logic.
-
-If using TinyGo, compile like so and set the `path` attribute to the output:
-```bash
-tinygo build -o example.wasm -scheduler=none --no-debug -target=wasi example.go`
-```
-
-### Notes
-
-* This is an alpha feature, so configuration is subject to change.
-* This module implements the host side of the waPC protocol using [wapc-go][4].
-* This uses [wazero][5] for the WebAssembly runtime as it has no dependencies,
- nor relies on CGO. This allows installation without shared libraries.
-* Many WebAssembly compilers leave memory unbounded and/or set to 16MB. Do not
- set a large pool size without considering memory amplification.
-
-[1]: https://wapc.io/docs/spec/
-[2]: https://github.com/dapr/docs/blob/v1.8/daprdocs/content/en/reference/components-reference/supported-middleware/middleware-wasm.md
-[3]: https://github.com/wapc/wapc-guest-tinygo
-[4]: https://github.com/wapc/wapc-go
-[5]: https://wazero.io
-
\ No newline at end of file
diff --git a/middleware/http/wasm/basic/basic.go b/middleware/http/wasm/basic/basic.go
deleted file mode 100644
index 9f4552e3e..000000000
--- a/middleware/http/wasm/basic/basic.go
+++ /dev/null
@@ -1,198 +0,0 @@
-package basic
-
-import (
- "bytes"
- "context"
- "encoding/json"
- "errors"
- "fmt"
- "net/http"
- "os"
- "runtime"
- "strconv"
- "time"
-
- "github.com/wapc/wapc-go"
- "github.com/wapc/wapc-go/engines/wazero"
-
- "github.com/dapr/components-contrib/internal/httputils"
- "github.com/dapr/components-contrib/middleware"
- "github.com/dapr/kit/logger"
-)
-
-// ctx substitutes for context propagation until middleware APIs support it.
-var ctx = context.Background()
-
-// middlewareMetadata includes configuration used for the WebAssembly handler.
-// Detailed notes are in README.md for visibility.
-//
-// Note: When changing this, you must update the docs with summary comments per
-// field.
-// https://github.com/dapr/docs/blob/v1.8/daprdocs/content/en/reference/components-reference/supported-middleware/middleware-wasm.md
-type middlewareMetadata struct {
- // Path is where to load a `%.wasm` file that implements the guest side of
- // the waPC protocol. No default.
- Path string `json:"path"`
-
- // PoolSize determines the amount of modules at the given path to load, per
- // request handler. Default: 10
- PoolSize poolSizeJSON `json:"poolSize"`
-
- // guest is WebAssembly binary implementing the waPC guest, loaded from Path.
- guest []byte
-}
-
-// poolSizeJSON is needed because go cannot unmarshal an integer from a string.
-type poolSizeJSON uint32
-
-// UnmarshalJSON allows decoding of a quoted uint32
-func (s *poolSizeJSON) UnmarshalJSON(b []byte) error {
- var n json.Number
- if err := json.Unmarshal(b, &n); err != nil {
- return fmt.Errorf("invalid poolSize: %w", err)
- }
- if i, err := strconv.ParseUint(string(n), 10, 32); err != nil {
- return fmt.Errorf("invalid poolSize: %w", err)
- } else {
- *s = poolSizeJSON(i)
- return nil
- }
-}
-
-// wapcMiddleware is a wasm basic middleware.
-type wapcMiddleware struct {
- logger logger.Logger
-}
-
-// NewMiddleware returns a new wasm basic middleware.
-func NewMiddleware(logger logger.Logger) middleware.Middleware {
- return &wapcMiddleware{logger: logger}
-}
-
-// GetHandler returns the HTTP handler provided by wasm basic middleware.
-func (m *wapcMiddleware) GetHandler(metadata middleware.Metadata) (func(next http.Handler) http.Handler, error) {
- rh, err := m.getHandler(metadata)
- if err != nil {
- return nil, err
- }
- runtime.SetFinalizer(rh, (*wapcRequestHandler).Close)
- return rh.requestHandler, nil
-}
-
-// getHandler is extracted for unit testing.
-func (m *wapcMiddleware) getHandler(metadata middleware.Metadata) (*wapcRequestHandler, error) {
- meta, err := m.getMetadata(metadata)
- if err != nil {
- return nil, fmt.Errorf("wasm basic: failed to parse metadata: %w", err)
- }
-
- var stdout, stderr bytes.Buffer
- config := &wapc.ModuleConfig{
- Logger: m.log, // waPC messages go here
- Stdout: &stdout, // reset per request
- Stderr: &stderr,
- }
-
- // This is a simple case, so the binary does not need any callbacks.
- mod, err := wazero.Engine().New(ctx, wapc.NoOpHostCallHandler, meta.guest, config)
- if err != nil {
- return nil, fmt.Errorf("wasm basic: error compiling wasm at %s: %w", meta.Path, err)
- }
-
- // WebAssembly modules are not goroutine safe (because they have no atomics
- // to implement garbage collection safely). Hence, we need a pool.
- pool, err := wapc.NewPool(ctx, mod, uint64(meta.PoolSize))
- if err != nil {
- return nil, fmt.Errorf("error creating module pool from wasm at %s: %w", meta.Path, err)
- }
-
- return &wapcRequestHandler{mod: mod, logger: m.logger, stdout: &stdout, stderr: &stderr, pool: pool}, nil
-}
-
-// log implements wapc.Logger.
-func (m *wapcMiddleware) log(msg string) {
- m.logger.Info(msg)
-}
-
-func (m *wapcMiddleware) getMetadata(metadata middleware.Metadata) (*middlewareMetadata, error) {
- b, err := json.Marshal(metadata.Properties)
- if err != nil {
- return nil, err
- }
-
- var data middlewareMetadata
- err = json.Unmarshal(b, &data)
- if err != nil {
- return nil, err
- }
-
- if data.Path == "" {
- return nil, errors.New("missing path")
- }
-
- data.guest, err = os.ReadFile(data.Path)
- if err != nil {
- return nil, fmt.Errorf("error reading path: %w", err)
- }
-
- if data.PoolSize == 0 {
- data.PoolSize = 10 // Default
- }
-
- return &data, nil
-}
-
-type wapcRequestHandler struct {
- mod wapc.Module
- logger logger.Logger
- stdout, stderr *bytes.Buffer
- pool *wapc.Pool
-}
-
-func (rh *wapcRequestHandler) requestHandler(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- instance, err := rh.pool.Get(1 * time.Second)
- if err != nil {
- httputils.RespondWithErrorAndMessage(w, http.StatusInternalServerError, "wasm pool busy")
- return
- }
- defer func() {
- rh.stdout.Reset()
- rh.stderr.Reset()
- _ = rh.pool.Return(instance)
- }()
-
- err = rh.handle(r, instance)
- if stdout := rh.stdout.String(); len(stdout) > 0 {
- rh.logger.Debugf("wasm stdout: %s", stdout)
- }
- if stderr := rh.stderr.String(); len(stderr) > 0 {
- rh.logger.Debugf("wasm stderr: %s", stderr)
- }
- if err != nil {
- httputils.RespondWithErrorAndMessage(w, http.StatusInternalServerError, err.Error())
- } else {
- next.ServeHTTP(w, r)
- }
- })
-}
-
-// handle is like http.Handler, except it accepts a waPC instance and returns
-// an error.
-func (rh *wapcRequestHandler) handle(r *http.Request, instance wapc.Instance) error {
- if uri, err := instance.Invoke(ctx, "rewrite", []byte(httputils.RequestURI(r))); err != nil {
- return err
- } else {
- return httputils.SetRequestURI(r, string(uri))
- }
-}
-
-// Close implements io.Closer
-func (rh *wapcRequestHandler) Close() error {
- // TODO: we have to use a finalizer as there's no way in dapr to close middleware, yet.
- // See https://github.com/dapr/dapr/pull/3088
- runtime.SetFinalizer(rh, nil)
-
- rh.pool.Close(ctx)
- return rh.mod.Close(ctx)
-}
diff --git a/middleware/http/wasm/basic/basic_test.go b/middleware/http/wasm/basic/basic_test.go
deleted file mode 100644
index ec037a1c1..000000000
--- a/middleware/http/wasm/basic/basic_test.go
+++ /dev/null
@@ -1,177 +0,0 @@
-package basic
-
-import (
- "fmt"
- "log"
- "net/http"
- "net/http/httptest"
- "os"
- "testing"
-
- "github.com/dapr/components-contrib/internal/httputils"
- "github.com/dapr/components-contrib/metadata"
-
- "github.com/stretchr/testify/require"
-
- "github.com/dapr/components-contrib/middleware"
- "github.com/dapr/components-contrib/middleware/http/wasm/basic/internal/test"
- "github.com/dapr/kit/logger"
-)
-
-var exampleWasm []byte
-
-// TestMain ensures we can read the example wasm prior to running unit tests.
-func TestMain(m *testing.M) {
- var err error
- exampleWasm, err = os.ReadFile("example/example.wasm")
- if err != nil {
- log.Panicln(err)
- }
- os.Exit(m.Run())
-}
-
-func Test_NewMiddleWare(t *testing.T) {
- l := test.NewLogger()
- require.Equal(t, &wapcMiddleware{logger: l}, NewMiddleware(l))
-}
-
-func Test_wapcMiddleware_log(t *testing.T) {
- l := test.NewLogger()
- m := &wapcMiddleware{logger: l}
- message := "alert"
- m.log(message)
-
- require.Equal(t, "Info(alert)\n", l.(fmt.Stringer).String())
-}
-
-func Test_wapcMiddleware_getMetadata(t *testing.T) {
- m := &wapcMiddleware{}
-
- type testCase struct {
- name string
- metadata metadata.Base
- expected *middlewareMetadata
- expectedErr string
- }
-
- tests := []testCase{
- {
- name: "empty path",
- metadata: metadata.Base{Properties: map[string]string{}},
- expectedErr: "missing path",
- },
- {
- name: "path dir not file",
- metadata: metadata.Base{Properties: map[string]string{
- "path": "./example",
- }},
- // Below ends in "is a directory" in unix, and "The handle is invalid." in windows.
- expectedErr: "error reading path: read ./example: ",
- },
- {
- name: "poolSize defaults to 10",
- metadata: metadata.Base{Properties: map[string]string{
- "path": "./example/example.wasm",
- }},
- expected: &middlewareMetadata{Path: "./example/example.wasm", PoolSize: 10, guest: exampleWasm},
- },
- {
- name: "poolSize",
- metadata: metadata.Base{Properties: map[string]string{
- "path": "./example/example.wasm",
- "poolSize": "1",
- }},
- expected: &middlewareMetadata{Path: "./example/example.wasm", PoolSize: 1, guest: exampleWasm},
- },
- {
- name: "poolSize invalid",
- metadata: metadata.Base{Properties: map[string]string{
- "path": "./example/example.wasm",
- "poolSize": "-1",
- }},
- expectedErr: `invalid poolSize: strconv.ParseUint: parsing "-1": invalid syntax`,
- },
- }
-
- for _, tt := range tests {
- tc := tt
- t.Run(tc.name, func(t *testing.T) {
- md, err := m.getMetadata(middleware.Metadata{Base: tc.metadata})
- if tc.expectedErr == "" {
- require.NoError(t, err)
- require.Equal(t, tc.expected, md)
- } else {
- // Use substring match as the error can be different in Windows.
- require.Contains(t, err.Error(), tc.expectedErr)
- }
- })
- }
-}
-
-func Test_wapcMiddleware_getHandler(t *testing.T) {
- m := &wapcMiddleware{logger: logger.NewLogger(t.Name())}
-
- type testCase struct {
- name string
- metadata metadata.Base
- expectedErr string
- }
-
- tests := []testCase{
- // This just tests the error message prefixes properly. Otherwise, it is
- // redundant to Test_wapcMiddleware_getMetadata
- {
- name: "requires path metadata",
- metadata: metadata.Base{Properties: map[string]string{}},
- expectedErr: "wasm basic: failed to parse metadata: missing path",
- },
- // This is more than Test_wapcMiddleware_getMetadata, as it ensures the
- // contents are actually wasm.
- {
- name: "path not wasm",
- metadata: metadata.Base{Properties: map[string]string{
- "path": "./example/example.go",
- }},
- expectedErr: "wasm basic: error compiling wasm at ./example/example.go: invalid binary",
- },
- {
- name: "ok",
- metadata: metadata.Base{Properties: map[string]string{
- "path": "./example/example.wasm",
- }},
- },
- }
-
- for _, tt := range tests {
- tc := tt
- t.Run(tc.name, func(t *testing.T) {
- h, err := m.getHandler(middleware.Metadata{Base: tc.metadata})
- if tc.expectedErr == "" {
- require.NoError(t, err)
- require.NotNil(t, h.mod)
- require.NotNil(t, h.pool)
- } else {
- require.EqualError(t, err, tc.expectedErr)
- }
- })
- }
-}
-
-func Test_Example(t *testing.T) {
- meta := metadata.Base{Properties: map[string]string{
- // example.wasm was compiled via the following:
- // tinygo build -o example.wasm -scheduler=none --no-debug -target=wasi hello.go`
- "path": "./example/example.wasm",
- "poolSize": "2",
- }}
- l := test.NewLogger()
- handlerFn, err := NewMiddleware(l).GetHandler(middleware.Metadata{Base: meta})
- require.NoError(t, err)
- handler := handlerFn(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
-
- r := httptest.NewRequest(http.MethodGet, "/v1.0/hi", nil)
- w := httptest.NewRecorder()
- handler.ServeHTTP(w, r)
- require.Equal(t, "/v1.0/hello", httputils.RequestURI(r))
- require.Empty(t, l.(fmt.Stringer).String())
-}
diff --git a/middleware/http/wasm/basic/example/Makefile b/middleware/http/wasm/basic/example/Makefile
deleted file mode 100644
index 37aa6c9b7..000000000
--- a/middleware/http/wasm/basic/example/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-build:
- @echo "Building Example Guest Wasm"
- @tinygo build -o example.wasm -scheduler=none --no-debug -target=wasi example.go
diff --git a/middleware/http/wasm/basic/example/example.go b/middleware/http/wasm/basic/example/example.go
deleted file mode 100644
index 56d7d67af..000000000
--- a/middleware/http/wasm/basic/example/example.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package main
-
-import "github.com/wapc/wapc-guest-tinygo"
-
-func main() {
- wapc.RegisterFunctions(wapc.Functions{"rewrite": rewrite})
-}
-
-// rewrite returns a new URI if necessary.
-func rewrite(requestURI []byte) ([]byte, error) {
- if string(requestURI) == "/v1.0/hi" {
- return []byte("/v1.0/hello"), nil
- }
- return requestURI, nil
-}
diff --git a/middleware/http/wasm/basic/example/example.wasm b/middleware/http/wasm/basic/example/example.wasm
deleted file mode 100755
index 4454fb1bc..000000000
Binary files a/middleware/http/wasm/basic/example/example.wasm and /dev/null differ
diff --git a/middleware/http/wasm/basic/example/go.sum b/middleware/http/wasm/basic/example/go.sum
deleted file mode 100644
index 56b5ac4d3..000000000
--- a/middleware/http/wasm/basic/example/go.sum
+++ /dev/null
@@ -1,2 +0,0 @@
-github.com/wapc/wapc-guest-tinygo v0.3.3 h1:jLebiwjVSHLGnS+BRabQ6+XOV7oihVWAc05Hf1SbeR0=
-github.com/wapc/wapc-guest-tinygo v0.3.3/go.mod h1:mzM3CnsdSYktfPkaBdZ8v88ZlfUDEy5Jh5XBOV3fYcw=
diff --git a/middleware/http/wasm/basic/internal/e2e-guests/go.sum b/middleware/http/wasm/basic/internal/e2e-guests/go.sum
deleted file mode 100644
index 56b5ac4d3..000000000
--- a/middleware/http/wasm/basic/internal/e2e-guests/go.sum
+++ /dev/null
@@ -1,2 +0,0 @@
-github.com/wapc/wapc-guest-tinygo v0.3.3 h1:jLebiwjVSHLGnS+BRabQ6+XOV7oihVWAc05Hf1SbeR0=
-github.com/wapc/wapc-guest-tinygo v0.3.3/go.mod h1:mzM3CnsdSYktfPkaBdZ8v88ZlfUDEy5Jh5XBOV3fYcw=
diff --git a/middleware/http/wasm/basic/internal/e2e-guests/output/main.wasm b/middleware/http/wasm/basic/internal/e2e-guests/output/main.wasm
deleted file mode 100755
index 51771c853..000000000
Binary files a/middleware/http/wasm/basic/internal/e2e-guests/output/main.wasm and /dev/null differ
diff --git a/middleware/http/wasm/basic/internal/e2e_test.go b/middleware/http/wasm/basic/internal/e2e_test.go
deleted file mode 100644
index dcfef18b0..000000000
--- a/middleware/http/wasm/basic/internal/e2e_test.go
+++ /dev/null
@@ -1,135 +0,0 @@
-package internal_test
-
-import (
- "fmt"
- "log"
- "net/http"
- "net/http/httptest"
- "os"
- "path"
- "strconv"
- "testing"
-
- "github.com/dapr/components-contrib/metadata"
-
- "github.com/stretchr/testify/require"
-
- "github.com/dapr/components-contrib/middleware"
- "github.com/dapr/components-contrib/middleware/http/wasm/basic"
- "github.com/dapr/components-contrib/middleware/http/wasm/basic/internal/test"
-)
-
-var guestWasm map[string][]byte
-
-const (
- guestWasmOutput = "output"
-)
-
-// TestMain ensures we can read the test wasm prior to running e2e tests.
-func TestMain(m *testing.M) {
- wasms := []string{guestWasmOutput}
- guestWasm = make(map[string][]byte, len(wasms))
- for _, name := range wasms {
- if wasm, err := os.ReadFile(path.Join("e2e-guests", name, "main.wasm")); err != nil {
- log.Panicln(err)
- } else {
- guestWasm[name] = wasm
- }
- }
- os.Exit(m.Run())
-}
-
-func Test_EndToEnd(t *testing.T) {
- type testCase struct {
- name string
- guest []byte
- poolSize int
- test func(t *testing.T, handler http.Handler, log fmt.Stringer)
- }
-
- tests := []testCase{
- {
- name: "consoleLog stdout and stderr",
- guest: guestWasm[guestWasmOutput],
- test: func(t *testing.T, handler http.Handler, log fmt.Stringer) {
- r := httptest.NewRequest(http.MethodGet, "/", nil)
- w := httptest.NewRecorder()
- handler.ServeHTTP(w, r)
-
- // First, we expect any console logging written inline from
- // init (main) and the request (rewrite) funcs to info level.
- //
- // Then, we expect to see stdout and stderr from both scopes
- // at debug level.
- require.Equal(t, `Info(main ConsoleLog)
-Info(request[0] ConsoleLog)
-Debug(wasm stdout: main Stdout
-request[0] Stdout
-)
-Debug(wasm stderr: main Stderr
-request[0] Stderr
-)
-`, log.String())
- },
- },
- {
- name: "multiple requests",
- guest: guestWasm[guestWasmOutput],
- poolSize: 2,
- test: func(t *testing.T, handler http.Handler, log fmt.Stringer) {
- // Service more requests than the pool size to ensure it works properly.
- for i := 0; i < 3; i++ {
- r := httptest.NewRequest(http.MethodGet, "/", nil)
- w := httptest.NewRecorder()
- handler.ServeHTTP(w, r)
- }
-
- // We expect to see initialization (main) twice, once for each
- // module in the pool. We expect to see request[1] which shows
- // round-robin back to the first module in the pool.
- require.Equal(t, `Info(main ConsoleLog)
-Info(main ConsoleLog)
-Info(request[0] ConsoleLog)
-Debug(wasm stdout: main Stdout
-main Stdout
-request[0] Stdout
-)
-Debug(wasm stderr: main Stderr
-main Stderr
-request[0] Stderr
-)
-Info(request[0] ConsoleLog)
-Debug(wasm stdout: request[0] Stdout
-)
-Debug(wasm stderr: request[0] Stderr
-)
-Info(request[1] ConsoleLog)
-Debug(wasm stdout: request[1] Stdout
-)
-Debug(wasm stderr: request[1] Stderr
-)
-`, log.String())
- },
- },
- }
-
- h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
- for _, tt := range tests {
- tc := tt
- t.Run(tc.name, func(t *testing.T) {
- poolSize := "1"
- if tc.poolSize > 0 {
- poolSize = strconv.Itoa(tc.poolSize)
- }
-
- wasmPath := path.Join(t.TempDir(), "guest.wasm")
- require.NoError(t, os.WriteFile(wasmPath, tc.guest, 0o600))
-
- meta := metadata.Base{Properties: map[string]string{"path": wasmPath, "poolSize": poolSize}}
- l := test.NewLogger()
- handlerFn, err := basic.NewMiddleware(l).GetHandler(middleware.Metadata{Base: meta})
- require.NoError(t, err)
- tc.test(t, handlerFn(h), l.(fmt.Stringer))
- })
- }
-}
diff --git a/middleware/http/wasm/basic/internal/test/logger.go b/middleware/http/wasm/basic/internal/test/logger.go
deleted file mode 100644
index f0c314110..000000000
--- a/middleware/http/wasm/basic/internal/test/logger.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package test
-
-import (
- "bytes"
- "fmt"
-
- "github.com/dapr/kit/logger"
-)
-
-// compile-time check to ensure testLogger implements logger.testLogger.
-var _ logger.Logger = &testLogger{}
-
-func NewLogger() logger.Logger {
- var buf bytes.Buffer
- return &testLogger{buf: &buf}
-}
-
-type testLogger struct {
- buf *bytes.Buffer
-}
-
-func (l *testLogger) String() string {
- return l.buf.String()
-}
-
-func (l *testLogger) EnableJSONOutput(enabled bool) {
- fmt.Fprintf(l.buf, "EnableJSONOutput(%v)\n", enabled)
-}
-
-func (l *testLogger) SetAppID(id string) {
- fmt.Fprintf(l.buf, "SetAppID(%v)\n", id)
-}
-
-func (l *testLogger) SetOutputLevel(outputLevel logger.LogLevel) {
- fmt.Fprintf(l.buf, "SetOutputLevel(%v)\n", outputLevel)
-}
-
-func (l *testLogger) WithLogType(logType string) logger.Logger {
- fmt.Fprintf(l.buf, "WithLogType(%v)\n", logType)
- return l
-}
-
-func (l *testLogger) Info(args ...interface{}) {
- fmt.Fprintf(l.buf, "Info(%v)\n", fmt.Sprint(args...))
-}
-
-func (l *testLogger) Infof(format string, args ...interface{}) {
- fmt.Fprintf(l.buf, "Info(%v)\n", fmt.Sprintf(format, args...))
-}
-
-func (l *testLogger) Debug(args ...interface{}) {
- fmt.Fprintf(l.buf, "Debug(%v)\n", fmt.Sprint(args...))
-}
-
-func (l *testLogger) Debugf(format string, args ...interface{}) {
- fmt.Fprintf(l.buf, "Debug(%v)\n", fmt.Sprintf(format, args...))
-}
-
-func (l *testLogger) Warn(args ...interface{}) {
- fmt.Fprintf(l.buf, "Warn(%v)\n", fmt.Sprint(args...))
-}
-
-func (l *testLogger) Warnf(format string, args ...interface{}) {
- fmt.Fprintf(l.buf, "Warn(%v)\n", fmt.Sprintf(format, args...))
-}
-
-func (l *testLogger) Error(args ...interface{}) {
- fmt.Fprintf(l.buf, "Error(%v)\n", fmt.Sprint(args...))
-}
-
-func (l *testLogger) Errorf(format string, args ...interface{}) {
- fmt.Fprintf(l.buf, "Error(%v)\n", fmt.Sprintf(format, args...))
-}
-
-func (l *testLogger) Fatal(args ...interface{}) {
- fmt.Fprintf(l.buf, "Fatal(%v)\n", fmt.Sprint(args...))
-}
-
-func (l *testLogger) Fatalf(format string, args ...interface{}) {
- fmt.Fprintf(l.buf, "Fatal(%v)\n", fmt.Sprintf(format, args...))
-}
diff --git a/middleware/http/wasm/benchmark_test.go b/middleware/http/wasm/benchmark_test.go
new file mode 100644
index 000000000..aefd01722
--- /dev/null
+++ b/middleware/http/wasm/benchmark_test.go
@@ -0,0 +1,140 @@
+package wasm
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "testing"
+
+ dapr "github.com/dapr/components-contrib/middleware"
+ "github.com/dapr/kit/logger"
+
+ "github.com/dapr/components-contrib/internal/httputils"
+ "github.com/dapr/components-contrib/metadata"
+)
+
+const parallel = 10
+
+func BenchmarkNative(b *testing.B) {
+ benchmarkAll(b, func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if httputils.RequestURI(r) == "/v1.0/hi?name=panda" {
+ httputils.SetRequestURI(r, "/v1.0/hello?name=teddy")
+ }
+ next.ServeHTTP(w, r)
+ })
+ })
+}
+
+func BenchmarkTinygo(b *testing.B) {
+ path := "./internal/e2e-guests/rewrite/main.wasm"
+ benchmarkMiddleware(b, path)
+}
+
+// BenchmarkWat gives baseline performance for the same handler by
+// writing it directly in WebAssembly Text Format.
+func BenchmarkWat(b *testing.B) {
+ path := "./internal/testdata/rewrite.wasm"
+ benchmarkMiddleware(b, path)
+}
+
+func benchmarkMiddleware(b *testing.B, path string) {
+ md := metadata.Base{Properties: map[string]string{"path": path}}
+
+ l := logger.NewLogger(b.Name())
+ l.SetOutput(io.Discard)
+
+ handlerFn, err := NewMiddleware(l).GetHandler(dapr.Metadata{Base: md})
+ if err != nil {
+ b.Fatal(err)
+ }
+ benchmarkAll(b, handlerFn)
+}
+
+var benches = map[string]struct {
+ newRequest func() *http.Request
+ test http.Handler
+}{
+ "rewrite": {
+ newRequest: func() *http.Request {
+ u, err := url.Parse("https://test.io/v1.0/hi?name=panda")
+ if err != nil {
+ panic(err)
+ }
+ return &http.Request{
+ Method: http.MethodGet,
+ URL: u,
+ Host: "test.io",
+ Header: map[string][]string{
+ "User-Agent": {"curl/7.79.1"},
+ "Accept": {"*/*"},
+ },
+ }
+ },
+ test: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if method := r.Method; method != http.MethodGet {
+ body := fmt.Sprintf("Unexpected request method: %q", method)
+ httputils.RespondWithErrorAndMessage(w, http.StatusInternalServerError, body)
+ }
+ if path := r.URL.Path; path != "/v1.0/hello" {
+ body := fmt.Sprintf("Expected wasm to rewrite path: %s", path)
+ httputils.RespondWithErrorAndMessage(w, http.StatusInternalServerError, body)
+ }
+ if query := r.URL.RawQuery; query != "name=teddy" {
+ body := fmt.Sprintf("Expected wasm to retain query: %s", query)
+ httputils.RespondWithErrorAndMessage(w, http.StatusInternalServerError, body)
+ }
+ w.Header().Set("Content-Type", "text/plain")
+ if _, err := w.Write([]byte("Hello, world!")); err != nil {
+ panic(err)
+ }
+ }),
+ },
+}
+
+func benchmarkAll(b *testing.B, mw func(http.Handler) http.Handler) {
+ for n, s := range benches {
+ b.Run(n, func(b *testing.B) {
+ b.SetParallelism(parallel)
+ benchmark(b, mw, n, s.newRequest, s.test)
+ })
+ }
+}
+
+func benchmark(
+ b *testing.B,
+ mw func(http.Handler) http.Handler,
+ name string,
+ newRequest func() *http.Request,
+ test http.Handler,
+) {
+ h := mw(test)
+ b.Run(name, func(b *testing.B) {
+ // We don't report allocations because memory allocations for TinyGo are
+ // in wasm which isn't visible to the Go benchmark.
+ for i := 0; i < b.N; i++ {
+ h.ServeHTTP(fakeResponseWriter{}, newRequest())
+ }
+ })
+}
+
+var _ http.ResponseWriter = fakeResponseWriter{}
+
+type fakeResponseWriter struct{}
+
+func (rw fakeResponseWriter) Header() http.Header {
+ return http.Header{}
+}
+
+func (rw fakeResponseWriter) Write(b []byte) (int, error) {
+ return len(b), nil
+}
+
+func (rw fakeResponseWriter) WriteHeader(statusCode int) {
+ // None of our benchmark tests should send failure status. If there's a
+ // failure, it is likely there's a problem in the test data.
+ if statusCode != 200 {
+ panic(statusCode)
+ }
+}
diff --git a/middleware/http/wasm/example/Makefile b/middleware/http/wasm/example/Makefile
new file mode 100644
index 000000000..9dc8900e7
--- /dev/null
+++ b/middleware/http/wasm/example/Makefile
@@ -0,0 +1,3 @@
+build:
+ @echo "Building Example Guest Wasm"
+ @tinygo build -o router.wasm -scheduler=none --no-debug -target=wasi router.go
diff --git a/middleware/http/wasm/basic/example/go.mod b/middleware/http/wasm/example/go.mod
similarity index 74%
rename from middleware/http/wasm/basic/example/go.mod
rename to middleware/http/wasm/example/go.mod
index d9157106d..adf5ec5b5 100644
--- a/middleware/http/wasm/basic/example/go.mod
+++ b/middleware/http/wasm/example/go.mod
@@ -2,6 +2,6 @@ module github.com/dapr/components-contrib/middleware/wasm/example
go 1.19
-require github.com/wapc/wapc-guest-tinygo v0.3.3
-
replace github.com/dapr/dapr => github.com/1046102779/dapr v0.0.0-20221021130037-635b70c24259
+
+require github.com/http-wasm/http-wasm-guest-tinygo v0.1.0
diff --git a/middleware/http/wasm/example/go.sum b/middleware/http/wasm/example/go.sum
new file mode 100644
index 000000000..6a27987f7
--- /dev/null
+++ b/middleware/http/wasm/example/go.sum
@@ -0,0 +1,2 @@
+github.com/http-wasm/http-wasm-guest-tinygo v0.1.0 h1:vcYHJkbfQ2G0bD/zupIzHe/h1LZQJiVGdn5eZZTJM88=
+github.com/http-wasm/http-wasm-guest-tinygo v0.1.0/go.mod h1:/3UO8OXP9nxe7d2qJ5ifTVkqM7KjaXxUZLoqBsDXpy0=
diff --git a/middleware/http/wasm/example/router.go b/middleware/http/wasm/example/router.go
new file mode 100644
index 000000000..a0d5c5ff8
--- /dev/null
+++ b/middleware/http/wasm/example/router.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+ "strings"
+
+ "github.com/http-wasm/http-wasm-guest-tinygo/handler"
+ "github.com/http-wasm/http-wasm-guest-tinygo/handler/api"
+)
+
+func main() {
+ handler.HandleRequestFn = handleRequest
+}
+
+// handleRequest implements a simple HTTP router.
+func handleRequest(req api.Request, resp api.Response) (next bool, reqCtx uint32) {
+ // If the URI starts with /host, trim it and dispatch to the next handler.
+ if uri := req.GetURI(); strings.HasPrefix(uri, "/host") {
+ req.SetURI(uri[5:])
+ next = true // proceed to the next handler on the host.
+ return
+ }
+
+ // Serve a static response
+ resp.Headers().Set("Content-Type", "text/plain")
+ resp.Body().WriteString("hello")
+ return // skip the next handler, as we wrote a response.
+}
diff --git a/middleware/http/wasm/example/router.wasm b/middleware/http/wasm/example/router.wasm
new file mode 100755
index 000000000..212b339da
Binary files /dev/null and b/middleware/http/wasm/example/router.wasm differ
diff --git a/middleware/http/wasm/httpwasm.go b/middleware/http/wasm/httpwasm.go
new file mode 100644
index 000000000..8949bbe45
--- /dev/null
+++ b/middleware/http/wasm/httpwasm.go
@@ -0,0 +1,169 @@
+package wasm
+
+import (
+ "bytes"
+ "context"
+ "crypto/rand"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+ "os"
+
+ "github.com/http-wasm/http-wasm-host-go/handler"
+
+ wasmnethttp "github.com/http-wasm/http-wasm-host-go/handler/nethttp"
+
+ "github.com/http-wasm/http-wasm-host-go/api"
+ "github.com/tetratelabs/wazero"
+
+ dapr "github.com/dapr/components-contrib/middleware"
+ "github.com/dapr/kit/logger"
+)
+
+// ctx substitutes for context propagation until middleware APIs support it.
+var ctx = context.Background()
+
+// middlewareMetadata includes configuration used for the WebAssembly handler.
+// Detailed notes are in README.md for visibility.
+//
+// Note: When changing this, you must update the docs with summary comments per
+// field.
+// https://github.com/dapr/docs/blob/v1.9/daprdocs/content/en/reference/components-reference/supported-middleware/middleware-wasm.md
+type middlewareMetadata struct {
+ // Path is where to load a `%.wasm` file that implements the guest side of
+ // the handler protocol. No default.
+ Path string `json:"path"`
+
+ // guest is WebAssembly binary implementing the waPC guest, loaded from Path.
+ guest []byte
+}
+
+type middleware struct {
+ logger logger.Logger
+}
+
+func NewMiddleware(logger logger.Logger) dapr.Middleware {
+ return &middleware{logger: logger}
+}
+
+func (m *middleware) GetHandler(metadata dapr.Metadata) (func(next http.Handler) http.Handler, error) {
+ rh, err := m.getHandler(metadata)
+ if err != nil {
+ return nil, err
+ }
+ return rh.requestHandler, nil
+}
+
+// getHandler is extracted for unit testing.
+func (m *middleware) getHandler(metadata dapr.Metadata) (*requestHandler, error) {
+ meta, err := m.getMetadata(metadata)
+ if err != nil {
+ return nil, fmt.Errorf("wasm basic: failed to parse metadata: %w", err)
+ }
+
+ var stdout, stderr bytes.Buffer
+ mw, err := wasmnethttp.NewMiddleware(ctx, meta.guest,
+ handler.Logger(m),
+ handler.ModuleConfig(wazero.NewModuleConfig().
+ WithStdout(&stdout). // reset per request
+ WithStderr(&stderr). // reset per request
+ // The below violate sand-boxing, but allow code to behave as expected.
+ WithRandSource(rand.Reader).
+ WithSysNanosleep().
+ WithSysWalltime().
+ WithSysNanosleep()))
+ if err != nil {
+ return nil, err
+ }
+
+ return &requestHandler{mw: mw, logger: m.logger, stdout: &stdout, stderr: &stderr}, nil
+}
+
+// IsEnabled implements the same method as documented on api.Logger.
+func (m *middleware) IsEnabled(level api.LogLevel) bool {
+ var l logger.LogLevel
+ switch level {
+ case api.LogLevelError:
+ l = logger.ErrorLevel
+ case api.LogLevelWarn:
+ l = logger.WarnLevel
+ case api.LogLevelInfo:
+ l = logger.InfoLevel
+ case api.LogLevelDebug:
+ l = logger.DebugLevel
+ default: // same as api.LogLevelNone
+ return false
+ }
+ return m.logger.IsOutputLevelEnabled(l)
+}
+
+// Log implements the same method as documented on api.Logger.
+func (m *middleware) Log(_ context.Context, level api.LogLevel, message string) {
+ switch level {
+ case api.LogLevelError:
+ m.logger.Error(message)
+ case api.LogLevelWarn:
+ m.logger.Warn(message)
+ case api.LogLevelInfo:
+ m.logger.Info(message)
+ case api.LogLevelDebug:
+ m.logger.Debug(message)
+ default: // same as api.LogLevelNone
+ return
+ }
+}
+
+func (m *middleware) getMetadata(metadata dapr.Metadata) (*middlewareMetadata, error) {
+ b, err := json.Marshal(metadata.Properties)
+ if err != nil {
+ return nil, err
+ }
+
+ var data middlewareMetadata
+ err = json.Unmarshal(b, &data)
+ if err != nil {
+ return nil, err
+ }
+
+ if data.Path == "" {
+ return nil, errors.New("missing path")
+ }
+
+ data.guest, err = os.ReadFile(data.Path)
+ if err != nil {
+ return nil, fmt.Errorf("error reading path: %w", err)
+ }
+
+ return &data, nil
+}
+
+type requestHandler struct {
+ mw wasmnethttp.Middleware
+ logger logger.Logger
+ stdout, stderr *bytes.Buffer
+}
+
+func (rh *requestHandler) requestHandler(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ h := rh.mw.NewHandler(r.Context(), next)
+ defer func() {
+ rh.stdout.Reset()
+ rh.stderr.Reset()
+ }()
+
+ h.ServeHTTP(w, r)
+
+ if stdout := rh.stdout.String(); len(stdout) > 0 {
+ rh.logger.Debugf("wasm stdout: %s", stdout)
+ }
+ if stderr := rh.stderr.String(); len(stderr) > 0 {
+ rh.logger.Debugf("wasm stderr: %s", stderr)
+ }
+ })
+}
+
+// Close implements io.Closer
+func (rh *requestHandler) Close() error {
+ return rh.mw.Close(ctx)
+}
diff --git a/middleware/http/wasm/httpwasm_test.go b/middleware/http/wasm/httpwasm_test.go
new file mode 100644
index 000000000..d60e000a1
--- /dev/null
+++ b/middleware/http/wasm/httpwasm_test.go
@@ -0,0 +1,148 @@
+package wasm
+
+import (
+ "bytes"
+ _ "embed"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/dapr/components-contrib/internal/httputils"
+
+ "github.com/dapr/components-contrib/metadata"
+
+ "github.com/http-wasm/http-wasm-host-go/api"
+
+ "github.com/stretchr/testify/require"
+
+ dapr "github.com/dapr/components-contrib/middleware"
+ "github.com/dapr/kit/logger"
+)
+
+func Test_NewMiddleWare(t *testing.T) {
+ l := logger.NewLogger(t.Name())
+ require.Equal(t, &middleware{logger: l}, NewMiddleware(l))
+}
+
+func Test_middleware_log(t *testing.T) {
+ l := logger.NewLogger(t.Name())
+ var buf bytes.Buffer
+ l.SetOutput(&buf)
+
+ m := &middleware{logger: l}
+ message := "alert"
+ m.Log(ctx, api.LogLevelInfo, message)
+
+ require.Contains(t, buf.String(), `level=info msg=alert`)
+}
+
+func Test_middleware_getMetadata(t *testing.T) {
+ m := &middleware{}
+
+ type testCase struct {
+ name string
+ metadata metadata.Base
+ expected *middlewareMetadata
+ expectedErr string
+ }
+
+ tests := []testCase{
+ {
+ name: "empty path",
+ metadata: metadata.Base{Properties: map[string]string{}},
+ expectedErr: "missing path",
+ },
+ {
+ name: "path dir not file",
+ metadata: metadata.Base{Properties: map[string]string{
+ "path": "./example",
+ }},
+ // Below ends in "is a directory" in unix, and "The handle is invalid." in windows.
+ expectedErr: "error reading path: read ./example: ",
+ },
+ }
+
+ for _, tt := range tests {
+ tc := tt
+ t.Run(tc.name, func(t *testing.T) {
+ md, err := m.getMetadata(dapr.Metadata{Base: tc.metadata})
+ if tc.expectedErr == "" {
+ require.NoError(t, err)
+ require.Equal(t, tc.expected, md)
+ } else {
+ // Use substring match as the error can be different in Windows.
+ require.Contains(t, err.Error(), tc.expectedErr)
+ }
+ })
+ }
+}
+
+func Test_middleware_getHandler(t *testing.T) {
+ m := &middleware{logger: logger.NewLogger(t.Name())}
+
+ type testCase struct {
+ name string
+ metadata metadata.Base
+ expectedErr string
+ }
+
+ tests := []testCase{
+ // This just tests the error message prefixes properly. Otherwise, it is
+ // redundant to Test_middleware_getMetadata
+ {
+ name: "requires path metadata",
+ metadata: metadata.Base{Properties: map[string]string{}},
+ expectedErr: "wasm basic: failed to parse metadata: missing path",
+ },
+ // This is more than Test_middleware_getMetadata, as it ensures the
+ // contents are actually wasm.
+ {
+ name: "path not wasm",
+ metadata: metadata.Base{Properties: map[string]string{
+ "path": "./example/router.go",
+ }},
+ expectedErr: "wasm: error compiling guest: invalid binary",
+ },
+ {
+ name: "ok",
+ metadata: metadata.Base{Properties: map[string]string{
+ "path": "./example/router.wasm",
+ }},
+ },
+ }
+
+ for _, tt := range tests {
+ tc := tt
+ t.Run(tc.name, func(t *testing.T) {
+ h, err := m.getHandler(dapr.Metadata{Base: tc.metadata})
+ if tc.expectedErr == "" {
+ require.NoError(t, err)
+ require.NotNil(t, h.mw)
+ } else {
+ require.EqualError(t, err, tc.expectedErr)
+ }
+ })
+ }
+}
+
+func Test_Example(t *testing.T) {
+ l := logger.NewLogger(t.Name())
+ var buf bytes.Buffer
+ l.SetOutput(&buf)
+
+ meta := metadata.Base{Properties: map[string]string{
+ // router.wasm was compiled via the following:
+ // tinygo build -o router.wasm -scheduler=none --no-debug -target=wasi router.go`
+ "path": "./example/router.wasm",
+ }}
+ handlerFn, err := NewMiddleware(l).GetHandler(dapr.Metadata{Base: meta})
+ require.NoError(t, err)
+
+ handler := handlerFn(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
+
+ r := httptest.NewRequest(http.MethodGet, "/host/hi?name=panda", nil)
+ w := httptest.NewRecorder()
+ handler.ServeHTTP(w, r)
+ require.Equal(t, "/hi?name=panda", httputils.RequestURI(r))
+ require.Empty(t, buf.String())
+}
diff --git a/middleware/http/wasm/basic/internal/e2e-guests/Makefile b/middleware/http/wasm/internal/e2e-guests/Makefile
similarity index 100%
rename from middleware/http/wasm/basic/internal/e2e-guests/Makefile
rename to middleware/http/wasm/internal/e2e-guests/Makefile
diff --git a/middleware/http/wasm/basic/internal/e2e-guests/README.md b/middleware/http/wasm/internal/e2e-guests/README.md
similarity index 100%
rename from middleware/http/wasm/basic/internal/e2e-guests/README.md
rename to middleware/http/wasm/internal/e2e-guests/README.md
diff --git a/middleware/http/wasm/basic/internal/e2e-guests/go.mod b/middleware/http/wasm/internal/e2e-guests/go.mod
similarity index 74%
rename from middleware/http/wasm/basic/internal/e2e-guests/go.mod
rename to middleware/http/wasm/internal/e2e-guests/go.mod
index 349c0b242..9ff448332 100644
--- a/middleware/http/wasm/basic/internal/e2e-guests/go.mod
+++ b/middleware/http/wasm/internal/e2e-guests/go.mod
@@ -2,6 +2,6 @@ module github.com/dapr/components-contrib/middleware/wasm/internal
go 1.19
-require github.com/wapc/wapc-guest-tinygo v0.3.3
-
replace github.com/dapr/dapr => github.com/1046102779/dapr v0.0.0-20221021130037-635b70c24259
+
+require github.com/http-wasm/http-wasm-guest-tinygo v0.1.0
diff --git a/middleware/http/wasm/internal/e2e-guests/go.sum b/middleware/http/wasm/internal/e2e-guests/go.sum
new file mode 100644
index 000000000..6a27987f7
--- /dev/null
+++ b/middleware/http/wasm/internal/e2e-guests/go.sum
@@ -0,0 +1,2 @@
+github.com/http-wasm/http-wasm-guest-tinygo v0.1.0 h1:vcYHJkbfQ2G0bD/zupIzHe/h1LZQJiVGdn5eZZTJM88=
+github.com/http-wasm/http-wasm-guest-tinygo v0.1.0/go.mod h1:/3UO8OXP9nxe7d2qJ5ifTVkqM7KjaXxUZLoqBsDXpy0=
diff --git a/middleware/http/wasm/basic/internal/e2e-guests/output/main.go b/middleware/http/wasm/internal/e2e-guests/output/main.go
similarity index 53%
rename from middleware/http/wasm/basic/internal/e2e-guests/output/main.go
rename to middleware/http/wasm/internal/e2e-guests/output/main.go
index f1ce44ad0..759dd10c1 100644
--- a/middleware/http/wasm/basic/internal/e2e-guests/output/main.go
+++ b/middleware/http/wasm/internal/e2e-guests/output/main.go
@@ -6,22 +6,24 @@ import (
"fmt"
"os"
- "github.com/wapc/wapc-guest-tinygo"
+ "github.com/http-wasm/http-wasm-guest-tinygo/handler"
+ "github.com/http-wasm/http-wasm-guest-tinygo/handler/api"
)
func main() {
fmt.Fprintln(os.Stdout, "main Stdout")
fmt.Fprintln(os.Stderr, "main Stderr")
- wapc.ConsoleLog("main ConsoleLog")
- wapc.RegisterFunctions(wapc.Functions{"rewrite": rewrite})
+ handler.Host.Log(api.LogLevelInfo, "main ConsoleLog")
+ handler.HandleRequestFn = log
}
var requestCount int
-func rewrite(requestURI []byte) ([]byte, error) {
+func log(api.Request, api.Response) (next bool, reqCtx uint32) {
fmt.Fprintf(os.Stdout, "request[%d] Stdout\n", requestCount)
fmt.Fprintf(os.Stderr, "request[%d] Stderr\n", requestCount)
- wapc.ConsoleLog(fmt.Sprintf("request[%d] ConsoleLog", requestCount))
+ handler.Host.Log(api.LogLevelInfo, fmt.Sprintf("request[%d] ConsoleLog", requestCount))
requestCount++
- return requestURI, nil
+ next = true
+ return
}
diff --git a/middleware/http/wasm/internal/e2e-guests/output/main.wasm b/middleware/http/wasm/internal/e2e-guests/output/main.wasm
new file mode 100755
index 000000000..28b3e3f06
Binary files /dev/null and b/middleware/http/wasm/internal/e2e-guests/output/main.wasm differ
diff --git a/middleware/http/wasm/internal/e2e-guests/rewrite/main.go b/middleware/http/wasm/internal/e2e-guests/rewrite/main.go
new file mode 100644
index 000000000..0709daf91
--- /dev/null
+++ b/middleware/http/wasm/internal/e2e-guests/rewrite/main.go
@@ -0,0 +1,21 @@
+package main
+
+import (
+ "github.com/http-wasm/http-wasm-guest-tinygo/handler"
+ "github.com/http-wasm/http-wasm-guest-tinygo/handler/api"
+)
+
+func main() {
+ handler.HandleRequestFn = handleRequest
+}
+
+// handle rewrites the request URI before dispatching to the next handler.
+//
+// Note: This is not a redirect, rather in-process routing.
+func handleRequest(req api.Request, resp api.Response) (next bool, reqCtx uint32) {
+ if req.GetURI() == "/v1.0/hi?name=panda" {
+ req.SetURI("/v1.0/hello?name=teddy")
+ }
+ next = true
+ return
+}
diff --git a/middleware/http/wasm/internal/e2e-guests/rewrite/main.wasm b/middleware/http/wasm/internal/e2e-guests/rewrite/main.wasm
new file mode 100755
index 000000000..f3bc7e41b
Binary files /dev/null and b/middleware/http/wasm/internal/e2e-guests/rewrite/main.wasm differ
diff --git a/middleware/http/wasm/internal/e2e_test.go b/middleware/http/wasm/internal/e2e_test.go
new file mode 100644
index 000000000..756cd9b7c
--- /dev/null
+++ b/middleware/http/wasm/internal/e2e_test.go
@@ -0,0 +1,148 @@
+package internal_test
+
+import (
+ "bytes"
+ "log"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "os"
+ "path"
+ "testing"
+
+ "github.com/dapr/components-contrib/middleware/http/wasm"
+
+ "github.com/dapr/kit/logger"
+
+ "github.com/dapr/components-contrib/metadata"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/dapr/components-contrib/middleware"
+)
+
+var guestWasm map[string][]byte
+
+const (
+ guestWasmOutput = "output"
+ guestWasmRewrite = "rewrite"
+)
+
+// TestMain ensures we can read the test wasm prior to running e2e tests.
+func TestMain(m *testing.M) {
+ wasms := []string{guestWasmOutput, guestWasmRewrite}
+ guestWasm = make(map[string][]byte, len(wasms))
+ for _, name := range wasms {
+ if wasm, err := os.ReadFile(path.Join("e2e-guests", name, "main.wasm")); err != nil {
+ log.Panicln(err)
+ } else {
+ guestWasm[name] = wasm
+ }
+ }
+ os.Exit(m.Run())
+}
+
+func Test_EndToEnd(t *testing.T) {
+ l := logger.NewLogger(t.Name())
+ var buf bytes.Buffer
+ l.SetOutputLevel(logger.DebugLevel)
+ l.SetOutput(&buf)
+
+ type testCase struct {
+ name string
+ guest []byte
+ test func(t *testing.T, handler http.Handler, log *bytes.Buffer)
+ }
+
+ tests := []testCase{
+ {
+ name: "consoleLog stdout and stderr",
+ guest: guestWasm[guestWasmOutput],
+ test: func(t *testing.T, handler http.Handler, log *bytes.Buffer) {
+ var w http.ResponseWriter
+ var r http.Request
+ handler.ServeHTTP(w, &r)
+
+ // First, we expect any console logging written inline from
+ // init (main) and the request[0-9] funcs to info level.
+ //
+ // Then, we expect to see stdout and stderr from both scopes
+ // at debug level.
+ for _, s := range []string{
+ `level=info msg="main ConsoleLog"`,
+ `level=info msg="request[0] ConsoleLog"`,
+ `level=debug msg="wasm stdout: main Stdout\nrequest[0] Stdout\n"`,
+ `level=debug msg="wasm stderr: main Stderr\nrequest[0] Stderr\n"`,
+ } {
+ require.Contains(t, log.String(), s)
+ }
+ },
+ },
+ {
+ name: "consoleLog multiple requests",
+ guest: guestWasm[guestWasmOutput],
+ test: func(t *testing.T, handler http.Handler, log *bytes.Buffer) {
+ // Service more requests than one to ensure pooling works properly.
+ for i := 0; i < 3; i++ {
+ r := httptest.NewRequest(http.MethodGet, "/", nil)
+ w := httptest.NewRecorder()
+ handler.ServeHTTP(w, r)
+ }
+
+ // We expect to see initialization (main) twice, once for each
+ // module in the pool. We expect to see request[1] which shows
+ // round-robin back to the first module in the pool.
+ for _, s := range []string{
+ `level=info msg="main ConsoleLog"`,
+ `level=info msg="request[0] ConsoleLog"`,
+ `level=debug msg="wasm stdout: main Stdout\nrequest[0] Stdout\n"`,
+ `level=debug msg="wasm stderr: main Stderr\nrequest[0] Stderr\n"`,
+ `level=info msg="request[1] ConsoleLog"`,
+ `level=debug msg="wasm stdout: request[1] Stdout\n"`,
+ `level=debug msg="wasm stderr: request[1] Stderr\n"`,
+ } {
+ require.Contains(t, log.String(), s)
+ }
+ },
+ },
+ {
+ name: "rewrite",
+ guest: guestWasm[guestWasmRewrite],
+ test: func(t *testing.T, handler http.Handler, log *bytes.Buffer) {
+ var w http.ResponseWriter
+ u, err := url.Parse("https://test.io/v1.0/hi?name=panda")
+ if err != nil {
+ panic(err)
+ }
+ r := &http.Request{
+ Method: http.MethodGet,
+ URL: u,
+ Host: "test.io",
+ Header: map[string][]string{
+ "User-Agent": {"curl/7.79.1"},
+ "Accept": {"*/*"},
+ },
+ }
+ handler.ServeHTTP(w, r)
+
+ require.Equal(t, "/v1.0/hello?name=teddy", r.URL.RequestURI())
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ tc := tt
+ t.Run(tc.name, func(t *testing.T) {
+ defer buf.Reset()
+
+ wasmPath := path.Join(t.TempDir(), "guest.wasm")
+ require.NoError(t, os.WriteFile(wasmPath, tc.guest, 0o600))
+
+ meta := metadata.Base{Properties: map[string]string{"path": wasmPath}}
+ handlerFn, err := wasm.NewMiddleware(l).GetHandler(middleware.Metadata{Base: meta})
+ require.NoError(t, err)
+ handler := handlerFn(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
+ tc.test(t, handler, &buf)
+ })
+ }
+}
diff --git a/middleware/http/wasm/internal/testdata/rewrite.wasm b/middleware/http/wasm/internal/testdata/rewrite.wasm
new file mode 100644
index 000000000..65bcc959b
Binary files /dev/null and b/middleware/http/wasm/internal/testdata/rewrite.wasm differ
diff --git a/middleware/http/wasm/internal/testdata/rewrite.wat b/middleware/http/wasm/internal/testdata/rewrite.wat
new file mode 100644
index 000000000..90bd546e4
--- /dev/null
+++ b/middleware/http/wasm/internal/testdata/rewrite.wat
@@ -0,0 +1,92 @@
+;; This is the same logic as ../e2e-guests/rewrite/main.go, but written in
+;; WebAssembly to establish baseline performance. For example, TinyGo should be
+;; slower than this, but other languages are unlikley to be faster.
+(module $rewrite
+ ;; get_uri writes the request URI value to memory, if it isn't larger than
+ ;; the buffer size limit. The result is the actual URI length in bytes.
+ (import "http_handler" "get_uri" (func $get_uri
+ (param $buf i32) (param $buf_limit i32)
+ (result (; uri_len ;) i32)))
+
+ ;; set_uri overwrites the request URI with one read from memory.
+ (import "http_handler" "set_uri" (func $set_uri
+ (param $uri i32) (param $uri_len i32)))
+
+ ;; http-wasm guests are required to export "memory", so that imported
+ ;; functions like "log" can read memory.
+ (memory (export "memory") 1 (; 1 page==64KB ;))
+
+ ;; define the URI we expect to rewrite
+ (global $match_uri i32 (i32.const 0))
+ (data (i32.const 0) "/v1.0/hi?name=panda")
+ (global $match_uri_len i32 (i32.const 19))
+
+ ;; define the URI we expect to rewrite
+ (global $new_uri i32 (i32.const 32))
+ (data (i32.const 32) "/v1.0/hello?name=teddy")
+ (global $new_uri_len i32 (i32.const 22))
+
+ ;; buf is an arbitrary area to write data.
+ (global $buf i32 (i32.const 1024))
+
+ ;; clear_buf clears any memory that may have been written.
+ (func $clear_buf
+ (memory.fill
+ (global.get $buf)
+ (global.get $match_uri_len)
+ (i32.const 0)))
+
+ ;; handle rewrites the HTTP request URI
+ (func (export "handle_request") (result (; ctx_next ;) i64)
+
+ (local $uri_len i32)
+
+ ;; First, read the uri into memory if not larger than our limit.
+
+ ;; uri_len = get_uri(uri, match_uri_len)
+ (local.set $uri_len
+ (call $get_uri (global.get $buf) (global.get $match_uri_len)))
+
+ ;; Next, if the length read is the same as our match uri, check to see if
+ ;; the characters are the same.
+
+ ;; if uri_len != match_uri_len { next() }
+ (if (i32.eq (local.get $uri_len) (global.get $match_uri_len))
+ (then (if (call $memeq ;; uri == match_uri
+ (global.get $buf)
+ (global.get $match_uri)
+ (global.get $match_uri_len)) (then
+
+ ;; Call the imported function that sets the HTTP uri.
+ (call $set_uri ;; uri = new_uri
+ (global.get $new_uri)
+ (global.get $new_uri_len))))))
+
+ ;; dispatch with the possibly rewritten uri.
+ (call $clear_buf)
+ (return (i64.const 1)))
+
+ ;; handle_response is no-op as this is a request-only handler.
+ (func (export "handle_response") (param $reqCtx i32) (param $is_error i32))
+
+ ;; memeq is like memcmp except it returns 0 (ne) or 1 (eq)
+ (func $memeq (param $ptr1 i32) (param $ptr2 i32) (param $len i32) (result i32)
+ (local $i1 i32)
+ (local $i2 i32)
+ (local.set $i1 (local.get $ptr1)) ;; i1 := ptr1
+ (local.set $i2 (local.get $ptr2)) ;; i2 := ptr1
+
+ (loop $len_gt_zero
+ ;; if mem[i1] != mem[i2]
+ (if (i32.ne (i32.load8_u (local.get $i1)) (i32.load8_u (local.get $i2)))
+ (then (return (i32.const 0)))) ;; return 0
+
+ (local.set $i1 (i32.add (local.get $i1) (i32.const 1))) ;; i1++
+ (local.set $i2 (i32.add (local.get $i2) (i32.const 1))) ;; i2++
+ (local.set $len (i32.sub (local.get $len) (i32.const 1))) ;; $len--
+
+ ;; if $len > 0 { continue } else { break }
+ (br_if $len_gt_zero (i32.gt_s (local.get $len) (i32.const 0))))
+
+ (i32.const 1)) ;; return 1
+)
diff --git a/nameresolution/kubernetes/kubernetes.go b/nameresolution/kubernetes/kubernetes.go
index 47a4bbbc1..41ad6084a 100644
--- a/nameresolution/kubernetes/kubernetes.go
+++ b/nameresolution/kubernetes/kubernetes.go
@@ -45,10 +45,13 @@ func (k *resolver) Init(metadata nameresolution.Metadata) error {
if err != nil {
return err
}
- if config, ok := configInterface.(map[string]string); ok {
- clusterDomain := config[ClusterDomainKey]
- if clusterDomain != "" {
- k.clusterDomain = clusterDomain
+ if config, ok := configInterface.(map[string]interface{}); ok {
+ clusterDomainPtr := config[ClusterDomainKey]
+ if clusterDomainPtr != nil {
+ clusterDomain, _ := clusterDomainPtr.(string)
+ if clusterDomain != "" {
+ k.clusterDomain = clusterDomain
+ }
}
}
diff --git a/nameresolution/kubernetes/kubernetes_test.go b/nameresolution/kubernetes/kubernetes_test.go
index cc6b345ae..f5010f383 100644
--- a/nameresolution/kubernetes/kubernetes_test.go
+++ b/nameresolution/kubernetes/kubernetes_test.go
@@ -36,7 +36,7 @@ func TestResolve(t *testing.T) {
func TestResolveWithCustomClusterDomain(t *testing.T) {
resolver := NewResolver(logger.NewLogger("test"))
_ = resolver.Init(nameresolution.Metadata{
- Configuration: map[string]string{
+ Configuration: map[string]interface{}{
"clusterDomain": "mydomain.com",
},
})
diff --git a/pubsub/aws/snssqs/snssqs.go b/pubsub/aws/snssqs/snssqs.go
index b11a06ad8..05ef43305 100644
--- a/pubsub/aws/snssqs/snssqs.go
+++ b/pubsub/aws/snssqs/snssqs.go
@@ -406,22 +406,6 @@ func (s *snsSqs) createSnsSqsSubscription(parentCtx context.Context, queueArn, t
return *subscribeOutput.SubscriptionArn, nil
}
-func (s *snsSqs) removeSnsSqsSubscription(parentCtx context.Context, subscriptionArn string) error {
- ctx, cancel := context.WithTimeout(parentCtx, s.opsTimeout)
- _, err := s.snsClient.UnsubscribeWithContext(ctx, &sns.UnsubscribeInput{
- SubscriptionArn: aws.String(subscriptionArn),
- })
- cancel()
- if err != nil {
- wrappedErr := fmt.Errorf("error unsubscribing to arn: %s %w", subscriptionArn, err)
- s.logger.Error(wrappedErr)
-
- return wrappedErr
- }
-
- return nil
-}
-
func (s *snsSqs) getSnsSqsSubscriptionArn(parentCtx context.Context, topicArn string) (string, error) {
ctx, cancel := context.WithTimeout(parentCtx, s.opsTimeout)
listSubscriptionsOutput, err := s.snsClient.ListSubscriptionsByTopicWithContext(ctx, &sns.ListSubscriptionsByTopicInput{TopicArn: aws.String(topicArn)})
@@ -817,7 +801,7 @@ func (s *snsSqs) Subscribe(subscribeCtx context.Context, req pubsub.SubscribeReq
}
// subscription creation is idempotent. Subscriptions are unique by topic/queue.
- subscriptionArn, err := s.getOrCreateSnsSqsSubscription(subscribeCtx, queueInfo.arn, topicArn)
+ _, err = s.getOrCreateSnsSqsSubscription(subscribeCtx, queueInfo.arn, topicArn)
if err != nil {
wrappedErr := fmt.Errorf("error subscribing topic: %s, to queue: %s, with error: %w", topicArn, queueInfo.arn, err)
s.logger.Error(wrappedErr)
@@ -855,13 +839,6 @@ func (s *snsSqs) Subscribe(subscribeCtx context.Context, req pubsub.SubscribeReq
// Remove the handler
delete(s.topicHandlers, sanitizedName)
- // If we can perform management operations, remove the subscription entirely
- if !s.metadata.disableEntityManagement {
- // Use a background context because subscribeCtx is canceled already
- // Error is logged already
- _ = s.removeSnsSqsSubscription(s.ctx, subscriptionArn)
- }
-
// If we don't have any topic left, close the poller
if len(s.topicHandlers) == 0 {
s.pollerCancel()
diff --git a/pubsub/azure/eventhubs/eventhubs_integration_test.go b/pubsub/azure/eventhubs/eventhubs_integration_test.go
index dddf66f5a..077e91ac9 100644
--- a/pubsub/azure/eventhubs/eventhubs_integration_test.go
+++ b/pubsub/azure/eventhubs/eventhubs_integration_test.go
@@ -52,11 +52,11 @@ func createIotHubPubsubMetadata() pubsub.Metadata {
metadata := pubsub.Metadata{
Base: metadata.Base{
Properties: map[string]string{
- connectionString: os.Getenv(iotHubConnectionStringEnvKey),
- consumerID: os.Getenv(iotHubConsumerGroupEnvKey),
- storageAccountName: os.Getenv(storageAccountNameEnvKey),
- storageAccountKey: os.Getenv(storageAccountKeyEnvKey),
- storageContainerName: testStorageContainerName,
+ "connectionString": os.Getenv(iotHubConnectionStringEnvKey),
+ "consumerID": os.Getenv(iotHubConsumerGroupEnvKey),
+ "storageAccountName": os.Getenv(storageAccountNameEnvKey),
+ "storageAccountKey": os.Getenv(storageAccountKeyEnvKey),
+ "storageContainerName": testStorageContainerName,
},
},
}
diff --git a/pubsub/jetstream/jetstream.go b/pubsub/jetstream/jetstream.go
index 970329ac8..65a516760 100644
--- a/pubsub/jetstream/jetstream.go
+++ b/pubsub/jetstream/jetstream.go
@@ -57,6 +57,9 @@ func (js *jetstreamPubSub) Init(metadata pubsub.Metadata) error {
} else if js.meta.tlsClientCert != "" && js.meta.tlsClientKey != "" {
js.l.Debug("Configure nats for tls client authentication")
opts = append(opts, nats.ClientCert(js.meta.tlsClientCert, js.meta.tlsClientKey))
+ } else if js.meta.token != "" {
+ js.l.Debug("Configure nats for token authentication")
+ opts = append(opts, nats.Token(js.meta.token))
}
js.nc, err = nats.Connect(js.meta.natsURL, opts...)
@@ -88,57 +91,78 @@ func (js *jetstreamPubSub) Features() []pubsub.Feature {
}
func (js *jetstreamPubSub) Publish(req *pubsub.PublishRequest) error {
- js.l.Debugf("Publishing topic %v with data: %v", req.Topic, req.Data)
- _, err := js.jsc.Publish(req.Topic, req.Data)
+ var opts []nats.PubOpt
+ var msgID string
+
+ event, err := pubsub.FromCloudEvent(req.Data, "", "", "", "")
+ if err != nil {
+ js.l.Debugf("error unmarshalling cloudevent: %v", err)
+ } else {
+ // Use the cloudevent id as the Nats-MsgId for deduplication
+ if id, ok := event["id"].(string); ok {
+ msgID = id
+ opts = append(opts, nats.MsgId(msgID))
+ }
+ }
+
+ if msgID == "" {
+ js.l.Warn("empty message ID, Jetstream deduplication will not be possible")
+ }
+
+ js.l.Debugf("Publishing to topic %v id: %s", req.Topic, msgID)
+ _, err = js.jsc.Publish(req.Topic, req.Data, opts...)
return err
}
func (js *jetstreamPubSub) Subscribe(ctx context.Context, req pubsub.SubscribeRequest, handler pubsub.Handler) error {
- var opts []nats.SubOpt
+ var consumerConfig nats.ConsumerConfig
+
+ consumerConfig.DeliverSubject = nats.NewInbox()
if v := js.meta.durableName; v != "" {
- opts = append(opts, nats.Durable(v))
+ consumerConfig.Durable = v
}
if v := js.meta.startTime; !v.IsZero() {
- opts = append(opts, nats.StartTime(v))
+ consumerConfig.OptStartTime = &v
} else if v := js.meta.startSequence; v > 0 {
- opts = append(opts, nats.StartSequence(v))
+ consumerConfig.OptStartSeq = v
} else if js.meta.deliverAll {
- opts = append(opts, nats.DeliverAll())
+ consumerConfig.DeliverPolicy = nats.DeliverAllPolicy
} else {
- opts = append(opts, nats.DeliverLast())
+ consumerConfig.DeliverPolicy = nats.DeliverLastPolicy
}
if js.meta.flowControl {
- opts = append(opts, nats.EnableFlowControl())
+ consumerConfig.FlowControl = true
}
if js.meta.ackWait != 0 {
- opts = append(opts, nats.AckWait(js.meta.ackWait))
+ consumerConfig.AckWait = js.meta.ackWait
}
if js.meta.maxDeliver != 0 {
- opts = append(opts, nats.MaxDeliver(js.meta.maxDeliver))
+ consumerConfig.MaxDeliver = js.meta.maxDeliver
}
if len(js.meta.backOff) != 0 {
- opts = append(opts, nats.BackOff(js.meta.backOff))
+ consumerConfig.BackOff = js.meta.backOff
}
if js.meta.maxAckPending != 0 {
- opts = append(opts, nats.MaxAckPending(js.meta.maxAckPending))
+ consumerConfig.MaxAckPending = js.meta.maxAckPending
}
if js.meta.replicas != 0 {
- opts = append(opts, nats.ConsumerReplicas(js.meta.replicas))
+ consumerConfig.Replicas = js.meta.replicas
}
if js.meta.memoryStorage {
- opts = append(opts, nats.ConsumerMemoryStorage())
+ consumerConfig.MemoryStorage = true
}
if js.meta.rateLimit != 0 {
- opts = append(opts, nats.RateLimit(js.meta.rateLimit))
+ consumerConfig.RateLimit = js.meta.rateLimit
}
if js.meta.hearbeat != 0 {
- opts = append(opts, nats.IdleHeartbeat(js.meta.hearbeat))
+ consumerConfig.Heartbeat = js.meta.hearbeat
}
+ consumerConfig.FilterSubject = req.Topic
natsHandler := func(m *nats.Msg) {
jsm, err := m.Metadata()
@@ -176,14 +200,27 @@ func (js *jetstreamPubSub) Subscribe(ctx context.Context, req pubsub.SubscribeRe
}
var err error
+ streamName := js.meta.streamName
+ if streamName == "" {
+ streamName, err = js.jsc.StreamNameBySubject(req.Topic)
+ if err != nil {
+ return err
+ }
+ }
var subscription *nats.Subscription
+
+ consumerInfo, err := js.jsc.AddConsumer(streamName, &consumerConfig)
+ if err != nil {
+ return err
+ }
+
if queue := js.meta.queueGroupName; queue != "" {
js.l.Debugf("nats: subscribed to subject %s with queue group %s",
req.Topic, js.meta.queueGroupName)
- subscription, err = js.jsc.QueueSubscribe(req.Topic, queue, natsHandler, opts...)
+ subscription, err = js.jsc.QueueSubscribe(req.Topic, queue, natsHandler, nats.Bind(streamName, consumerInfo.Name))
} else {
js.l.Debugf("nats: subscribed to subject %s", req.Topic)
- subscription, err = js.jsc.Subscribe(req.Topic, natsHandler, opts...)
+ subscription, err = js.jsc.Subscribe(req.Topic, natsHandler, nats.Bind(streamName, consumerInfo.Name))
}
if err != nil {
return err
diff --git a/pubsub/jetstream/metadata.go b/pubsub/jetstream/metadata.go
index 7f8203d24..e35708952 100644
--- a/pubsub/jetstream/metadata.go
+++ b/pubsub/jetstream/metadata.go
@@ -27,11 +27,13 @@ type metadata struct {
jwt string
seedKey string
+ token string
tlsClientCert string
tlsClientKey string
name string
+ streamName string
durableName string
queueGroupName string
startSequence uint64
@@ -57,6 +59,7 @@ func parseMetadata(psm pubsub.Metadata) (metadata, error) {
return metadata{}, fmt.Errorf("missing nats URL")
}
+ m.token = psm.Properties["token"]
m.jwt = psm.Properties["jwt"]
m.seedKey = psm.Properties["seedKey"]
@@ -141,5 +144,7 @@ func parseMetadata(psm pubsub.Metadata) (metadata, error) {
m.hearbeat = v
}
+ m.streamName = psm.Properties["streamName"]
+
return m, nil
}
diff --git a/pubsub/jetstream/metadata_test.go b/pubsub/jetstream/metadata_test.go
index 9ee8c8365..0ad9007bc 100644
--- a/pubsub/jetstream/metadata_test.go
+++ b/pubsub/jetstream/metadata_test.go
@@ -71,6 +71,50 @@ func TestParseMetadata(t *testing.T) {
},
expectErr: false,
},
+ {
+ desc: "Valid Metadata with token",
+ input: pubsub.Metadata{Base: mdata.Base{
+ Properties: map[string]string{
+ "natsURL": "nats://localhost:4222",
+ "name": "myName",
+ "durableName": "myDurable",
+ "queueGroupName": "myQueue",
+ "startSequence": "1",
+ "startTime": "1629328511",
+ "deliverAll": "true",
+ "flowControl": "true",
+ "ackWait": "2s",
+ "maxDeliver": "10",
+ "backOff": "500ms, 2s, 10s",
+ "maxAckPending": "5000",
+ "replicas": "3",
+ "memoryStorage": "true",
+ "rateLimit": "20000",
+ "hearbeat": "1s",
+ "token": "myToken",
+ },
+ }},
+ want: metadata{
+ natsURL: "nats://localhost:4222",
+ name: "myName",
+ durableName: "myDurable",
+ queueGroupName: "myQueue",
+ startSequence: 1,
+ startTime: time.Unix(1629328511, 0),
+ deliverAll: true,
+ flowControl: true,
+ ackWait: 2 * time.Second,
+ maxDeliver: 10,
+ backOff: []time.Duration{time.Millisecond * 500, time.Second * 2, time.Second * 10},
+ maxAckPending: 5000,
+ replicas: 3,
+ memoryStorage: true,
+ rateLimit: 20000,
+ hearbeat: time.Second * 1,
+ token: "myToken",
+ },
+ expectErr: false,
+ },
{
desc: "Invalid metadata with missing seed key",
input: pubsub.Metadata{Base: mdata.Base{
@@ -126,7 +170,7 @@ func TestParseMetadata(t *testing.T) {
expectErr: true,
},
{
- desc: "Invalid metadata with missing tls client client",
+ desc: "Invalid metadata with missing tls client",
input: pubsub.Metadata{Base: mdata.Base{
Properties: map[string]string{
"natsURL": "nats://localhost:4222",
diff --git a/pubsub/kubemq/kubemq.go b/pubsub/kubemq/kubemq.go
new file mode 100644
index 000000000..814ad6fee
--- /dev/null
+++ b/pubsub/kubemq/kubemq.go
@@ -0,0 +1,81 @@
+package kubemq
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ "github.com/google/uuid"
+
+ "github.com/dapr/components-contrib/pubsub"
+ "github.com/dapr/kit/logger"
+)
+
+type kubeMQ struct {
+ metadata *metadata
+ logger logger.Logger
+ ctx context.Context
+ ctxCancel context.CancelFunc
+ eventsClient *kubeMQEvents
+ eventStoreClient *kubeMQEventStore
+}
+
+func NewKubeMQ(logger logger.Logger) pubsub.PubSub {
+ return &kubeMQ{
+ logger: logger,
+ }
+}
+
+func (k *kubeMQ) Init(metadata pubsub.Metadata) error {
+ meta, err := createMetadata(metadata)
+ if err != nil {
+ k.logger.Errorf("error init kubemq client error: %s", err.Error())
+ return err
+ }
+ k.metadata = meta
+ k.ctx, k.ctxCancel = context.WithCancel(context.Background())
+ if meta.isStore {
+ k.eventStoreClient = newKubeMQEventsStore(k.logger)
+ _ = k.eventStoreClient.Init(meta)
+ } else {
+ k.eventsClient = newkubeMQEvents(k.logger)
+ _ = k.eventsClient.Init(meta)
+ }
+ return nil
+}
+
+func (k *kubeMQ) Features() []pubsub.Feature {
+ return nil
+}
+
+func (k *kubeMQ) Publish(req *pubsub.PublishRequest) error {
+ if k.metadata.isStore {
+ return k.eventStoreClient.Publish(req)
+ } else {
+ return k.eventsClient.Publish(req)
+ }
+}
+
+func (k *kubeMQ) Subscribe(ctx context.Context, req pubsub.SubscribeRequest, handler pubsub.Handler) error {
+ if k.metadata.isStore {
+ return k.eventStoreClient.Subscribe(ctx, req, handler)
+ } else {
+ return k.eventsClient.Subscribe(ctx, req, handler)
+ }
+}
+
+func (k *kubeMQ) Close() error {
+ if k.metadata.isStore {
+ return k.eventStoreClient.Close()
+ } else {
+ return k.eventsClient.Close()
+ }
+}
+
+func getRandomID() string {
+ randomUUID, err := uuid.NewRandom()
+ if err != nil {
+ return fmt.Sprintf("%d", time.Now().UnixNano())
+ }
+ return randomUUID.String()
+}
diff --git a/pubsub/kubemq/kubemq_events.go b/pubsub/kubemq/kubemq_events.go
new file mode 100644
index 000000000..19d31b7a4
--- /dev/null
+++ b/pubsub/kubemq/kubemq_events.go
@@ -0,0 +1,177 @@
+package kubemq
+
+import (
+ "context"
+ "sync"
+ "time"
+
+ "github.com/kubemq-io/kubemq-go"
+
+ "github.com/dapr/components-contrib/pubsub"
+ "github.com/dapr/kit/logger"
+)
+
+type kubemqEventsClient interface {
+ Stream(ctx context.Context, onError func(err error)) (func(msg *kubemq.Event) error, error)
+ Subscribe(ctx context.Context, request *kubemq.EventsSubscription, onEvent func(msg *kubemq.Event, err error)) error
+ Close() error
+}
+
+type kubeMQEvents struct {
+ lock sync.RWMutex
+ client kubemqEventsClient
+ metadata *metadata
+ logger logger.Logger
+ publishFunc func(event *kubemq.Event) error
+ resultChan chan error
+ waitForResultTimeout time.Duration
+ ctx context.Context
+ ctxCancel context.CancelFunc
+ isInitialized bool
+}
+
+func newkubeMQEvents(logger logger.Logger) *kubeMQEvents {
+ return &kubeMQEvents{
+ client: nil,
+ metadata: nil,
+ logger: logger,
+ publishFunc: nil,
+ resultChan: make(chan error, 1),
+ waitForResultTimeout: 60 * time.Second,
+ ctx: nil,
+ ctxCancel: nil,
+ isInitialized: false,
+ }
+}
+
+func (k *kubeMQEvents) init() error {
+ k.lock.RLock()
+ isInit := k.isInitialized
+ k.lock.RUnlock()
+ if isInit {
+ return nil
+ }
+ k.lock.Lock()
+ defer k.lock.Unlock()
+ k.ctx, k.ctxCancel = context.WithCancel(context.Background())
+ clientID := k.metadata.clientID
+ if clientID == "" {
+ clientID = getRandomID()
+ }
+ client, err := kubemq.NewEventsClient(k.ctx,
+ kubemq.WithAddress(k.metadata.host, k.metadata.port),
+ kubemq.WithClientId(clientID),
+ kubemq.WithTransportType(kubemq.TransportTypeGRPC),
+ kubemq.WithCheckConnection(true),
+ kubemq.WithAuthToken(k.metadata.authToken),
+ kubemq.WithAutoReconnect(true),
+ kubemq.WithReconnectInterval(time.Second))
+ if err != nil {
+ k.logger.Errorf("error init kubemq client error: %s", err.Error())
+ return err
+ }
+ k.ctx, k.ctxCancel = context.WithCancel(context.Background())
+ k.client = client
+ if err := k.setPublishStream(); err != nil {
+ k.logger.Errorf("error init kubemq client error: %w", err.Error())
+ return err
+ }
+ k.isInitialized = true
+ return nil
+}
+
+func (k *kubeMQEvents) Init(meta *metadata) error {
+ k.metadata = meta
+ _ = k.init()
+ return nil
+}
+
+func (k *kubeMQEvents) setPublishStream() error {
+ var err error
+ k.publishFunc, err = k.client.Stream(k.ctx, func(err error) {
+ select {
+ case k.resultChan <- err:
+ default:
+ }
+ })
+ return err
+}
+
+func (k *kubeMQEvents) Publish(req *pubsub.PublishRequest) error {
+ if err := k.init(); err != nil {
+ return err
+ }
+ k.logger.Debugf("kubemq pub/sub: publishing message to %s", req.Topic)
+ event := &kubemq.Event{
+ Id: "",
+ Channel: req.Topic,
+ Metadata: "",
+ Body: req.Data,
+ ClientId: k.metadata.clientID,
+ Tags: map[string]string{},
+ }
+ if err := k.publishFunc(event); err != nil {
+ k.logger.Errorf("kubemq pub/sub error: publishing to %s failed with error: %s", req.Topic, err.Error())
+ return err
+ }
+ return nil
+}
+
+func (k *kubeMQEvents) Features() []pubsub.Feature {
+ return nil
+}
+
+func (k *kubeMQEvents) Subscribe(ctx context.Context, req pubsub.SubscribeRequest, handler pubsub.Handler) error {
+ if err := k.init(); err != nil {
+ return err
+ }
+ clientID := k.metadata.clientID
+ if clientID == "" {
+ clientID = getRandomID()
+ }
+ k.logger.Debugf("kubemq pub/sub: subscribing to %s", req.Topic)
+ err := k.client.Subscribe(ctx, &kubemq.EventsSubscription{
+ Channel: req.Topic,
+ Group: k.metadata.group,
+ ClientId: clientID,
+ }, func(event *kubemq.Event, err error) {
+ if err != nil {
+ k.logger.Errorf("kubemq pub/sub error: subscribing to %s failed with error: %s", req.Topic, err.Error())
+ return
+ }
+ if ctx.Err() != nil {
+ return
+ }
+ msg := &pubsub.NewMessage{
+ Data: event.Body,
+ Topic: req.Topic,
+ }
+
+ if err := handler(k.ctx, msg); err != nil {
+ k.logger.Errorf("kubemq events pub/sub error: error handling message from topic '%s', %s", req.Topic, err.Error())
+ if k.metadata.disableReDelivery {
+ return
+ }
+ if err := k.Publish(&pubsub.PublishRequest{
+ Data: msg.Data,
+ Topic: msg.Topic,
+ }); err != nil {
+ k.logger.Errorf("kubemq pub/sub error: error resending message from topic '%s', %s", req.Topic, err.Error())
+ }
+ }
+ })
+ if err != nil {
+ k.logger.Errorf("kubemq events pub/sub error: error subscribing to topic '%s', %s", req.Topic, err.Error())
+ return err
+ }
+ time.Sleep(1 * time.Second)
+ k.logger.Debugf("kubemq pub/sub: subscribed to %s completed", req.Topic)
+ return nil
+}
+
+func (k *kubeMQEvents) Close() error {
+ if k.ctxCancel != nil {
+ k.ctxCancel()
+ }
+ return k.client.Close()
+}
diff --git a/pubsub/kubemq/kubemq_events_test.go b/pubsub/kubemq/kubemq_events_test.go
new file mode 100644
index 000000000..11d8eeeac
--- /dev/null
+++ b/pubsub/kubemq/kubemq_events_test.go
@@ -0,0 +1,205 @@
+package kubemq
+
+import (
+ "context"
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/kubemq-io/kubemq-go"
+ "github.com/stretchr/testify/assert"
+
+ "github.com/dapr/components-contrib/pubsub"
+ "github.com/dapr/kit/logger"
+)
+
+type kubemqEventsMock struct {
+ resultError error
+ subscribeErr error
+ resultCh chan error
+ publishError error
+ publishTimeout time.Duration
+}
+
+func (k *kubemqEventsMock) publish(msg *kubemq.Event) error {
+ if k.publishError != nil {
+ return k.publishError
+ }
+ go func() {
+ if k.publishTimeout > 0 {
+ time.Sleep(k.publishTimeout)
+ }
+ k.resultCh <- k.resultError
+ }()
+
+ return nil
+}
+
+func (k *kubemqEventsMock) Stream(ctx context.Context, onError func(err error)) (func(msg *kubemq.Event) error, error) {
+ go func() {
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case result := <-k.resultCh:
+ onError(result)
+ }
+ }
+ }()
+ return k.publish, nil
+}
+
+func (k *kubemqEventsMock) Subscribe(ctx context.Context, request *kubemq.EventsSubscription, onEvent func(msg *kubemq.Event, err error)) error {
+ return k.subscribeErr
+}
+
+func (k *kubemqEventsMock) Close() error {
+ return nil
+}
+
+func (k *kubemqEventsMock) setResultError(err error) *kubemqEventsMock {
+ k.resultError = err
+ return k
+}
+
+func (k *kubemqEventsMock) setSubscribeError(err error) *kubemqEventsMock {
+ k.subscribeErr = err
+ return k
+}
+
+func (k *kubemqEventsMock) setPublishTimeout(timeout time.Duration) *kubemqEventsMock {
+ k.publishTimeout = timeout
+ return k
+}
+
+func (k *kubemqEventsMock) setPublishError(err error) *kubemqEventsMock {
+ k.publishError = err
+ return k
+}
+
+func newKubemqEventsMock() *kubemqEventsMock {
+ return &kubemqEventsMock{
+ resultError: nil,
+ subscribeErr: nil,
+ resultCh: make(chan error, 1),
+ }
+}
+
+func Test_kubeMQEvents_Publish(t *testing.T) {
+ tests := []struct {
+ name string
+ req *pubsub.PublishRequest
+ timeout time.Duration
+ publishErr error
+ resultError error
+ wantErr bool
+ }{
+ {
+ name: "publish with no error",
+ req: &pubsub.PublishRequest{
+ Data: []byte("data"),
+ Topic: "some-topic",
+ },
+ resultError: nil,
+
+ wantErr: false,
+ },
+ {
+ name: "publish with publish error",
+ req: &pubsub.PublishRequest{
+ Data: []byte("data"),
+ Topic: "some-topic",
+ },
+ resultError: nil,
+ publishErr: fmt.Errorf("some error"),
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ k := newkubeMQEvents(logger.NewLogger("kubemq-test"))
+ k.ctx, k.ctxCancel = context.WithCancel(context.Background())
+ client := newKubemqEventsMock().
+ setResultError(tt.resultError).
+ setPublishError(tt.publishErr)
+ k.isInitialized = true
+ k.metadata = &metadata{
+ host: "",
+ port: 0,
+ clientID: "some-client-id",
+ authToken: "",
+ group: "",
+ isStore: false,
+ }
+ if tt.timeout > 0 {
+ k.waitForResultTimeout = tt.timeout - 1*time.Second
+ client.setPublishTimeout(tt.timeout)
+ }
+ k.client = client
+ _ = k.setPublishStream()
+ err := k.Publish(tt.req)
+ if tt.wantErr {
+ assert.Error(t, err)
+ } else {
+ assert.NoError(t, err)
+ }
+ _ = k.Features()
+ _ = k.Close()
+ }
+}
+
+func Test_kubeMQEvents_Subscribe(t *testing.T) {
+ tests := []struct {
+ name string
+ reqMsg *pubsub.NewMessage
+ subscribeError error
+ subscribeHandler pubsub.Handler
+ wantErr bool
+ }{
+ {
+ name: "subscribe with no error",
+ reqMsg: &pubsub.NewMessage{
+ Data: []byte("data"),
+ Topic: "some-topic",
+ },
+ subscribeHandler: func(ctx context.Context, msg *pubsub.NewMessage) error {
+ return nil
+ },
+ subscribeError: nil,
+ wantErr: false,
+ }, {
+ name: "subscribe with error",
+ reqMsg: &pubsub.NewMessage{
+ Data: []byte("data"),
+ Topic: "some-topic",
+ },
+ subscribeHandler: func(ctx context.Context, msg *pubsub.NewMessage) error {
+ return nil
+ },
+ subscribeError: fmt.Errorf("some error"),
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ k := newkubeMQEvents(logger.NewLogger("kubemq-test"))
+ k.ctx, k.ctxCancel = context.WithCancel(context.Background())
+ k.client = newKubemqEventsMock().
+ setSubscribeError(tt.subscribeError)
+ k.isInitialized = true
+ k.metadata = &metadata{
+ host: "",
+ port: 0,
+ clientID: "some-client-id",
+ authToken: "",
+ group: "",
+ isStore: false,
+ }
+ err := k.Subscribe(k.ctx, pubsub.SubscribeRequest{Topic: "some-topic"}, tt.subscribeHandler)
+ if tt.wantErr {
+ assert.Error(t, err)
+ } else {
+ assert.NoError(t, err)
+ }
+ _ = k.Features()
+ _ = k.Close()
+ }
+}
diff --git a/pubsub/kubemq/kubemq_eventstore.go b/pubsub/kubemq/kubemq_eventstore.go
new file mode 100644
index 000000000..0c7896fdf
--- /dev/null
+++ b/pubsub/kubemq/kubemq_eventstore.go
@@ -0,0 +1,194 @@
+package kubemq
+
+import (
+ "context"
+ "fmt"
+ "sync"
+ "time"
+
+ "github.com/kubemq-io/kubemq-go"
+
+ "github.com/dapr/components-contrib/pubsub"
+ "github.com/dapr/kit/logger"
+)
+
+// interface used to allow unit testing.
+type kubemqEventsStoreClient interface {
+ Stream(ctx context.Context, onResult func(result *kubemq.EventStoreResult, err error)) (func(msg *kubemq.EventStore) error, error)
+ Subscribe(ctx context.Context, request *kubemq.EventsStoreSubscription, onEvent func(msg *kubemq.EventStoreReceive, err error)) error
+ Close() error
+}
+
+type kubeMQEventStore struct {
+ lock sync.RWMutex
+ client kubemqEventsStoreClient
+ metadata *metadata
+ logger logger.Logger
+ publishFunc func(msg *kubemq.EventStore) error
+ resultChan chan *kubemq.EventStoreResult
+ waitForResultTimeout time.Duration
+ ctx context.Context
+ ctxCancel context.CancelFunc
+ isInitialized bool
+}
+
+func newKubeMQEventsStore(logger logger.Logger) *kubeMQEventStore {
+ return &kubeMQEventStore{
+ client: nil,
+ metadata: nil,
+ logger: logger,
+ publishFunc: nil,
+ resultChan: make(chan *kubemq.EventStoreResult, 1),
+ waitForResultTimeout: 60 * time.Second,
+ ctx: nil,
+ ctxCancel: nil,
+ isInitialized: false,
+ }
+}
+
+func (k *kubeMQEventStore) init() error {
+ k.lock.RLock()
+ isInit := k.isInitialized
+ k.lock.RUnlock()
+ if isInit {
+ return nil
+ }
+ k.lock.Lock()
+ defer k.lock.Unlock()
+ k.ctx, k.ctxCancel = context.WithCancel(context.Background())
+ clientID := k.metadata.clientID
+ if clientID == "" {
+ clientID = getRandomID()
+ }
+ client, err := kubemq.NewEventsStoreClient(k.ctx,
+ kubemq.WithAddress(k.metadata.host, k.metadata.port),
+ kubemq.WithClientId(clientID),
+ kubemq.WithTransportType(kubemq.TransportTypeGRPC),
+ kubemq.WithCheckConnection(true),
+ kubemq.WithAuthToken(k.metadata.authToken),
+ kubemq.WithAutoReconnect(true),
+ kubemq.WithReconnectInterval(time.Second))
+ if err != nil {
+ k.logger.Errorf("error init kubemq client error: %s", err.Error())
+ return err
+ }
+ k.ctx, k.ctxCancel = context.WithCancel(context.Background())
+ k.client = client
+ if err := k.setPublishStream(); err != nil {
+ k.logger.Errorf("error init kubemq client error: %w", err.Error())
+ return err
+ }
+ k.isInitialized = true
+ return nil
+}
+
+func (k *kubeMQEventStore) Init(meta *metadata) error {
+ k.metadata = meta
+ _ = k.init()
+ return nil
+}
+
+func (k *kubeMQEventStore) setPublishStream() error {
+ var err error
+ k.publishFunc, err = k.client.Stream(k.ctx, func(result *kubemq.EventStoreResult, err error) {
+ select {
+ case k.resultChan <- result:
+ default:
+ }
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (k *kubeMQEventStore) Publish(req *pubsub.PublishRequest) error {
+ if err := k.init(); err != nil {
+ return err
+ }
+ k.logger.Debugf("kubemq pub/sub: publishing message to %s", req.Topic)
+ event := &kubemq.EventStore{
+ Id: "",
+ Channel: req.Topic,
+ Metadata: "",
+ Body: req.Data,
+ ClientId: k.metadata.clientID,
+ Tags: map[string]string{},
+ }
+ if err := k.publishFunc(event); err != nil {
+ k.logger.Errorf("kubemq pub/sub error: publishing to %s failed with error: %s", req.Topic, err.Error())
+ return err
+ }
+ select {
+ case res := <-k.resultChan:
+ if res.Err != nil {
+ return res.Err
+ }
+ case <-time.After(k.waitForResultTimeout):
+ return fmt.Errorf("kubemq pub/sub error: timeout waiting for response")
+ }
+ return nil
+}
+
+func (k *kubeMQEventStore) Features() []pubsub.Feature {
+ return nil
+}
+
+func (k *kubeMQEventStore) Subscribe(ctx context.Context, req pubsub.SubscribeRequest, handler pubsub.Handler) error {
+ if err := k.init(); err != nil {
+ return err
+ }
+ clientID := k.metadata.clientID
+ if clientID == "" {
+ clientID = getRandomID()
+ }
+
+ k.logger.Debugf("kubemq pub/sub: subscribing to %s", req.Topic)
+ err := k.client.Subscribe(ctx, &kubemq.EventsStoreSubscription{
+ Channel: req.Topic,
+ Group: k.metadata.group,
+ ClientId: clientID,
+ SubscriptionType: kubemq.StartFromNewEvents(),
+ }, func(event *kubemq.EventStoreReceive, err error) {
+ if err != nil {
+ k.logger.Errorf("kubemq pub/sub error: subscribing to %s failed with error: %s", req.Topic, err.Error())
+ return
+ }
+ if ctx.Err() != nil {
+ return
+ }
+ msg := &pubsub.NewMessage{
+ Data: event.Body,
+ Topic: req.Topic,
+ Metadata: nil,
+ ContentType: nil,
+ }
+
+ if err := handler(ctx, msg); err != nil {
+ k.logger.Errorf("kubemq pub/sub error: error handling message from topic '%s', %s, resending...", req.Topic, err.Error())
+ if k.metadata.disableReDelivery {
+ return
+ }
+ if err := k.Publish(&pubsub.PublishRequest{
+ Data: msg.Data,
+ Topic: msg.Topic,
+ }); err != nil {
+ k.logger.Errorf("kubemq pub/sub error: error resending message from topic '%s', %s", req.Topic, err.Error())
+ }
+ }
+ })
+ if err != nil {
+ k.logger.Errorf("kubemq pub/sub error: error subscribing to topic '%s', %s", req.Topic, err.Error())
+ return err
+ }
+ time.Sleep(1 * time.Second)
+ k.logger.Debugf("kubemq pub/sub: subscribed to %s completed", req.Topic)
+ return nil
+}
+
+func (k *kubeMQEventStore) Close() error {
+ if k.ctxCancel != nil {
+ k.ctxCancel()
+ }
+ return k.client.Close()
+}
diff --git a/pubsub/kubemq/kubemq_eventstore_test.go b/pubsub/kubemq/kubemq_eventstore_test.go
new file mode 100644
index 000000000..b4d87abd0
--- /dev/null
+++ b/pubsub/kubemq/kubemq_eventstore_test.go
@@ -0,0 +1,228 @@
+package kubemq
+
+import (
+ "context"
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/kubemq-io/kubemq-go"
+ "github.com/stretchr/testify/assert"
+
+ "github.com/dapr/components-contrib/pubsub"
+ "github.com/dapr/kit/logger"
+)
+
+type kubemqEventsStoreMock struct {
+ resultError error
+ subscribeErr error
+ resultCh chan error
+ publishError error
+ publishTimeout time.Duration
+}
+
+func (k *kubemqEventsStoreMock) publish(msg *kubemq.EventStore) error {
+ if k.publishError != nil {
+ return k.publishError
+ }
+ go func() {
+ if k.publishTimeout > 0 {
+ time.Sleep(k.publishTimeout)
+ }
+ k.resultCh <- k.resultError
+ }()
+
+ return nil
+}
+
+func (k *kubemqEventsStoreMock) Stream(ctx context.Context, onResult func(result *kubemq.EventStoreResult, err error)) (func(msg *kubemq.EventStore) error, error) {
+ go func() {
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case result := <-k.resultCh:
+ onResult(&kubemq.EventStoreResult{
+ Id: "",
+ Sent: false,
+ Err: result,
+ }, nil)
+ }
+ }
+ }()
+ return k.publish, nil
+}
+
+func (k *kubemqEventsStoreMock) Subscribe(ctx context.Context, request *kubemq.EventsStoreSubscription, onEvent func(msg *kubemq.EventStoreReceive, err error)) error {
+ return k.subscribeErr
+}
+
+func (k *kubemqEventsStoreMock) Close() error {
+ return nil
+}
+
+func (k *kubemqEventsStoreMock) setResultError(err error) *kubemqEventsStoreMock {
+ k.resultError = err
+ return k
+}
+
+func (k *kubemqEventsStoreMock) setSubscribeError(err error) *kubemqEventsStoreMock {
+ k.subscribeErr = err
+ return k
+}
+
+func (k *kubemqEventsStoreMock) setPublishTimeout(timeout time.Duration) *kubemqEventsStoreMock {
+ k.publishTimeout = timeout
+ return k
+}
+
+func (k *kubemqEventsStoreMock) setPublishError(err error) *kubemqEventsStoreMock {
+ k.publishError = err
+ return k
+}
+
+func newKubemqEventsStoreMock() *kubemqEventsStoreMock {
+ return &kubemqEventsStoreMock{
+ resultError: nil,
+ subscribeErr: nil,
+ resultCh: make(chan error, 1),
+ }
+}
+
+func Test_kubeMQEventsStore_Publish(t *testing.T) {
+ tests := []struct {
+ name string
+ req *pubsub.PublishRequest
+ timeout time.Duration
+ publishErr error
+ resultError error
+ wantErr bool
+ }{
+ {
+ name: "publish with no error",
+ req: &pubsub.PublishRequest{
+ Data: []byte("data"),
+ Topic: "some-topic",
+ },
+ resultError: nil,
+
+ wantErr: false,
+ },
+ {
+ name: "publish with error",
+ req: &pubsub.PublishRequest{
+ Data: []byte("data"),
+ Topic: "some-topic",
+ },
+ resultError: fmt.Errorf("some error"),
+ wantErr: true,
+ },
+ {
+ name: "publish with timeout error",
+ req: &pubsub.PublishRequest{
+ Data: []byte("data"),
+ Topic: "some-topic",
+ },
+ resultError: nil,
+ timeout: 3 * time.Second,
+ wantErr: true,
+ },
+ {
+ name: "publish with publish error",
+ req: &pubsub.PublishRequest{
+ Data: []byte("data"),
+ Topic: "some-topic",
+ },
+ resultError: nil,
+ publishErr: fmt.Errorf("some error"),
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ k := newKubeMQEventsStore(logger.NewLogger("kubemq-test"))
+ k.ctx, k.ctxCancel = context.WithCancel(context.Background())
+ client := newKubemqEventsStoreMock().
+ setResultError(tt.resultError).
+ setPublishError(tt.publishErr)
+ k.isInitialized = true
+ k.metadata = &metadata{
+ host: "",
+ port: 0,
+ clientID: "some-client-id",
+ authToken: "",
+ group: "",
+ isStore: true,
+ }
+ if tt.timeout > 0 {
+ k.waitForResultTimeout = tt.timeout - 1*time.Second
+ client.setPublishTimeout(tt.timeout)
+ }
+ k.client = client
+ _ = k.setPublishStream()
+ err := k.Publish(tt.req)
+ if tt.wantErr {
+ assert.Error(t, err)
+ } else {
+ assert.NoError(t, err)
+ }
+ _ = k.Features()
+ _ = k.Close()
+ }
+}
+
+func Test_kubeMQkubeMQEventsStore_Subscribe(t *testing.T) {
+ tests := []struct {
+ name string
+ reqMsg *pubsub.NewMessage
+ subscribeError error
+ subscribeHandler pubsub.Handler
+ wantErr bool
+ }{
+ {
+ name: "subscribe with no error",
+ reqMsg: &pubsub.NewMessage{
+ Data: []byte("data"),
+ Topic: "some-topic",
+ },
+ subscribeHandler: func(ctx context.Context, msg *pubsub.NewMessage) error {
+ return nil
+ },
+ subscribeError: nil,
+ wantErr: false,
+ }, {
+ name: "subscribe with error",
+ reqMsg: &pubsub.NewMessage{
+ Data: []byte("data"),
+ Topic: "some-topic",
+ },
+ subscribeHandler: func(ctx context.Context, msg *pubsub.NewMessage) error {
+ return nil
+ },
+ subscribeError: fmt.Errorf("some error"),
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ k := newKubeMQEventsStore(logger.NewLogger("kubemq-test"))
+ k.ctx, k.ctxCancel = context.WithCancel(context.Background())
+ k.client = newKubemqEventsStoreMock().
+ setSubscribeError(tt.subscribeError)
+ k.isInitialized = true
+ k.metadata = &metadata{
+ host: "",
+ port: 0,
+ clientID: "some-client-id",
+ authToken: "",
+ group: "",
+ isStore: true,
+ }
+ err := k.Subscribe(k.ctx, pubsub.SubscribeRequest{Topic: "some-topic"}, tt.subscribeHandler)
+ if tt.wantErr {
+ assert.Error(t, err)
+ } else {
+ assert.NoError(t, err)
+ }
+ _ = k.Features()
+ _ = k.Close()
+ }
+}
diff --git a/pubsub/kubemq/kubemq_test.go b/pubsub/kubemq/kubemq_test.go
new file mode 100644
index 000000000..a46f6e4ca
--- /dev/null
+++ b/pubsub/kubemq/kubemq_test.go
@@ -0,0 +1,162 @@
+package kubemq
+
+import (
+ "context"
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ mdata "github.com/dapr/components-contrib/metadata"
+ "github.com/dapr/components-contrib/pubsub"
+ "github.com/dapr/kit/logger"
+)
+
+func getMockEventsClient() *kubeMQEvents {
+ return &kubeMQEvents{
+ client: newKubemqEventsMock(),
+ metadata: nil,
+ logger: nil,
+ publishFunc: nil,
+ resultChan: nil,
+ waitForResultTimeout: 0,
+ ctx: nil,
+ ctxCancel: nil,
+ isInitialized: true,
+ }
+}
+
+func getMockEventsStoreClient() *kubeMQEventStore {
+ return &kubeMQEventStore{
+ client: newKubemqEventsStoreMock(),
+ metadata: nil,
+ logger: nil,
+ publishFunc: nil,
+ resultChan: nil,
+ waitForResultTimeout: 0,
+ ctx: nil,
+ ctxCancel: nil,
+ isInitialized: true,
+ }
+}
+
+func Test_kubeMQ_Init(t *testing.T) {
+ tests := []struct {
+ name string
+ meta pubsub.Metadata
+ eventsClient *kubeMQEvents
+ eventStoreClient *kubeMQEventStore
+ wantErr bool
+ }{
+ {
+ name: "init events store client",
+ meta: pubsub.Metadata{
+ Base: mdata.Base{
+ Properties: map[string]string{
+ "address": "localhost:50000",
+ "channel": "test",
+ "clientID": "clientID",
+ "authToken": "authToken",
+ "group": "group",
+ "store": "true",
+ "useMock": "true",
+ },
+ },
+ },
+ eventsClient: nil,
+ eventStoreClient: getMockEventsStoreClient(),
+ wantErr: false,
+ },
+ {
+ name: "init events client",
+ meta: pubsub.Metadata{
+ Base: mdata.Base{
+ Properties: map[string]string{
+ "address": "localhost:50000",
+ "channel": "test",
+ "clientID": "clientID",
+ "authToken": "authToken",
+ "group": "group",
+ "store": "false",
+ "useMock": "true",
+ },
+ },
+ },
+ eventsClient: getMockEventsClient(),
+ eventStoreClient: nil,
+ wantErr: false,
+ },
+ {
+ name: "init error",
+ meta: pubsub.Metadata{
+ Base: mdata.Base{
+ Properties: map[string]string{
+ "address": "badaddress",
+ },
+ },
+ },
+ eventsClient: nil,
+ eventStoreClient: nil,
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ k := NewKubeMQ(logger.NewLogger("test"))
+ err := k.Init(tt.meta)
+ assert.Equal(t, tt.wantErr, err != nil)
+ })
+ }
+}
+
+func Test_kubeMQ_Close(t *testing.T) {
+ type fields struct {
+ metadata *metadata
+ logger logger.Logger
+ ctx context.Context
+ ctxCancel context.CancelFunc
+ eventsClient *kubeMQEvents
+ eventStoreClient *kubeMQEventStore
+ }
+ tests := []struct {
+ name string
+ fields fields
+ wantErr assert.ErrorAssertionFunc
+ }{
+ {
+ name: "close events client",
+ fields: fields{
+ metadata: &metadata{
+ isStore: false,
+ },
+ eventsClient: getMockEventsClient(),
+ eventStoreClient: nil,
+ },
+ wantErr: assert.NoError,
+ },
+ {
+ name: "close events store client",
+ fields: fields{
+ metadata: &metadata{
+ isStore: true,
+ },
+ eventsClient: nil,
+ eventStoreClient: getMockEventsStoreClient(),
+ },
+ wantErr: assert.NoError,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ k := &kubeMQ{
+ metadata: tt.fields.metadata,
+ logger: tt.fields.logger,
+ ctx: tt.fields.ctx,
+ ctxCancel: tt.fields.ctxCancel,
+ eventsClient: tt.fields.eventsClient,
+ eventStoreClient: tt.fields.eventStoreClient,
+ }
+ tt.wantErr(t, k.Close(), fmt.Sprintf("Close()"))
+ })
+ }
+}
diff --git a/pubsub/kubemq/metadata.go b/pubsub/kubemq/metadata.go
new file mode 100644
index 000000000..c907836d5
--- /dev/null
+++ b/pubsub/kubemq/metadata.go
@@ -0,0 +1,80 @@
+package kubemq
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/dapr/components-contrib/pubsub"
+)
+
+type metadata struct {
+ host string
+ port int
+ clientID string
+ authToken string
+ group string
+ isStore bool
+ disableReDelivery bool
+}
+
+func parseAddress(address string) (string, int, error) {
+ var host string
+ var port int
+ var err error
+ hostPort := strings.Split(address, ":")
+ if len(hostPort) != 2 {
+ return "", 0, fmt.Errorf("invalid kubeMQ address, address format is invalid")
+ }
+ host = hostPort[0]
+ if len(host) == 0 {
+ return "", 0, fmt.Errorf("invalid kubeMQ address, host is empty")
+ }
+ port, err = strconv.Atoi(hostPort[1])
+ if err != nil {
+ return "", 0, fmt.Errorf("invalid kubeMQ address, port is invalid")
+ }
+ return host, port, nil
+}
+
+// createMetadata creates a new instance from the pubsub metadata
+func createMetadata(pubSubMetadata pubsub.Metadata) (*metadata, error) {
+ result := &metadata{}
+ if val, found := pubSubMetadata.Properties["address"]; found && val != "" {
+ var err error
+ result.host, result.port, err = parseAddress(val)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ return nil, fmt.Errorf("invalid kubeMQ address, address is empty")
+ }
+ if val, found := pubSubMetadata.Properties["clientID"]; found && val != "" {
+ result.clientID = val
+ }
+
+ if val, found := pubSubMetadata.Properties["authToken"]; found && val != "" {
+ result.authToken = val
+ }
+
+ if val, found := pubSubMetadata.Properties["group"]; found && val != "" {
+ result.group = val
+ }
+ result.isStore = true
+ if val, found := pubSubMetadata.Properties["store"]; found && val != "" {
+ switch val {
+ case "false":
+ result.isStore = false
+ case "true":
+ result.isStore = true
+ default:
+ return nil, fmt.Errorf("invalid kubeMQ store value, store can be true or false")
+ }
+ }
+ if val, found := pubSubMetadata.Properties["disableReDelivery"]; found && val != "" {
+ if val == "true" {
+ result.disableReDelivery = true
+ }
+ }
+ return result, nil
+}
diff --git a/pubsub/kubemq/metadata_test.go b/pubsub/kubemq/metadata_test.go
new file mode 100644
index 000000000..51d24980d
--- /dev/null
+++ b/pubsub/kubemq/metadata_test.go
@@ -0,0 +1,170 @@
+package kubemq
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ mdata "github.com/dapr/components-contrib/metadata"
+ "github.com/dapr/components-contrib/pubsub"
+)
+
+func Test_createMetadata(t *testing.T) {
+ tests := []struct {
+ name string
+ meta pubsub.Metadata
+ want *metadata
+ wantErr bool
+ }{
+ {
+ name: "create valid metadata",
+ meta: pubsub.Metadata{
+ Base: mdata.Base{
+ Properties: map[string]string{
+ "address": "localhost:50000",
+ "channel": "test",
+ "clientID": "clientID",
+ "authToken": "authToken",
+ "group": "group",
+ "store": "true",
+ "useMock": "true",
+ "disableReDelivery": "true",
+ },
+ },
+ },
+ want: &metadata{
+ host: "localhost",
+ port: 50000,
+ clientID: "clientID",
+ authToken: "authToken",
+ group: "group",
+ isStore: true,
+ disableReDelivery: true,
+ },
+ wantErr: false,
+ },
+ {
+ name: "create valid metadata with empty group",
+ meta: pubsub.Metadata{
+ Base: mdata.Base{
+ Properties: map[string]string{
+ "address": "localhost:50000",
+ "clientID": "clientID",
+ "authToken": "authToken",
+ "store": "false",
+ },
+ },
+ },
+ want: &metadata{
+ host: "localhost",
+ port: 50000,
+ clientID: "clientID",
+ authToken: "authToken",
+ group: "",
+ isStore: false,
+ },
+ wantErr: false,
+ },
+ {
+ name: "create valid metadata with empty authToken",
+ meta: pubsub.Metadata{
+ Base: mdata.Base{
+ Properties: map[string]string{
+ "address": "localhost:50000",
+ "channel": "test",
+ "clientID": "clientID",
+ "group": "group",
+ "store": "true",
+ },
+ },
+ },
+ want: &metadata{
+ host: "localhost",
+ port: 50000,
+ clientID: "clientID",
+ authToken: "",
+ group: "group",
+ isStore: true,
+ },
+ wantErr: false,
+ },
+ {
+ name: "create invalid metadata with bad host",
+ meta: pubsub.Metadata{
+ Base: mdata.Base{
+ Properties: map[string]string{
+ "address": ":50000",
+ "clientID": "clientID",
+ },
+ },
+ },
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "create invalid metadata with bad port",
+ meta: pubsub.Metadata{
+ Base: mdata.Base{
+ Properties: map[string]string{
+ "address": "localhost:badport",
+ "clientID": "clientID",
+ },
+ },
+ },
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "create invalid metadata with empty address",
+ meta: pubsub.Metadata{
+ Base: mdata.Base{
+ Properties: map[string]string{
+ "address": "",
+ "clientID": "clientID",
+ },
+ },
+ },
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "create invalid metadata with bad address format",
+ meta: pubsub.Metadata{
+ Base: mdata.Base{
+ Properties: map[string]string{
+ "address": "localhost:50000:badport",
+ "clientID": "clientID",
+ },
+ },
+ },
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "create invalid metadata with bad store info",
+ meta: pubsub.Metadata{
+ Base: mdata.Base{
+ Properties: map[string]string{
+ "address": "localhost:50000",
+ "clientID": "clientID",
+ "store": "bad",
+ },
+ },
+ },
+ want: nil,
+ wantErr: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := createMetadata(tt.meta)
+ if tt.wantErr {
+ assert.Error(t, err)
+ } else {
+ assert.NoError(t, err)
+ assert.Equal(t, tt.want, got)
+ }
+ })
+ }
+}
diff --git a/pubsub/mqtt/mqtt.go b/pubsub/mqtt/mqtt.go
index 3e56d0f57..fec6dc77b 100644
--- a/pubsub/mqtt/mqtt.go
+++ b/pubsub/mqtt/mqtt.go
@@ -22,6 +22,7 @@ import (
"fmt"
"net/url"
"regexp"
+ "strconv"
"strings"
"sync"
"time"
@@ -249,11 +250,6 @@ func (m *mqttPubSub) onMessage(ctx context.Context) func(client mqtt.Client, mqt
return func(client mqtt.Client, mqttMsg mqtt.Message) {
ack := false
defer func() {
- // Do not send N/ACKs on retained messages
- if mqttMsg.Retained() {
- return
- }
-
// MQTT does not support NACK's, so in case of error we need to re-enqueue the message and then send a positive ACK for this message
// Note that if the connection drops before the message is explicitly ACK'd below, then it's automatically re-sent (assuming QoS is 1 or greater, which is the default). So we do not risk losing messages.
// Problem with this approach is that if the service crashes between the time the message is re-enqueued and when the ACK is sent, the message may be delivered twice
@@ -281,8 +277,9 @@ func (m *mqttPubSub) onMessage(ctx context.Context) func(client mqtt.Client, mqt
}()
msg := pubsub.NewMessage{
- Topic: mqttMsg.Topic(),
- Data: mqttMsg.Payload(),
+ Topic: mqttMsg.Topic(),
+ Data: mqttMsg.Payload(),
+ Metadata: map[string]string{"retained": strconv.FormatBool(mqttMsg.Retained())},
}
topicHandler := m.handlerForTopic(msg.Topic)
diff --git a/pubsub/rabbitmq/metadata.go b/pubsub/rabbitmq/metadata.go
index 5c477f91b..fd531024c 100644
--- a/pubsub/rabbitmq/metadata.go
+++ b/pubsub/rabbitmq/metadata.go
@@ -21,8 +21,10 @@ import (
amqp "github.com/rabbitmq/amqp091-go"
- "github.com/dapr/components-contrib/pubsub"
"github.com/dapr/kit/logger"
+
+ contribMetadata "github.com/dapr/components-contrib/metadata"
+ "github.com/dapr/components-contrib/pubsub"
)
type metadata struct {
@@ -45,6 +47,7 @@ type metadata struct {
exchangeKind string
publisherConfirm bool
concurrency pubsub.ConcurrencyMode
+ defaultQueueTTL *time.Duration
}
const (
@@ -191,6 +194,15 @@ func createMetadata(pubSubMetadata pubsub.Metadata, log logger.Logger) (*metadat
}
}
+ ttl, ok, err := contribMetadata.TryGetTTL(pubSubMetadata.Properties)
+ if err != nil {
+ return &result, fmt.Errorf("%s parse RabbitMQ ttl metadata with error: %s", errorMessagePrefix, err)
+ }
+
+ if ok {
+ result.defaultQueueTTL = &ttl
+ }
+
c, err := pubsub.Concurrency(pubSubMetadata.Properties)
if err != nil {
return &result, err
diff --git a/pubsub/rabbitmq/rabbitmq.go b/pubsub/rabbitmq/rabbitmq.go
index 852af79db..0e4280908 100644
--- a/pubsub/rabbitmq/rabbitmq.go
+++ b/pubsub/rabbitmq/rabbitmq.go
@@ -24,8 +24,10 @@ import (
amqp "github.com/rabbitmq/amqp091-go"
- "github.com/dapr/components-contrib/pubsub"
"github.com/dapr/kit/logger"
+
+ contribMetadata "github.com/dapr/components-contrib/metadata"
+ "github.com/dapr/components-contrib/pubsub"
)
const (
@@ -65,6 +67,8 @@ type rabbitMQ struct {
}
// interface used to allow unit testing.
+//
+//nolint:interfacebloat
type rabbitMQChannelBroker interface {
PublishWithContext(ctx context.Context, exchange string, key string, mandatory bool, immediate bool, msg amqp.Publishing) error
PublishWithDeferredConfirmWithContext(ctx context.Context, exchange string, key string, mandatory bool, immediate bool, msg amqp.Publishing) (*amqp.DeferredConfirmation, error)
@@ -190,10 +194,23 @@ func (r *rabbitMQ) publishSync(req *pubsub.PublishRequest) (rabbitMQChannelBroke
routingKey = val
}
+ ttl, ok, err := contribMetadata.TryGetTTL(req.Metadata)
+ if err != nil {
+ r.logger.Warnf("%s publishing to %s failed parse TryGetTTL: %v, it is ignored.", logMessagePrefix, req.Topic, err)
+ }
+ var expiration string
+ if ok {
+ // RabbitMQ expects the duration in ms
+ expiration = strconv.FormatInt(ttl.Milliseconds(), 10)
+ } else if r.metadata.defaultQueueTTL != nil {
+ expiration = strconv.FormatInt(r.metadata.defaultQueueTTL.Milliseconds(), 10)
+ }
+
confirm, err := r.channel.PublishWithDeferredConfirmWithContext(r.ctx, req.Topic, routingKey, false, false, amqp.Publishing{
ContentType: "text/plain",
Body: req.Data,
DeliveryMode: r.metadata.deliveryMode,
+ Expiration: expiration,
})
if err != nil {
r.logger.Errorf("%s publishing to %s failed in channel.Publish: %v", logMessagePrefix, req.Topic, err)
@@ -545,7 +562,7 @@ func (r *rabbitMQ) Close() error {
}
func (r *rabbitMQ) Features() []pubsub.Feature {
- return nil
+ return []pubsub.Feature{pubsub.FeatureMessageTTL}
}
func mustReconnect(channel rabbitMQChannelBroker, err error) bool {
diff --git a/pubsub/rocketmq/metadata.go b/pubsub/rocketmq/metadata.go
index 2ee9547f3..dc6a8817f 100644
--- a/pubsub/rocketmq/metadata.go
+++ b/pubsub/rocketmq/metadata.go
@@ -14,68 +14,171 @@ limitations under the License.
package rocketmq
import (
- "errors"
"fmt"
"github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/pubsub"
- "github.com/dapr/kit/logger"
-)
-
-var (
- ErrRocketmqPublishMsg = errors.New("rocketmq publish msg error")
- ErrRocketmqValidPublishMsgTyp = errors.New("rocketmq publish msg error, invalid msg type")
)
const (
metadataRocketmqTag = "rocketmq-tag"
metadataRocketmqKey = "rocketmq-key"
metadataRocketmqShardingKey = "rocketmq-shardingkey"
+ metadataRocketmqQueue = "rocketmq-queue"
metadataRocketmqConsumerGroup = "rocketmq-consumerGroup"
metadataRocketmqType = "rocketmq-sub-type"
metadataRocketmqExpression = "rocketmq-sub-expression"
metadataRocketmqBrokerName = "rocketmq-broker-name"
+ metadataRocketmqQueueID = "rocketmq-queue-id"
)
+type QueueSelectorType string
+
+const (
+ HashQueueSelector QueueSelectorType = "hash"
+ RandomQueueSelector QueueSelectorType = "random"
+ ManualQueueSelector QueueSelectorType = "manual"
+ RoundRobinQueueSelector QueueSelectorType = "roundRobin"
+ DaprQueueSelector QueueSelectorType = "dapr"
+)
+
+// RocketMQ Go Client Options
type rocketMQMetaData struct {
- // rocketmq Credentials
- AccessKey string `mapstructure:"accessKey"`
- SecretKey string `mapstructure:"secretKey"`
- NameServer string `mapstructure:"nameServer"`
- // Deprecated: use ProducerGroup instead.
+ // rocketmq instance name, it will be registered to the broker
+ InstanceName string `mapstructure:"instanceName"`
+ // Deprecated: consumer group name
GroupName string `mapstructure:"groupName"`
+ ConsumerGroup string `mapstructure:"consumerGroup"`
+ // producer group name
ProducerGroup string `mapstructure:"producerGroup"`
- NameSpace string `mapstructure:"nameSpace"`
- // consumer group rocketmq's subscribers
- ConsumerGroup string `mapstructure:"consumerGroup"`
- ConsumerBatchSize int `mapstructure:"consumerBatchSize"`
+ // rocketmq namespace
+ NameSpace string `mapstructure:"nameSpace"`
// rocketmq's name server domain
NameServerDomain string `mapstructure:"nameServerDomain"`
- // msg's content-type
- ContentType string `mapstructure:"content-type"`
- // retry times to connect rocketmq's broker
+ // rocketmq's name server
+ NameServer string `mapstructure:"nameServer"`
+ // rocketmq Credentials
+ AccessKey string `mapstructure:"accessKey"`
+ SecretKey string `mapstructure:"secretKey"`
+ SecurityToken string `mapstructure:"securityToken"`
+ // retry times to send msg to broker
Retries int `mapstructure:"retries"`
+
+ // Producer Queue selector
+ // There are five implementations of queue selector,Hash, Random, Manual, RoundRobin, Dapr,respectively
+ //
+ // Dapr Queue selector is design by dapr developers
+ ProducerQueueSelector QueueSelectorType `mapstructure:"producerQueueSelector"`
+
+ // Message model defines the way how messages are delivered to each consumer clients
+ // RocketMQ supports two message models: clustering and broadcasting. If clustering is set, consumer clients with
+ // the same {@link #ConsumerGroup} would only consume shards of the messages subscribed, which achieves load
+ // balances; Conversely, if the broadcasting is set, each consumer client will consume all subscribed messages
+ // separately.
+ //
+ // This field defaults to clustering.
+ ConsumerModel string `mapstructure:"consumerModel"`
+
+ // Consuming point on consumer booting.
+ // There are three consuming points:
+ // - CONSUME_FROM_LAST_OFFSET: consumer clients pick up where it stopped previously. If it were a newly booting up
+ // consumer client, according aging of the consumer group, there are two cases.
+ // cases1:
+ // if the consumer group is created so recently that the earliest message being subscribed has yet
+ // expired, which means the consumer group represents a lately launched business, consuming will
+ // start from the very beginning.
+ // case2:
+ // if the earliest message being subscribed has expired, consuming will start from the latest messages,
+ // meaning messages born prior to the booting timestamp would be ignored.
+ // - CONSUME_FROM_FIRST_OFFSET: Consumer client will start from earliest messages available.
+ // - CONSUME_FROM_TIMESTAMP: Consumer client will start from specified timestamp, which means messages born
+ // prior to {@link #consumeTimestamp} will be ignored
+ FromWhere string `mapstructure:"fromWhere"`
+
+ /**
+ * Backtracking consumption time with second precision. Time format is
+ * 20131223171201
+ * Implying Seventeen twelve and 01 seconds on December 23, 2013 year
+ * Default backtracking consumption time Half an hour ago.
+ *
+ * RocketMQ Go Client does not support configuration in github.com/apache/rocketmq-client-go/v2 v2.1.1-rc2
+ */
+ ConsumeTimestamp string `mapstructure:"consumeTimestamp"`
+
+ // Whether it is an ordered message using FIFO order
+ //
+ // This field defaults to false.
+ ConsumeOrderly string `mapstructure:"consumeOrderly"`
+
+ // Batch consumption size
+ ConsumeMessageBatchMaxSize int `mapstructure:"consumeMessageBatchMaxSize"`
+
+ // Concurrently max span offset.it has no effect on sequential consumption
+ ConsumeConcurrentlyMaxSpan int `mapstructure:"consumeConcurrentlyMaxSpan"`
+
+ // Max re-consume times. -1 means 16 times.
+ //
+ // If messages are re-consumed more than {@link #maxReconsumeTimes} before Success, it's be directed to a deletion
+ // queue waiting.
+ MaxReconsumeTimes int32 `mapstructure:"maxReconsumeTimes"`
+ AutoCommit string `mapstructure:"autoCommit"`
+
+ // Maximum amount of time a message may block the consuming thread.
+ //
+ // RocketMQ Go Client does not support configuration in github.com/apache/rocketmq-client-go/v2 v2.1.1-rc2
+ ConsumeTimeout int `mapstructure:"consumeTimeout"`
+
+ // The socket timeout in milliseconds
+ ConsumerPullTimeout int `mapstructure:"consumerPullTimeout"`
+
+ // Message pull Interval
+ PullInterval int `mapstructure:"pullInterval"`
+
+ // Deprecated: The number of messages pulled from the broker at a time
+ ConsumerBatchSize int `mapstructure:"consumerBatchSize"`
+ // The number of messages pulled from the broker at a time
+ PullBatchSize int32 `mapstructure:"pullBatchSize"`
+
+ // Flow control threshold on queue level, each message queue will cache at most 1000 messages by default,
+ // Consider the {PullBatchSize}, the instantaneous value may exceed the limit
+ //
+ // RocketMQ Go Client does not support configuration in github.com/apache/rocketmq-client-go/v2 v2.1.1-rc2
+ PullThresholdForQueue int64 `mapstructure:"pullThresholdForQueue"`
+
+ // Flow control threshold on topic level, default value is -1(Unlimited)
+ //
+ // The value of {@code pullThresholdForQueue} will be overwritten and calculated based on
+ // {@code pullThresholdForTopic} if it isn't unlimited
+ //
+ // For example, if the value of pullThresholdForTopic is 1000 and 10 message queues are assigned to this consumer,
+ // then pullThresholdForQueue will be set to 100
+ //
+ // RocketMQ Go Client does not support configuration in github.com/apache/rocketmq-client-go/v2 v2.1.1-rc2
+ PullThresholdForTopic int64 `mapstructure:"pullThresholdForTopic"`
+
+ // RocketMQ Go Client does not support configuration in github.com/apache/rocketmq-client-go/v2 v2.1.1-rc2
+ PullThresholdSizeForQueue int `mapstructure:"pullThresholdSizeForQueue"`
+
+ // Limit the cached message size on topic level, default value is -1 MiB(Unlimited)
+ //
+ // The value of {@code pullThresholdSizeForQueue} will be overwritten and calculated based on
+ // {@code pullThresholdSizeForTopic} if it isn't unlimited
+ //
+ // For example, if the value of pullThresholdSizeForTopic is 1000 MiB and 10 message queues are
+ // assigned to this consumer, then pullThresholdSizeForQueue will be set to 100 MiB
+ //
+ // RocketMQ Go Client does not support configuration in github.com/apache/rocketmq-client-go/v2 v2.1.1-rc2
+ PullThresholdSizeForTopic int `mapstructure:"pullThresholdSizeForTopic"`
+ ContentType string `mapstructure:"content-type"` // msg's content-type
// Deprecated: send msg timeout to connect rocketmq's broker, nanoseconds
SendTimeOut int `mapstructure:"sendTimeOut"`
- // send msg timeout to connect rocketmq's broker, seconds
- SendTimeOutSec int `mapstructure:"sendTimeOutSec"`
-}
+ // timeout for send msg to rocketmq broker, in seconds
+ SendTimeOutSec int `mapstructure:"sendTimeOutSec"`
+ LogLevel string `mapstructure:"logLevel"`
-func getDefaultRocketMQMetaData() *rocketMQMetaData {
- return &rocketMQMetaData{
- AccessKey: "",
- SecretKey: "",
- NameServer: "",
- GroupName: "",
- ProducerGroup: "",
- NameSpace: "",
- ConsumerGroup: "",
- ConsumerBatchSize: 0,
- NameServerDomain: "",
- ContentType: pubsub.DefaultCloudEventDataContentType,
- Retries: 3,
- SendTimeOutSec: 60,
- }
+ // The RocketMQ message properties in this collection are passed to the APP in Data
+ // Separate multiple properties with ","
+ MsgProperties string `mapstructure:"mspProperties"`
}
func (s *rocketMQMetaData) Decode(in interface{}) error {
@@ -85,8 +188,18 @@ func (s *rocketMQMetaData) Decode(in interface{}) error {
return nil
}
-func parseRocketMQMetaData(metadata pubsub.Metadata, logger logger.Logger) (*rocketMQMetaData, error) {
- rMetaData := getDefaultRocketMQMetaData()
+const (
+ KeyConsumeFromWhere string = "consumeFromWhere"
+ KeyQueueSelector string = "queueSelector"
+)
+
+func parseRocketMQMetaData(metadata pubsub.Metadata) (*rocketMQMetaData, error) {
+ rMetaData := &rocketMQMetaData{
+ Retries: 3,
+ LogLevel: "warn",
+ PullInterval: 100,
+ ConsumerPullTimeout: 30,
+ }
if metadata.Properties != nil {
err := rMetaData.Decode(metadata.Properties)
if err != nil {
@@ -94,19 +207,16 @@ func parseRocketMQMetaData(metadata pubsub.Metadata, logger logger.Logger) (*roc
}
}
- if rMetaData.GroupName != "" {
- logger.Warn("pubsub.rocketmq: metadata property 'groupName' has been deprecated - use 'producerGroup' instead. See: https://docs.dapr.io/reference/components-reference/supported-pubsub/setup-rocketmq/")
- }
-
if rMetaData.ProducerGroup == "" {
rMetaData.ProducerGroup = metadata.Properties[pubsub.RuntimeConsumerIDKey]
}
- if rMetaData.SendTimeOut != 0 {
- logger.Warn("pubsub.rocketmq: metadata property 'sendTimeOut' has been deprecated - use 'sendTimeOutSec' instead. See: https://docs.dapr.io/reference/components-reference/supported-pubsub/setup-rocketmq/")
- if rMetaData.SendTimeOutSec == 0 {
- rMetaData.SendTimeOutSec = rMetaData.SendTimeOut / 1000000
- }
+ if rMetaData.FromWhere == "" {
+ rMetaData.FromWhere = metadata.Properties[KeyConsumeFromWhere]
+ }
+
+ if rMetaData.ProducerQueueSelector == "" {
+ rMetaData.ProducerQueueSelector = QueueSelectorType(metadata.Properties[KeyQueueSelector])
}
return rMetaData, nil
diff --git a/pubsub/rocketmq/metadata_test.go b/pubsub/rocketmq/metadata_test.go
index e303d1774..587222b8d 100644
--- a/pubsub/rocketmq/metadata_test.go
+++ b/pubsub/rocketmq/metadata_test.go
@@ -21,21 +21,76 @@ import (
mdata "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/pubsub"
- "github.com/dapr/kit/logger"
)
func TestMetaDataDecode(t *testing.T) {
props := map[string]string{
- "accessKey": "**",
- "secretKey": "***",
- "nameServer": "http://test.nameserver",
- "consumerGroup": "defaultGroup",
- "nameSpace": "defaultNamespace",
+ "instanceName": "dapr-rocketmq-test",
+ "producerGroup": "dapr-rocketmq-test-g-p",
+ "consumerGroup": "dapr-rocketmq-test-g-c",
+ "groupName": "dapr-rocketmq-test-g-c",
+ "nameSpace": "dapr-test",
+ "nameServerDomain": "www.baidu.com",
+ "nameServer": "test.nameserver",
+ "accessKey": "accessKey",
+ "secretKey": "secretKey",
+ "securityToken": "securityToken",
+ "retries": "5",
+ "consumerModel": "Clustering",
+ "fromWhere": "ConsumeFromLastOffset",
+ "consumeTimestamp": "20220817101902",
+ "consumeOrderly": "true",
+ "consumeMessageBatchMaxSize": "10",
+ "consumeConcurrentlyMaxSpan": "10",
+ "maxReconsumeTimes": "10000",
+ "autoCommit": "true",
+ "consumeTimeout": "10",
+ "consumerPullTimeout": "10",
+ "pullInterval": "10",
+ "consumerBatchSize": "10",
+ "pullBatchSize": "10",
+ "pullThresholdForQueue": "100",
+ "pullThresholdForTopic": "100",
+ "pullThresholdSizeForQueue": "10",
+ "pullThresholdSizeForTopic": "10",
+ "content-type": "json",
+ "sendTimeOutSec": "10",
+ "logLevel": "ERROR",
+ "mspProperties": "UNIQ_KEY",
}
pubsubMeta := pubsub.Metadata{Base: mdata.Base{Properties: props}}
- metaData, err := parseRocketMQMetaData(pubsubMeta, logger.NewLogger("test"))
+ metaData, err := parseRocketMQMetaData(pubsubMeta)
require.NoError(t, err)
- assert.Equal(t, "**", metaData.AccessKey)
- assert.Equal(t, "***", metaData.SecretKey)
- assert.Equal(t, "defaultGroup", metaData.ConsumerGroup)
+ assert.Equal(t, "dapr-rocketmq-test", metaData.InstanceName)
+ assert.Equal(t, "dapr-rocketmq-test-g-p", metaData.ProducerGroup)
+ assert.Equal(t, "dapr-rocketmq-test-g-c", metaData.ConsumerGroup)
+ assert.Equal(t, "dapr-rocketmq-test-g-c", metaData.GroupName)
+ assert.Equal(t, "dapr-test", metaData.NameSpace)
+ assert.Equal(t, "www.baidu.com", metaData.NameServerDomain)
+ assert.Equal(t, "test.nameserver", metaData.NameServer)
+ assert.Equal(t, "accessKey", metaData.AccessKey)
+ assert.Equal(t, "secretKey", metaData.SecretKey)
+ assert.Equal(t, "securityToken", metaData.SecurityToken)
+ assert.Equal(t, 5, metaData.Retries)
+ assert.Equal(t, "Clustering", metaData.ConsumerModel)
+ assert.Equal(t, "ConsumeFromLastOffset", metaData.FromWhere)
+ assert.Equal(t, "20220817101902", metaData.ConsumeTimestamp)
+ assert.Equal(t, "true", metaData.ConsumeOrderly)
+ assert.Equal(t, 10, metaData.ConsumeMessageBatchMaxSize)
+ assert.Equal(t, 10, metaData.ConsumeConcurrentlyMaxSpan)
+ assert.Equal(t, int32(10000), metaData.MaxReconsumeTimes)
+ assert.Equal(t, "true", metaData.AutoCommit)
+ assert.Equal(t, 10, metaData.ConsumeTimeout)
+ assert.Equal(t, 10, metaData.ConsumerPullTimeout)
+ assert.Equal(t, 10, metaData.PullInterval)
+ assert.Equal(t, int32(10), metaData.PullBatchSize)
+ assert.Equal(t, int(10), metaData.ConsumerBatchSize)
+ assert.Equal(t, int64(100), metaData.PullThresholdForQueue)
+ assert.Equal(t, int64(100), metaData.PullThresholdForTopic)
+ assert.Equal(t, 10, metaData.PullThresholdSizeForQueue)
+ assert.Equal(t, 10, metaData.PullThresholdSizeForTopic)
+ assert.Equal(t, "json", metaData.ContentType)
+ assert.Equal(t, 10, metaData.SendTimeOutSec)
+ assert.Equal(t, "ERROR", metaData.LogLevel)
+ assert.Equal(t, "UNIQ_KEY", metaData.MsgProperties)
}
diff --git a/pubsub/rocketmq/rocketmq.go b/pubsub/rocketmq/rocketmq.go
index cec794562..d0b82d854 100644
--- a/pubsub/rocketmq/rocketmq.go
+++ b/pubsub/rocketmq/rocketmq.go
@@ -16,7 +16,10 @@ package rocketmq
import (
"context"
"encoding/json"
+ "errors"
"fmt"
+ "strconv"
+ "strings"
"sync"
"time"
@@ -24,112 +27,252 @@ import (
mqc "github.com/apache/rocketmq-client-go/v2/consumer"
"github.com/apache/rocketmq-client-go/v2/primitive"
mqp "github.com/apache/rocketmq-client-go/v2/producer"
- "github.com/cenkalti/backoff/v4"
+ "github.com/apache/rocketmq-client-go/v2/rlog"
+ "github.com/dapr/components-contrib/internal/utils"
"github.com/dapr/components-contrib/pubsub"
"github.com/dapr/kit/logger"
- "github.com/dapr/kit/retry"
)
-type topicData struct {
- selector mqc.MessageSelector
- handler pubsub.Handler
- consumerGroup string
- mqType string
- mqExpr string
+type daprQueueSelector struct {
+ hashQueueSelector mqp.QueueSelector
+ roundRobinQueueSelector mqp.QueueSelector
+}
+
+func NewDaprQueueSelector() *daprQueueSelector {
+ return &daprQueueSelector{
+ hashQueueSelector: mqp.NewHashQueueSelector(),
+ roundRobinQueueSelector: mqp.NewRoundRobinQueueSelector(),
+ }
+}
+
+func (p *daprQueueSelector) Select(msg *primitive.Message, queues []*primitive.MessageQueue) *primitive.MessageQueue {
+ if msg.Queue != nil {
+ return msg.Queue
+ }
+ if queue := msg.GetProperty(metadataRocketmqQueue); queue != "" {
+ for _, q := range queues {
+ if strconv.Itoa(q.QueueId) == queue {
+ return q
+ }
+ }
+ }
+ key := msg.GetShardingKey()
+ if len(key) == 0 {
+ return p.roundRobinQueueSelector.Select(msg, queues)
+ }
+ return p.hashQueueSelector.Select(msg, queues)
}
type rocketMQ struct {
- name string
- metadata *rocketMQMetaData
-
- logger logger.Logger
- topics map[string]topicData
- producer mq.Producer
- producerLock sync.RWMutex
- consumer mq.PushConsumer
- consumerLock sync.RWMutex
-
- ctx context.Context
- cancel context.CancelFunc
+ name string
+ metadata *rocketMQMetaData
+ producer mq.Producer
+ producerLock sync.Mutex
+ consumer mq.PushConsumer
+ consumerLock sync.Mutex
+ topics map[string]mqc.MessageSelector
+ msgProperties map[string]bool
+ logger logger.Logger
+ ctx context.Context
+ cancel context.CancelFunc
}
func NewRocketMQ(l logger.Logger) pubsub.PubSub {
return &rocketMQ{
name: "rocketmq",
logger: l,
- topics: make(map[string]topicData),
- producerLock: sync.RWMutex{},
- consumerLock: sync.RWMutex{},
+ producerLock: sync.Mutex{},
+ consumerLock: sync.Mutex{},
}
}
func (r *rocketMQ) Init(metadata pubsub.Metadata) error {
var err error
- r.metadata, err = parseRocketMQMetaData(metadata, r.logger)
+ r.metadata, err = parseRocketMQMetaData(metadata)
if err != nil {
return err
}
+ r.topics = make(map[string]mqc.MessageSelector)
+ r.msgProperties = make(map[string]bool)
+ rlog.SetLogLevel(r.metadata.LogLevel)
+ if r.metadata.MsgProperties != "" {
+ mps := strings.Split(r.metadata.MsgProperties, ",")
+ for _, mp := range mps {
+ r.msgProperties[mp] = true
+ }
+ }
r.ctx, r.cancel = context.WithCancel(context.Background())
return nil
}
+func parseNameServer(nameServer string) []string {
+ if strings.Contains(nameServer, ",") {
+ return strings.Split(nameServer, ",")
+ } else if strings.Contains(nameServer, ";") {
+ return strings.Split(nameServer, ";")
+ } else {
+ return []string{nameServer}
+ }
+}
+
func (r *rocketMQ) setUpConsumer() (mq.PushConsumer, error) {
opts := make([]mqc.Option, 0)
+ if r.metadata.InstanceName != "" {
+ opts = append(opts, mqc.WithInstance(r.metadata.InstanceName))
+ }
if r.metadata.ConsumerGroup != "" {
opts = append(opts, mqc.WithGroupName(r.metadata.ConsumerGroup))
+ } else if r.metadata.GroupName != "" {
+ r.metadata.ConsumerGroup = r.metadata.GroupName
+ opts = append(opts, mqc.WithGroupName(r.metadata.ConsumerGroup))
+ r.logger.Warnf("set the consumer group name, please use the keyword consumerGroup")
}
- if r.metadata.ConsumerBatchSize != 0 {
- opts = append(opts, mqc.WithPullBatchSize(int32(r.metadata.ConsumerBatchSize)))
+ if r.metadata.NameServer != "" {
+ opts = append(opts, mqc.WithNameServer(parseNameServer(r.metadata.NameServer)))
}
if r.metadata.NameSpace != "" {
opts = append(opts, mqc.WithNamespace(r.metadata.NameSpace))
}
- if r.metadata.Retries != 0 {
- opts = append(opts, mqc.WithRetry(r.metadata.Retries))
- }
if r.metadata.NameServerDomain != "" {
opts = append(opts, mqc.WithNameServerDomain(r.metadata.NameServerDomain))
}
- if r.metadata.NameServer != "" {
- opts = append(opts, mqc.WithNameServer(primitive.NamesrvAddr{r.metadata.NameServer}))
- }
if r.metadata.AccessKey != "" && r.metadata.SecretKey != "" {
opts = append(opts, mqc.WithCredentials(primitive.Credentials{
- AccessKey: r.metadata.AccessKey,
- SecretKey: r.metadata.SecretKey,
+ AccessKey: r.metadata.AccessKey,
+ SecretKey: r.metadata.SecretKey,
+ SecurityToken: r.metadata.SecurityToken,
}))
}
- return mq.NewPushConsumer(opts...)
+ if r.metadata.Retries > 0 {
+ opts = append(opts, mqc.WithRetry(r.metadata.Retries))
+ }
+ if r.metadata.ConsumerModel != "" {
+ switch strings.ToLower(r.metadata.ConsumerModel) {
+ case "broadcasting":
+ opts = append(opts, mqc.WithConsumerModel(mqc.BroadCasting))
+ case "clustering":
+ opts = append(opts, mqc.WithConsumerModel(mqc.Clustering))
+ default:
+ r.metadata.ConsumerModel = "Clustering"
+ opts = append(opts, mqc.WithConsumerModel(mqc.Clustering))
+ r.logger.Warnf("%s Consumer Model[%s] is invalid: expected [broadcasting, clustering]; "+
+ "we will use default model [clustering]", r.name, r.metadata.ConsumerModel)
+ }
+ }
+ if r.metadata.FromWhere != "" {
+ switch strings.ToLower(r.metadata.FromWhere) {
+ case "consumefromlastoffset":
+ opts = append(opts, mqc.WithConsumeFromWhere(mqc.ConsumeFromLastOffset))
+ case "consumefromfirstoffset":
+ opts = append(opts, mqc.WithConsumeFromWhere(mqc.ConsumeFromFirstOffset))
+ case "consumefromtimestamp":
+ opts = append(opts, mqc.WithConsumeFromWhere(mqc.ConsumeFromTimestamp))
+ default:
+ r.metadata.FromWhere = "ConsumeFromLastOffset"
+ opts = append(opts, mqc.WithConsumeFromWhere(mqc.ConsumeFromLastOffset))
+ r.logger.Warnf("%s Consumer FromWhere[%s] is error, "+
+ "expected [ConsumeFromLastOffset, ConsumeFromFirstOffset, ConsumeFromTimestamp], "+
+ "we will use default value [ConsumeFromLastOffset]", r.name, r.metadata.FromWhere)
+ }
+ }
+ if r.metadata.ConsumeOrderly != "" {
+ if utils.IsTruthy(r.metadata.ConsumeOrderly) {
+ opts = append(opts, mqc.WithConsumerOrder(true))
+ // in orderly message mode, if no value is set of MessageBatchMaxSize, the recommended value [1] is used
+ if r.metadata.ConsumeMessageBatchMaxSize <= 0 {
+ r.metadata.ConsumeMessageBatchMaxSize = 1
+ }
+ } else {
+ opts = append(opts, mqc.WithConsumerOrder(false))
+ }
+ }
+ if r.metadata.ConsumeMessageBatchMaxSize > 0 {
+ opts = append(opts, mqc.WithConsumeMessageBatchMaxSize(r.metadata.ConsumeMessageBatchMaxSize))
+ }
+ if r.metadata.MaxReconsumeTimes > 0 {
+ opts = append(opts, mqc.WithMaxReconsumeTimes(r.metadata.MaxReconsumeTimes))
+ }
+ if r.metadata.AutoCommit != "" {
+ opts = append(opts, mqc.WithAutoCommit(utils.IsTruthy(r.metadata.AutoCommit)))
+ }
+ if r.metadata.PullInterval > 0 {
+ opts = append(opts, mqc.WithPullInterval(time.Duration(r.metadata.PullInterval)*time.Millisecond))
+ }
+ if r.metadata.PullBatchSize > 0 {
+ opts = append(opts, mqc.WithPullBatchSize(r.metadata.PullBatchSize))
+ } else if r.metadata.ConsumerBatchSize > 0 {
+ r.metadata.PullBatchSize = int32(r.metadata.ConsumerBatchSize)
+ opts = append(opts, mqc.WithPullBatchSize(r.metadata.PullBatchSize))
+ r.logger.Warn("set the number of msg pulled from the broker at a time, " +
+ "please use pullBatchSize instead of consumerBatchSize")
+ }
+ c, e := mqc.NewPushConsumer(opts...)
+ if e != nil {
+ return nil, e
+ }
+ return c, e
}
func (r *rocketMQ) setUpProducer() (mq.Producer, error) {
opts := make([]mqp.Option, 0)
- if r.metadata.Retries != 0 {
- opts = append(opts, mqp.WithRetry(r.metadata.Retries))
- }
- if r.metadata.GroupName != "" {
- opts = append(opts, mqp.WithGroupName(r.metadata.GroupName))
+ if r.metadata.InstanceName != "" {
+ opts = append(opts, mqp.WithInstanceName(r.metadata.InstanceName))
}
if r.metadata.ProducerGroup != "" {
opts = append(opts, mqp.WithGroupName(r.metadata.ProducerGroup))
+ } else if r.metadata.GroupName != "" {
+ r.metadata.ProducerGroup = r.metadata.GroupName
+ opts = append(opts, mqp.WithGroupName(r.metadata.ProducerGroup))
+ r.logger.Warnf("set the producer group name, please use the keyword producerGroup")
}
- if r.metadata.NameServerDomain != "" {
- opts = append(opts, mqp.WithNameServerDomain(r.metadata.NameServerDomain))
+ if r.metadata.NameServer != "" {
+ opts = append(opts, mqp.WithNameServer(parseNameServer(r.metadata.NameServer)))
}
if r.metadata.NameSpace != "" {
opts = append(opts, mqp.WithNamespace(r.metadata.NameSpace))
}
- if r.metadata.NameServer != "" {
- opts = append(opts, mqp.WithNameServer(primitive.NamesrvAddr{r.metadata.NameServer}))
+ if r.metadata.NameServerDomain != "" {
+ opts = append(opts, mqp.WithNameServerDomain(r.metadata.NameServerDomain))
}
if r.metadata.AccessKey != "" && r.metadata.SecretKey != "" {
opts = append(opts, mqp.WithCredentials(primitive.Credentials{
- AccessKey: r.metadata.AccessKey,
- SecretKey: r.metadata.SecretKey,
+ AccessKey: r.metadata.AccessKey,
+ SecretKey: r.metadata.SecretKey,
+ SecurityToken: r.metadata.SecurityToken,
}))
}
+ if r.metadata.Retries > 0 {
+ opts = append(opts, mqp.WithRetry(r.metadata.Retries))
+ }
+ if r.metadata.SendTimeOutSec > 0 {
+ opts = append(opts, mqp.WithSendMsgTimeout(time.Duration(r.metadata.SendTimeOutSec)*time.Second))
+ } else if r.metadata.SendTimeOut > 0 {
+ r.metadata.SendTimeOutSec = r.metadata.SendTimeOut / int(time.Second.Nanoseconds())
+ opts = append(opts, mqp.WithSendMsgTimeout(time.Duration(r.metadata.SendTimeOutSec)*time.Second))
+ r.logger.Warn("set the timeout for send msg to rocketmq broker, please use the keyword sendTimeOutSec. " +
+ "SendTimeOutSec is in seconds, SendTimeOut is in nanoseconds")
+ } else {
+ opts = append(opts, mqp.WithSendMsgTimeout(30*time.Second))
+ r.logger.Warn("You have not set a timeout for send msg to rocketmq broker, " +
+ "The default value of 30 seconds will be used. ")
+ }
+ switch r.metadata.ProducerQueueSelector {
+ case HashQueueSelector:
+ opts = append(opts, mqp.WithQueueSelector(mqp.NewHashQueueSelector()))
+ case RandomQueueSelector:
+ opts = append(opts, mqp.WithQueueSelector(mqp.NewRandomQueueSelector()))
+ case RoundRobinQueueSelector:
+ opts = append(opts, mqp.WithQueueSelector(mqp.NewRoundRobinQueueSelector()))
+ case ManualQueueSelector:
+ opts = append(opts, mqp.WithQueueSelector(mqp.NewManualQueueSelector()))
+ case DaprQueueSelector:
+ opts = append(opts, mqp.WithQueueSelector(NewDaprQueueSelector()))
+ default:
+ opts = append(opts, mqp.WithQueueSelector(NewDaprQueueSelector()))
+ }
+
producer, err := mq.NewProducer(opts...)
if err != nil {
return nil, err
@@ -146,208 +289,198 @@ func (r *rocketMQ) Features() []pubsub.Feature {
return nil
}
+func (r *rocketMQ) getProducer() (mq.Producer, error) {
+ if nil != r.producer {
+ return r.producer, nil
+ }
+ r.producerLock.Lock()
+ defer r.producerLock.Unlock()
+ if nil != r.producer {
+ return r.producer, nil
+ }
+ producer, e := r.setUpProducer()
+ if e != nil {
+ return nil, e
+ }
+ r.producer = producer
+ return r.producer, nil
+}
+
+func (r *rocketMQ) resetProducer() {
+ r.producerLock.Lock()
+ defer r.producerLock.Unlock()
+ r.producer = nil
+}
+
func (r *rocketMQ) Publish(req *pubsub.PublishRequest) error {
r.logger.Debugf("rocketmq publish topic:%s with data:%v", req.Topic, req.Data)
- msg := newRocketMQMessage(req)
-
- publishBo := backoff.NewExponentialBackOff()
- publishBo.InitialInterval = 100 * time.Millisecond
- bo := backoff.WithMaxRetries(publishBo, 3)
- bo = backoff.WithContext(bo, r.ctx)
- return retry.NotifyRecover(
- func() (err error) {
- r.producerLock.RLock()
- producer := r.producer
- r.producerLock.RUnlock()
-
- if producer == nil {
- r.producerLock.Lock()
- r.producer, err = r.setUpProducer()
- if err != nil {
- r.producer = nil
- }
- producer = r.producer
- r.producerLock.Unlock()
- if err != nil {
- return err
- }
- }
-
- sendTimeOut := time.Duration(r.metadata.SendTimeOutSec) * time.Second
- ctx, cancel := context.WithTimeout(r.ctx, sendTimeOut)
- defer cancel()
- result, err := producer.SendSync(ctx, msg)
- if err != nil {
- r.producerLock.Lock()
- r.producer = nil
- r.producerLock.Unlock()
- r.logger.Errorf("error send message topic:%s : %v", req.Topic, err)
- return ErrRocketmqPublishMsg
- }
- r.logger.Debugf("rocketmq send result topic:%s tag:%s status:%v", req.Topic, msg.GetTags(), result.Status)
- return nil
- },
- bo,
- func(err error, d time.Duration) {
- r.logger.Errorf("rocketmq error: fail to send message. topic:%s. Retrying...", msg.Topic)
- },
- func() {
- r.logger.Infof("rocketmq successfully sent message after it previously failed. topic:%s.", msg.Topic)
- },
- )
-}
-
-func newRocketMQMessage(req *pubsub.PublishRequest) *primitive.Message {
- return primitive.NewMessage(req.Topic, req.Data).
- WithTag(req.Metadata[metadataRocketmqTag]).
- WithKeys([]string{req.Metadata[metadataRocketmqKey]}).
- WithShardingKey(req.Metadata[metadataRocketmqShardingKey])
-}
-
-type mqSubscribeCallback func(ctx context.Context, msgs ...*primitive.MessageExt) (mqc.ConsumeResult, error)
-
-func (r *rocketMQ) adaptCallback(topic, consumerGroup, mqType, mqExpr string, handler pubsub.Handler) mqSubscribeCallback {
- return func(ctx context.Context, msgs ...*primitive.MessageExt) (mqc.ConsumeResult, error) {
- success := true
- for _, msg := range msgs {
- cloudEventsMap := pubsub.NewCloudEventsEnvelope(msg.MsgId, msg.StoreHost, r.name, msg.GetProperty(primitive.PropertyKeys), msg.Topic, r.name, r.metadata.ContentType, msg.Body, "", "")
- dataBytes, err := json.Marshal(cloudEventsMap)
- if err != nil {
- r.logger.Warn("rocketmq fail to marshal cloudEventsMap message, topic:%s cloudEventsMap-length:%d err:%newMessage ", msg.Topic, len(msg.Body), err)
- success = false
- continue
- }
- metadata := map[string]string{
- metadataRocketmqType: mqType,
- metadataRocketmqExpression: mqExpr,
- metadataRocketmqConsumerGroup: consumerGroup,
- }
- if msg.Queue != nil {
- metadata[metadataRocketmqBrokerName] = msg.Queue.BrokerName
- }
- newMessage := &pubsub.NewMessage{
- Topic: topic,
- Data: dataBytes,
- Metadata: metadata,
- }
- err = handler(ctx, newMessage)
- if err != nil {
- r.logger.Errorf("rocketmq error: fail to process message. topic:%s cloudEventsMap-length:%d err:%v.", newMessage.Topic, len(msg.Body), err)
- success = false
- }
+ msg := primitive.NewMessage(req.Topic, req.Data)
+ for k, v := range req.Metadata {
+ switch strings.ToLower(k) {
+ case metadataRocketmqTag:
+ msg.WithTag(v)
+ case metadataRocketmqKey:
+ msg.WithKeys(strings.Split(v, ","))
+ case metadataRocketmqShardingKey:
+ msg.WithShardingKey(v)
+ default:
+ msg.WithProperty(k, v)
}
- if !success {
- return mqc.ConsumeRetryLater, nil
- }
- return mqc.ConsumeSuccess, nil
}
+ producer, e := r.getProducer()
+ if e != nil {
+ return fmt.Errorf("rocketmq message send fail because producer failed to initialize: %v", e)
+ }
+ result, e := producer.SendSync(r.ctx, msg)
+ if e != nil {
+ r.resetProducer()
+ m := fmt.Sprintf("rocketmq message send fail, topic[%s]: %v", req.Topic, e)
+ r.logger.Error(m)
+ return errors.New(m)
+ }
+ r.logger.Debugf("rocketmq message send result: topic[%s], tag[%s], status[%v]", req.Topic, msg.GetTags(), result.Status)
+ return nil
}
func (r *rocketMQ) Subscribe(ctx context.Context, req pubsub.SubscribeRequest, handler pubsub.Handler) error {
- if req.Metadata == nil {
- req.Metadata = make(map[string]string)
+ selector, e := buildMessageSelector(req)
+ if e != nil {
+ r.logger.Warnf("rocketmq subscribe failed: %v", e)
+ return e
}
- var (
- mqExpr = req.Metadata[metadataRocketmqExpression]
- mqType = req.Metadata[metadataRocketmqType]
- )
- if !r.validMqTypeParams(mqType) {
- return ErrRocketmqValidPublishMsgTyp
- }
- consumerGroup := r.metadata.ConsumerGroup
- if group, ok := req.Metadata[metadataRocketmqConsumerGroup]; ok {
- consumerGroup = group
+
+ var cb func(ctx context.Context, msgs ...*primitive.MessageExt) (mqc.ConsumeResult, error)
+ if utils.IsTruthy(r.metadata.ConsumeOrderly) {
+ cb = r.consumeMessageOrderly(req.Topic, selector, handler)
+ } else {
+ cb = r.consumeMessageConcurrently(req.Topic, selector, handler)
}
r.consumerLock.Lock()
defer r.consumerLock.Unlock()
- // Start the subscription
- // When the connection is ready, add the topic
- // Use the global context here to maintain the connection
- r.startSubscription(ctx, func() {
- r.topics[req.Topic] = topicData{
- handler: handler,
- selector: mqc.MessageSelector{
- Type: mqc.ExpressionType(mqType),
- Expression: mqExpr,
- },
- consumerGroup: consumerGroup,
- mqExpr: mqExpr,
- mqType: mqType,
+ r.topics[req.Topic] = *selector
+
+ if nil == r.consumer {
+ // if consumer is not initialized, initialize it
+ if r.consumer, e = r.setUpConsumer(); e != nil {
+ return fmt.Errorf("consumer setup failed: %v", e)
}
- })
+ // consumer will start after one second.
+ // Consumers who complete the subscription within 1 second, will begin the subscription immediately upon launch.
+ // Consumers who do not complete the subscription within 1 second, will start the subscription after 20 seconds.
+ // The 20-second time is the interval for RocketMQ to refresh the topic route.
+ go func() {
+ time.Sleep(time.Second)
+ if e = r.consumer.Start(); e == nil {
+ r.logger.Infof("consumer start success: Group[%s], Topics[%v]", r.metadata.ConsumerGroup, r.topics)
+ } else {
+ r.logger.Errorf("consumer start failed: %v", e)
+ }
+ }()
+ }
- // Listen for context cancelation to remove the subscription
- go func() {
- select {
- case <-ctx.Done():
- case <-r.ctx.Done():
- }
-
- r.consumerLock.Lock()
- defer r.consumerLock.Unlock()
-
- // If this is the last subscription or if the global context is done, close the connection entirely
- if len(r.topics) <= 1 || r.ctx.Err() != nil {
- _ = r.consumer.Shutdown()
- r.consumer = nil
- delete(r.topics, req.Topic)
- return
- }
-
- // Reconnect with one less topic
- r.startSubscription(r.ctx, func() {
- delete(r.topics, req.Topic)
- })
- }()
+ // subscribe topic
+ if e = r.consumer.Subscribe(req.Topic, *selector, cb); e != nil {
+ r.logger.Errorf("subscribe topic[%s] Group[%s] failed, error: %v", req.Topic, r.metadata.ConsumerGroup, e)
+ return e
+ }
+ r.logger.Infof("subscribe topic[%s] success, Group[%s], Topics[%v]", req.Topic, r.metadata.ConsumerGroup, r.topics)
return nil
}
-// Should be wrapped around r.consumerLock lock
-func (r *rocketMQ) startSubscription(ctx context.Context, onConnRready func()) (err error) {
- // reset synchronization
- if r.consumer != nil {
- r.logger.Infof("re-initializing the consumer")
- _ = r.consumer.Shutdown()
- r.consumer = nil
- } else {
- r.logger.Infof("initializing the consumer")
+func buildMessageSelector(req pubsub.SubscribeRequest) (*mqc.MessageSelector, error) {
+ if req.Metadata == nil {
+ req.Metadata = make(map[string]string)
+ }
+ mqExpr := req.Metadata[metadataRocketmqExpression]
+ mqType := req.Metadata[metadataRocketmqType]
+
+ var ExpressionType mqc.ExpressionType
+ switch strings.ToUpper(mqType) {
+ case "", string(mqc.TAG):
+ ExpressionType = mqc.TAG
+ case string(mqc.SQL92):
+ ExpressionType = mqc.SQL92
+ default:
+ return nil, fmt.Errorf("rocketmq msg type invalid: %s, expected value is 'tag' or 'sql92' or ''", mqType)
}
- r.consumer, err = r.setUpConsumer()
- if err != nil {
- r.consumer = nil
- return err
- }
-
- // Invoke onConnReady so changes to the topics can be made safely
- onConnRready()
-
- for topic, data := range r.topics {
- cb := r.adaptCallback(topic, r.metadata.ConsumerGroup, string(data.selector.Type), data.selector.Expression, data.handler)
- err = r.consumer.Subscribe(topic, data.selector, cb)
- if err != nil {
- r.logger.Errorf("subscribe topic:%v failed,error:%v", topic, err)
- continue
- }
- }
-
- err = r.consumer.Start()
- if err != nil {
- return fmt.Errorf("consumer start failed. %w", err)
- }
-
- return nil
+ return &mqc.MessageSelector{
+ Type: ExpressionType,
+ Expression: mqExpr,
+ }, nil
}
-func (r *rocketMQ) validMqTypeParams(mqType string) bool {
- if len(mqType) != 0 && (mqType != string(mqc.SQL92) && mqType != string(mqc.TAG)) {
- r.logger.Warnf("rocketmq subscribe failed because some illegal type(%s).", mqType)
- return false
+func (r *rocketMQ) buildPubsubMessage(topic, mqType, mqExpr string, msg *primitive.MessageExt) (*pubsub.NewMessage, error) {
+ cloudEventsMap := pubsub.NewCloudEventsEnvelope(msg.MsgId, msg.StoreHost, "", "", msg.Topic, r.name, r.metadata.ContentType, msg.Body, "", "")
+ cloudEventsMap[primitive.PropertyKeys] = msg.GetKeys()
+ cloudEventsMap[primitive.PropertyShardingKey] = msg.GetShardingKey()
+ cloudEventsMap[primitive.PropertyTags] = msg.GetTags()
+ cloudEventsMap[primitive.PropertyMsgRegion] = msg.GetRegionID()
+ for k, v := range msg.GetProperties() {
+ if _, ok := r.msgProperties[k]; ok {
+ cloudEventsMap[k] = v
+ }
+ if strings.EqualFold(k, pubsub.TraceIDField) {
+ cloudEventsMap[pubsub.TraceIDField] = v
+ }
+ }
+ dataBytes, err := json.Marshal(cloudEventsMap)
+ if err != nil {
+ return nil, err
+ }
+ metadata := map[string]string{
+ metadataRocketmqType: mqType,
+ metadataRocketmqExpression: mqExpr,
+ metadataRocketmqConsumerGroup: r.metadata.ProducerGroup,
+ }
+ if msg.Queue != nil {
+ metadata[metadataRocketmqBrokerName] = msg.Queue.BrokerName
+ metadata[metadataRocketmqQueueID] = strconv.Itoa(msg.Queue.QueueId)
+ }
+ return &pubsub.NewMessage{
+ Topic: topic,
+ Data: dataBytes,
+ Metadata: metadata,
+ }, nil
+}
+
+func (r *rocketMQ) consumeMessageOrderly(topic string, selector *mqc.MessageSelector, handler pubsub.Handler) func(ctx context.Context, msgs ...*primitive.MessageExt) (mqc.ConsumeResult, error) {
+ return func(ctx context.Context, msgs ...*primitive.MessageExt) (mqc.ConsumeResult, error) {
+ for _, msg := range msgs {
+ newMessage, e := r.buildPubsubMessage(topic, string(selector.Type), selector.Expression, msg)
+ if e != nil {
+ r.logger.Errorf("rocketmq message consume fail, topic: %s, msgId: %s, error: %v", newMessage.Topic, msg.MsgId, e)
+ return mqc.SuspendCurrentQueueAMoment, nil
+ }
+ e = handler(ctx, newMessage)
+ if e != nil {
+ r.logger.Errorf("rocketmq message consume fail, topic: %s, msgId: %s, error: %v", newMessage.Topic, msg.MsgId, e)
+ return mqc.SuspendCurrentQueueAMoment, nil
+ }
+ }
+ return mqc.ConsumeSuccess, nil
+ }
+}
+
+func (r *rocketMQ) consumeMessageConcurrently(topic string, selector *mqc.MessageSelector, handler pubsub.Handler) func(ctx context.Context, msgs ...*primitive.MessageExt) (mqc.ConsumeResult, error) {
+ return func(ctx context.Context, msgs ...*primitive.MessageExt) (mqc.ConsumeResult, error) {
+ for _, msg := range msgs {
+ newMessage, e := r.buildPubsubMessage(topic, string(selector.Type), selector.Expression, msg)
+ if e != nil {
+ r.logger.Errorf("rocketmq message consume fail, topic: %s, msgId: %s, error: %v", newMessage.Topic, msg.MsgId, e)
+ return mqc.ConsumeRetryLater, nil
+ }
+ e = handler(ctx, newMessage)
+ if e != nil {
+ r.logger.Errorf("rocketmq message consume fail, topic: %s, msgId: %s, error: %v", newMessage.Topic, msg.MsgId, e)
+ return mqc.ConsumeRetryLater, nil
+ }
+ }
+ return mqc.ConsumeSuccess, nil
}
- return true
}
func (r *rocketMQ) Close() error {
@@ -360,7 +493,7 @@ func (r *rocketMQ) Close() error {
r.producer = nil
- if r.consumer != nil {
+ if nil != r.consumer {
_ = r.consumer.Shutdown()
r.consumer = nil
}
diff --git a/pubsub/rocketmq/rocketmq_test.go b/pubsub/rocketmq/rocketmq_test.go
index 621787eb9..7c9f361ce 100644
--- a/pubsub/rocketmq/rocketmq_test.go
+++ b/pubsub/rocketmq/rocketmq_test.go
@@ -16,6 +16,7 @@ package rocketmq
import (
"context"
"testing"
+ "time"
"github.com/stretchr/testify/assert"
@@ -26,60 +27,196 @@ import (
func getTestMetadata() map[string]string {
return map[string]string{
- "nameServer": "127.0.0.1:9876",
- "consumerGroup": "dapr.rocketmq.producer",
- "accessKey": "RocketMQ",
- "secretKey": "12345",
- "retries": "2",
+ "nameServer": "127.0.0.1:9876",
+ "consumerGroup": "dapr.rocketmq.producer",
+ "accessKey": "RocketMQ",
+ "secretKey": "12345",
+ "consumerBatchSize": "1",
+ "consumerThreadNums": "2",
+ "retries": "2",
+ "sendMsgTimeout": "30",
}
}
func TestParseRocketMQMetadata(t *testing.T) {
- t.Run("correct metadata", func(t *testing.T) {
- meta := getTestMetadata()
- _, err := parseRocketMQMetaData(pubsub.Metadata{Base: mdata.Base{Properties: meta}}, logger.NewLogger("test"))
- assert.Nil(t, err)
- })
-
- t.Run("correct init", func(t *testing.T) {
- meta := getTestMetadata()
- r := NewRocketMQ(logger.NewLogger("test"))
- err := r.Init(pubsub.Metadata{Base: mdata.Base{Properties: meta}})
- assert.Nil(t, err)
- })
-
- t.Run("setup producer missing nameserver", func(t *testing.T) {
- meta := getTestMetadata()
- delete(meta, "nameServer")
- r := NewRocketMQ(logger.NewLogger("test"))
- err := r.Init(pubsub.Metadata{Base: mdata.Base{Properties: meta}})
- assert.Nil(t, err)
- req := &pubsub.PublishRequest{
- Data: []byte("hello"),
- PubsubName: "rocketmq",
- Topic: "test",
- Metadata: map[string]string{},
- }
- err = r.Publish(req)
- assert.NotNil(t, err)
- })
-
- t.Run("subscribe illegal type", func(t *testing.T) {
- meta := getTestMetadata()
- r := NewRocketMQ(logger.NewLogger("test"))
- err := r.Init(pubsub.Metadata{Base: mdata.Base{Properties: meta}})
- assert.Nil(t, err)
-
- req := pubsub.SubscribeRequest{
- Topic: "test",
- Metadata: map[string]string{
- metadataRocketmqType: "incorrect type",
- },
- }
- handler := func(ctx context.Context, msg *pubsub.NewMessage) error {
- return nil
- }
- err = r.Subscribe(context.Background(), req, handler)
- assert.NotNil(t, err)
- })
+ meta := getTestMetadata()
+ _, err := parseRocketMQMetaData(pubsub.Metadata{Base: mdata.Base{Properties: meta}})
+ assert.Nil(t, err)
+}
+
+func TestRocketMQ_Init(t *testing.T) {
+ meta := getTestMetadata()
+ r := NewRocketMQ(logger.NewLogger("test"))
+ err := r.Init(pubsub.Metadata{Base: mdata.Base{Properties: meta}})
+ assert.Nil(t, err)
+}
+
+func TestRocketMQ_Publish_Currently(t *testing.T) {
+ l, r, e := BuildRocketMQ()
+ assert.Nil(t, e)
+
+ req := &pubsub.PublishRequest{
+ Data: []byte("{\"key\": 1, \"value\": \"1\"}"),
+ PubsubName: "rocketmq",
+ Topic: "ZCY_ZHIXING_TEST_test",
+ Metadata: map[string]string{},
+ }
+ e = r.Publish(req)
+ if e != nil {
+ l.Error(e)
+ return
+ }
+ assert.Nil(t, e)
+
+ req = &pubsub.PublishRequest{
+ Data: []byte("{\"key\": 2, \"value\": \"2\"}"),
+ PubsubName: "rocketmq",
+ Topic: "ZCY_ZHIXING_TEST_test",
+ Metadata: map[string]string{
+ "rocketmq-tag": "tag",
+ "rocketmq-key": "2",
+ "rocketmq-shardingkey": "key",
+ "traceId": "4a09073987b148348ae0420435cddf5e",
+ },
+ }
+ e = r.Publish(req)
+ assert.Nil(t, e)
+
+ req = &pubsub.PublishRequest{
+ Data: []byte("{\"key\": 3, \"value\": \"3\"}"),
+ PubsubName: "rocketmq",
+ Topic: "ZCY_ZHIXING_TEST_test",
+ Metadata: map[string]string{
+ "rocketmq-tag": "tag",
+ "rocketmq-key": "3",
+ "rocketmq-shardingkey": "key",
+ },
+ }
+ e = r.Publish(req)
+ assert.Nil(t, e)
+
+ req = &pubsub.PublishRequest{
+ Data: []byte("{\"key\": 4, \"value\": \"4\"}"),
+ PubsubName: "rocketmq",
+ Topic: "ZCY_ZHIXING_TEST_test",
+ Metadata: map[string]string{
+ "rocketmq-tag": "tag",
+ "rocketmq-key": "4",
+ "rocketmq-shardingkey": "key",
+ },
+ }
+ e = r.Publish(req)
+ assert.Nil(t, e)
+}
+
+func TestRocketMQ_Publish_Orderly(t *testing.T) {
+ l, r, e := BuildRocketMQ()
+ assert.Nil(t, e)
+
+ req := &pubsub.PublishRequest{
+ Data: []byte("{\"key\": 1, \"value\": \"1\", \"sKey\": \"sKeyHello\"}"),
+ PubsubName: "rocketmq",
+ Topic: "ZCY_ZHIXING_TEST_ORDER_test",
+ Metadata: map[string]string{
+ "rocketmq-tag": "tag",
+ "rocketmq-key": "1",
+ "rocketmq-shardingkey": "sKey",
+ "rocketmq-queue": "2",
+ },
+ }
+ e = r.Publish(req)
+ if e != nil {
+ l.Error(e)
+ return
+ }
+ assert.Nil(t, e)
+
+ req = &pubsub.PublishRequest{
+ Data: []byte("{\"key\": 2, \"value\": \"2\", \"sKey\": \"sKeyHello\"}"),
+ PubsubName: "rocketmq",
+ Topic: "ZCY_ZHIXING_TEST_ORDER_test",
+ Metadata: map[string]string{
+ "rocketmq-tag": "tag",
+ "rocketmq-key": "2",
+ "rocketmq-shardingkey": "sKey",
+ "rocketmq-queue": "3",
+ },
+ }
+ e = r.Publish(req)
+ assert.Nil(t, e)
+
+ req = &pubsub.PublishRequest{
+ Data: []byte("{\"key\": 3, \"value\": \"3\", \"sKey\": \"sKeyHello\"}"),
+ PubsubName: "rocketmq",
+ Topic: "ZCY_ZHIXING_TEST_ORDER_test",
+ Metadata: map[string]string{
+ "rocketmq-tag": "tag",
+ "rocketmq-key": "3",
+ "rocketmq-shardingkey": "sKey",
+ },
+ }
+ e = r.Publish(req)
+ assert.Nil(t, e)
+}
+
+func TestRocketMQ_Subscribe_Currently(t *testing.T) {
+ l, r, e := BuildRocketMQ()
+ assert.Nil(t, e)
+
+ req := pubsub.SubscribeRequest{
+ Topic: "ZCY_ZHIXING_TEST_test",
+ }
+ handler := func(ctx context.Context, msg *pubsub.NewMessage) error {
+ l.Info(string(msg.Data))
+ return nil
+ }
+ e = r.Subscribe(context.Background(), req, handler)
+ if e != nil {
+ l.Error(e)
+ return
+ }
+ assert.Nil(t, e)
+ time.Sleep(20 * time.Second)
+}
+
+func TestRocketMQ_Subscribe_Orderly(t *testing.T) {
+ l, r, e := BuildRocketMQ()
+ assert.Nil(t, e)
+
+ handler := func(ctx context.Context, msg *pubsub.NewMessage) error {
+ l.Info(msg.Topic, string(msg.Data))
+ return nil
+ }
+ req := pubsub.SubscribeRequest{
+ Topic: "ZCY_ZHIXING_TEST_ORDER_test",
+ Metadata: map[string]string{
+ metadataRocketmqType: "tag",
+ metadataRocketmqExpression: "*",
+ },
+ }
+ e = r.Subscribe(context.Background(), req, handler)
+ if e != nil {
+ l.Error(e)
+ return
+ }
+ assert.Nil(t, e)
+
+ req = pubsub.SubscribeRequest{
+ Topic: "ZCY_ZHIXING_TEST_test",
+ Metadata: map[string]string{
+ metadataRocketmqType: "tag",
+ metadataRocketmqExpression: "*",
+ },
+ }
+ e = r.Subscribe(context.Background(), req, handler)
+ assert.Nil(t, e)
+ time.Sleep(20 * time.Second)
+}
+
+func BuildRocketMQ() (logger.Logger, pubsub.PubSub, error) {
+ meta := getTestMetadata()
+ l := logger.NewLogger("test")
+ r := NewRocketMQ(l)
+ err := r.Init(pubsub.Metadata{Base: mdata.Base{Properties: meta}})
+ return l, r, err
}
diff --git a/secretstores/README.md b/secretstores/README.md
index 66725a685..3631ceb65 100644
--- a/secretstores/README.md
+++ b/secretstores/README.md
@@ -4,4 +4,4 @@ Secret Stores provide a common way to interact with different secret stores, clo
## Implementing a new Secret Store
-A compliant secret store needs to implement the `SecretStore` inteface included in the [`secret_store.go`](secret_store.go) file.
+A compliant secret store needs to implement the `SecretStore` interface included in the [`secret_store.go`](secret_store.go) file.
diff --git a/secretstores/alicloud/parameterstore/parameterstore.go b/secretstores/alicloud/parameterstore/parameterstore.go
index 6563883fb..cfee8c2e3 100644
--- a/secretstores/alicloud/parameterstore/parameterstore.go
+++ b/secretstores/alicloud/parameterstore/parameterstore.go
@@ -15,8 +15,8 @@ package parameterstore
import (
"context"
- "encoding/json"
"fmt"
+ "reflect"
"strconv"
"time"
@@ -25,6 +25,7 @@ import (
util "github.com/alibabacloud-go/tea-utils/service"
"github.com/alibabacloud-go/tea/tea"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/secretstores"
"github.com/dapr/kit/logger"
)
@@ -42,7 +43,7 @@ func NewParameterStore(logger logger.Logger) secretstores.SecretStore {
return &oosSecretStore{logger: logger}
}
-type parameterStoreMetaData struct {
+type ParameterStoreMetaData struct {
RegionID *string `json:"regionId"`
AccessKeyID *string `json:"accessKeyId"`
AccessKeySecret *string `json:"accessKeySecret"`
@@ -151,7 +152,7 @@ func (o *oosSecretStore) BulkGetSecret(ctx context.Context, req secretstores.Bul
return response, nil
}
-func (o *oosSecretStore) getClient(metadata *parameterStoreMetaData) (*oos.Client, error) {
+func (o *oosSecretStore) getClient(metadata *ParameterStoreMetaData) (*oos.Client, error) {
config := &client.Config{
RegionId: metadata.RegionID,
AccessKeyId: metadata.AccessKeyID,
@@ -161,18 +162,9 @@ func (o *oosSecretStore) getClient(metadata *parameterStoreMetaData) (*oos.Clien
return oos.NewClient(config)
}
-func (o *oosSecretStore) getParameterStoreMetadata(spec secretstores.Metadata) (*parameterStoreMetaData, error) {
- b, err := json.Marshal(spec.Properties)
- if err != nil {
- return nil, err
- }
-
- var meta parameterStoreMetaData
- err = json.Unmarshal(b, &meta)
- if err != nil {
- return nil, err
- }
-
+func (o *oosSecretStore) getParameterStoreMetadata(spec secretstores.Metadata) (*ParameterStoreMetaData, error) {
+ meta := ParameterStoreMetaData{}
+ metadata.DecodeMetadata(spec.Properties, &meta)
return &meta, nil
}
@@ -204,3 +196,10 @@ func (o *oosSecretStore) getPathFromMetadata(metadata map[string]string) *string
func (o *oosSecretStore) Features() []secretstores.Feature {
return []secretstores.Feature{} // No Feature supported.
}
+
+func (o *oosSecretStore) GetComponentMetadata() map[string]string {
+ metadataStruct := ParameterStoreMetaData{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/secretstores/aws/parameterstore/parameterstore.go b/secretstores/aws/parameterstore/parameterstore.go
index dfc84119f..6b81ae67b 100644
--- a/secretstores/aws/parameterstore/parameterstore.go
+++ b/secretstores/aws/parameterstore/parameterstore.go
@@ -15,14 +15,15 @@ package parameterstore
import (
"context"
- "encoding/json"
"fmt"
+ "reflect"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ssm"
"github.com/aws/aws-sdk-go/service/ssm/ssmiface"
awsAuth "github.com/dapr/components-contrib/internal/authentication/aws"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/secretstores"
"github.com/dapr/kit/logger"
)
@@ -39,7 +40,7 @@ func NewParameterStore(logger logger.Logger) secretstores.SecretStore {
return &ssmSecretStore{logger: logger}
}
-type parameterStoreMetaData struct {
+type ParameterStoreMetaData struct {
Region string `json:"region"`
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
@@ -151,7 +152,7 @@ func (s *ssmSecretStore) BulkGetSecret(ctx context.Context, req secretstores.Bul
return resp, nil
}
-func (s *ssmSecretStore) getClient(metadata *parameterStoreMetaData) (*ssm.SSM, error) {
+func (s *ssmSecretStore) getClient(metadata *ParameterStoreMetaData) (*ssm.SSM, error) {
sess, err := awsAuth.GetClient(metadata.AccessKey, metadata.SecretKey, metadata.SessionToken, metadata.Region, "")
if err != nil {
return nil, err
@@ -160,22 +161,20 @@ func (s *ssmSecretStore) getClient(metadata *parameterStoreMetaData) (*ssm.SSM,
return ssm.New(sess), nil
}
-func (s *ssmSecretStore) getSecretManagerMetadata(spec secretstores.Metadata) (*parameterStoreMetaData, error) {
- b, err := json.Marshal(spec.Properties)
- if err != nil {
- return nil, err
- }
-
- var meta parameterStoreMetaData
- err = json.Unmarshal(b, &meta)
- if err != nil {
- return nil, err
- }
-
- return &meta, nil
+func (s *ssmSecretStore) getSecretManagerMetadata(spec secretstores.Metadata) (*ParameterStoreMetaData, error) {
+ meta := ParameterStoreMetaData{}
+ err := metadata.DecodeMetadata(spec.Properties, &meta)
+ return &meta, err
}
// Features returns the features available in this secret store.
func (s *ssmSecretStore) Features() []secretstores.Feature {
return []secretstores.Feature{} // No Feature supported.
}
+
+func (s *ssmSecretStore) GetComponentMetadata() map[string]string {
+ metadataStruct := ParameterStoreMetaData{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/secretstores/aws/secretmanager/secretmanager.go b/secretstores/aws/secretmanager/secretmanager.go
index 70707447c..1318940c2 100644
--- a/secretstores/aws/secretmanager/secretmanager.go
+++ b/secretstores/aws/secretmanager/secretmanager.go
@@ -17,11 +17,13 @@ import (
"context"
"encoding/json"
"fmt"
+ "reflect"
"github.com/aws/aws-sdk-go/service/secretsmanager"
"github.com/aws/aws-sdk-go/service/secretsmanager/secretsmanageriface"
awsAuth "github.com/dapr/components-contrib/internal/authentication/aws"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/secretstores"
"github.com/dapr/kit/logger"
)
@@ -38,7 +40,7 @@ func NewSecretManager(logger logger.Logger) secretstores.SecretStore {
return &smSecretStore{logger: logger}
}
-type secretManagerMetaData struct {
+type SecretManagerMetaData struct {
Region string `json:"region"`
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
@@ -134,7 +136,7 @@ func (s *smSecretStore) BulkGetSecret(ctx context.Context, req secretstores.Bulk
return resp, nil
}
-func (s *smSecretStore) getClient(metadata *secretManagerMetaData) (*secretsmanager.SecretsManager, error) {
+func (s *smSecretStore) getClient(metadata *SecretManagerMetaData) (*secretsmanager.SecretsManager, error) {
sess, err := awsAuth.GetClient(metadata.AccessKey, metadata.SecretKey, metadata.SessionToken, metadata.Region, "")
if err != nil {
return nil, err
@@ -143,13 +145,13 @@ func (s *smSecretStore) getClient(metadata *secretManagerMetaData) (*secretsmana
return secretsmanager.New(sess), nil
}
-func (s *smSecretStore) getSecretManagerMetadata(spec secretstores.Metadata) (*secretManagerMetaData, error) {
+func (s *smSecretStore) getSecretManagerMetadata(spec secretstores.Metadata) (*SecretManagerMetaData, error) {
b, err := json.Marshal(spec.Properties)
if err != nil {
return nil, err
}
- var meta secretManagerMetaData
+ var meta SecretManagerMetaData
err = json.Unmarshal(b, &meta)
if err != nil {
return nil, err
@@ -162,3 +164,10 @@ func (s *smSecretStore) getSecretManagerMetadata(spec secretstores.Metadata) (*s
func (s *smSecretStore) Features() []secretstores.Feature {
return []secretstores.Feature{} // No Feature supported.
}
+
+func (s *smSecretStore) GetComponentMetadata() map[string]string {
+ metadataStruct := SecretManagerMetaData{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/secretstores/azure/keyvault/keyvault.go b/secretstores/azure/keyvault/keyvault.go
index 0af130a17..f77d2eb27 100644
--- a/secretstores/azure/keyvault/keyvault.go
+++ b/secretstores/azure/keyvault/keyvault.go
@@ -16,6 +16,7 @@ package keyvault
import (
"context"
"fmt"
+ "reflect"
"strconv"
"strings"
@@ -24,6 +25,7 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets"
azauth "github.com/dapr/components-contrib/internal/authentication/azure"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/secretstores"
"github.com/dapr/kit/logger"
)
@@ -31,7 +33,6 @@ import (
// Keyvault secret store component metadata properties
// This is in addition to what's defined in authentication/azure.
const (
- componentVaultName = "vaultName"
VersionID = "version_id"
secretItemIDPrefix = "/secrets/"
)
@@ -46,6 +47,10 @@ type keyvaultSecretStore struct {
logger logger.Logger
}
+type KeyvaultMetadata struct {
+ VaultName string
+}
+
// NewAzureKeyvaultSecretStore returns a new Azure Key Vault secret store.
func NewAzureKeyvaultSecretStore(logger logger.Logger) secretstores.SecretStore {
return &keyvaultSecretStore{
@@ -56,10 +61,14 @@ func NewAzureKeyvaultSecretStore(logger logger.Logger) secretstores.SecretStore
}
// Init creates a Azure Key Vault client.
-func (k *keyvaultSecretStore) Init(metadata secretstores.Metadata) error {
+func (k *keyvaultSecretStore) Init(meta secretstores.Metadata) error {
+ m := KeyvaultMetadata{}
+ if err := metadata.DecodeMetadata(meta.Properties, &m); err != nil {
+ return err
+ }
// Fix for maintaining backwards compatibility with a change introduced in 1.3 that allowed specifying an Azure environment by setting a FQDN for vault name
// This should be considered deprecated and users should rely the "azureEnvironment" metadata instead, but it's maintained here for backwards-compatibility
- if vaultName, ok := metadata.Properties[componentVaultName]; ok {
+ if m.VaultName != "" {
keyVaultSuffixToEnvironment := map[string]string{
".vault.azure.net": "AZUREPUBLICCLOUD",
".vault.azure.cn": "AZURECHINACLOUD",
@@ -67,26 +76,25 @@ func (k *keyvaultSecretStore) Init(metadata secretstores.Metadata) error {
".vault.microsoftazure.de": "AZUREGERMANCLOUD",
}
for suffix, environment := range keyVaultSuffixToEnvironment {
- if strings.HasSuffix(vaultName, suffix) {
- metadata.Properties["azureEnvironment"] = environment
- vaultName = strings.TrimSuffix(vaultName, suffix)
- if strings.HasPrefix(vaultName, "https://") {
- vaultName = strings.TrimPrefix(vaultName, "https://")
+ if strings.HasSuffix(m.VaultName, suffix) {
+ meta.Properties["azureEnvironment"] = environment
+ m.VaultName = strings.TrimSuffix(m.VaultName, suffix)
+ if strings.HasPrefix(m.VaultName, "https://") {
+ m.VaultName = strings.TrimPrefix(m.VaultName, "https://")
}
- metadata.Properties[componentVaultName] = vaultName
-
+ k.vaultName = m.VaultName
break
}
}
}
// Initialization code
- settings, err := azauth.NewEnvironmentSettings("keyvault", metadata.Properties)
+ settings, err := azauth.NewEnvironmentSettings("keyvault", meta.Properties)
if err != nil {
return err
}
- k.vaultName = settings.Values[componentVaultName]
+ k.vaultName = m.VaultName
k.vaultDNSSuffix = settings.AzureEnvironment.KeyVaultDNSSuffix
cred, err := settings.GetTokenCredential()
@@ -185,11 +193,11 @@ func (k *keyvaultSecretStore) getVaultURI() string {
func (k *keyvaultSecretStore) getMaxResultsFromMetadata(metadata map[string]string) (*int32, error) {
if s, ok := metadata["maxresults"]; ok && s != "" {
- val, err := strconv.Atoi(s) //nolint:gosec
+ val, err := strconv.Atoi(s)
if err != nil {
return nil, err
}
- converted := int32(val)
+ converted := int32(val) //nolint:gosec
return &converted, nil
}
@@ -201,3 +209,10 @@ func (k *keyvaultSecretStore) getMaxResultsFromMetadata(metadata map[string]stri
func (k *keyvaultSecretStore) Features() []secretstores.Feature {
return []secretstores.Feature{} // No Feature supported.
}
+
+func (k *keyvaultSecretStore) GetComponentMetadata() map[string]string {
+ metadataStruct := KeyvaultMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/secretstores/gcp/secretmanager/secretmanager.go b/secretstores/gcp/secretmanager/secretmanager.go
index 79e50fb98..c818461fa 100644
--- a/secretstores/gcp/secretmanager/secretmanager.go
+++ b/secretstores/gcp/secretmanager/secretmanager.go
@@ -17,12 +17,14 @@ import (
"context"
"encoding/json"
"fmt"
+ "reflect"
secretmanager "cloud.google.com/go/secretmanager/apiv1"
"cloud.google.com/go/secretmanager/apiv1/secretmanagerpb"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/secretstores"
"github.com/dapr/kit/logger"
@@ -31,21 +33,17 @@ import (
const VersionID = "version_id"
-type gcpCredentials struct {
- Type string `json:"type"`
- ProjectID string `json:"project_id"`
- PrivateKey string `json:"private_key"`
- ClientEmail string `json:"client_email"`
- PrivateKeyID string `json:"private_key_id"`
- ClientID string `json:"client_id"`
- AuthURI string `json:"auth_uri"`
- TokenURI string `json:"token_uri"`
- AuthProviderCertURL string `json:"auth_provider_x509_cert_url"`
- ClientCertURL string `json:"client_x509_cert_url"`
-}
-
-type secretManagerMetadata struct {
- gcpCredentials
+type GcpSecretManagerMetadata struct {
+ Type string `mapstructure:"type" json:"type"`
+ ProjectID string `mapstructure:"project_id" json:"project_id"`
+ PrivateKey string `mapstructure:"private_key" json:"private_key"`
+ ClientEmail string `mapstructure:"client_email" json:"client_email"`
+ PrivateKeyID string `mapstructure:"private_key_id" json:"private_key_id"`
+ ClientID string `mapstructure:"client_id" json:"client_id"`
+ AuthURI string `mapstructure:"auth_uri" json:"auth_uri"`
+ TokenURI string `mapstructure:"token_uri" json:"token_uri"`
+ AuthProviderCertURL string `mapstructure:"auth_provider_x509_cert_url" json:"auth_provider_x509_cert_url"`
+ ClientCertURL string `mapstructure:"client_x509_cert_url" json:"client_x509_cert_url"`
}
type gcpSecretemanagerClient interface {
@@ -87,7 +85,7 @@ func (s *Store) Init(metadataRaw secretstores.Metadata) error {
return nil
}
-func (s *Store) getClient(metadata *secretManagerMetadata) (*secretmanager.Client, error) {
+func (s *Store) getClient(metadata *GcpSecretManagerMetadata) (*secretmanager.Client, error) {
b, _ := json.Marshal(metadata)
clientOptions := option.WithCredentialsJSON(b)
ctx := context.Background()
@@ -177,17 +175,9 @@ func (s *Store) getSecret(ctx context.Context, secretName string, versionID stri
return &secret, nil
}
-func (s *Store) parseSecretManagerMetadata(metadataRaw secretstores.Metadata) (*secretManagerMetadata, error) {
- b, err := json.Marshal(metadataRaw.Properties)
- if err != nil {
- return nil, err
- }
-
- var meta secretManagerMetadata
- err = json.Unmarshal(b, &meta)
- if err != nil {
- return nil, err
- }
+func (s *Store) parseSecretManagerMetadata(metadataRaw secretstores.Metadata) (*GcpSecretManagerMetadata, error) {
+ meta := GcpSecretManagerMetadata{}
+ metadata.DecodeMetadata(metadataRaw.Properties, &meta)
if meta.Type == "" {
return nil, fmt.Errorf("missing property `type` in metadata")
@@ -213,3 +203,10 @@ func (s *Store) Close() error {
func (s *Store) Features() []secretstores.Feature {
return []secretstores.Feature{} // No Feature supported.
}
+
+func (s *Store) GetComponentMetadata() map[string]string {
+ metadataStruct := GcpSecretManagerMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/secretstores/hashicorp/vault/vault.go b/secretstores/hashicorp/vault/vault.go
index 3411a38ca..a598037e4 100644
--- a/secretstores/hashicorp/vault/vault.go
+++ b/secretstores/hashicorp/vault/vault.go
@@ -25,12 +25,13 @@ import (
"net/http"
"os"
"path/filepath"
- "strconv"
+ "reflect"
"strings"
jsoniter "github.com/json-iterator/go"
"golang.org/x/net/http2"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/secretstores"
"github.com/dapr/kit/logger"
)
@@ -88,6 +89,21 @@ type vaultSecretStore struct {
logger logger.Logger
}
+type VaultMetadata struct {
+ CaCert string
+ CaPath string
+ CaPem string
+ SkipVerify string
+ TLSServerName string
+ VaultAddr string
+ VaultKVPrefix string
+ VaultKVUsePrefix bool
+ VaultToken string
+ VaultTokenMountPath string
+ EnginePath string
+ VaultValueType string
+}
+
// tlsConfig is TLS configuration to interact with HashiCorp Vault.
type tlsConfig struct {
vaultCAPem string
@@ -121,11 +137,17 @@ func NewHashiCorpVaultSecretStore(logger logger.Logger) secretstores.SecretStore
}
// Init creates a HashiCorp Vault client.
-func (v *vaultSecretStore) Init(metadata secretstores.Metadata) error {
- props := metadata.Properties
+func (v *vaultSecretStore) Init(meta secretstores.Metadata) error {
+ m := VaultMetadata{
+ VaultKVUsePrefix: true,
+ }
+ err := metadata.DecodeMetadata(meta.Properties, &m)
+ if err != nil {
+ return err
+ }
// Get Vault address
- address := props[componentVaultAddress]
+ address := m.VaultAddr
if address == "" {
address = defaultVaultAddress
}
@@ -133,49 +155,38 @@ func (v *vaultSecretStore) Init(metadata secretstores.Metadata) error {
v.vaultAddress = address
v.vaultEnginePath = defaultVaultEnginePath
- if val, ok := props[vaultEnginePath]; ok && val != "" {
- v.vaultEnginePath = val
+ if m.EnginePath != "" {
+ v.vaultEnginePath = m.EnginePath
}
v.vaultValueType = valueTypeMap
- if val, found := props[vaultValueType]; found && val != "" {
- switch valueType(val) {
+ if m.VaultValueType != "" {
+ switch valueType(m.VaultValueType) {
case valueTypeMap:
case valueTypeText:
v.vaultValueType = valueTypeText
default:
- return fmt.Errorf("vault init error, invalid value type %s, accepted values are map or text", val)
+ return fmt.Errorf("vault init error, invalid value type %s, accepted values are map or text", m.VaultValueType)
}
}
- v.vaultToken = props[componentVaultToken]
- v.vaultTokenMountPath = props[componentVaultTokenMountPath]
+ v.vaultToken = m.VaultToken
+ v.vaultTokenMountPath = m.VaultTokenMountPath
initErr := v.initVaultToken()
if initErr != nil {
return initErr
}
- vaultKVUsePrefix := props[componentVaultKVUsePrefix]
- vaultKVPrefix := props[componentVaultKVPrefix]
- convertedVaultKVUsePrefix := true
- if vaultKVUsePrefix != "" {
- if v, err := strconv.ParseBool(vaultKVUsePrefix); err == nil {
- convertedVaultKVUsePrefix = v
- } else if err != nil {
- return fmt.Errorf("unable to convert Use Prefix to boolean")
- }
- }
-
- if !convertedVaultKVUsePrefix {
+ vaultKVPrefix := m.VaultKVPrefix
+ if !m.VaultKVUsePrefix {
vaultKVPrefix = ""
} else if vaultKVPrefix == "" {
vaultKVPrefix = defaultVaultKVPrefix
}
-
v.vaultKVPrefix = vaultKVPrefix
// Generate TLS config
- tlsConf := metadataToTLSConfig(props)
+ tlsConf := metadataToTLSConfig(&m)
client, err := v.createHTTPClient(tlsConf)
if err != nil {
@@ -187,20 +198,20 @@ func (v *vaultSecretStore) Init(metadata secretstores.Metadata) error {
return nil
}
-func metadataToTLSConfig(props map[string]string) *tlsConfig {
+func metadataToTLSConfig(meta *VaultMetadata) *tlsConfig {
tlsConf := tlsConfig{}
// Configure TLS settings
- skipVerify := props[componentSkipVerify]
+ skipVerify := meta.SkipVerify
tlsConf.vaultSkipVerify = false
if skipVerify == "true" {
tlsConf.vaultSkipVerify = true
}
- tlsConf.vaultCACert = props[componentCaCert]
- tlsConf.vaultCAPem = props[componentCaPem]
- tlsConf.vaultCAPath = props[componentCaPath]
- tlsConf.vaultServerName = props[componentTLSServerName]
+ tlsConf.vaultCACert = meta.CaCert
+ tlsConf.vaultCAPem = meta.CaPem
+ tlsConf.vaultCAPath = meta.CaPath
+ tlsConf.vaultServerName = meta.TLSServerName
return &tlsConf
}
@@ -226,11 +237,11 @@ func (v *vaultSecretStore) getSecret(ctx context.Context, secret, version string
defer httpresp.Body.Close()
- if httpresp.StatusCode != 200 {
+ if httpresp.StatusCode != http.StatusOK {
var b bytes.Buffer
io.Copy(&b, httpresp.Body)
v.logger.Debugf("getSecret %s couldn't get successful response: %#v, %s", secret, httpresp, b.String())
- if httpresp.StatusCode == 404 {
+ if httpresp.StatusCode == http.StatusNotFound {
// handle not found error
return nil, fmt.Errorf("getSecret %s failed %w", secret, ErrNotFound)
}
@@ -344,7 +355,7 @@ func (v *vaultSecretStore) listKeysUnderPath(ctx context.Context, path string) (
defer httpresp.Body.Close()
- if httpresp.StatusCode != 200 {
+ if httpresp.StatusCode != http.StatusOK {
var b bytes.Buffer
io.Copy(&b, httpresp.Body)
v.logger.Debugf("list keys couldn't get successful response: %#v, %s", httpresp, b.String())
@@ -508,5 +519,16 @@ func readCertificateFolder(certPool *x509.CertPool, path string) error {
// Features returns the features available in this secret store.
func (v *vaultSecretStore) Features() []secretstores.Feature {
+ if v.vaultValueType == valueTypeText {
+ return []secretstores.Feature{}
+ }
+
return []secretstores.Feature{secretstores.FeatureMultipleKeyValuesPerSecret}
}
+
+func (v *vaultSecretStore) GetComponentMetadata() map[string]string {
+ metadataStruct := VaultMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/secretstores/hashicorp/vault/vault_test.go b/secretstores/hashicorp/vault/vault_test.go
index 0fc662e84..99dca5fd3 100644
--- a/secretstores/hashicorp/vault/vault_test.go
+++ b/secretstores/hashicorp/vault/vault_test.go
@@ -28,49 +28,53 @@ import (
const (
// base64 encoded certificate.
- certificate = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURVakNDQWpvQ0NRRFlZdzdMeXN4VXRUQU5CZ2txaGtpRzl3MEJBUXNGQURCck1Rc3dDUVlEVlFRR0V3SkQKUVRFWk1CY0dBMVVFQ0F3UVFuSnBkR2x6YUNCRGIyeDFiV0pwWVRFU01CQUdBMVVFQnd3SlZtRnVZMjkxZG1WeQpNUk13RVFZRFZRUUtEQXB0YVhOb2NtRmpiM0p3TVJnd0ZnWURWUVFEREE5MllYVnNkSEJ5YjJwbFkzUXVhVzh3CkhoY05NVGt4TVRBeE1UQTBPREV5V2hjTk1qQXhNRE14TVRBME9ERXlXakJyTVFzd0NRWURWUVFHRXdKRFFURVoKTUJjR0ExVUVDQXdRUW5KcGRHbHphQ0JEYjJ4MWJXSnBZVEVTTUJBR0ExVUVCd3dKVm1GdVkyOTFkbVZ5TVJNdwpFUVlEVlFRS0RBcHRhWE5vY21GamIzSndNUmd3RmdZRFZRUUREQTkyWVhWc2RIQnliMnBsWTNRdWFXOHdnZ0VpCk1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQ3JtaitTTmtGUHEvK2FXUFV1MlpFamtSK3AKTm1PeEVNSnZZcGhHNkJvRFAySE9ZbGRzdk9FWkRkbTBpWFlmeFIwZm5rUmtTMWEzSlZiYmhINWJnTElKb0dxcwo5aWpzN2hyQ0Rrdk9uRWxpUEZuc05pQ2NWNDNxNkZYaFMvNFpoNGpOMnlyUkU2UmZiS1BEeUw0a282NkFhSld1CnVkTldKVWpzSFZBSWowZHlnTXFKYm0rT29iSzk5ckUxcDg5Z3RNUStJdzFkWnUvUFF4SjlYOStMeXdxZUxPckQKOWhpNWkxajNFUUp2RXQxSVUzclEwc2E0NU5zZkt4YzEwZjdhTjJuSDQzSnhnMVRiZXNPOWYrcWlyeDBHYmVSYQpyVmNaazNVaFc2cHZmam9XbDBEc0NwNTJwZDBQN05rUmhmak44b2RMN0h3bFVIc1NqemlSYytsTG5YREJBZ01CCkFBRXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBSVdKdmRPZ01PUnQxWk53SENkNTNieTlkMlBkcW5tWHFZZ20KNDZHK2Fvb1dSeTJKMEMwS3ZOVGZGbEJFOUlydzNXUTVNMnpqY25qSUp5bzNLRUM5TDdPMnQ1WC9LTGVDck5ZVgpIc1d4cU5BTVBGY2VBa09HT0I1TThGVllkdjJTaVV2UDJjMEZQSzc2WFVzcVNkdnRsWGFkTk5ENzE3T0NTNm0yCnBIVjh1NWJNd1VmR2NCVFpEV2o4bjIzRVdHaXdnYkJkdDc3Z3h3YWc5NTROZkM2Ny9nSUc5ZlRrTTQ4aVJCUzEKc0NGYVBjMkFIT3hiMSs0ajVCMVY2Z29iZDZYWkFvbHdNaTNHUUtkbEM1NXZNeTNwK09WbDNNbEc3RWNTVUpMdApwZ2ZKaWw3L3dTWWhpUnhJU3hrYkk5cWhvNEwzZm5PZVB3clFVd2FzU1ZiL1lxbHZ2WHM9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
- expectedTok = "myRootToken"
- expectedTokMountPath = "./vault.txt"
+ certificate = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURVakNDQWpvQ0NRRFlZdzdMeXN4VXRUQU5CZ2txaGtpRzl3MEJBUXNGQURCck1Rc3dDUVlEVlFRR0V3SkQKUVRFWk1CY0dBMVVFQ0F3UVFuSnBkR2x6YUNCRGIyeDFiV0pwWVRFU01CQUdBMVVFQnd3SlZtRnVZMjkxZG1WeQpNUk13RVFZRFZRUUtEQXB0YVhOb2NtRmpiM0p3TVJnd0ZnWURWUVFEREE5MllYVnNkSEJ5YjJwbFkzUXVhVzh3CkhoY05NVGt4TVRBeE1UQTBPREV5V2hjTk1qQXhNRE14TVRBME9ERXlXakJyTVFzd0NRWURWUVFHRXdKRFFURVoKTUJjR0ExVUVDQXdRUW5KcGRHbHphQ0JEYjJ4MWJXSnBZVEVTTUJBR0ExVUVCd3dKVm1GdVkyOTFkbVZ5TVJNdwpFUVlEVlFRS0RBcHRhWE5vY21GamIzSndNUmd3RmdZRFZRUUREQTkyWVhWc2RIQnliMnBsWTNRdWFXOHdnZ0VpCk1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQ3JtaitTTmtGUHEvK2FXUFV1MlpFamtSK3AKTm1PeEVNSnZZcGhHNkJvRFAySE9ZbGRzdk9FWkRkbTBpWFlmeFIwZm5rUmtTMWEzSlZiYmhINWJnTElKb0dxcwo5aWpzN2hyQ0Rrdk9uRWxpUEZuc05pQ2NWNDNxNkZYaFMvNFpoNGpOMnlyUkU2UmZiS1BEeUw0a282NkFhSld1CnVkTldKVWpzSFZBSWowZHlnTXFKYm0rT29iSzk5ckUxcDg5Z3RNUStJdzFkWnUvUFF4SjlYOStMeXdxZUxPckQKOWhpNWkxajNFUUp2RXQxSVUzclEwc2E0NU5zZkt4YzEwZjdhTjJuSDQzSnhnMVRiZXNPOWYrcWlyeDBHYmVSYQpyVmNaazNVaFc2cHZmam9XbDBEc0NwNTJwZDBQN05rUmhmak44b2RMN0h3bFVIc1NqemlSYytsTG5YREJBZ01CCkFBRXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBSVdKdmRPZ01PUnQxWk53SENkNTNieTlkMlBkcW5tWHFZZ20KNDZHK2Fvb1dSeTJKMEMwS3ZOVGZGbEJFOUlydzNXUTVNMnpqY25qSUp5bzNLRUM5TDdPMnQ1WC9LTGVDck5ZVgpIc1d4cU5BTVBGY2VBa09HT0I1TThGVllkdjJTaVV2UDJjMEZQSzc2WFVzcVNkdnRsWGFkTk5ENzE3T0NTNm0yCnBIVjh1NWJNd1VmR2NCVFpEV2o4bjIzRVdHaXdnYkJkdDc3Z3h3YWc5NTROZkM2Ny9nSUc5ZlRrTTQ4aVJCUzEKc0NGYVBjMkFIT3hiMSs0ajVCMVY2Z29iZDZYWkFvbHdNaTNHUUtkbEM1NXZNeTNwK09WbDNNbEc3RWNTVUpMdApwZ2ZKaWw3L3dTWWhpUnhJU3hrYkk5cWhvNEwzZm5PZVB3clFVd2FzU1ZiL1lxbHZ2WHM9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
+ expectedTok = "myRootToken"
+ expectedTokenMountFileContents = "Hey! TokenMountFile contents here!"
)
+func createTempFileWithContent(t *testing.T, contents string) (fileName string, cleanUpFunc func()) {
+ dir := os.TempDir()
+ f, err := os.CreateTemp(dir, "vault-token")
+ assert.NoError(t, err)
+ fileName = f.Name()
+ cleanUpFunc = func() {
+ os.Remove(fileName)
+ }
+
+ _, err = f.WriteString(contents)
+ assert.NoError(t, err)
+
+ return fileName, cleanUpFunc
+}
+
+func createTokenMountPathFile(t *testing.T) (fileName string, cleanUpFunc func()) {
+ return createTempFileWithContent(t, expectedTokenMountFileContents)
+}
+
func TestReadVaultToken(t *testing.T) {
+ tokenString := "This-IS-TheRootToken"
+ tmpFileName, cleanUpFunc := createTempFileWithContent(t, tokenString)
+ defer cleanUpFunc()
+
t.Run("read correct token", func(t *testing.T) {
- dir := os.TempDir()
- f, err := os.CreateTemp(dir, "vault-token")
- assert.NoError(t, err)
- fileName := f.Name()
- defer os.Remove(fileName)
-
- tokenString := "thisisnottheroottoken"
- _, err = f.WriteString(tokenString)
- assert.NoError(t, err)
-
v := vaultSecretStore{
- vaultTokenMountPath: f.Name(),
+ vaultTokenMountPath: tmpFileName,
}
- err = v.initVaultToken()
+ err := v.initVaultToken()
assert.Nil(t, err)
assert.Equal(t, tokenString, v.vaultToken)
})
t.Run("read incorrect token", func(t *testing.T) {
- dir := os.TempDir()
- f, err := os.CreateTemp(dir, "vault-token")
- assert.NoError(t, err)
- fileName := f.Name()
- defer os.Remove(fileName)
-
- tokenString := "thisisnottheroottoken"
- _, err = f.WriteString(tokenString)
- assert.NoError(t, err)
-
v := vaultSecretStore{
- vaultTokenMountPath: f.Name(),
+ vaultTokenMountPath: tmpFileName,
}
- err = v.initVaultToken()
+
+ err := v.initVaultToken()
assert.Nil(t, err)
- assert.NotEqual(t, "thisistheroottoken", v.vaultToken)
+ assert.NotEqual(t, "ThisIs-NOT-TheRootToken", v.vaultToken)
})
t.Run("read token from vaultToken", func(t *testing.T) {
@@ -98,7 +102,11 @@ func TestVaultTLSConfig(t *testing.T) {
Base: metadata.Base{Properties: properties},
}
- tlsConfig := metadataToTLSConfig(m.Properties)
+ meta := VaultMetadata{}
+ err := metadata.DecodeMetadata(m.Properties, &meta)
+ assert.NoError(t, err)
+
+ tlsConfig := metadataToTLSConfig(&meta)
skipVerify, err := strconv.ParseBool(properties["skipVerify"])
assert.Nil(t, err)
assert.Equal(t, properties["caCert"], tlsConfig.vaultCACert)
@@ -126,6 +134,9 @@ func TestVaultEnginePath(t *testing.T) {
}
func TestVaultTokenPrefix(t *testing.T) {
+ expectedTokMountPath, cleanUpFunc := createTokenMountPathFile(t)
+ defer cleanUpFunc()
+
t.Run("default value of vaultKVUsePrefix is true to emulate previous behaviour", func(t *testing.T) {
properties := map[string]string{
componentVaultToken: expectedTok,
@@ -140,11 +151,9 @@ func TestVaultTokenPrefix(t *testing.T) {
logger: nil,
}
- // This call will throw an error on Windows systems because of the of
- // the call x509.SystemCertPool() because system root pool is not
- // available on Windows so ignore the error for when the tests are run
- // on the Windows platform during CI
- _ = target.Init(m)
+ if err := target.Init(m); err != nil {
+ t.Fatal(err)
+ }
assert.Equal(t, defaultVaultKVPrefix, target.vaultKVPrefix)
})
@@ -165,16 +174,14 @@ func TestVaultTokenPrefix(t *testing.T) {
logger: nil,
}
- // This call will throw an error on Windows systems because of the of
- // the call x509.SystemCertPool() because system root pool is not
- // available on Windows so ignore the error for when the tests are run
- // on the Windows platform during CI
- _ = target.Init(m)
+ if err := target.Init(m); err != nil {
+ t.Fatal(err)
+ }
assert.Equal(t, "", target.vaultKVPrefix)
})
- t.Run("if vaultKVUsePrefix is not castable to bool return error", func(t *testing.T) {
+ t.Run("if vaultKVUsePrefix is not castable to bool we treat it as False", func(t *testing.T) {
properties := map[string]string{
"vaultKVPrefix": "myCustomString",
"vaultKVUsePrefix": "invalidSetting",
@@ -185,22 +192,17 @@ func TestVaultTokenPrefix(t *testing.T) {
Base: metadata.Base{Properties: properties},
}
- target := &vaultSecretStore{
- client: nil,
- logger: nil,
- }
+ meta := VaultMetadata{}
+ metadata.DecodeMetadata(m.Properties, &meta)
- // This call will throw an error on Windows systems because of the of
- // the call x509.SystemCertPool() because system root pool is not
- // available on Windows so ignore the error for when the tests are run
- // on the Windows platform during CI
- err := target.Init(m)
-
- assert.NotNil(t, err)
+ assert.False(t, meta.VaultKVUsePrefix)
})
}
func TestVaultTokenMountPathOrVaultTokenRequired(t *testing.T) {
+ expectedTokMountPath, cleanUpFunc := createTokenMountPathFile(t)
+ defer cleanUpFunc()
+
t.Run("without vaultTokenMount or vaultToken", func(t *testing.T) {
properties := map[string]string{}
@@ -235,13 +237,11 @@ func TestVaultTokenMountPathOrVaultTokenRequired(t *testing.T) {
logger: nil,
}
- // This call will throw an error on Windows systems because of the of
- // the call x509.SystemCertPool() because system root pool is not
- // available on Windows so ignore the error for when the tests are run
- // on the Windows platform during CI
- _ = target.Init(m)
+ if err := target.Init(m); err != nil {
+ t.Fatal(err)
+ }
- assert.Equal(t, "", target.vaultToken)
+ assert.Equal(t, expectedTokenMountFileContents, target.vaultToken)
assert.Equal(t, expectedTokMountPath, target.vaultTokenMountPath)
})
@@ -259,11 +259,9 @@ func TestVaultTokenMountPathOrVaultTokenRequired(t *testing.T) {
logger: nil,
}
- // This call will throw an error on Windows systems because of the of
- // the call x509.SystemCertPool() because system root pool is not
- // available on Windows so ignore the error for when the tests are run
- // on the Windows platform during CI
- _ = target.Init(m)
+ if err := target.Init(m); err != nil {
+ t.Fatal(err)
+ }
assert.Equal(t, "", target.vaultTokenMountPath)
assert.Equal(t, expectedTok, target.vaultToken)
@@ -294,9 +292,12 @@ func TestVaultTokenMountPathOrVaultTokenRequired(t *testing.T) {
}
func TestDefaultVaultAddress(t *testing.T) {
+ expectedTokMountPath, cleanUpFunc := createTokenMountPathFile(t)
+ defer cleanUpFunc()
+
t.Run("with blank vaultAddr", func(t *testing.T) {
properties := map[string]string{
- "vaultTokenMountPath": "./vault.txt",
+ "vaultTokenMountPath": expectedTokMountPath,
}
m := secretstores.Metadata{
@@ -308,11 +309,9 @@ func TestDefaultVaultAddress(t *testing.T) {
logger: nil,
}
- // This call will throw an error on Windows systems because of the of
- // the call x509.SystemCertPool() because system root pool is not
- // available on Windows so ignore the error for when the tests are run
- // on the Windows platform during CI
- _ = target.Init(m)
+ if err := target.Init(m); err != nil {
+ t.Fatal(err)
+ }
assert.Equal(t, defaultVaultAddress, target.vaultAddress, "default was not set")
})
@@ -409,10 +408,49 @@ func getCertificate() []byte {
}
func TestGetFeatures(t *testing.T) {
- s := NewHashiCorpVaultSecretStore(logger.NewLogger("test"))
- // Yes, we are skipping initialization as feature retrieval doesn't depend on it.
- t.Run("Vault supports MULTIPLE_KEY_VALUES_PER_SECRET", func(t *testing.T) {
+ initVaultWithVaultValueType := func(vaultValueType string) secretstores.SecretStore {
+ properties := map[string]string{
+ "vaultToken": expectedTok,
+ "skipVerify": "true",
+ "vaultValueType": vaultValueType,
+ }
+
+ m := secretstores.Metadata{
+ Base: metadata.Base{Properties: properties},
+ }
+
+ target := &vaultSecretStore{
+ client: nil,
+ logger: nil,
+ }
+
+ // This call will throw an error on Windows systems because of the of
+ // the call x509.SystemCertPool() because system root pool is not
+ // available on Windows so ignore the error for when the tests are run
+ // on the Windows platform during CI
+ _ = target.Init(m)
+
+ return target
+ }
+
+ t.Run("Vault supports MULTIPLE_KEY_VALUES_PER_SECRET by default", func(t *testing.T) {
+ // Yes, we are skipping initialization as feature retrieval doesn't depend on it for the default value
+ s := NewHashiCorpVaultSecretStore(logger.NewLogger("test"))
f := s.Features()
assert.True(t, secretstores.FeatureMultipleKeyValuesPerSecret.IsPresent(f))
})
+
+ t.Run("Vault supports MULTIPLE_KEY_VALUES_PER_SECRET if configured with vaultValueType=map", func(t *testing.T) {
+ // Yes, we are skipping initialization as feature retrieval doesn't depend on it for the default value
+ s := initVaultWithVaultValueType("text")
+ f := s.Features()
+ assert.False(t, secretstores.FeatureMultipleKeyValuesPerSecret.IsPresent(f))
+ })
+
+ t.Run("Vault does not support MULTIPLE_KEY_VALUES_PER_SECRET if configured with vaultValueType=text", func(t *testing.T) {
+ // Yes, we are skipping initialization as feature retrieval doesn't depend on it for the default value
+ s := initVaultWithVaultValueType("text")
+ f := s.Features()
+ assert.False(t, secretstores.FeatureMultipleKeyValuesPerSecret.IsPresent(f))
+ })
}
diff --git a/secretstores/huaweicloud/csms/csms.go b/secretstores/huaweicloud/csms/csms.go
index b57882f2e..b218d3ccc 100644
--- a/secretstores/huaweicloud/csms/csms.go
+++ b/secretstores/huaweicloud/csms/csms.go
@@ -15,23 +15,22 @@ package csms
import (
"context"
+ "reflect"
"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
csms "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/csms/v1"
"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/csms/v1/model"
csmsRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/csms/v1/region"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/secretstores"
"github.com/dapr/kit/logger"
)
const (
- region string = "region"
- accessKey string = "accessKey"
- secretAccessKey string = "secretAccessKey"
- pageLimit string = "100"
- latestVersion string = "latest"
- versionID string = "version_id"
+ pageLimit string = "100"
+ latestVersion string = "latest"
+ versionID string = "version_id"
)
type csmsClient interface {
@@ -46,21 +45,29 @@ type csmsSecretStore struct {
logger logger.Logger
}
+type CsmsSecretStoreMetadata struct {
+ Region string
+ AccessKey string
+ SecretAccessKey string
+}
+
// NewHuaweiCsmsSecretStore returns a new Huawei csms secret store.
func NewHuaweiCsmsSecretStore(logger logger.Logger) secretstores.SecretStore {
return &csmsSecretStore{logger: logger}
}
// Init creates a Huawei csms client.
-func (c *csmsSecretStore) Init(metadata secretstores.Metadata) error {
+func (c *csmsSecretStore) Init(meta secretstores.Metadata) error {
+ m := CsmsSecretStoreMetadata{}
+ metadata.DecodeMetadata(meta.Properties, &m)
auth := basic.NewCredentialsBuilder().
- WithAk(metadata.Properties[accessKey]).
- WithSk(metadata.Properties[secretAccessKey]).
+ WithAk(m.AccessKey).
+ WithSk(m.SecretAccessKey).
Build()
c.client = csms.NewCsmsClient(
csms.CsmsClientBuilder().
- WithRegion(csmsRegion.ValueOf(metadata.Properties[region])).
+ WithRegion(csmsRegion.ValueOf(m.Region)).
WithCredential(auth).
Build())
@@ -149,3 +156,10 @@ func (c *csmsSecretStore) getSecretNames(ctx context.Context, marker *string) ([
func (c *csmsSecretStore) Features() []secretstores.Feature {
return []secretstores.Feature{} // No Feature supported.
}
+
+func (c *csmsSecretStore) GetComponentMetadata() map[string]string {
+ metadataStruct := CsmsSecretStoreMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/secretstores/kubernetes/kubernetes.go b/secretstores/kubernetes/kubernetes.go
index e7a199397..34a111e87 100644
--- a/secretstores/kubernetes/kubernetes.go
+++ b/secretstores/kubernetes/kubernetes.go
@@ -18,11 +18,13 @@ import (
"context"
"errors"
"os"
+ "reflect"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
kubeclient "github.com/dapr/components-contrib/internal/authentication/kubernetes"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/secretstores"
"github.com/dapr/kit/logger"
)
@@ -114,3 +116,11 @@ func (k *kubernetesSecretStore) getNamespaceFromMetadata(metadata map[string]str
func (k *kubernetesSecretStore) Features() []secretstores.Feature {
return []secretstores.Feature{}
}
+
+func (k *kubernetesSecretStore) GetComponentMetadata() map[string]string {
+ type unusedMetadataStruct struct{}
+ metadataStruct := unusedMetadataStruct{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/secretstores/local/env/envstore.go b/secretstores/local/env/envstore.go
index d2ce3377f..232d7a3b4 100644
--- a/secretstores/local/env/envstore.go
+++ b/secretstores/local/env/envstore.go
@@ -16,8 +16,10 @@ package env
import (
"context"
"os"
+ "reflect"
"strings"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/secretstores"
"github.com/dapr/kit/logger"
)
@@ -67,3 +69,11 @@ func (s *envSecretStore) BulkGetSecret(ctx context.Context, req secretstores.Bul
func (s *envSecretStore) Features() []secretstores.Feature {
return []secretstores.Feature{} // No Feature supported.
}
+
+func (s *envSecretStore) GetComponentMetadata() map[string]string {
+ type unusedMetadataStruct struct{}
+ metadataStruct := unusedMetadataStruct{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/secretstores/local/file/filestore.go b/secretstores/local/file/filestore.go
index 32515ed7c..4acbace13 100644
--- a/secretstores/local/file/filestore.go
+++ b/secretstores/local/file/filestore.go
@@ -30,9 +30,9 @@ import (
)
type localSecretStoreMetaData struct {
- SecretsFile string `mapstructure:"secretsFile"`
- NestedSeparator string `mapstructure:"nestedSeparator"`
- MultiValued bool `mapstructure:"multiValued"`
+ SecretsFile string
+ NestedSeparator string
+ MultiValued bool
}
var _ secretstores.SecretStore = (*localSecretStore)(nil)
@@ -276,3 +276,10 @@ func (j *localSecretStore) readLocalFile(secretsFile string) (map[string]interfa
func (j *localSecretStore) Features() []secretstores.Feature {
return j.features
}
+
+func (j *localSecretStore) GetComponentMetadata() map[string]string {
+ metadataStruct := localSecretStoreMetaData{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/secretstores/secret_store.go b/secretstores/secret_store.go
index 331d3f688..3df22fa38 100644
--- a/secretstores/secret_store.go
+++ b/secretstores/secret_store.go
@@ -30,6 +30,8 @@ type SecretStore interface {
BulkGetSecret(ctx context.Context, req BulkGetSecretRequest) (BulkGetSecretResponse, error)
// Features lists the features supported by the secret store.
Features() []Feature
+ // GetComponentMetadata returns the metadata options for the secret store.
+ GetComponentMetadata() map[string]string
}
func Ping(secretStore SecretStore) error {
diff --git a/secretstores/tencentcloud/ssm/ssm.go b/secretstores/tencentcloud/ssm/ssm.go
index 336709e49..865aed829 100644
--- a/secretstores/tencentcloud/ssm/ssm.go
+++ b/secretstores/tencentcloud/ssm/ssm.go
@@ -16,21 +16,19 @@ package ssm
import (
"context"
"errors"
+ "reflect"
"strconv"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
ssm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssm/v20190923"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/secretstores"
"github.com/dapr/kit/logger"
)
const (
- SecretID = "SecretID"
- SecretKey = "SecretKey"
- Token = "Token"
- Region = "Region"
VersionID = "VersionID"
RequestID = "RequestID"
ValueType = "SecretValueType"
@@ -56,6 +54,13 @@ type ssmSecretStore struct {
logger logger.Logger
}
+type SsmMetadata struct {
+ SecretID string
+ SecretKey string
+ Token string
+ Region string
+}
+
// NewSSM returns a new TencentCloud ssm secret store.
func NewSSM(logger logger.Logger) secretstores.SecretStore {
return &ssmSecretStore{
@@ -64,22 +69,19 @@ func NewSSM(logger logger.Logger) secretstores.SecretStore {
}
// Init creates a TencentCloud ssm client.
-func (s *ssmSecretStore) Init(metadata secretstores.Metadata) error {
- var (
- err error
- region string
- )
+func (s *ssmSecretStore) Init(meta secretstores.Metadata) error {
+ m := SsmMetadata{}
+ err := metadata.DecodeMetadata(meta.Properties, &m)
+ if err != nil {
+ return err
+ }
- secretID := metadata.Properties[SecretID]
- secretKey := metadata.Properties[SecretKey]
- token := metadata.Properties[Token]
- region = metadata.Properties[Region]
- if secretID == "" || secretKey == "" {
+ if m.SecretID == "" || m.SecretKey == "" {
return errors.New("secret params are empty")
}
- credential := common.NewTokenCredential(secretID, secretKey, token)
- s.client, err = ssm.NewClient(credential, region, profile.NewClientProfile())
+ credential := common.NewTokenCredential(m.SecretID, m.SecretKey, m.Token)
+ s.client, err = ssm.NewClient(credential, m.Region, profile.NewClientProfile())
if err != nil {
return err
}
@@ -190,3 +192,10 @@ func (s *ssmSecretStore) getSecretNames(ctx context.Context, offset *uint64) ([]
func (s *ssmSecretStore) Features() []secretstores.Feature {
return []secretstores.Feature{} // No Feature supported.
}
+
+func (s *ssmSecretStore) GetComponentMetadata() map[string]string {
+ metadataStruct := SsmMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/aerospike/aerospike.go b/state/aerospike/aerospike.go
index f2beb4fdf..7164dd07b 100644
--- a/state/aerospike/aerospike.go
+++ b/state/aerospike/aerospike.go
@@ -18,24 +18,25 @@ import (
"encoding/json"
"errors"
"fmt"
+ "reflect"
"strconv"
"strings"
as "github.com/aerospike/aerospike-client-go"
"github.com/aerospike/aerospike-client-go/types"
- "github.com/agrea/ptr"
jsoniter "github.com/json-iterator/go"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
-// metadata values.
-const (
- hosts = "hosts"
- namespace = "namespace"
- set = "set" // optional
-)
+type aerospikeMetadata struct {
+ Hosts string
+ Namespace string
+ Set string // optional
+}
var (
errMissingHosts = errors.New("aerospike: value for 'hosts' missing")
@@ -66,32 +67,37 @@ func NewAerospikeStateStore(logger logger.Logger) state.Store {
return s
}
-func validateMetadata(metadata state.Metadata) error {
- if metadata.Properties[hosts] == "" {
- return errMissingHosts
+func parseAndValidateMetadata(meta state.Metadata) (*aerospikeMetadata, error) {
+ var m aerospikeMetadata
+ decodeErr := metadata.DecodeMetadata(meta.Properties, &m)
+ if decodeErr != nil {
+ return nil, decodeErr
}
- if metadata.Properties[namespace] == "" {
- return errMissingHosts
+
+ if m.Hosts == "" {
+ return nil, errMissingHosts
+ }
+ if m.Namespace == "" {
+ return nil, errMissingHosts
}
// format is host1:port1,host2:port2
- hostsMeta := metadata.Properties[hosts]
- _, err := parseHosts(hostsMeta)
+ _, err := parseHosts(m.Hosts)
if err != nil {
- return err
+ return nil, err
}
- return nil
+ return &m, nil
}
// Init does metadata and connection parsing.
func (aspike *Aerospike) Init(metadata state.Metadata) error {
- err := validateMetadata(metadata)
+ m, err := parseAndValidateMetadata(metadata)
if err != nil {
return err
}
- hostsMeta := metadata.Properties[hosts]
+ hostsMeta := m.Hosts
hostPorts, _ := parseHosts(hostsMeta)
c, err := as.NewClientWithPolicyAndHost(nil, hostPorts...)
@@ -99,8 +105,8 @@ func (aspike *Aerospike) Init(metadata state.Metadata) error {
return fmt.Errorf("aerospike: failed to connect %v", err)
}
aspike.client = c
- aspike.namespace = metadata.Properties[namespace]
- aspike.set = metadata.Properties[set]
+ aspike.namespace = m.Namespace
+ aspike.set = m.Set
return nil
}
@@ -192,7 +198,7 @@ func (aspike *Aerospike) Get(ctx context.Context, req *state.GetRequest) (*state
return &state.GetResponse{
Data: value,
- ETag: ptr.String(strconv.FormatUint(uint64(record.Generation), 10)),
+ ETag: ptr.Of(strconv.FormatUint(uint64(record.Generation), 10)),
}, nil
}
@@ -264,3 +270,10 @@ func convertETag(eTag string) (uint32, error) {
return uint32(i), nil
}
+
+func (aspike *Aerospike) GetComponentMetadata() map[string]string {
+ metadataStruct := aerospikeMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/aerospike/aerospike_test.go b/state/aerospike/aerospike_test.go
index fb0f17674..5ae1dbd4c 100644
--- a/state/aerospike/aerospike_test.go
+++ b/state/aerospike/aerospike_test.go
@@ -22,6 +22,12 @@ import (
"github.com/dapr/components-contrib/state"
)
+const (
+ hosts = "hosts"
+ namespace = "namespace"
+ set = "set"
+)
+
func TestValidateMetadataForValidInputs(t *testing.T) {
type testCase struct {
name string
@@ -45,7 +51,7 @@ func TestValidateMetadataForValidInputs(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
metadata := state.Metadata{Base: metadata.Base{Properties: test.properties}}
- err := validateMetadata(metadata)
+ _, err := parseAndValidateMetadata(metadata)
assert.Nil(t, err)
})
}
@@ -79,7 +85,7 @@ func TestValidateMetadataForInvalidInputs(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
metadata := state.Metadata{Base: metadata.Base{Properties: test.properties}}
- err := validateMetadata(metadata)
+ _, err := parseAndValidateMetadata(metadata)
assert.NotNil(t, err)
})
}
diff --git a/state/alicloud/tablestore/tablestore.go b/state/alicloud/tablestore/tablestore.go
index 3e47f1fab..0b6bc92d7 100644
--- a/state/alicloud/tablestore/tablestore.go
+++ b/state/alicloud/tablestore/tablestore.go
@@ -15,14 +15,15 @@ package tablestore
import (
"context"
- "encoding/json"
+ "reflect"
- "github.com/agrea/ptr"
"github.com/aliyun/aliyun-tablestore-go-sdk/tablestore"
jsoniter "github.com/json-iterator/go"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
const (
@@ -97,7 +98,7 @@ func (s *AliCloudTableStore) getResp(columns []*tablestore.AttributeColumn) *sta
if column.ColumnName == stateValue {
getResp.Data = unmarshal(column.Value)
} else if column.ColumnName == sateEtag {
- getResp.ETag = ptr.String(column.Value.(string))
+ getResp.ETag = ptr.Of(column.Value.(string))
}
}
@@ -235,19 +236,10 @@ func (s *AliCloudTableStore) batchWrite(ctx context.Context, setReqs []state.Set
return nil
}
-func (s *AliCloudTableStore) parse(metadata state.Metadata) (*tablestoreMetadata, error) {
- b, err := json.Marshal(metadata.Properties)
- if err != nil {
- return nil, err
- }
-
+func (s *AliCloudTableStore) parse(meta state.Metadata) (*tablestoreMetadata, error) {
var m tablestoreMetadata
- err = json.Unmarshal(b, &m)
- if err != nil {
- return nil, err
- }
-
- return &m, nil
+ err := metadata.DecodeMetadata(meta.Properties, &m)
+ return &m, err
}
func (s *AliCloudTableStore) primaryKey(key string) *tablestore.PrimaryKey {
@@ -256,3 +248,10 @@ func (s *AliCloudTableStore) primaryKey(key string) *tablestore.PrimaryKey {
return pk
}
+
+func (s *AliCloudTableStore) GetComponentMetadata() map[string]string {
+ metadataStruct := tablestoreMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/alicloud/tablestore/tablestore_test.go b/state/alicloud/tablestore/tablestore_test.go
index 6c11482b6..790b4fc40 100644
--- a/state/alicloud/tablestore/tablestore_test.go
+++ b/state/alicloud/tablestore/tablestore_test.go
@@ -17,12 +17,12 @@ import (
"context"
"testing"
- "github.com/agrea/ptr"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
func TestTableStoreMetadata(t *testing.T) {
@@ -62,7 +62,7 @@ func TestReadAndWrite(t *testing.T) {
setReq := &state.SetRequest{
Key: "theFirstKey",
Value: "value of key",
- ETag: ptr.String("the etag"),
+ ETag: ptr.Of("the etag"),
}
err := store.Set(context.Background(), setReq)
assert.Nil(t, err)
@@ -82,7 +82,7 @@ func TestReadAndWrite(t *testing.T) {
setReq := &state.SetRequest{
Key: "theSecondKey",
Value: "1234",
- ETag: ptr.String("the etag"),
+ ETag: ptr.Of("the etag"),
}
err := store.Set(context.Background(), setReq)
assert.Nil(t, err)
diff --git a/state/aws/dynamodb/dynamodb.go b/state/aws/dynamodb/dynamodb.go
index 3b705cfab..9bf829847 100644
--- a/state/aws/dynamodb/dynamodb.go
+++ b/state/aws/dynamodb/dynamodb.go
@@ -17,8 +17,8 @@ import (
"context"
"crypto/rand"
"encoding/binary"
- "encoding/json"
"fmt"
+ "reflect"
"strconv"
"time"
@@ -29,6 +29,7 @@ import (
jsoniterator "github.com/json-iterator/go"
awsAuth "github.com/dapr/components-contrib/internal/authentication/aws"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
)
@@ -285,22 +286,20 @@ func (d *StateStore) BulkDelete(ctx context.Context, req []state.DeleteRequest)
return e
}
-func (d *StateStore) getDynamoDBMetadata(metadata state.Metadata) (*dynamoDBMetadata, error) {
- b, err := json.Marshal(metadata.Properties)
- if err != nil {
- return nil, err
- }
+func (d *StateStore) GetComponentMetadata() map[string]string {
+ metadataStruct := dynamoDBMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
- var meta dynamoDBMetadata
- err = json.Unmarshal(b, &meta)
- if err != nil {
- return nil, err
- }
- if meta.Table == "" {
+func (d *StateStore) getDynamoDBMetadata(meta state.Metadata) (*dynamoDBMetadata, error) {
+ var m dynamoDBMetadata
+ err := metadata.DecodeMetadata(meta.Properties, &m)
+ if m.Table == "" {
return nil, fmt.Errorf("missing dynamodb table name")
}
-
- return &meta, nil
+ return &m, err
}
func (d *StateStore) getClient(metadata *dynamoDBMetadata) (*dynamodb.DynamoDB, error) {
diff --git a/state/azure/blobstorage/blobstorage.go b/state/azure/blobstorage/blobstorage.go
index 024c8e1fe..fb532dcf6 100644
--- a/state/azure/blobstorage/blobstorage.go
+++ b/state/azure/blobstorage/blobstorage.go
@@ -37,90 +37,46 @@ package blobstorage
import (
"context"
- b64 "encoding/base64"
"fmt"
"io"
- "net"
- "net/url"
+ "reflect"
"strings"
- "github.com/Azure/azure-storage-blob-go/azblob"
- "github.com/agrea/ptr"
+ "github.com/Azure/azure-sdk-for-go/sdk/azcore"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/bloberror"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container"
jsoniter "github.com/json-iterator/go"
- azauth "github.com/dapr/components-contrib/internal/authentication/azure"
+ storageinternal "github.com/dapr/components-contrib/internal/component/azure/blobstorage"
mdutils "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
const (
- keyDelimiter = "||"
- contentType = "ContentType"
- contentMD5 = "ContentMD5"
- contentEncoding = "ContentEncoding"
- contentLanguage = "ContentLanguage"
- contentDisposition = "ContentDisposition"
- cacheControl = "CacheControl"
+ keyDelimiter = "||"
)
// StateStore Type.
type StateStore struct {
state.DefaultBulkStore
- containerURL azblob.ContainerURL
- json jsoniter.API
+ containerClient *container.Client
+ json jsoniter.API
features []state.Feature
logger logger.Logger
}
-type blobStorageMetadata struct {
- accountName string
- containerName string
-}
-
// Init the connection to blob storage, optionally creates a blob container if it doesn't exist.
func (r *StateStore) Init(metadata state.Metadata) error {
- meta, err := getBlobStorageMetadata(metadata.Properties)
+ var err error
+ r.containerClient, _, err = storageinternal.CreateContainerStorageClient(r.logger, metadata.Properties)
if err != nil {
return err
}
-
- credential, env, err := azauth.GetAzureStorageBlobCredentials(r.logger, meta.accountName, metadata.Properties)
- if err != nil {
- return fmt.Errorf("invalid credentials with error: %s", err.Error())
- }
-
- userAgent := "dapr-" + logger.DaprVersion
- options := azblob.PipelineOptions{
- Telemetry: azblob.TelemetryOptions{Value: userAgent},
- }
- p := azblob.NewPipeline(credential, options)
-
- var URL *url.URL
- customEndpoint, ok := mdutils.GetMetadataProperty(metadata.Properties, azauth.StorageEndpointKeys...)
- if ok && customEndpoint != "" {
- URL, err = url.Parse(fmt.Sprintf("%s/%s/%s", customEndpoint, meta.accountName, meta.containerName))
- } else {
- URL, err = url.Parse(fmt.Sprintf("https://%s.blob.%s/%s", meta.accountName, env.StorageEndpointSuffix, meta.containerName))
- }
- if err != nil {
- return err
- }
- containerURL := azblob.NewContainerURL(*URL, p)
-
- _, err = net.LookupHost(URL.Hostname())
- if err != nil {
- return err
- }
-
- ctx := context.Background()
- _, err = containerURL.Create(ctx, azblob.Metadata{}, azblob.PublicAccessNone)
- r.logger.Debugf("error creating container: %s", err)
-
- r.containerURL = containerURL
- r.logger.Debugf("using container '%s'", meta.containerName)
-
return nil
}
@@ -131,32 +87,34 @@ func (r *StateStore) Features() []state.Feature {
// Delete the state.
func (r *StateStore) Delete(ctx context.Context, req *state.DeleteRequest) error {
- r.logger.Debugf("delete %s", req.Key)
return r.deleteFile(ctx, req)
}
// Get the state.
func (r *StateStore) Get(ctx context.Context, req *state.GetRequest) (*state.GetResponse, error) {
- r.logger.Debugf("get %s", req.Key)
return r.readFile(ctx, req)
}
// Set the state.
func (r *StateStore) Set(ctx context.Context, req *state.SetRequest) error {
- r.logger.Debugf("saving %s", req.Key)
return r.writeFile(ctx, req)
}
func (r *StateStore) Ping() error {
- accessConditions := azblob.BlobAccessConditions{}
-
- if _, err := r.containerURL.GetProperties(context.Background(), accessConditions.LeaseAccessConditions); err != nil {
- return fmt.Errorf("blob storage: error connecting to Blob storage at %s: %s", r.containerURL.URL().Host, err)
+ if _, err := r.containerClient.GetProperties(context.Background(), nil); err != nil {
+ return fmt.Errorf("blob storage: error connecting to Blob storage at %s: %s", r.containerClient.URL(), err)
}
return nil
}
+func (r *StateStore) GetComponentMetadata() map[string]string {
+ metadataStruct := storageinternal.BlobStorageMetadata{}
+ metadataInfo := map[string]string{}
+ mdutils.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
+
// NewAzureBlobStorageStore instance.
func NewAzureBlobStorageStore(logger logger.Logger) state.Store {
s := &StateStore{
@@ -169,31 +127,10 @@ func NewAzureBlobStorageStore(logger logger.Logger) state.Store {
return s
}
-func getBlobStorageMetadata(metadata map[string]string) (*blobStorageMetadata, error) {
- meta := blobStorageMetadata{}
-
- if val, ok := mdutils.GetMetadataProperty(metadata, azauth.StorageAccountNameKeys...); ok && val != "" {
- meta.accountName = val
- } else {
- return nil, fmt.Errorf("missing or empty %s field from metadata", azauth.StorageAccountNameKeys[0])
- }
-
- if val, ok := mdutils.GetMetadataProperty(metadata, azauth.StorageContainerNameKeys...); ok && val != "" {
- meta.containerName = val
- } else {
- return nil, fmt.Errorf("missing or empty %s field from metadata", azauth.StorageContainerNameKeys[0])
- }
-
- return &meta, nil
-}
-
func (r *StateStore) readFile(ctx context.Context, req *state.GetRequest) (*state.GetResponse, error) {
- blobURL := r.containerURL.NewBlockBlobURL(getFileName(req.Key))
-
- resp, err := blobURL.Download(ctx, 0, azblob.CountToEnd, azblob.BlobAccessConditions{}, false)
+ blockBlobClient := r.containerClient.NewBlockBlobClient(getFileName(req.Key))
+ blobDownloadResponse, err := blockBlobClient.DownloadStream(ctx, nil)
if err != nil {
- r.logger.Debugf("download file %s, err %s", req.Key, err)
-
if isNotFoundError(err) {
return &state.GetResponse{}, nil
}
@@ -201,110 +138,79 @@ func (r *StateStore) readFile(ctx context.Context, req *state.GetRequest) (*stat
return &state.GetResponse{}, err
}
- bodyStream := resp.Body(azblob.RetryReaderOptions{})
- data, err := io.ReadAll(bodyStream)
+ reader := blobDownloadResponse.Body
+ defer reader.Close()
+ blobData, err := io.ReadAll(reader)
if err != nil {
- r.logger.Debugf("read file %s, err %s", req.Key, err)
- return &state.GetResponse{}, err
+ return &state.GetResponse{}, fmt.Errorf("error reading az blob: %w", err)
}
- contentType := resp.ContentType()
+ contentType := blobDownloadResponse.ContentType
return &state.GetResponse{
- Data: data,
- ETag: ptr.String(string(resp.ETag())),
- ContentType: &contentType,
+ Data: blobData,
+ ETag: ptr.Of(string(*blobDownloadResponse.ETag)),
+ ContentType: contentType,
}, nil
}
func (r *StateStore) writeFile(ctx context.Context, req *state.SetRequest) error {
- accessConditions := azblob.BlobAccessConditions{}
+ modifiedAccessConditions := blob.ModifiedAccessConditions{}
if req.ETag != nil && *req.ETag != "" {
- accessConditions.IfMatch = azblob.ETag(*req.ETag)
+ modifiedAccessConditions.IfMatch = ptr.Of(azcore.ETag(*req.ETag))
}
if req.Options.Concurrency == state.FirstWrite && (req.ETag == nil || *req.ETag == "") {
- accessConditions.IfNoneMatch = azblob.ETag("*")
+ modifiedAccessConditions.IfNoneMatch = ptr.Of(azcore.ETagAny)
}
- blobURL := r.containerURL.NewBlockBlobURL(getFileName(req.Key))
+ accessConditions := blob.AccessConditions{
+ ModifiedAccessConditions: &modifiedAccessConditions,
+ }
- blobHTTPHeaders, err := r.createBlobHTTPHeadersFromRequest(req)
+ blobHTTPHeaders, err := storageinternal.CreateBlobHTTPHeadersFromRequest(req.Metadata, req.ContentType, r.logger)
if err != nil {
return err
}
- _, err = azblob.UploadBufferToBlockBlob(ctx, r.marshal(req), blobURL, azblob.UploadToBlockBlobOptions{
- Metadata: req.Metadata,
- AccessConditions: accessConditions,
- BlobHTTPHeaders: blobHTTPHeaders,
- })
- if err != nil {
- r.logger.Debugf("write file %s, err %s", req.Key, err)
+ uploadOptions := azblob.UploadBufferOptions{
+ AccessConditions: &accessConditions,
+ Metadata: storageinternal.SanitizeMetadata(r.logger, req.Metadata),
+ HTTPHeaders: &blobHTTPHeaders,
+ }
+
+ blockBlobClient := r.containerClient.NewBlockBlobClient(getFileName(req.Key))
+ _, err = blockBlobClient.UploadBuffer(ctx, r.marshal(req), &uploadOptions)
+
+ if err != nil {
// Check if the error is due to ETag conflict
if req.ETag != nil && isETagConflictError(err) {
return state.NewETagError(state.ETagMismatch, err)
}
- return err
+ return fmt.Errorf("error uploading az blob: %w", err)
}
return nil
}
-func (r *StateStore) createBlobHTTPHeadersFromRequest(req *state.SetRequest) (azblob.BlobHTTPHeaders, error) {
- var blobHTTPHeaders azblob.BlobHTTPHeaders
- if val, ok := req.Metadata[contentType]; ok && val != "" {
- blobHTTPHeaders.ContentType = val
- delete(req.Metadata, contentType)
- }
-
- if req.ContentType != nil {
- if blobHTTPHeaders.ContentType != "" {
- r.logger.Warnf("ContentType received from request Metadata %s, as well as ContentType property %s, choosing value from contentType property", blobHTTPHeaders.ContentType, *req.ContentType)
- }
- blobHTTPHeaders.ContentType = *req.ContentType
- }
-
- if val, ok := req.Metadata[contentMD5]; ok && val != "" {
- sDec, err := b64.StdEncoding.DecodeString(val)
- if err != nil || len(sDec) != 16 {
- return azblob.BlobHTTPHeaders{}, fmt.Errorf("the MD5 value specified in Content MD5 is invalid, MD5 value must be 128 bits and base64 encoded")
- }
- blobHTTPHeaders.ContentMD5 = sDec
- delete(req.Metadata, contentMD5)
- }
- if val, ok := req.Metadata[contentEncoding]; ok && val != "" {
- blobHTTPHeaders.ContentEncoding = val
- delete(req.Metadata, contentEncoding)
- }
- if val, ok := req.Metadata[contentLanguage]; ok && val != "" {
- blobHTTPHeaders.ContentLanguage = val
- delete(req.Metadata, contentLanguage)
- }
- if val, ok := req.Metadata[contentDisposition]; ok && val != "" {
- blobHTTPHeaders.ContentDisposition = val
- delete(req.Metadata, contentDisposition)
- }
- if val, ok := req.Metadata[cacheControl]; ok && val != "" {
- blobHTTPHeaders.CacheControl = val
- delete(req.Metadata, cacheControl)
- }
- return blobHTTPHeaders, nil
-}
-
func (r *StateStore) deleteFile(ctx context.Context, req *state.DeleteRequest) error {
- blobURL := r.containerURL.NewBlockBlobURL(getFileName(req.Key))
- accessConditions := azblob.BlobAccessConditions{}
+ blockBlobClient := r.containerClient.NewBlockBlobClient(getFileName(req.Key))
+ modifiedAccessConditions := blob.ModifiedAccessConditions{}
if req.ETag != nil && *req.ETag != "" {
- accessConditions.IfMatch = azblob.ETag(*req.ETag)
+ modifiedAccessConditions.IfMatch = ptr.Of(azcore.ETag(*req.ETag))
}
- _, err := blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone, accessConditions)
- if err != nil {
- r.logger.Debugf("delete file %s, err %s", req.Key, err)
+ deleteOptions := blob.DeleteOptions{
+ DeleteSnapshots: nil,
+ AccessConditions: &blob.AccessConditions{
+ ModifiedAccessConditions: &modifiedAccessConditions,
+ },
+ }
+ _, err := blockBlobClient.Delete(ctx, &deleteOptions)
+ if err != nil {
if req.ETag != nil && isETagConflictError(err) {
return state.NewETagError(state.ETagMismatch, err)
} else if isNotFoundError(err) {
@@ -340,13 +246,9 @@ func (r *StateStore) marshal(req *state.SetRequest) []byte {
}
func isNotFoundError(err error) bool {
- azureError, ok := err.(azblob.StorageError)
-
- return ok && azureError.ServiceCode() == azblob.ServiceCodeBlobNotFound
+ return bloberror.HasCode(err, bloberror.BlobNotFound)
}
func isETagConflictError(err error) bool {
- azureError, ok := err.(azblob.StorageError)
-
- return ok && azureError.ServiceCode() == azblob.ServiceCodeConditionNotMet
+ return bloberror.HasCode(err, bloberror.ConditionNotMet)
}
diff --git a/state/azure/blobstorage/blobstorage_test.go b/state/azure/blobstorage/blobstorage_test.go
index 2aa666c91..e8ec8a97b 100644
--- a/state/azure/blobstorage/blobstorage_test.go
+++ b/state/azure/blobstorage/blobstorage_test.go
@@ -34,8 +34,7 @@ func TestInit(t *testing.T) {
}
err := s.Init(m)
assert.Nil(t, err)
- assert.Equal(t, "acc.blob.core.windows.net", s.containerURL.URL().Host)
- assert.Equal(t, "/dapr", s.containerURL.URL().Path)
+ assert.Equal(t, "https://acc.blob.core.windows.net/dapr", s.containerClient.URL())
})
t.Run("Init with missing metadata", func(t *testing.T) {
@@ -53,31 +52,12 @@ func TestInit(t *testing.T) {
"accountKey": "e+Dnvl8EOxYxV94nurVaRQ==",
"containerName": "dapr",
}
- err := s.Init(m)
+ s.Init(m)
+ err := s.Ping()
assert.NotNil(t, err)
})
}
-func TestGetBlobStorageMetaData(t *testing.T) {
- t.Run("Nothing at all passed", func(t *testing.T) {
- m := make(map[string]string)
- _, err := getBlobStorageMetadata(m)
-
- assert.NotNil(t, err)
- })
-
- t.Run("All parameters passed and parsed", func(t *testing.T) {
- m := make(map[string]string)
- m["accountName"] = "acc"
- m["containerName"] = "dapr"
- meta, err := getBlobStorageMetadata(m)
-
- assert.Nil(t, err)
- assert.Equal(t, "acc", meta.accountName)
- assert.Equal(t, "dapr", meta.containerName)
- })
-}
-
func TestFileName(t *testing.T) {
t.Run("Valid composite key", func(t *testing.T) {
key := getFileName("app_id||key")
@@ -89,41 +69,3 @@ func TestFileName(t *testing.T) {
assert.Equal(t, "key", key)
})
}
-
-func TestBlobHTTPHeaderGeneration(t *testing.T) {
- s := NewAzureBlobStorageStore(logger.NewLogger("logger")).(*StateStore)
- t.Run("Content type is set from request, forward compatibility", func(t *testing.T) {
- contentType := "application/json"
- req := &state.SetRequest{
- ContentType: &contentType,
- }
-
- blobHeaders, err := s.createBlobHTTPHeadersFromRequest(req)
- assert.Nil(t, err)
- assert.Equal(t, "application/json", blobHeaders.ContentType)
- })
- t.Run("Content type and metadata provided (conflict), content type chosen", func(t *testing.T) {
- contentType := "application/json"
- req := &state.SetRequest{
- ContentType: &contentType,
- Metadata: map[string]string{
- contentType: "text/plain",
- },
- }
-
- blobHeaders, err := s.createBlobHTTPHeadersFromRequest(req)
- assert.Nil(t, err)
- assert.Equal(t, "application/json", blobHeaders.ContentType)
- })
- t.Run("ContentType not provided, metadata provided set backward compatibility", func(t *testing.T) {
- req := &state.SetRequest{
- Metadata: map[string]string{
- contentType: "text/plain",
- },
- }
-
- blobHeaders, err := s.createBlobHTTPHeadersFromRequest(req)
- assert.Nil(t, err)
- assert.Equal(t, "text/plain", blobHeaders.ContentType)
- })
-}
diff --git a/state/azure/cosmosdb/cosmosdb.go b/state/azure/cosmosdb/cosmosdb.go
index 617399c19..411fc844f 100644
--- a/state/azure/cosmosdb/cosmosdb.go
+++ b/state/azure/cosmosdb/cosmosdb.go
@@ -20,6 +20,7 @@ import (
"errors"
"fmt"
"net/http"
+ "reflect"
"strconv"
"strings"
"time"
@@ -32,6 +33,7 @@ import (
"github.com/dapr/components-contrib/contenttype"
"github.com/dapr/components-contrib/internal/authentication/azure"
+ contribmeta "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/components-contrib/state/query"
"github.com/dapr/kit/logger"
@@ -104,22 +106,23 @@ func NewCosmosDBStateStore(logger logger.Logger) state.Store {
return s
}
+func (c *StateStore) GetComponentMetadata() map[string]string {
+ metadataStruct := metadata{}
+ metadataInfo := map[string]string{}
+ contribmeta.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
+
// Init does metadata and connection parsing.
func (c *StateStore) Init(meta state.Metadata) error {
c.logger.Debugf("CosmosDB init start")
- b, err := json.Marshal(meta.Properties)
- if err != nil {
- return err
- }
-
m := metadata{
ContentType: "application/json",
}
-
- err = json.Unmarshal(b, &m)
- if err != nil {
- return err
+ errDecode := contribmeta.DecodeMetadata(meta.Properties, &m)
+ if errDecode != nil {
+ return errDecode
}
if m.URL == "" {
@@ -140,6 +143,9 @@ func (c *StateStore) Init(meta state.Metadata) error {
opts := azcosmos.ClientOptions{
ClientOptions: policy.ClientOptions{
PerCallPolicies: []policy.Policy{queryPolicy},
+ Telemetry: policy.TelemetryOptions{
+ ApplicationID: "dapr-" + logger.DaprVersion,
+ },
},
}
@@ -147,7 +153,7 @@ func (c *StateStore) Init(meta state.Metadata) error {
var client *azcosmos.Client
if m.MasterKey != "" {
var cred azcosmos.KeyCredential
- cred, err = azcosmos.NewKeyCredential(m.MasterKey)
+ cred, err := azcosmos.NewKeyCredential(m.MasterKey)
if err != nil {
return err
}
@@ -158,7 +164,7 @@ func (c *StateStore) Init(meta state.Metadata) error {
} else {
// Fallback to using Azure AD
var env azure.EnvironmentSettings
- env, err = azure.NewEnvironmentSettings("cosmosdb", meta.Properties)
+ env, err := azure.NewEnvironmentSettings("cosmosdb", meta.Properties)
if err != nil {
return err
}
@@ -358,7 +364,7 @@ func (c *StateStore) Multi(ctx context.Context, request *state.TransactionalStat
numOperations := 0
// Loop through the list of operations. Create and add the operation to the batch
for _, o := range request.Operations {
- var options *azcosmos.TransactionalBatchItemOptions
+ options := &azcosmos.TransactionalBatchItemOptions{}
if o.Operation == state.Upsert {
req := o.Request.(state.SetRequest)
diff --git a/state/azure/tablestorage/tablestorage.go b/state/azure/tablestorage/tablestorage.go
index 1f8fa073b..e13ea2c68 100644
--- a/state/azure/tablestorage/tablestorage.go
+++ b/state/azure/tablestorage/tablestorage.go
@@ -40,16 +40,17 @@ package tablestorage
import (
"context"
"fmt"
+ "reflect"
"strings"
"time"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
+ "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/data/aztables"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
azauth "github.com/dapr/components-contrib/internal/authentication/azure"
- "github.com/dapr/components-contrib/internal/utils"
mdutils "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
@@ -59,10 +60,8 @@ const (
keyDelimiter = "||"
valueEntityProperty = "Value"
- cosmosDBModeKey = "cosmosDbMode"
- serviceURLKey = "serviceURL"
- skipCreateTableKey = "skipCreateTable"
- timeout = 15 * time.Second
+ cosmosDBModeKey = "cosmosDbMode"
+ timeout = 15 * time.Second
)
type StateStore struct {
@@ -76,12 +75,12 @@ type StateStore struct {
}
type tablesMetadata struct {
- accountName string
- accountKey string // optional, if not provided, will use Azure AD authentication
- tableName string
- cosmosDBMode bool // if true, use CosmosDB Table API, otherwise use Azure Table Storage
- serviceURL string // optional, if not provided, will use default Azure service URL
- skipCreateTable bool // skip attempt to create table - useful for fine grained AAD roles
+ AccountName string
+ AccountKey string // optional, if not provided, will use Azure AD authentication
+ TableName string
+ CosmosDBMode bool // if true, use CosmosDB Table API, otherwise use Azure Table Storage
+ ServiceURL string // optional, if not provided, will use default Azure service URL
+ SkipCreateTable bool // skip attempt to create table - useful for fine grained AAD roles
}
// Init Initialises connection to table storage, optionally creates a table if it doesn't exist.
@@ -93,25 +92,33 @@ func (r *StateStore) Init(metadata state.Metadata) error {
var client *aztables.ServiceClient
- r.cosmosDBMode = meta.cosmosDBMode
- serviceURL := meta.serviceURL
+ r.cosmosDBMode = meta.CosmosDBMode
+ serviceURL := meta.ServiceURL
if serviceURL == "" {
if r.cosmosDBMode {
- serviceURL = fmt.Sprintf("https://%s.table.cosmos.azure.com", meta.accountName)
+ serviceURL = fmt.Sprintf("https://%s.table.cosmos.azure.com", meta.AccountName)
} else {
- serviceURL = fmt.Sprintf("https://%s.table.core.windows.net", meta.accountName)
+ serviceURL = fmt.Sprintf("https://%s.table.core.windows.net", meta.AccountName)
}
}
- if meta.accountKey != "" {
+ opts := aztables.ClientOptions{
+ ClientOptions: policy.ClientOptions{
+ Telemetry: policy.TelemetryOptions{
+ ApplicationID: "dapr-" + logger.DaprVersion,
+ },
+ },
+ }
+
+ if meta.AccountKey != "" {
// use shared key authentication
- cred, innerErr := aztables.NewSharedKeyCredential(meta.accountName, meta.accountKey)
+ cred, innerErr := aztables.NewSharedKeyCredential(meta.AccountName, meta.AccountKey)
if innerErr != nil {
return innerErr
}
- client, innerErr = aztables.NewServiceClientWithSharedKey(serviceURL, cred, nil)
+ client, innerErr = aztables.NewServiceClientWithSharedKey(serviceURL, cred, &opts)
if innerErr != nil {
return innerErr
}
@@ -132,16 +139,16 @@ func (r *StateStore) Init(metadata state.Metadata) error {
if innerErr != nil {
return innerErr
}
- client, innerErr = aztables.NewServiceClient(serviceURL, token, nil)
+ client, innerErr = aztables.NewServiceClient(serviceURL, token, &opts)
if err != nil {
return innerErr
}
}
- if !meta.skipCreateTable {
+ if !meta.SkipCreateTable {
createContext, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
- _, innerErr := client.CreateTable(createContext, meta.tableName, nil)
+ _, innerErr := client.CreateTable(createContext, meta.TableName, nil)
if innerErr != nil {
if isTableAlreadyExistsError(innerErr) {
// error creating table, but it already exists so we're fine
@@ -151,9 +158,9 @@ func (r *StateStore) Init(metadata state.Metadata) error {
}
}
}
- r.client = client.NewClient(meta.tableName)
+ r.client = client.NewClient(meta.TableName)
- r.logger.Debugf("table initialised, account: %s, cosmosDbMode: %s, table: %s", meta.accountName, meta.cosmosDBMode, meta.tableName)
+ r.logger.Debugf("table initialised, account: %s, cosmosDbMode: %s, table: %s", meta.AccountName, meta.CosmosDBMode, meta.TableName)
return nil
}
@@ -208,6 +215,13 @@ func (r *StateStore) Set(ctx context.Context, req *state.SetRequest) error {
return err
}
+func (r *StateStore) GetComponentMetadata() map[string]string {
+ metadataStruct := tablesMetadata{}
+ metadataInfo := map[string]string{}
+ mdutils.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
+
func NewAzureTablesStateStore(logger logger.Logger) state.Store {
s := &StateStore{
json: jsoniter.ConfigFastest,
@@ -219,39 +233,26 @@ func NewAzureTablesStateStore(logger logger.Logger) state.Store {
return s
}
-func getTablesMetadata(metadata map[string]string) (*tablesMetadata, error) {
- meta := tablesMetadata{}
+func getTablesMetadata(meta map[string]string) (*tablesMetadata, error) {
+ m := tablesMetadata{}
+ err := mdutils.DecodeMetadata(meta, &m)
- if val, ok := mdutils.GetMetadataProperty(metadata, azauth.StorageAccountNameKeys...); ok && val != "" {
- meta.accountName = val
+ if val, ok := mdutils.GetMetadataProperty(meta, azauth.StorageAccountNameKeys...); ok && val != "" {
+ m.AccountName = val
} else {
return nil, errors.New(fmt.Sprintf("missing or empty %s field from metadata", azauth.StorageAccountNameKeys[0]))
}
// Can be empty (such as when using Azure AD for auth)
- meta.accountKey, _ = mdutils.GetMetadataProperty(metadata, azauth.StorageAccountKeyKeys...)
+ m.AccountKey, _ = mdutils.GetMetadataProperty(meta, azauth.StorageAccountKeyKeys...)
- if val, ok := mdutils.GetMetadataProperty(metadata, azauth.StorageTableNameKeys...); ok && val != "" {
- meta.tableName = val
+ if val, ok := mdutils.GetMetadataProperty(meta, azauth.StorageTableNameKeys...); ok && val != "" {
+ m.TableName = val
} else {
return nil, errors.New(fmt.Sprintf("missing or empty %s field from metadata", azauth.StorageTableNameKeys[0]))
}
- if val, ok := metadata[cosmosDBModeKey]; ok && val != "" {
- meta.cosmosDBMode = utils.IsTruthy(val)
- }
-
- if val, ok := metadata[serviceURLKey]; ok && val != "" {
- meta.serviceURL = val
- } else {
- meta.serviceURL = ""
- }
-
- if val, ok := metadata[skipCreateTableKey]; ok && val != "" {
- meta.skipCreateTable = utils.IsTruthy(val)
- }
-
- return &meta, nil
+ return &m, err
}
func (r *StateStore) writeRow(ctx context.Context, req *state.SetRequest) error {
diff --git a/state/azure/tablestorage/tablestorage_test.go b/state/azure/tablestorage/tablestorage_test.go
index a5b525c57..ffc88136f 100644
--- a/state/azure/tablestorage/tablestorage_test.go
+++ b/state/azure/tablestorage/tablestorage_test.go
@@ -32,12 +32,14 @@ func TestGetTableStorageMetadata(t *testing.T) {
m["accountName"] = "acc"
m["accountKey"] = "key"
m["tableName"] = "dapr"
+ m[cosmosDBModeKey] = "on"
meta, err := getTablesMetadata(m)
assert.Nil(t, err)
- assert.Equal(t, "acc", meta.accountName)
- assert.Equal(t, "key", meta.accountKey)
- assert.Equal(t, "dapr", meta.tableName)
+ assert.Equal(t, "acc", meta.AccountName)
+ assert.Equal(t, "key", meta.AccountKey)
+ assert.Equal(t, "dapr", meta.TableName)
+ assert.Equal(t, true, meta.CosmosDBMode)
})
t.Run("All parameters passed and parsed, using aliases", func(t *testing.T) {
@@ -48,9 +50,9 @@ func TestGetTableStorageMetadata(t *testing.T) {
meta, err := getTablesMetadata(m)
assert.Nil(t, err)
- assert.Equal(t, "acc", meta.accountName)
- assert.Equal(t, "key", meta.accountKey)
- assert.Equal(t, "dapr", meta.tableName)
+ assert.Equal(t, "acc", meta.AccountName)
+ assert.Equal(t, "key", meta.AccountKey)
+ assert.Equal(t, "dapr", meta.TableName)
})
}
diff --git a/state/cassandra/cassandra.go b/state/cassandra/cassandra.go
index 4a8c49c98..a5916c105 100644
--- a/state/cassandra/cassandra.go
+++ b/state/cassandra/cassandra.go
@@ -15,14 +15,14 @@ package cassandra
import (
"context"
- "errors"
"fmt"
+ "reflect"
"strconv"
- "strings"
"github.com/gocql/gocql"
jsoniter "github.com/json-iterator/go"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
)
@@ -57,15 +57,15 @@ type Cassandra struct {
}
type cassandraMetadata struct {
- hosts []string
- port int
- protoVersion int
- replicationFactor int
- username string
- password string
- consistency string
- table string
- keyspace string
+ Hosts []string
+ Port int
+ ProtoVersion int
+ ReplicationFactor int
+ Username string
+ Password string
+ Consistency string
+ Table string
+ Keyspace string
}
// NewCassandraStateStore returns a new cassandra state store.
@@ -95,17 +95,17 @@ func (c *Cassandra) Init(metadata state.Metadata) error {
}
c.session = session
- err = c.tryCreateKeyspace(meta.keyspace, meta.replicationFactor)
+ err = c.tryCreateKeyspace(meta.Keyspace, meta.ReplicationFactor)
if err != nil {
- return fmt.Errorf("error creating keyspace %s: %s", meta.keyspace, err)
+ return fmt.Errorf("error creating keyspace %s: %s", meta.Keyspace, err)
}
- err = c.tryCreateTable(meta.table, meta.keyspace)
+ err = c.tryCreateTable(meta.Table, meta.Keyspace)
if err != nil {
- return fmt.Errorf("error creating table %s: %s", meta.table, err)
+ return fmt.Errorf("error creating table %s: %s", meta.Table, err)
}
- c.table = fmt.Sprintf("%s.%s", meta.keyspace, meta.table)
+ c.table = fmt.Sprintf("%s.%s", meta.Keyspace, meta.Table)
return nil
}
@@ -124,13 +124,13 @@ func (c *Cassandra) tryCreateTable(table, keyspace string) error {
}
func (c *Cassandra) createClusterConfig(metadata *cassandraMetadata) (*gocql.ClusterConfig, error) {
- clusterConfig := gocql.NewCluster(metadata.hosts...)
- if metadata.username != "" && metadata.password != "" {
- clusterConfig.Authenticator = gocql.PasswordAuthenticator{Username: metadata.username, Password: metadata.password}
+ clusterConfig := gocql.NewCluster(metadata.Hosts...)
+ if metadata.Username != "" && metadata.Password != "" {
+ clusterConfig.Authenticator = gocql.PasswordAuthenticator{Username: metadata.Username, Password: metadata.Password}
}
- clusterConfig.Port = metadata.port
- clusterConfig.ProtoVersion = metadata.protoVersion
- cons, err := c.getConsistency(metadata.consistency)
+ clusterConfig.Port = metadata.Port
+ clusterConfig.ProtoVersion = metadata.ProtoVersion
+ cons, err := c.getConsistency(metadata.Consistency)
if err != nil {
return nil, err
}
@@ -167,67 +167,49 @@ func (c *Cassandra) getConsistency(consistency string) (gocql.Consistency, error
return 0, fmt.Errorf("consistency mode %s not found", consistency)
}
-func getCassandraMetadata(metadata state.Metadata) (*cassandraMetadata, error) {
- meta := cassandraMetadata{
- protoVersion: defaultProtoVersion,
- table: defaultTable,
- keyspace: defaultKeyspace,
- replicationFactor: defaultReplicationFactor,
- consistency: "All",
- port: defaultPort,
+func getCassandraMetadata(meta state.Metadata) (*cassandraMetadata, error) {
+ m := cassandraMetadata{
+ ProtoVersion: defaultProtoVersion,
+ Table: defaultTable,
+ Keyspace: defaultKeyspace,
+ ReplicationFactor: defaultReplicationFactor,
+ Consistency: "All",
+ Port: defaultPort,
+ }
+ err := metadata.DecodeMetadata(meta.Properties, &m)
+ if err != nil {
+ return nil, err
}
- if val, ok := metadata.Properties[hosts]; ok && val != "" {
- meta.hosts = strings.Split(val, ",")
- } else {
- return nil, errors.New("missing or empty hosts field from metadata")
+ if m.Hosts == nil || len(m.Hosts) == 0 {
+ return nil, fmt.Errorf("missing or empty hosts field from metadata")
}
- if val, ok := metadata.Properties[port]; ok && val != "" {
+ if val, ok := meta.Properties[port]; ok && val != "" {
p, err := strconv.ParseInt(val, 0, 32)
if err != nil {
return nil, fmt.Errorf("error parsing port field: %s", err)
}
- meta.port = int(p)
+ m.Port = int(p)
}
- if val, ok := metadata.Properties[consistency]; ok && val != "" {
- meta.consistency = val
- }
-
- if val, ok := metadata.Properties[table]; ok && val != "" {
- meta.table = val
- }
-
- if val, ok := metadata.Properties[keyspace]; ok && val != "" {
- meta.keyspace = val
- }
-
- if val, ok := metadata.Properties[username]; ok && val != "" {
- meta.username = val
- }
-
- if val, ok := metadata.Properties[password]; ok && val != "" {
- meta.password = val
- }
-
- if val, ok := metadata.Properties[protoVersion]; ok && val != "" {
+ if val, ok := meta.Properties[protoVersion]; ok && val != "" {
p, err := strconv.ParseInt(val, 0, 32)
if err != nil {
return nil, fmt.Errorf("error parsing protoVersion field: %s", err)
}
- meta.protoVersion = int(p)
+ m.ProtoVersion = int(p)
}
- if val, ok := metadata.Properties[replicationFactor]; ok && val != "" {
+ if val, ok := meta.Properties[replicationFactor]; ok && val != "" {
r, err := strconv.ParseInt(val, 0, 32)
if err != nil {
return nil, fmt.Errorf("error parsing replicationFactor field: %s", err)
}
- meta.replicationFactor = int(r)
+ m.ReplicationFactor = int(r)
}
- return &meta, nil
+ return &m, nil
}
// Delete performs a delete operation.
@@ -333,3 +315,10 @@ func parseTTL(requestMetadata map[string]string) (*int, error) {
return nil, nil
}
+
+func (c *Cassandra) GetComponentMetadata() map[string]string {
+ metadataStruct := cassandraMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/cassandra/cassandra_test.go b/state/cassandra/cassandra_test.go
index 3133d65f2..7087fc6b2 100644
--- a/state/cassandra/cassandra_test.go
+++ b/state/cassandra/cassandra_test.go
@@ -15,6 +15,7 @@ package cassandra
import (
"strconv"
+ "strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -34,18 +35,18 @@ func TestGetCassandraMetadata(t *testing.T) {
metadata, err := getCassandraMetadata(m)
assert.Nil(t, err)
- assert.Equal(t, properties[hosts], metadata.hosts[0])
- assert.Equal(t, "All", metadata.consistency)
- assert.Equal(t, defaultKeyspace, metadata.keyspace)
- assert.Equal(t, defaultProtoVersion, metadata.protoVersion)
- assert.Equal(t, defaultReplicationFactor, metadata.replicationFactor)
- assert.Equal(t, defaultTable, metadata.table)
- assert.Equal(t, defaultPort, metadata.port)
+ assert.Equal(t, properties[hosts], metadata.Hosts[0])
+ assert.Equal(t, "All", metadata.Consistency)
+ assert.Equal(t, defaultKeyspace, metadata.Keyspace)
+ assert.Equal(t, defaultProtoVersion, metadata.ProtoVersion)
+ assert.Equal(t, defaultReplicationFactor, metadata.ReplicationFactor)
+ assert.Equal(t, defaultTable, metadata.Table)
+ assert.Equal(t, defaultPort, metadata.Port)
})
t.Run("With custom values", func(t *testing.T) {
properties := map[string]string{
- hosts: "127.0.0.1",
+ hosts: "127.0.0.1,10.10.10.10",
port: "9043",
consistency: "Quorum",
keyspace: "keyspace",
@@ -61,15 +62,16 @@ func TestGetCassandraMetadata(t *testing.T) {
metadata, err := getCassandraMetadata(m)
assert.Nil(t, err)
- assert.Equal(t, properties[hosts], metadata.hosts[0])
- assert.Equal(t, properties[consistency], metadata.consistency)
- assert.Equal(t, properties[keyspace], metadata.keyspace)
- assert.Equal(t, 3, metadata.protoVersion)
- assert.Equal(t, 2, metadata.replicationFactor)
- assert.Equal(t, properties[table], metadata.table)
- assert.Equal(t, properties[username], metadata.username)
- assert.Equal(t, properties[password], metadata.password)
- assert.Equal(t, 9043, metadata.port)
+ assert.Equal(t, strings.Split(properties[hosts], ",")[0], metadata.Hosts[0])
+ assert.Equal(t, strings.Split(properties[hosts], ",")[1], metadata.Hosts[1])
+ assert.Equal(t, properties[consistency], metadata.Consistency)
+ assert.Equal(t, properties[keyspace], metadata.Keyspace)
+ assert.Equal(t, 3, metadata.ProtoVersion)
+ assert.Equal(t, 2, metadata.ReplicationFactor)
+ assert.Equal(t, properties[table], metadata.Table)
+ assert.Equal(t, properties[username], metadata.Username)
+ assert.Equal(t, properties[password], metadata.Password)
+ assert.Equal(t, 9043, metadata.Port)
})
t.Run("Incorrect proto version", func(t *testing.T) {
diff --git a/state/cockroachdb/cockroachdb.go b/state/cockroachdb/cockroachdb.go
index e355dccfa..f2972a4eb 100644
--- a/state/cockroachdb/cockroachdb.go
+++ b/state/cockroachdb/cockroachdb.go
@@ -15,7 +15,9 @@ package cockroachdb
import (
"context"
+ "reflect"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
)
@@ -108,3 +110,10 @@ func (c *CockroachDB) Close() error {
return nil
}
+
+func (c *CockroachDB) GetComponentMetadata() map[string]string {
+ metadataStruct := cockroachDBMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/cockroachdb/cockroachdb_access.go b/state/cockroachdb/cockroachdb_access.go
index c71222df8..638dd5093 100644
--- a/state/cockroachdb/cockroachdb_access.go
+++ b/state/cockroachdb/cockroachdb_access.go
@@ -16,64 +16,86 @@ package cockroachdb
import (
"context"
"database/sql"
+ "database/sql/driver"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"strconv"
-
- "github.com/agrea/ptr"
+ "time"
"github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/components-contrib/state/query"
"github.com/dapr/components-contrib/state/utils"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
+ "github.com/dapr/kit/retry"
// Blank import for the underlying PostgreSQL driver.
_ "github.com/jackc/pgx/v5/stdlib"
)
const (
- connectionStringKey = "connectionString"
- errMissingConnectionString = "missing connection string"
- tableName = "state"
+ connectionStringKey = "connectionString"
+ errMissingConnectionString = "missing connection string"
+ tableName = "state"
+ defaultMaxConnectionAttempts = 5 // A bad driver connection error can occur inside the sql code so this essentially allows for more retries since the sql code does not allow that to be changed
)
// cockroachDBAccess implements dbaccess.
type cockroachDBAccess struct {
logger logger.Logger
- metadata state.Metadata
+ metadata cockroachDBMetadata
db *sql.DB
connectionString string
}
+type cockroachDBMetadata struct {
+ ConnectionString string
+ TableName string
+ MaxConnectionAttempts *int
+}
+
// newCockroachDBAccess creates a new instance of cockroachDBAccess.
func newCockroachDBAccess(logger logger.Logger) *cockroachDBAccess {
logger.Debug("Instantiating new CockroachDB state store")
return &cockroachDBAccess{
- logger: logger,
- metadata: state.Metadata{
- Base: metadata.Base{Properties: map[string]string{}},
- },
+ logger: logger,
+ metadata: cockroachDBMetadata{},
db: nil,
connectionString: "",
}
}
+func parseMetadata(meta state.Metadata) (*cockroachDBMetadata, error) {
+ m := cockroachDBMetadata{}
+ metadata.DecodeMetadata(meta.Properties, &m)
+
+ if m.ConnectionString == "" {
+ return nil, errors.New(errMissingConnectionString)
+ }
+
+ return &m, nil
+}
+
// Init sets up CockroachDB connection and ensures that the state table exists.
func (p *cockroachDBAccess) Init(metadata state.Metadata) error {
p.logger.Debug("Initializing CockroachDB state store")
- p.metadata = metadata
+ meta, err := parseMetadata(metadata)
+ if err != nil {
+ return err
+ }
+ p.metadata = *meta
- if val, ok := metadata.Properties[connectionStringKey]; ok && val != "" {
- p.connectionString = val
- } else {
+ if p.metadata.ConnectionString == "" {
p.logger.Error("Missing CockroachDB connection string")
return fmt.Errorf(errMissingConnectionString)
+ } else {
+ p.connectionString = p.metadata.ConnectionString
}
databaseConn, err := sql.Open("pgx", p.connectionString)
@@ -93,16 +115,17 @@ func (p *cockroachDBAccess) Init(metadata state.Metadata) error {
return err
}
+ // Ensure that a connection to the database is actually established
+ err = p.Ping()
+ if err != nil {
+ return err
+ }
+
return nil
}
// Set makes an insert or update to the database.
func (p *cockroachDBAccess) Set(ctx context.Context, req *state.SetRequest) error {
- return state.SetWithOptions(ctx, p.setValue, req)
-}
-
-// setValue is an internal implementation of set to enable passing the logic to state.SetWithRetries as a func.
-func (p *cockroachDBAccess) setValue(ctx context.Context, req *state.SetRequest) error {
p.logger.Debug("Setting state value in CockroachDB")
value, isBinary, err := validateAndReturnValue(req)
@@ -177,6 +200,7 @@ func (p *cockroachDBAccess) BulkSet(ctx context.Context, req []state.SetRequest)
// Get returns data from the database. If data does not exist for the key an empty state.GetResponse will be returned.
func (p *cockroachDBAccess) Get(ctx context.Context, req *state.GetRequest) (*state.GetResponse, error) {
p.logger.Debug("Getting state value from CockroachDB")
+
if req.Key == "" {
return nil, fmt.Errorf("missing key in get operation")
}
@@ -208,7 +232,7 @@ func (p *cockroachDBAccess) Get(ctx context.Context, req *state.GetRequest) (*st
return &state.GetResponse{
Data: data,
- ETag: ptr.String(strconv.Itoa(etag)),
+ ETag: ptr.Of(strconv.Itoa(etag)),
Metadata: req.Metadata,
ContentType: nil,
}, nil
@@ -216,7 +240,7 @@ func (p *cockroachDBAccess) Get(ctx context.Context, req *state.GetRequest) (*st
return &state.GetResponse{
Data: []byte(value),
- ETag: ptr.String(strconv.Itoa(etag)),
+ ETag: ptr.Of(strconv.Itoa(etag)),
Metadata: req.Metadata,
ContentType: nil,
}, nil
@@ -224,12 +248,8 @@ func (p *cockroachDBAccess) Get(ctx context.Context, req *state.GetRequest) (*st
// Delete removes an item from the state store.
func (p *cockroachDBAccess) Delete(ctx context.Context, req *state.DeleteRequest) error {
- return state.DeleteWithOptions(ctx, p.deleteValue, req)
-}
-
-// deleteValue is an internal implementation of delete to enable passing the logic to state.DeleteWithRetries as a func.
-func (p *cockroachDBAccess) deleteValue(ctx context.Context, req *state.DeleteRequest) error {
p.logger.Debug("Deleting state value from CockroachDB")
+
if req.Key == "" {
return fmt.Errorf("missing key in delete operation")
}
@@ -349,7 +369,7 @@ func (p *cockroachDBAccess) Query(ctx context.Context, req *state.QueryRequest)
query: "",
params: []interface{}{},
limit: 0,
- skip: ptr.Int64(0),
+ skip: ptr.Of[int64](0),
}
qbuilder := query.NewQueryBuilder(stateQuery)
if err := qbuilder.BuildQuery(&req.Query); err != nil {
@@ -380,7 +400,27 @@ func (p *cockroachDBAccess) Query(ctx context.Context, req *state.QueryRequest)
// Ping implements database ping.
func (p *cockroachDBAccess) Ping() error {
- return p.db.Ping()
+ retryCount := defaultMaxConnectionAttempts
+ if p.metadata.MaxConnectionAttempts != nil && *p.metadata.MaxConnectionAttempts >= 0 {
+ retryCount = *p.metadata.MaxConnectionAttempts
+ }
+ config := retry.DefaultConfig()
+ config.Policy = retry.PolicyExponential
+ config.MaxInterval = 100 * time.Millisecond
+ config.MaxRetries = int64(retryCount)
+ backoff := config.NewBackOff()
+
+ return retry.NotifyRecover(func() error {
+ err := p.db.Ping()
+ if errors.Is(err, driver.ErrBadConn) {
+ return fmt.Errorf("error when attempting to establish connection with cockroachDB: %v", err)
+ }
+ return nil
+ }, backoff, func(err error, _ time.Duration) {
+ p.logger.Debugf("Could not establish connection with cockroachDB. Retrying...: %v", err)
+ }, func() {
+ p.logger.Debug("Successfully established connection with cockroachDB after it previously failed")
+ })
}
// Close implements io.Close.
diff --git a/state/cockroachdb/cockroachdb_query.go b/state/cockroachdb/cockroachdb_query.go
index 78593f9a2..34bfcce23 100644
--- a/state/cockroachdb/cockroachdb_query.go
+++ b/state/cockroachdb/cockroachdb_query.go
@@ -20,11 +20,10 @@ import (
"strconv"
"strings"
- "github.com/agrea/ptr"
-
"github.com/dapr/components-contrib/state"
"github.com/dapr/components-contrib/state/query"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
type Query struct {
@@ -154,7 +153,7 @@ func (q *Query) execute(ctx context.Context, logger logger.Logger, db *sql.DB) (
result := state.QueryItem{
Key: key,
Data: data,
- ETag: ptr.String(strconv.Itoa(etag)),
+ ETag: ptr.Of(strconv.Itoa(etag)),
Error: "",
ContentType: nil,
}
diff --git a/state/cockroachdb/cockroachdb_query_test.go b/state/cockroachdb/cockroachdb_query_test.go
index 34b5c9c94..73e185332 100644
--- a/state/cockroachdb/cockroachdb_query_test.go
+++ b/state/cockroachdb/cockroachdb_query_test.go
@@ -18,10 +18,10 @@ import (
"os"
"testing"
- "github.com/agrea/ptr"
"github.com/stretchr/testify/assert"
"github.com/dapr/components-contrib/state/query"
+ "github.com/dapr/kit/ptr"
)
func TestPostgresqlQueryBuildQuery(t *testing.T) {
@@ -67,7 +67,7 @@ func TestPostgresqlQueryBuildQuery(t *testing.T) {
query: "",
params: nil,
limit: 0,
- skip: ptr.Int64(0),
+ skip: ptr.Of[int64](0),
}
qbuilder := query.NewQueryBuilder(stateQuery)
err = qbuilder.BuildQuery(&storeQuery)
diff --git a/state/couchbase/couchbase.go b/state/couchbase/couchbase.go
index 538dc6acc..b334d6a7c 100644
--- a/state/couchbase/couchbase.go
+++ b/state/couchbase/couchbase.go
@@ -15,17 +15,18 @@ package couchbase
import (
"context"
- "errors"
"fmt"
+ "reflect"
"strconv"
- "github.com/agrea/ptr"
jsoniter "github.com/json-iterator/go"
"gopkg.in/couchbase/gocb.v1"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/components-contrib/state/utils"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
const (
@@ -52,6 +53,15 @@ type Couchbase struct {
logger logger.Logger
}
+type couchbaseMetadata struct {
+ CouchbaseURL string
+ Username string
+ Password string
+ BucketName string
+ NumReplicasDurableReplication uint
+ NumReplicasDurablePersistence uint
+}
+
// NewCouchbaseStateStore returns a new couchbase state store.
func NewCouchbaseStateStore(logger logger.Logger) state.Store {
s := &Couchbase{
@@ -64,57 +74,65 @@ func NewCouchbaseStateStore(logger logger.Logger) state.Store {
return s
}
-func validateMetadata(metadata state.Metadata) error {
- if metadata.Properties[couchbaseURL] == "" {
- return errors.New("couchbase error: couchbase URL is missing")
+func parseAndValidateMetadata(meta state.Metadata) (*couchbaseMetadata, error) {
+ m := couchbaseMetadata{}
+ err := metadata.DecodeMetadata(meta.Properties, &m)
+ if err != nil {
+ return nil, err
}
- if metadata.Properties[username] == "" {
- return errors.New("couchbase error: couchbase username is missing")
+ if m.CouchbaseURL == "" {
+ return nil, fmt.Errorf("couchbase error: couchbase URL is missing")
}
- if metadata.Properties[password] == "" {
- return errors.New("couchbase error: couchbase password is missing")
+ if m.Username == "" {
+ return nil, fmt.Errorf("couchbase error: couchbase username is missing")
}
- if metadata.Properties[bucketName] == "" {
- return errors.New("couchbase error: couchbase bucket name is missing")
+ if m.Password == "" {
+ return nil, fmt.Errorf("couchbase error: couchbase password is missing")
}
- v := metadata.Properties[numReplicasDurableReplication]
+ if m.BucketName == "" {
+ return nil, fmt.Errorf("couchbase error: couchbase bucket name is missing")
+ }
+
+ v := meta.Properties[numReplicasDurableReplication]
if v != "" {
- _, err := strconv.ParseUint(v, 10, 0)
+ num, err := strconv.ParseUint(v, 10, 0)
if err != nil {
- return fmt.Errorf("couchbase error: %v", err)
+ return nil, fmt.Errorf("couchbase error: %v", err)
}
+ m.NumReplicasDurableReplication = uint(num)
}
- v = metadata.Properties[numReplicasDurablePersistence]
+ v = meta.Properties[numReplicasDurablePersistence]
if v != "" {
- _, err := strconv.ParseUint(v, 10, 0)
+ num, err := strconv.ParseUint(v, 10, 0)
if err != nil {
- return fmt.Errorf("couchbase error: %v", err)
+ return nil, fmt.Errorf("couchbase error: %v", err)
}
+ m.NumReplicasDurablePersistence = uint(num)
}
- return nil
+ return &m, nil
}
// Init does metadata and connection parsing.
func (cbs *Couchbase) Init(metadata state.Metadata) error {
- err := validateMetadata(metadata)
+ meta, err := parseAndValidateMetadata(metadata)
if err != nil {
return err
}
- cbs.bucketName = metadata.Properties[bucketName]
- c, err := gocb.Connect(metadata.Properties[couchbaseURL])
+ cbs.bucketName = meta.BucketName
+ c, err := gocb.Connect(meta.CouchbaseURL)
if err != nil {
- return fmt.Errorf("couchbase error: unable to connect to couchbase at %s - %v ", metadata.Properties[couchbaseURL], err)
+ return fmt.Errorf("couchbase error: unable to connect to couchbase at %s - %v ", meta.CouchbaseURL, err)
}
// does not actually trigger the authentication
c.Authenticate(gocb.PasswordAuthenticator{
- Username: metadata.Properties[username],
- Password: metadata.Properties[password],
+ Username: meta.Username,
+ Password: meta.Password,
})
// with RBAC, bucket-passwords are no longer used - https://docs.couchbase.com/go-sdk/1.6/sdk-authentication-overview.html#authenticating-with-legacy-sdk-versions
@@ -126,14 +144,12 @@ func (cbs *Couchbase) Init(metadata state.Metadata) error {
r := metadata.Properties[numReplicasDurableReplication]
if r != "" {
- r2, _ := strconv.ParseUint(r, 10, 0)
- cbs.numReplicasDurableReplication = uint(r2)
+ cbs.numReplicasDurableReplication = meta.NumReplicasDurableReplication
}
p := metadata.Properties[numReplicasDurablePersistence]
if p != "" {
- p2, _ := strconv.ParseUint(p, 10, 0)
- cbs.numReplicasDurablePersistence = uint(p2)
+ cbs.numReplicasDurablePersistence = meta.NumReplicasDurablePersistence
}
return nil
@@ -202,7 +218,7 @@ func (cbs *Couchbase) Get(ctx context.Context, req *state.GetRequest) (*state.Ge
return &state.GetResponse{
Data: data.([]byte),
- ETag: ptr.String(strconv.FormatUint(uint64(cas), 10)),
+ ETag: ptr.Of(strconv.FormatUint(uint64(cas), 10)),
}, nil
}
@@ -249,3 +265,10 @@ func eTagToCas(eTag string) (gocb.Cas, error) {
return cas, nil
}
+
+func (cbs *Couchbase) GetComponentMetadata() map[string]string {
+ metadataStruct := couchbaseMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/couchbase/couchbase_test.go b/state/couchbase/couchbase_test.go
index ad1c45e5e..91375ce4e 100644
--- a/state/couchbase/couchbase_test.go
+++ b/state/couchbase/couchbase_test.go
@@ -14,6 +14,7 @@ limitations under the License.
package couchbase
import (
+ "fmt"
"testing"
"github.com/stretchr/testify/assert"
@@ -33,8 +34,9 @@ func TestValidateMetadata(t *testing.T) {
}
metadata := state.Metadata{Base: metadata.Base{Properties: props}}
- err := validateMetadata(metadata)
+ meta, err := parseAndValidateMetadata(metadata)
assert.Equal(t, nil, err)
+ assert.Equal(t, props[couchbaseURL], meta.CouchbaseURL)
})
t.Run("with optional fields", func(t *testing.T) {
props := map[string]string{
@@ -47,8 +49,10 @@ func TestValidateMetadata(t *testing.T) {
}
metadata := state.Metadata{Base: metadata.Base{Properties: props}}
- err := validateMetadata(metadata)
+ meta, err := parseAndValidateMetadata(metadata)
assert.Equal(t, nil, err)
+ assert.Equal(t, props[couchbaseURL], meta.CouchbaseURL)
+ assert.Equal(t, props[numReplicasDurablePersistence], fmt.Sprintf("%d", meta.NumReplicasDurablePersistence))
})
t.Run("With missing couchbase URL", func(t *testing.T) {
props := map[string]string{
@@ -57,7 +61,7 @@ func TestValidateMetadata(t *testing.T) {
bucketName: "testbucket",
}
metadata := state.Metadata{Base: metadata.Base{Properties: props}}
- err := validateMetadata(metadata)
+ _, err := parseAndValidateMetadata(metadata)
assert.NotNil(t, err)
})
t.Run("With missing username", func(t *testing.T) {
@@ -67,7 +71,7 @@ func TestValidateMetadata(t *testing.T) {
bucketName: "testbucket",
}
metadata := state.Metadata{Base: metadata.Base{Properties: props}}
- err := validateMetadata(metadata)
+ _, err := parseAndValidateMetadata(metadata)
assert.NotNil(t, err)
})
t.Run("With missing password", func(t *testing.T) {
@@ -77,7 +81,7 @@ func TestValidateMetadata(t *testing.T) {
bucketName: "testbucket",
}
metadata := state.Metadata{Base: metadata.Base{Properties: props}}
- err := validateMetadata(metadata)
+ _, err := parseAndValidateMetadata(metadata)
assert.NotNil(t, err)
})
t.Run("With missing bucket", func(t *testing.T) {
@@ -87,7 +91,7 @@ func TestValidateMetadata(t *testing.T) {
password: "secret",
}
metadata := state.Metadata{Base: metadata.Base{Properties: props}}
- err := validateMetadata(metadata)
+ _, err := parseAndValidateMetadata(metadata)
assert.NotNil(t, err)
})
t.Run("With invalid durable replication", func(t *testing.T) {
@@ -98,7 +102,7 @@ func TestValidateMetadata(t *testing.T) {
numReplicasDurableReplication: "junk",
}
metadata := state.Metadata{Base: metadata.Base{Properties: props}}
- err := validateMetadata(metadata)
+ _, err := parseAndValidateMetadata(metadata)
assert.NotNil(t, err)
})
t.Run("With invalid durable persistence", func(t *testing.T) {
@@ -109,7 +113,7 @@ func TestValidateMetadata(t *testing.T) {
numReplicasDurablePersistence: "junk",
}
metadata := state.Metadata{Base: metadata.Base{Properties: props}}
- err := validateMetadata(metadata)
+ _, err := parseAndValidateMetadata(metadata)
assert.NotNil(t, err)
})
}
diff --git a/state/gcp/firestore/firestore.go b/state/gcp/firestore/firestore.go
index 9a37d7ee5..3071bc6e1 100644
--- a/state/gcp/firestore/firestore.go
+++ b/state/gcp/firestore/firestore.go
@@ -18,11 +18,13 @@ import (
"encoding/json"
"errors"
"fmt"
+ "reflect"
"cloud.google.com/go/datastore"
jsoniter "github.com/json-iterator/go"
"google.golang.org/api/option"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
)
@@ -39,17 +41,17 @@ type Firestore struct {
}
type firestoreMetadata struct {
- Type string `json:"type"`
- ProjectID string `json:"project_id"`
- PrivateKeyID string `json:"private_key_id"`
- PrivateKey string `json:"private_key"`
- ClientEmail string `json:"client_email"`
- ClientID string `json:"client_id"`
- AuthURI string `json:"auth_uri"`
- TokenURI string `json:"token_uri"`
- AuthProviderCertURL string `json:"auth_provider_x509_cert_url"`
- ClientCertURL string `json:"client_x509_cert_url"`
- EntityKind string `json:"entity_kind"`
+ Type string `json:"type" mapstructure:"type"`
+ ProjectID string `json:"project_id" mapstructure:"project_id"`
+ PrivateKeyID string `json:"private_key_id" mapstructure:"private_key_id"`
+ PrivateKey string `json:"private_key" mapstructure:"private_key"`
+ ClientEmail string `json:"client_email" mapstructure:"client_email"`
+ ClientID string `json:"client_id" mapstructure:"client_id"`
+ AuthURI string `json:"auth_uri" mapstructure:"auth_uri"`
+ TokenURI string `json:"token_uri" mapstructure:"token_uri"`
+ AuthProviderCertURL string `json:"auth_provider_x509_cert_url" mapstructure:"auth_provider_x509_cert_url"`
+ ClientCertURL string `json:"client_x509_cert_url" mapstructure:"client_x509_cert_url"`
+ EntityKind string `json:"entity_kind" mapstructure:"entity_kind"`
}
type StateEntity struct {
@@ -111,7 +113,8 @@ func (f *Firestore) Get(ctx context.Context, req *state.GetRequest) (*state.GetR
}, nil
}
-func (f *Firestore) setValue(ctx context.Context, req *state.SetRequest) error {
+// Set saves state into Firestore.
+func (f *Firestore) Set(ctx context.Context, req *state.SetRequest) error {
err := state.CheckRequestOptions(req.Options)
if err != nil {
return err
@@ -139,12 +142,8 @@ func (f *Firestore) setValue(ctx context.Context, req *state.SetRequest) error {
return nil
}
-// Set saves state into Firestore with retry.
-func (f *Firestore) Set(ctx context.Context, req *state.SetRequest) error {
- return state.SetWithOptions(ctx, f.setValue, req)
-}
-
-func (f *Firestore) deleteValue(ctx context.Context, req *state.DeleteRequest) error {
+// Delete performs a delete operation.
+func (f *Firestore) Delete(ctx context.Context, req *state.DeleteRequest) error {
key := datastore.NameKey(f.entityKind, req.Key, nil)
err := f.client.Delete(ctx, key)
@@ -155,40 +154,43 @@ func (f *Firestore) deleteValue(ctx context.Context, req *state.DeleteRequest) e
return nil
}
-// Delete performs a delete operation.
-func (f *Firestore) Delete(ctx context.Context, req *state.DeleteRequest) error {
- return state.DeleteWithOptions(ctx, f.deleteValue, req)
-}
-
-func getFirestoreMetadata(metadata state.Metadata) (*firestoreMetadata, error) {
- meta := firestoreMetadata{
+func getFirestoreMetadata(meta state.Metadata) (*firestoreMetadata, error) {
+ m := firestoreMetadata{
EntityKind: defaultEntityKind,
}
+
+ err := metadata.DecodeMetadata(meta.Properties, &m)
+ if err != nil {
+ return nil, err
+ }
+
requiredMetaProperties := []string{
"type", "project_id", "private_key_id", "private_key", "client_email", "client_id",
"auth_uri", "token_uri", "auth_provider_x509_cert_url", "client_x509_cert_url",
}
+ metadataMap := map[string]string{}
+ bytes, err := json.Marshal(m)
+ if err != nil {
+ return nil, err
+ }
+ err = json.Unmarshal(bytes, &metadataMap)
+ if err != nil {
+ return nil, err
+ }
+
for _, k := range requiredMetaProperties {
- if val, ok := metadata.Properties[k]; !ok || len(val) < 1 {
+ if val, ok := metadataMap[k]; !ok || len(val) < 1 {
return nil, fmt.Errorf("error parsing required field: %s", k)
}
}
- meta.Type = metadata.Properties["type"]
- meta.ProjectID = metadata.Properties["project_id"]
- meta.PrivateKeyID = metadata.Properties["private_key_id"]
- meta.PrivateKey = metadata.Properties["private_key"]
- meta.ClientEmail = metadata.Properties["client_email"]
- meta.ClientID = metadata.Properties["client_id"]
- meta.AuthURI = metadata.Properties["auth_uri"]
- meta.TokenURI = metadata.Properties["token_uri"]
- meta.AuthProviderCertURL = metadata.Properties["auth_provider_x509_cert_url"]
- meta.ClientCertURL = metadata.Properties["client_x509_cert_url"]
-
- if val, ok := metadata.Properties["entity_kind"]; ok && val != "" {
- meta.EntityKind = val
- }
-
- return &meta, nil
+ return &m, nil
+}
+
+func (f *Firestore) GetComponentMetadata() map[string]string {
+ metadataStruct := firestoreMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
}
diff --git a/state/hashicorp/consul/consul.go b/state/hashicorp/consul/consul.go
index 5387623d8..5f47494d7 100644
--- a/state/hashicorp/consul/consul.go
+++ b/state/hashicorp/consul/consul.go
@@ -17,13 +17,15 @@ import (
"context"
"encoding/json"
"fmt"
+ "reflect"
- "github.com/agrea/ptr"
"github.com/hashicorp/consul/api"
"github.com/pkg/errors"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
// Consul is a state store implementation for HashiCorp Consul.
@@ -88,18 +90,9 @@ func (c *Consul) Features() []state.Feature {
}
func metadataToConfig(connInfo map[string]string) (*consulConfig, error) {
- b, err := json.Marshal(connInfo)
- if err != nil {
- return nil, err
- }
-
- var config consulConfig
- err = json.Unmarshal(b, &config)
- if err != nil {
- return nil, err
- }
-
- return &config, nil
+ m := &consulConfig{}
+ err := metadata.DecodeMetadata(connInfo, m)
+ return m, err
}
// Get retrieves a Consul KV item.
@@ -121,7 +114,7 @@ func (c *Consul) Get(ctx context.Context, req *state.GetRequest) (*state.GetResp
return &state.GetResponse{
Data: resp.Value,
- ETag: ptr.String(queryMeta.LastContentHash),
+ ETag: ptr.Of(queryMeta.LastContentHash),
}, nil
}
@@ -162,3 +155,10 @@ func (c *Consul) Delete(ctx context.Context, req *state.DeleteRequest) error {
return nil
}
+
+func (c *Consul) GetComponentMetadata() map[string]string {
+ metadataStruct := consulConfig{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/hazelcast/hazelcast.go b/state/hazelcast/hazelcast.go
index 47a30134b..07fb0fd4e 100644
--- a/state/hazelcast/hazelcast.go
+++ b/state/hazelcast/hazelcast.go
@@ -15,23 +15,19 @@ package hazelcast
import (
"context"
- "errors"
"fmt"
+ "reflect"
"strings"
"github.com/hazelcast/hazelcast-go-client"
"github.com/hazelcast/hazelcast-go-client/core"
jsoniter "github.com/json-iterator/go"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
)
-const (
- hazelcastServers = "hazelcastServers"
- hazelcastMap = "hazelcastMap"
-)
-
// Hazelcast state store.
type Hazelcast struct {
state.DefaultBulkStore
@@ -40,6 +36,11 @@ type Hazelcast struct {
logger logger.Logger
}
+type hazelcastMetadata struct {
+ HazelcastServers string
+ HazelcastMap string
+}
+
// NewHazelcastStore returns a new hazelcast backed state store.
func NewHazelcastStore(logger logger.Logger) state.Store {
s := &Hazelcast{
@@ -51,24 +52,29 @@ func NewHazelcastStore(logger logger.Logger) state.Store {
return s
}
-func validateMetadata(metadata state.Metadata) error {
- if metadata.Properties[hazelcastServers] == "" {
- return errors.New("hazelcast error: missing hazelcast servers")
+func validateAndParseMetadata(meta state.Metadata) (*hazelcastMetadata, error) {
+ m := &hazelcastMetadata{}
+ err := metadata.DecodeMetadata(meta.Properties, m)
+ if err != nil {
+ return nil, err
}
- if metadata.Properties[hazelcastMap] == "" {
- return errors.New("hazelcast error: missing hazelcast map name")
+ if m.HazelcastServers == "" {
+ return nil, fmt.Errorf("hazelcast error: missing hazelcast servers")
+ }
+ if m.HazelcastMap == "" {
+ return nil, fmt.Errorf("hazelcast error: missing hazelcast map name")
}
- return nil
+ return m, nil
}
// Init does metadata and connection parsing.
func (store *Hazelcast) Init(metadata state.Metadata) error {
- err := validateMetadata(metadata)
+ meta, err := validateAndParseMetadata(metadata)
if err != nil {
return err
}
- servers := metadata.Properties[hazelcastServers]
+ servers := meta.HazelcastServers
hzConfig := hazelcast.NewConfig()
hzConfig.NetworkConfig().AddAddress(strings.Split(servers, ",")...)
@@ -77,7 +83,7 @@ func (store *Hazelcast) Init(metadata state.Metadata) error {
if err != nil {
return fmt.Errorf("hazelcast error: %v", err)
}
- store.hzMap, err = client.GetMap(metadata.Properties[hazelcastMap])
+ store.hzMap, err = client.GetMap(meta.HazelcastMap)
if err != nil {
return fmt.Errorf("hazelcast error: %v", err)
@@ -151,3 +157,10 @@ func (store *Hazelcast) Delete(ctx context.Context, req *state.DeleteRequest) er
return nil
}
+
+func (store *Hazelcast) GetComponentMetadata() map[string]string {
+ metadataStruct := hazelcastMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/hazelcast/hazelcast_test.go b/state/hazelcast/hazelcast_test.go
index f125d81a0..109f04b43 100644
--- a/state/hazelcast/hazelcast_test.go
+++ b/state/hazelcast/hazelcast_test.go
@@ -28,7 +28,7 @@ func TestValidateMetadata(t *testing.T) {
m := state.Metadata{
Base: metadata.Base{Properties: properties},
}
- err := validateMetadata(m)
+ _, err := validateAndParseMetadata(m)
assert.NotNil(t, err)
})
@@ -39,7 +39,7 @@ func TestValidateMetadata(t *testing.T) {
m := state.Metadata{
Base: metadata.Base{Properties: properties},
}
- err := validateMetadata(m)
+ _, err := validateAndParseMetadata(m)
assert.NotNil(t, err)
})
@@ -50,7 +50,7 @@ func TestValidateMetadata(t *testing.T) {
m := state.Metadata{
Base: metadata.Base{Properties: properties},
}
- err := validateMetadata(m)
+ _, err := validateAndParseMetadata(m)
assert.NotNil(t, err)
})
@@ -62,7 +62,8 @@ func TestValidateMetadata(t *testing.T) {
m := state.Metadata{
Base: metadata.Base{Properties: properties},
}
- err := validateMetadata(m)
+ meta, err := validateAndParseMetadata(m)
assert.Nil(t, err)
+ assert.Equal(t, properties["hazelcastServers"], meta.HazelcastServers)
})
}
diff --git a/state/in-memory/in_memory.go b/state/in-memory/in_memory.go
index 21907fc1b..16ad28e88 100644
--- a/state/in-memory/in_memory.go
+++ b/state/in-memory/in_memory.go
@@ -15,22 +15,29 @@ package inmemory
import (
"context"
+ "encoding/base64"
+ "encoding/json"
+ "errors"
"fmt"
"strconv"
"sync"
"time"
+ "github.com/google/uuid"
jsoniter "github.com/json-iterator/go"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
"github.com/dapr/components-contrib/state"
+ "github.com/dapr/components-contrib/state/utils"
)
type inMemStateStoreItem struct {
- data []byte
- etag *string
- expire int64
+ data []byte
+ etag *string
+ expire *int64
+ isBinary bool
}
type inMemoryStore struct {
@@ -61,10 +68,13 @@ func (store *inMemoryStore) Close() error {
if store.cancel != nil {
store.cancel()
}
+
// release memory reference
store.lock.Lock()
defer store.lock.Unlock()
- store.items = map[string]*inMemStateStoreItem{}
+ for k := range store.items {
+ delete(store.items, k)
+ }
return nil
}
@@ -75,7 +85,7 @@ func (store *inMemoryStore) Features() []state.Feature {
func (store *inMemoryStore) Delete(ctx context.Context, req *state.DeleteRequest) error {
// step1: validate parameters
- if err := store.doDeleteValidateParameters(req); err != nil {
+ if err := state.CheckRequestOptions(req.Options); err != nil {
return err
}
@@ -94,13 +104,17 @@ func (store *inMemoryStore) Delete(ctx context.Context, req *state.DeleteRequest
return nil
}
-func (store *inMemoryStore) doDeleteValidateParameters(req *state.DeleteRequest) error {
- return state.CheckRequestOptions(req.Options)
-}
-
func (store *inMemoryStore) doValidateEtag(key string, etag *string, concurrency string) error {
- if etag != nil && *etag != "" && concurrency == state.FirstWrite {
- // For FirstWrite, we need to validate etag before delete
+ hasEtag := etag != nil && *etag != ""
+
+ if concurrency == state.FirstWrite && !hasEtag {
+ item := store.items[key]
+ if item != nil {
+ return state.NewETagError(state.ETagMismatch, errors.New("item already exists and no etag was passed"))
+ } else {
+ return nil
+ }
+ } else if hasEtag {
item := store.items[key]
if item == nil {
return state.NewETagError(state.ETagMismatch, fmt.Errorf("state not exist or expired for key=%s", key))
@@ -127,9 +141,8 @@ func (store *inMemoryStore) BulkDelete(ctx context.Context, req []state.DeleteRe
}
// step1: validate parameters
-
for i := 0; i < len(req); i++ {
- if err := store.doDeleteValidateParameters(&req[i]); err != nil {
+ if err := state.CheckRequestOptions(&req[i].Options); err != nil {
return err
}
}
@@ -155,14 +168,32 @@ func (store *inMemoryStore) BulkDelete(ctx context.Context, req []state.DeleteRe
func (store *inMemoryStore) Get(ctx context.Context, req *state.GetRequest) (*state.GetResponse, error) {
item := store.doGetWithReadLock(ctx, req.Key)
- if item != nil && isExpired(item.expire) {
+ if item != nil && isExpired(item) {
item = store.doGetWithWriteLock(ctx, req.Key)
}
if item == nil {
return &state.GetResponse{Data: nil, ETag: nil}, nil
}
- return &state.GetResponse{Data: unmarshal(item.data), ETag: item.etag}, nil
+
+ data := item.data
+ if item.isBinary {
+ var (
+ s string
+ err error
+ )
+
+ if err = jsoniter.Unmarshal(data, &s); err != nil {
+ return nil, err
+ }
+
+ data, err = base64.StdEncoding.DecodeString(s)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return &state.GetResponse{Data: data, ETag: item.etag}, nil
}
func (store *inMemoryStore) doGetWithReadLock(ctx context.Context, key string) *inMemStateStoreItem {
@@ -180,24 +211,36 @@ func (store *inMemoryStore) doGetWithWriteLock(ctx context.Context, key string)
if item == nil {
return nil
}
- if isExpired(item.expire) {
+ if isExpired(item) {
store.doDelete(ctx, key)
return nil
}
return item
}
-func isExpired(expire int64) bool {
- if expire <= 0 {
+func isExpired(item *inMemStateStoreItem) bool {
+ if item == nil || item.expire == nil {
return false
}
- return time.Now().UnixMilli() > expire
+ return time.Now().UnixMilli() > *item.expire
}
func (store *inMemoryStore) BulkGet(ctx context.Context, req []state.GetRequest) (bool, []state.BulkGetResponse, error) {
return false, nil, nil
}
+func (store *inMemoryStore) marshal(v any) (bt []byte, isBinary bool, err error) {
+ byteArray, isBinary := v.([]uint8)
+ if isBinary {
+ v = base64.StdEncoding.EncodeToString(byteArray)
+ }
+ bt, err = utils.Marshal(v, json.Marshal)
+ if err != nil {
+ return nil, false, err
+ }
+ return bt, isBinary, nil
+}
+
func (store *inMemoryStore) Set(ctx context.Context, req *state.SetRequest) error {
// step1: validate parameters
ttlInSeconds, err := store.doSetValidateParameters(req)
@@ -205,31 +248,36 @@ func (store *inMemoryStore) Set(ctx context.Context, req *state.SetRequest) erro
return err
}
- b, _ := marshal(req.Value)
// step2 and step3 should be protected by write-lock
store.lock.Lock()
defer store.lock.Unlock()
// step2: validate etag if needed
- if err := store.doValidateEtag(req.Key, req.ETag, req.Options.Concurrency); err != nil {
+ err = store.doValidateEtag(req.Key, req.ETag, req.Options.Concurrency)
+ if err != nil {
return err
}
// step3: do really set
+ bt, isBinary, err := store.marshal(req.Value)
+ if err != nil {
+ return err
+ }
+
// this operation won't fail
- store.doSet(ctx, req.Key, b, req.ETag, ttlInSeconds)
+ store.doSet(ctx, req.Key, bt, ttlInSeconds, isBinary)
return nil
}
func (store *inMemoryStore) doSetValidateParameters(req *state.SetRequest) (int, error) {
err := state.CheckRequestOptions(req.Options)
if err != nil {
- return -1, err
+ return 0, err
}
ttlInSeconds, err := doParseTTLInSeconds(req.Metadata)
if err != nil {
- return -1, err
+ return 0, err
}
return ttlInSeconds, nil
@@ -253,19 +301,26 @@ func doParseTTLInSeconds(metadata map[string]string) (int, error) {
return i, nil
}
-func (store *inMemoryStore) doSet(ctx context.Context, key string, data []byte, etag *string, ttlInSeconds int) {
- store.items[key] = &inMemStateStoreItem{
- data: data,
- etag: etag,
- expire: time.Now().UnixMilli() + int64(ttlInSeconds)*1000,
+func (store *inMemoryStore) doSet(ctx context.Context, key string, data []byte, ttlInSeconds int, isBinary bool) {
+ etag := uuid.New().String()
+ el := &inMemStateStoreItem{
+ data: data,
+ etag: &etag,
+ isBinary: isBinary,
}
+ if ttlInSeconds > 0 {
+ el.expire = ptr.Of(time.Now().UnixMilli() + int64(ttlInSeconds)*1000)
+ }
+
+ store.items[key] = el
}
// innerSetRequest is only used to pass ttlInSeconds and data with SetRequest.
type innerSetRequest struct {
- req state.SetRequest
- ttlInSeconds int
- data []byte
+ req state.SetRequest
+ ttl int
+ data []byte
+ isBinary bool
}
func (store *inMemoryStore) BulkSet(ctx context.Context, req []state.SetRequest) error {
@@ -281,11 +336,15 @@ func (store *inMemoryStore) BulkSet(ctx context.Context, req []state.SetRequest)
return err
}
- b, _ := marshal(req[i].Value)
+ bt, isBinary, err := store.marshal(req[i].Value)
+ if err != nil {
+ return err
+ }
innerSetRequest := &innerSetRequest{
- req: req[i],
- ttlInSeconds: ttlInSeconds,
- data: b,
+ req: req[i],
+ ttl: ttlInSeconds,
+ data: bt,
+ isBinary: isBinary,
}
innerSetRequestList = append(innerSetRequestList, innerSetRequest)
}
@@ -305,7 +364,7 @@ func (store *inMemoryStore) BulkSet(ctx context.Context, req []state.SetRequest)
// step3: do really set
// these operations won't fail
for _, innerSetRequest := range innerSetRequestList {
- store.doSet(ctx, innerSetRequest.req.Key, innerSetRequest.data, innerSetRequest.req.ETag, innerSetRequest.ttlInSeconds)
+ store.doSet(ctx, innerSetRequest.req.Key, innerSetRequest.data, innerSetRequest.ttl, innerSetRequest.isBinary)
}
return nil
}
@@ -316,24 +375,28 @@ func (store *inMemoryStore) Multi(ctx context.Context, request *state.Transactio
}
// step1: validate parameters
- for _, o := range request.Operations {
+ for i, o := range request.Operations {
if o.Operation == state.Upsert {
s := o.Request.(state.SetRequest)
ttlInSeconds, err := store.doSetValidateParameters(&s)
if err != nil {
return err
}
- b, _ := marshal(s.Value)
+ bt, isBinary, err := store.marshal(s.Value)
+ if err != nil {
+ return err
+ }
innerSetRequest := &innerSetRequest{
- req: s,
- ttlInSeconds: ttlInSeconds,
- data: b,
+ req: s,
+ ttl: ttlInSeconds,
+ data: bt,
+ isBinary: isBinary,
}
// replace with innerSetRequest
- o.Request = innerSetRequest
+ request.Operations[i].Request = innerSetRequest
} else if o.Operation == state.Delete {
d := o.Request.(state.DeleteRequest)
- err := store.doDeleteValidateParameters(&d)
+ err := state.CheckRequestOptions(&d)
if err != nil {
return err
}
@@ -347,7 +410,7 @@ func (store *inMemoryStore) Multi(ctx context.Context, request *state.Transactio
// step2: validate etag if needed
for _, o := range request.Operations {
if o.Operation == state.Upsert {
- s := o.Request.(innerSetRequest)
+ s := o.Request.(*innerSetRequest)
err := store.doValidateEtag(s.req.Key, s.req.ETag, s.req.Options.Concurrency)
if err != nil {
return err
@@ -365,8 +428,8 @@ func (store *inMemoryStore) Multi(ctx context.Context, request *state.Transactio
// these operations won't fail
for _, o := range request.Operations {
if o.Operation == state.Upsert {
- s := o.Request.(innerSetRequest)
- store.doSet(ctx, s.req.Key, s.data, s.req.ETag, s.ttlInSeconds)
+ s := o.Request.(*innerSetRequest)
+ store.doSet(ctx, s.req.Key, s.data, s.ttl, s.isBinary)
} else if o.Operation == state.Delete {
d := o.Request.(state.DeleteRequest)
store.doDelete(ctx, d.Key)
@@ -375,20 +438,6 @@ func (store *inMemoryStore) Multi(ctx context.Context, request *state.Transactio
return nil
}
-func marshal(value interface{}) ([]byte, error) {
- v, _ := jsoniter.MarshalToString(value)
-
- return []byte(v), nil
-}
-
-func unmarshal(val interface{}) []byte {
- var output string
-
- jsoniter.UnmarshalFromString(string(val.([]byte)), &output)
-
- return []byte(output)
-}
-
func (store *inMemoryStore) startCleanThread() {
for {
select {
@@ -405,8 +454,13 @@ func (store *inMemoryStore) doCleanExpiredItems() {
defer store.lock.Unlock()
for key, item := range store.items {
- if isExpired(item.expire) {
+ if item.expire != nil && isExpired(item) {
store.doDelete(context.Background(), key)
}
}
}
+
+func (store *inMemoryStore) GetComponentMetadata() map[string]string {
+ // no metadata, hence no metadata struct to convert here
+ return map[string]string{}
+}
diff --git a/state/in-memory/in_memory_test.go b/state/in-memory/in_memory_test.go
index 9f93242e5..bdd4e857d 100644
--- a/state/in-memory/in_memory_test.go
+++ b/state/in-memory/in_memory_test.go
@@ -18,7 +18,6 @@ import (
"testing"
"time"
- "github.com/agrea/ptr"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
@@ -42,7 +41,6 @@ func TestReadAndWrite(t *testing.T) {
setReq := &state.SetRequest{
Key: keyA,
Value: valueA,
- ETag: ptr.String("the etag"),
}
err := store.Set(context.Background(), setReq)
assert.Nil(t, err)
@@ -51,9 +49,11 @@ func TestReadAndWrite(t *testing.T) {
Key: keyA,
}
resp, err := store.Get(context.Background(), getReq)
- assert.Nil(t, err)
+ assert.NoError(t, err)
assert.NotNil(t, resp)
- assert.Equal(t, valueA, string(resp.Data))
+ assert.Equal(t, `"`+valueA+`"`, string(resp.Data))
+ _ = assert.NotNil(t, resp.ETag) &&
+ assert.NotEmpty(t, *resp.ETag)
})
t.Run("get nothing when expired", func(t *testing.T) {
@@ -64,7 +64,7 @@ func TestReadAndWrite(t *testing.T) {
Metadata: map[string]string{"ttlInSeconds": "1"},
}
err := store.Set(context.Background(), setReq)
- assert.Nil(t, err)
+ assert.NoError(t, err)
// simulate expiration
time.Sleep(2 * time.Second)
// get
@@ -72,7 +72,7 @@ func TestReadAndWrite(t *testing.T) {
Key: keyA,
}
resp, err := store.Get(context.Background(), getReq)
- assert.Nil(t, err)
+ assert.NoError(t, err)
assert.NotNil(t, resp)
assert.Nil(t, resp.Data)
assert.Nil(t, resp.ETag)
@@ -82,31 +82,30 @@ func TestReadAndWrite(t *testing.T) {
// set
setReq := &state.SetRequest{
Key: "theSecondKey",
- Value: "1234",
- ETag: ptr.String("the etag"),
+ Value: 1234,
}
err := store.Set(context.Background(), setReq)
- assert.Nil(t, err)
+ assert.NoError(t, err)
// get
getReq := &state.GetRequest{
Key: "theSecondKey",
}
resp, err := store.Get(context.Background(), getReq)
- assert.Nil(t, err)
+ assert.NoError(t, err)
assert.NotNil(t, resp)
- assert.Equal(t, "1234", string(resp.Data))
+ assert.Equal(t, `1234`, string(resp.Data))
})
t.Run("BulkSet two keys", func(t *testing.T) {
err := store.BulkSet(context.Background(), []state.SetRequest{{
Key: "theFirstKey",
- Value: "666",
+ Value: "42",
}, {
Key: "theSecondKey",
- Value: "777",
+ Value: "84",
}})
- assert.Nil(t, err)
+ assert.NoError(t, err)
})
t.Run("BulkGet fails when not supported", func(t *testing.T) {
@@ -116,7 +115,7 @@ func TestReadAndWrite(t *testing.T) {
Key: "theSecondKey",
}})
- assert.Nil(t, err)
+ assert.NoError(t, err)
assert.Equal(t, false, supportBulk)
})
@@ -125,6 +124,6 @@ func TestReadAndWrite(t *testing.T) {
Key: "theFirstKey",
}
err := store.Delete(context.Background(), req)
- assert.Nil(t, err)
+ assert.NoError(t, err)
})
}
diff --git a/state/jetstream/jetstream.go b/state/jetstream/jetstream.go
index 998ef1333..bf8f77a6b 100644
--- a/state/jetstream/jetstream.go
+++ b/state/jetstream/jetstream.go
@@ -16,10 +16,12 @@ package jetstream
import (
"context"
"fmt"
+ "reflect"
"strings"
jsoniter "github.com/json-iterator/go"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/components-contrib/state/utils"
"github.com/dapr/kit/logger"
@@ -38,11 +40,11 @@ type StateStore struct {
}
type jetstreamMetadata struct {
- name string
- natsURL string
- jwt string
- seedKey string
- bucket string
+ Name string
+ NatsURL string
+ Jwt string
+ SeedKey string
+ Bucket string
}
// NewJetstreamStateStore returns a new nats jetstream KV state store.
@@ -64,18 +66,18 @@ func (js *StateStore) Init(metadata state.Metadata) error {
}
var opts []nats.Option
- opts = append(opts, nats.Name(meta.name))
+ opts = append(opts, nats.Name(meta.Name))
// Set nats.UserJWT options when jwt and seed key is provided.
- if meta.jwt != "" && meta.seedKey != "" {
+ if meta.Jwt != "" && meta.SeedKey != "" {
opts = append(opts, nats.UserJWT(func() (string, error) {
- return meta.jwt, nil
+ return meta.Jwt, nil
}, func(nonce []byte) ([]byte, error) {
- return sigHandler(meta.seedKey, nonce)
+ return sigHandler(meta.SeedKey, nonce)
}))
}
- js.nc, err = nats.Connect(meta.natsURL, opts...)
+ js.nc, err = nats.Connect(meta.NatsURL, opts...)
if err != nil {
return err
}
@@ -85,7 +87,7 @@ func (js *StateStore) Init(metadata state.Metadata) error {
return err
}
- js.bucket, err = jsc.KeyValue(meta.bucket)
+ js.bucket, err = jsc.KeyValue(meta.Bucket)
if err != nil {
return err
}
@@ -121,31 +123,30 @@ func (js *StateStore) Delete(ctx context.Context, req *state.DeleteRequest) erro
return js.bucket.Delete(escape(req.Key))
}
-func (js *StateStore) getMetadata(metadata state.Metadata) (jetstreamMetadata, error) {
+func (js *StateStore) getMetadata(meta state.Metadata) (jetstreamMetadata, error) {
var m jetstreamMetadata
+ err := metadata.DecodeMetadata(meta.Properties, &m)
+ if err != nil {
+ return jetstreamMetadata{}, err
+ }
- if v, ok := metadata.Properties["natsURL"]; ok && v != "" {
- m.natsURL = v
- } else {
+ if m.NatsURL == "" {
return jetstreamMetadata{}, fmt.Errorf("missing nats URL")
}
- m.jwt = metadata.Properties["jwt"]
- m.seedKey = metadata.Properties["seedKey"]
-
- if m.jwt != "" && m.seedKey == "" {
+ if m.Jwt != "" && m.SeedKey == "" {
return jetstreamMetadata{}, fmt.Errorf("missing seed key")
}
- if m.jwt == "" && m.seedKey != "" {
+ if m.Jwt == "" && m.SeedKey != "" {
return jetstreamMetadata{}, fmt.Errorf("missing jwt")
}
- if m.name = metadata.Properties["name"]; m.name == "" {
- m.name = "dapr.io - statestore.jetstream"
+ if m.Name == "" {
+ m.Name = "dapr.io - statestore.jetstream"
}
- if m.bucket = metadata.Properties["bucket"]; m.bucket == "" {
+ if m.Bucket == "" {
return jetstreamMetadata{}, fmt.Errorf("missing bucket")
}
@@ -169,3 +170,10 @@ func sigHandler(seedKey string, nonce []byte) ([]byte, error) {
func escape(key string) string {
return strings.ReplaceAll(key, "||", ".")
}
+
+func (js *StateStore) GetComponentMetadata() map[string]string {
+ metadataStruct := jetstreamMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/memcached/memcached.go b/state/memcached/memcached.go
index 921cb5ddc..8ef93a85b 100644
--- a/state/memcached/memcached.go
+++ b/state/memcached/memcached.go
@@ -17,20 +17,20 @@ import (
"context"
"errors"
"fmt"
+ "reflect"
"strconv"
- "strings"
"time"
"github.com/bradfitz/gomemcache/memcache"
jsoniter "github.com/json-iterator/go"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/components-contrib/state/utils"
"github.com/dapr/kit/logger"
)
const (
- hosts = "hosts"
maxIdleConnections = "maxIdleConnections"
timeout = "timeout"
ttlInSeconds = "ttlInSeconds"
@@ -47,9 +47,9 @@ type Memcached struct {
}
type memcachedMetadata struct {
- hosts []string
- maxIdleConnections int
- timeout time.Duration
+ Hosts []string
+ MaxIdleConnections int
+ Timeout int
}
func NewMemCacheStateStore(logger logger.Logger) state.Store {
@@ -68,9 +68,13 @@ func (m *Memcached) Init(metadata state.Metadata) error {
return err
}
- client := memcache.New(meta.hosts...)
- client.Timeout = meta.timeout
- client.MaxIdleConns = meta.maxIdleConnections
+ client := memcache.New(meta.Hosts...)
+ if meta.Timeout < 0 {
+ client.Timeout = defaultTimeout
+ } else {
+ client.Timeout = time.Duration(meta.Timeout) * time.Millisecond
+ }
+ client.MaxIdleConns = meta.MaxIdleConnections
m.client = client
@@ -87,35 +91,38 @@ func (m *Memcached) Features() []state.Feature {
return nil
}
-func getMemcachedMetadata(metadata state.Metadata) (*memcachedMetadata, error) {
- meta := memcachedMetadata{
- maxIdleConnections: defaultMaxIdleConnections,
- timeout: defaultTimeout,
+func getMemcachedMetadata(meta state.Metadata) (*memcachedMetadata, error) {
+ m := memcachedMetadata{
+ MaxIdleConnections: defaultMaxIdleConnections,
+ Timeout: -1,
}
- if val, ok := metadata.Properties[hosts]; ok && val != "" {
- meta.hosts = strings.Split(val, ",")
- } else {
+ err := metadata.DecodeMetadata(meta.Properties, &m)
+ if err != nil {
+ return nil, err
+ }
+
+ if m.Hosts == nil || len(m.Hosts) == 0 {
return nil, errors.New("missing or empty hosts field from metadata")
}
- if val, ok := metadata.Properties[maxIdleConnections]; ok && val != "" {
+ if val, ok := meta.Properties[maxIdleConnections]; ok && val != "" {
p, err := strconv.Atoi(val)
if err != nil {
return nil, fmt.Errorf("error parsing maxIdleConnections")
}
- meta.maxIdleConnections = p
+ m.MaxIdleConnections = p
}
- if val, ok := metadata.Properties[timeout]; ok && val != "" {
+ if val, ok := meta.Properties[timeout]; ok && val != "" {
p, err := strconv.Atoi(val)
if err != nil {
return nil, fmt.Errorf("error parsing timeout")
}
- meta.timeout = time.Duration(p) * time.Millisecond
+ m.Timeout = p
}
- return &meta, nil
+ return &m, nil
}
func (m *Memcached) parseTTL(req *state.SetRequest) (*int32, error) {
@@ -140,7 +147,7 @@ func (m *Memcached) parseTTL(req *state.SetRequest) (*int32, error) {
return nil, nil
}
-func (m *Memcached) setValue(ctx context.Context, req *state.SetRequest) error {
+func (m *Memcached) Set(ctx context.Context, req *state.SetRequest) error {
var bt []byte
ttl, err := m.parseTTL(req)
if err != nil {
@@ -188,6 +195,9 @@ func (m *Memcached) Get(ctx context.Context, req *state.GetRequest) (*state.GetR
}, nil
}
-func (m *Memcached) Set(ctx context.Context, req *state.SetRequest) error {
- return state.SetWithOptions(ctx, m.setValue, req)
+func (m *Memcached) GetComponentMetadata() map[string]string {
+ metadataStruct := memcachedMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
}
diff --git a/state/memcached/memcached_test.go b/state/memcached/memcached_test.go
index a6d3899be..cd45a1c20 100644
--- a/state/memcached/memcached_test.go
+++ b/state/memcached/memcached_test.go
@@ -45,9 +45,9 @@ func TestMemcachedMetadata(t *testing.T) {
}
metadata, err := getMemcachedMetadata(m)
assert.Nil(t, err)
- assert.Equal(t, properties["hosts"], metadata.hosts[0])
- assert.Equal(t, defaultMaxIdleConnections, metadata.maxIdleConnections)
- assert.Equal(t, defaultTimeout, metadata.timeout)
+ assert.Equal(t, properties["hosts"], metadata.Hosts[0])
+ assert.Equal(t, defaultMaxIdleConnections, metadata.MaxIdleConnections)
+ assert.Equal(t, -1, metadata.Timeout)
})
t.Run("with required configuration, multiple host", func(t *testing.T) {
@@ -60,9 +60,9 @@ func TestMemcachedMetadata(t *testing.T) {
split := strings.Split(properties["hosts"], ",")
metadata, err := getMemcachedMetadata(m)
assert.Nil(t, err)
- assert.Equal(t, split, metadata.hosts)
- assert.Equal(t, defaultMaxIdleConnections, metadata.maxIdleConnections)
- assert.Equal(t, defaultTimeout, metadata.timeout)
+ assert.Equal(t, split, metadata.Hosts)
+ assert.Equal(t, defaultMaxIdleConnections, metadata.MaxIdleConnections)
+ assert.Equal(t, -1, metadata.Timeout)
})
t.Run("with optional configuration, multiple hosts", func(t *testing.T) {
@@ -77,9 +77,9 @@ func TestMemcachedMetadata(t *testing.T) {
split := strings.Split(properties["hosts"], ",")
metadata, err := getMemcachedMetadata(m)
assert.Nil(t, err)
- assert.Equal(t, split, metadata.hosts)
- assert.Equal(t, 10, metadata.maxIdleConnections)
- assert.Equal(t, 5000*time.Millisecond, metadata.timeout)
+ assert.Equal(t, split, metadata.Hosts)
+ assert.Equal(t, 10, metadata.MaxIdleConnections)
+ assert.Equal(t, int(5000*time.Millisecond), metadata.Timeout*int(time.Millisecond))
})
}
diff --git a/state/mongodb/mongodb.go b/state/mongodb/mongodb.go
index f87fa0dff..0ee1aff47 100644
--- a/state/mongodb/mongodb.go
+++ b/state/mongodb/mongodb.go
@@ -20,10 +20,10 @@ import (
"encoding/json"
"errors"
"fmt"
+ "reflect"
"strconv"
"time"
- "github.com/agrea/ptr"
"github.com/google/uuid"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
@@ -32,9 +32,11 @@ import (
"go.mongodb.org/mongo-driver/mongo/readconcern"
"go.mongodb.org/mongo-driver/mongo/writeconcern"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/components-contrib/state/query"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
const (
@@ -44,8 +46,6 @@ const (
databaseName = "databaseName"
collectionName = "collectionName"
server = "server"
- writeConcern = "writeConcern"
- readConcern = "readConcern"
operationTimeout = "operationTimeout"
params = "params"
id = "_id"
@@ -82,16 +82,16 @@ type MongoDB struct {
}
type mongoDBMetadata struct {
- host string
- username string
- password string
- databaseName string
- collectionName string
- server string
- writeconcern string
- readconcern string
- params string
- operationTimeout time.Duration
+ Host string
+ Username string
+ Password string
+ DatabaseName string
+ CollectionName string
+ Server string
+ Writeconcern string
+ Readconcern string
+ Params string
+ OperationTimeout time.Duration
}
// Item is Mongodb document wrapper.
@@ -119,7 +119,7 @@ func (m *MongoDB) Init(metadata state.Metadata) error {
return err
}
- m.operationTimeout = meta.operationTimeout
+ m.operationTimeout = meta.OperationTimeout
client, err := getMongoDBClient(meta)
if err != nil {
@@ -127,26 +127,26 @@ func (m *MongoDB) Init(metadata state.Metadata) error {
}
if err = client.Ping(context.Background(), nil); err != nil {
- return fmt.Errorf("error in connecting to mongodb, host: %s error: %s", meta.host, err)
+ return fmt.Errorf("error in connecting to mongodb, host: %s error: %s", meta.Host, err)
}
m.client = client
// get the write concern
- wc, err := getWriteConcernObject(meta.writeconcern)
+ wc, err := getWriteConcernObject(meta.Writeconcern)
if err != nil {
return fmt.Errorf("error in getting write concern object: %s", err)
}
// get the read concern
- rc, err := getReadConcernObject(meta.readconcern)
+ rc, err := getReadConcernObject(meta.Readconcern)
if err != nil {
return fmt.Errorf("error in getting read concern object: %s", err)
}
m.metadata = *meta
opts := options.Collection().SetWriteConcern(wc).SetReadConcern(rc)
- collection := m.client.Database(meta.databaseName).Collection(meta.collectionName, opts)
+ collection := m.client.Database(meta.DatabaseName).Collection(meta.CollectionName, opts)
m.collection = collection
@@ -170,7 +170,7 @@ func (m *MongoDB) Set(ctx context.Context, req *state.SetRequest) error {
func (m *MongoDB) Ping() error {
if err := m.client.Ping(context.Background(), nil); err != nil {
- return fmt.Errorf("mongoDB store: error connecting to mongoDB at %s: %s", m.metadata.host, err)
+ return fmt.Errorf("mongoDB store: error connecting to mongoDB at %s: %s", m.metadata.Host, err)
}
return nil
@@ -253,7 +253,7 @@ func (m *MongoDB) Get(ctx context.Context, req *state.GetRequest) (*state.GetRes
return &state.GetResponse{
Data: data,
- ETag: ptr.String(result.Etag),
+ ETag: ptr.Of(result.Etag),
}, nil
}
@@ -345,19 +345,19 @@ func (m *MongoDB) Query(ctx context.Context, req *state.QueryRequest) (*state.Qu
}
func getMongoURI(metadata *mongoDBMetadata) string {
- if len(metadata.server) != 0 {
- if metadata.username != "" && metadata.password != "" {
- return fmt.Sprintf(connectionURIFormatWithSrvAndCredentials, metadata.username, metadata.password, metadata.server, metadata.databaseName, metadata.params)
+ if len(metadata.Server) != 0 {
+ if metadata.Username != "" && metadata.Password != "" {
+ return fmt.Sprintf(connectionURIFormatWithSrvAndCredentials, metadata.Username, metadata.Password, metadata.Server, metadata.DatabaseName, metadata.Params)
}
- return fmt.Sprintf(connectionURIFormatWithSrv, metadata.server, metadata.params)
+ return fmt.Sprintf(connectionURIFormatWithSrv, metadata.Server, metadata.Params)
}
- if metadata.username != "" && metadata.password != "" {
- return fmt.Sprintf(connectionURIFormatWithAuthentication, metadata.username, metadata.password, metadata.host, metadata.databaseName, metadata.params)
+ if metadata.Username != "" && metadata.Password != "" {
+ return fmt.Sprintf(connectionURIFormatWithAuthentication, metadata.Username, metadata.Password, metadata.Host, metadata.DatabaseName, metadata.Params)
}
- return fmt.Sprintf(connectionURIFormat, metadata.host, metadata.databaseName, metadata.params)
+ return fmt.Sprintf(connectionURIFormat, metadata.Host, metadata.DatabaseName, metadata.Params)
}
func getMongoDBClient(metadata *mongoDBMetadata) (*mongo.Client, error) {
@@ -367,7 +367,7 @@ func getMongoDBClient(metadata *mongoDBMetadata) (*mongo.Client, error) {
clientOptions := options.Client().ApplyURI(uri)
// Connect to MongoDB
- ctx, cancel := context.WithTimeout(context.Background(), metadata.operationTimeout)
+ ctx, cancel := context.WithTimeout(context.Background(), metadata.OperationTimeout)
defer cancel()
daprUserAgent := "dapr-" + logger.DaprVersion
@@ -385,66 +385,35 @@ func getMongoDBClient(metadata *mongoDBMetadata) (*mongo.Client, error) {
return client, nil
}
-func getMongoDBMetaData(metadata state.Metadata) (*mongoDBMetadata, error) {
- meta := mongoDBMetadata{
- databaseName: defaultDatabaseName,
- collectionName: defaultCollectionName,
- operationTimeout: defaultTimeout,
+func getMongoDBMetaData(meta state.Metadata) (*mongoDBMetadata, error) {
+ m := mongoDBMetadata{
+ DatabaseName: defaultDatabaseName,
+ CollectionName: defaultCollectionName,
+ OperationTimeout: defaultTimeout,
}
- if val, ok := metadata.Properties[host]; ok && val != "" {
- meta.host = val
+ decodeErr := metadata.DecodeMetadata(meta.Properties, &m)
+ if decodeErr != nil {
+ return nil, decodeErr
}
- if val, ok := metadata.Properties[server]; ok && val != "" {
- meta.server = val
- }
-
- if len(meta.host) == 0 && len(meta.server) == 0 {
+ if len(m.Host) == 0 && len(m.Server) == 0 {
return nil, errors.New("must set 'host' or 'server' fields in metadata")
}
- if len(meta.host) != 0 && len(meta.server) != 0 {
+ if len(m.Host) != 0 && len(m.Server) != 0 {
return nil, errors.New("'host' or 'server' fields are mutually exclusive")
}
- if val, ok := metadata.Properties[username]; ok && val != "" {
- meta.username = val
- }
-
- if val, ok := metadata.Properties[password]; ok && val != "" {
- meta.password = val
- }
-
- if val, ok := metadata.Properties[databaseName]; ok && val != "" {
- meta.databaseName = val
- }
-
- if val, ok := metadata.Properties[collectionName]; ok && val != "" {
- meta.collectionName = val
- }
-
- if val, ok := metadata.Properties[writeConcern]; ok && val != "" {
- meta.writeconcern = val
- }
-
- if val, ok := metadata.Properties[readConcern]; ok && val != "" {
- meta.readconcern = val
- }
-
- if val, ok := metadata.Properties[params]; ok && val != "" {
- meta.params = val
- }
-
var err error
- if val, ok := metadata.Properties[operationTimeout]; ok && val != "" {
- meta.operationTimeout, err = time.ParseDuration(val)
+ if val, ok := meta.Properties[operationTimeout]; ok && val != "" {
+ m.OperationTimeout, err = time.ParseDuration(val)
if err != nil {
return nil, errors.New("incorrect operationTimeout field from metadata")
}
}
- return &meta, nil
+ return &m, nil
}
func getWriteConcernObject(cn string) (*writeconcern.WriteConcern, error) {
@@ -483,3 +452,10 @@ func getReadConcernObject(cn string) (*readconcern.ReadConcern, error) {
return nil, fmt.Errorf("readConcern %s not found", cn)
}
+
+func (m *MongoDB) GetComponentMetadata() map[string]string {
+ metadataStruct := mongoDBMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/mongodb/mongodb_test.go b/state/mongodb/mongodb_test.go
index 88c677cbe..80cf8867b 100644
--- a/state/mongodb/mongodb_test.go
+++ b/state/mongodb/mongodb_test.go
@@ -33,9 +33,9 @@ func TestGetMongoDBMetadata(t *testing.T) {
metadata, err := getMongoDBMetaData(m)
assert.Nil(t, err)
- assert.Equal(t, properties[host], metadata.host)
- assert.Equal(t, defaultDatabaseName, metadata.databaseName)
- assert.Equal(t, defaultCollectionName, metadata.collectionName)
+ assert.Equal(t, properties[host], metadata.Host)
+ assert.Equal(t, defaultDatabaseName, metadata.DatabaseName)
+ assert.Equal(t, defaultCollectionName, metadata.CollectionName)
})
t.Run("With custom values", func(t *testing.T) {
@@ -52,11 +52,11 @@ func TestGetMongoDBMetadata(t *testing.T) {
metadata, err := getMongoDBMetaData(m)
assert.Nil(t, err)
- assert.Equal(t, properties[host], metadata.host)
- assert.Equal(t, properties[databaseName], metadata.databaseName)
- assert.Equal(t, properties[collectionName], metadata.collectionName)
- assert.Equal(t, properties[username], metadata.username)
- assert.Equal(t, properties[password], metadata.password)
+ assert.Equal(t, properties[host], metadata.Host)
+ assert.Equal(t, properties[databaseName], metadata.DatabaseName)
+ assert.Equal(t, properties[collectionName], metadata.CollectionName)
+ assert.Equal(t, properties[username], metadata.Username)
+ assert.Equal(t, properties[password], metadata.Password)
})
t.Run("Missing hosts", func(t *testing.T) {
diff --git a/state/mysql/mysql.go b/state/mysql/mysql.go
index f4c1d6766..d0a89f911 100644
--- a/state/mysql/mysql.go
+++ b/state/mysql/mysql.go
@@ -20,15 +20,16 @@ import (
"encoding/json"
"errors"
"fmt"
+ "reflect"
"strconv"
"strings"
"time"
"github.com/google/uuid"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
- "github.com/dapr/kit/ptr"
)
// Optimistic Concurrency is implemented using a string column that stores a UUID.
@@ -86,6 +87,14 @@ type MySQL struct {
factory iMySQLFactory
}
+type mySQLMetadata struct {
+ TableName string
+ SchemaName string
+ ConnectionString string
+ Timeout int
+ PemPath string
+}
+
// NewMySQLStateStore creates a new instance of MySQL state store.
func NewMySQLStateStore(logger logger.Logger) state.Store {
factory := newMySQLFactory(logger)
@@ -131,46 +140,46 @@ func (m *MySQL) Init(metadata state.Metadata) error {
}
func (m *MySQL) parseMetadata(md map[string]string) error {
- val, ok := md[keyTableName]
- if ok && val != "" {
+ meta := mySQLMetadata{
+ TableName: defaultTableName,
+ SchemaName: defaultSchemaName,
+ }
+ err := metadata.DecodeMetadata(md, &meta)
+ if err != nil {
+ return err
+ }
+
+ if meta.TableName != "" {
// Sanitize the table name
- if !validIdentifier(val) {
- return fmt.Errorf("table name '%s' is not valid", val)
+ if !validIdentifier(meta.TableName) {
+ return fmt.Errorf("table name '%s' is not valid", meta.TableName)
}
- m.tableName = val
- } else {
- // Default to the constant
- m.tableName = defaultTableName
}
+ m.tableName = meta.TableName
- val, ok = md[keySchemaName]
- if ok && val != "" {
+ if meta.SchemaName != "" {
// Sanitize the schema name
- if !validIdentifier(val) {
- return fmt.Errorf("schema name '%s' is not valid", val)
+ if !validIdentifier(meta.SchemaName) {
+ return fmt.Errorf("schema name '%s' is not valid", meta.SchemaName)
}
- m.schemaName = val
- } else {
- // Default to the constant
- m.schemaName = defaultSchemaName
}
+ m.schemaName = meta.SchemaName
- m.connectionString, ok = md[keyConnectionString]
- if !ok || m.connectionString == "" {
+ if meta.ConnectionString == "" {
m.logger.Error("Missing MySql connection string")
return fmt.Errorf(errMissingConnectionString)
}
+ m.connectionString = meta.ConnectionString
- val, ok = md[keyPemPath]
- if ok && val != "" {
- err := m.factory.RegisterTLSConfig(val)
+ if meta.PemPath != "" {
+ err := m.factory.RegisterTLSConfig(meta.PemPath)
if err != nil {
m.logger.Error(err)
return err
}
}
- val, ok = md[keyTimeoutInSeconds]
+ val, ok := md[keyTimeoutInSeconds]
if ok && val != "" {
n, err := strconv.Atoi(val)
if err == nil && n > 0 {
@@ -454,14 +463,14 @@ func (m *MySQL) Get(parentCtx context.Context, req *state.GetRequest) (*state.Ge
return &state.GetResponse{
Data: data,
- ETag: ptr.Of(eTag),
+ ETag: &eTag,
Metadata: req.Metadata,
}, nil
}
return &state.GetResponse{
Data: value,
- ETag: ptr.Of(eTag),
+ ETag: &eTag,
Metadata: req.Metadata,
}, nil
}
@@ -728,3 +737,10 @@ type querier interface {
QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
}
+
+func (m *MySQL) GetComponentMetadata() map[string]string {
+ metadataStruct := mySQLMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/oci/objectstorage/objectstorage.go b/state/oci/objectstorage/objectstorage.go
index 8351c821f..75f95f84e 100644
--- a/state/oci/objectstorage/objectstorage.go
+++ b/state/oci/objectstorage/objectstorage.go
@@ -18,8 +18,10 @@ import (
"context"
"fmt"
"io"
+ "net/http"
"os"
"path"
+ "reflect"
"strconv"
"strings"
"time"
@@ -30,6 +32,7 @@ import (
"github.com/oracle/oci-go-sdk/v54/common/auth"
"github.com/oracle/oci-go-sdk/v54/objectstorage"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
)
@@ -39,7 +42,6 @@ const (
instancePrincipalAuthenticationKey = "instancePrincipalAuthentication"
configFileAuthenticationKey = "configFileAuthentication"
configFilePathKey = "configFilePath"
- configFileProfileKey = "configFileProfile"
tenancyKey = "tenancyOCID"
compartmentKey = "compartmentOCID"
regionKey = "region"
@@ -62,19 +64,19 @@ type StateStore struct {
client objectStoreClient
}
-type Metadata struct {
- userOCID string
- bucketName string
- region string
- tenancyOCID string
- fingerPrint string
- privateKey string
- compartmentOCID string
- namespace string
- configFilePath string
- configFileProfile string
- instancePrincipalAuthentication bool
- configFileAuthentication bool
+type objectStoreMetadata struct {
+ UserOCID string
+ BucketName string
+ Region string
+ TenancyOCID string
+ FingerPrint string
+ PrivateKey string
+ CompartmentOCID string
+ Namespace string
+ ConfigFilePath string
+ ConfigFileProfile string
+ InstancePrincipalAuthentication bool
+ ConfigFileAuthentication bool
OCIObjectStorageClient *objectstorage.ObjectStorageClient
}
@@ -89,7 +91,7 @@ type objectStoreClient interface {
}
type objectStorageClient struct {
- objectStorageMetadata *Metadata
+ objectStorageMetadata *objectStoreMetadata
}
type ociObjectStorageClient struct {
@@ -122,7 +124,7 @@ func (r *StateStore) Init(metadata state.Metadata) error {
if cerr != nil {
return fmt.Errorf("failed to create bucket : %w", cerr)
}
- r.logger.Debugf("OCI Object Storage State Store initialized using bucket '%s'", meta.bucketName)
+ r.logger.Debugf("OCI Object Storage State Store initialized using bucket '%s'", meta.BucketName)
return nil
}
@@ -178,30 +180,8 @@ func NewOCIObjectStorageStore(logger logger.Logger) state.Store {
/************** private helper functions. */
-func getValue(metadata map[string]string, key string, valueRequired bool) (value string, err error) {
- if val, ok := metadata[key]; ok && val != "" {
- return val, nil
- }
- if !valueRequired {
- return "", nil
- }
- return "", fmt.Errorf("missing or empty %s field from metadata", key)
-}
-
-func getOptionalBooleanValue(metadata map[string]string, key string) (value bool, err error) {
- stringValue, _ := getValue(metadata, key, false)
- if stringValue == "" {
- stringValue = "false"
- }
- value, err = strconv.ParseBool(stringValue)
- if err != nil {
- return false, fmt.Errorf("incorrect value %s for %s, should be 'true' or 'false'", stringValue, key)
- }
- return value, nil
-}
-
-func getConfigFilePath(meta map[string]string) (value string, err error) {
- value, _ = getValue(meta, configFilePathKey, false)
+func getConfigFilePath(configFilePath string) (value string, err error) {
+ value = configFilePath
if strings.HasPrefix(value, "~/") {
return "", fmt.Errorf("%s is set to %s which starts with ~/; this is not supported - please provide absolute path to configuration file", configFilePathKey, value)
}
@@ -216,52 +196,51 @@ func getConfigFilePath(meta map[string]string) (value string, err error) {
return value, nil
}
-func getObjectStorageMetadata(metadata map[string]string) (*Metadata, error) {
- meta := Metadata{}
+func getObjectStorageMetadata(meta map[string]string) (*objectStoreMetadata, error) {
+ m := objectStoreMetadata{}
+ errDecode := metadata.DecodeMetadata(meta, &m)
+ if errDecode != nil {
+ return nil, errDecode
+ }
+
var err error
- if meta.instancePrincipalAuthentication, err = getOptionalBooleanValue(metadata, instancePrincipalAuthenticationKey); err != nil {
- return nil, err
- }
- if meta.configFileAuthentication, err = getOptionalBooleanValue(metadata, configFileAuthenticationKey); err != nil {
- return nil, err
- }
- if meta.configFileAuthentication {
- if meta.configFilePath, err = getConfigFilePath(metadata); err != nil {
+
+ if m.ConfigFileAuthentication {
+ if m.ConfigFilePath, err = getConfigFilePath(m.ConfigFilePath); err != nil {
return nil, err
}
- meta.configFileProfile, _ = getValue(metadata, configFileProfileKey, false)
}
- if meta.bucketName, err = getValue(metadata, bucketNameKey, true); err != nil {
- return nil, err
+ if m.BucketName == "" {
+ return nil, fmt.Errorf("missing or empty %s field from metadata", bucketNameKey)
}
- if meta.compartmentOCID, err = getValue(metadata, compartmentKey, true); err != nil {
- return nil, err
+ if m.CompartmentOCID == "" {
+ return nil, fmt.Errorf("missing or empty %s field from metadata", compartmentKey)
}
- externalAuthentication := meta.instancePrincipalAuthentication || meta.configFileAuthentication
+ externalAuthentication := m.InstancePrincipalAuthentication || m.ConfigFileAuthentication
if !externalAuthentication {
- err = getIdentityAuthenticationDetails(metadata, &meta)
+ err = getIdentityAuthenticationDetails(m)
if err != nil {
return nil, err
}
}
- return &meta, nil
+ return &m, nil
}
-func getIdentityAuthenticationDetails(metadata map[string]string, meta *Metadata) (err error) {
- if meta.region, err = getValue(metadata, regionKey, true); err != nil {
- return err
+func getIdentityAuthenticationDetails(meta objectStoreMetadata) (err error) {
+ if meta.Region == "" {
+ return fmt.Errorf("missing or empty %s field from metadata", regionKey)
}
- if meta.userOCID, err = getValue(metadata, userKey, true); err != nil {
- return err
+ if meta.UserOCID == "" {
+ return fmt.Errorf("missing or empty %s field from metadata", userKey)
}
- if meta.fingerPrint, err = getValue(metadata, fingerPrintKey, true); err != nil {
- return err
+ if meta.FingerPrint == "" {
+ return fmt.Errorf("missing or empty %s field from metadata", fingerPrintKey)
}
- if meta.privateKey, err = getValue(metadata, privateKeyKey, true); err != nil {
- return err
+ if meta.PrivateKey == "" {
+ return fmt.Errorf("missing or empty %s field from metadata", privateKeyKey)
}
- if meta.tenancyOCID, err = getValue(metadata, tenancyKey, true); err != nil {
- return err
+ if meta.TenancyOCID == "" {
+ return fmt.Errorf("missing or empty %s field from metadata", tenancyKey)
}
return nil
}
@@ -424,7 +403,7 @@ func (c *ociObjectStorageClient) ensureBucketExists(ctx context.Context, client
// verify if bucket exists.
response, err := client.GetBucket(ctx, req)
if err != nil {
- if response.RawResponse.StatusCode == 404 {
+ if response.RawResponse.StatusCode == http.StatusNotFound {
err = createBucket(ctx, client, namespace, name, compartmentOCID)
if err == nil {
c.logger.Debugf("Created OCI Object Storage Bucket %s as State Store", name)
@@ -455,16 +434,16 @@ func createBucket(ctx context.Context, client objectstorage.ObjectStorageClient,
// ***** the functions that interact with OCI Object Storage AND constitute the objectStoreClient interface.
func (c *ociObjectStorageClient) getObject(ctx context.Context, objectname string) (content []byte, etag *string, metadata map[string]string, err error) {
- c.logger.Debugf("read file %s from OCI ObjectStorage StateStore %s ", objectname, &c.objectStorageMetadata.bucketName)
+ c.logger.Debugf("read file %s from OCI ObjectStorage StateStore %s ", objectname, &c.objectStorageMetadata.BucketName)
request := objectstorage.GetObjectRequest{
- NamespaceName: &c.objectStorageMetadata.namespace,
- BucketName: &c.objectStorageMetadata.bucketName,
+ NamespaceName: &c.objectStorageMetadata.Namespace,
+ BucketName: &c.objectStorageMetadata.BucketName,
ObjectName: &objectname,
}
response, err := c.objectStorageMetadata.OCIObjectStorageClient.GetObject(ctx, request)
if err != nil {
c.logger.Debugf("Issue in OCI ObjectStorage with retrieving object %s, error: %s", objectname, err)
- if response.RawResponse.StatusCode == 404 {
+ if response.RawResponse.StatusCode == http.StatusNotFound {
return nil, nil, nil, nil
}
return nil, nil, nil, fmt.Errorf("failed to retrieve object : %w", err)
@@ -476,8 +455,8 @@ func (c *ociObjectStorageClient) getObject(ctx context.Context, objectname strin
func (c *ociObjectStorageClient) deleteObject(ctx context.Context, objectname string, etag *string) (err error) {
request := objectstorage.DeleteObjectRequest{
- NamespaceName: &c.objectStorageMetadata.namespace,
- BucketName: &c.objectStorageMetadata.bucketName,
+ NamespaceName: &c.objectStorageMetadata.Namespace,
+ BucketName: &c.objectStorageMetadata.BucketName,
ObjectName: &objectname,
IfMatch: etag,
}
@@ -490,8 +469,8 @@ func (c *ociObjectStorageClient) deleteObject(ctx context.Context, objectname st
func (c *ociObjectStorageClient) putObject(ctx context.Context, objectname string, contentLen int64, content io.ReadCloser, metadata map[string]string, etag *string) error {
request := objectstorage.PutObjectRequest{
- NamespaceName: &c.objectStorageMetadata.namespace,
- BucketName: &c.objectStorageMetadata.bucketName,
+ NamespaceName: &c.objectStorageMetadata.Namespace,
+ BucketName: &c.objectStorageMetadata.BucketName,
ObjectName: &objectname,
ContentLength: &contentLen,
PutObjectBody: content,
@@ -499,7 +478,7 @@ func (c *ociObjectStorageClient) putObject(ctx context.Context, objectname strin
IfMatch: etag,
}
_, err := c.objectStorageMetadata.OCIObjectStorageClient.PutObject(ctx, request)
- c.logger.Debugf("Put object ", objectname, " in bucket ", &c.objectStorageMetadata.bucketName)
+ c.logger.Debugf("Put object ", objectname, " in bucket ", &c.objectStorageMetadata.BucketName)
if err != nil {
return fmt.Errorf("failed to put object on OCI : %w", err)
}
@@ -508,7 +487,7 @@ func (c *ociObjectStorageClient) putObject(ctx context.Context, objectname strin
func (c *ociObjectStorageClient) initStorageBucket() error {
ctx := context.Background()
- err := c.ensureBucketExists(ctx, *c.objectStorageMetadata.OCIObjectStorageClient, c.objectStorageMetadata.namespace, c.objectStorageMetadata.bucketName, c.objectStorageMetadata.compartmentOCID)
+ err := c.ensureBucketExists(ctx, *c.objectStorageMetadata.OCIObjectStorageClient, c.objectStorageMetadata.Namespace, c.objectStorageMetadata.BucketName, c.objectStorageMetadata.CompartmentOCID)
if err != nil {
return fmt.Errorf("failed to read or create bucket : %w", err)
}
@@ -517,7 +496,7 @@ func (c *ociObjectStorageClient) initStorageBucket() error {
func (c *ociObjectStorageClient) initOCIObjectStorageClient() (*objectstorage.ObjectStorageClient, error) {
var configurationProvider common.ConfigurationProvider
- if c.objectStorageMetadata.instancePrincipalAuthentication {
+ if c.objectStorageMetadata.InstancePrincipalAuthentication {
c.logger.Debugf("instance principal authentication is used. ")
var err error
configurationProvider, err = auth.InstancePrincipalConfigurationProvider()
@@ -525,12 +504,12 @@ func (c *ociObjectStorageClient) initOCIObjectStorageClient() (*objectstorage.Ob
return nil, fmt.Errorf("failed to get oci configurationprovider based on instance principal authentication : %w", err)
}
} else {
- if c.objectStorageMetadata.configFileAuthentication {
- c.logger.Debugf("configuration file based authentication is used with configuration file path %s and configuration profile %s. ", c.objectStorageMetadata.configFilePath, c.objectStorageMetadata.configFileProfile)
- configurationProvider = common.CustomProfileConfigProvider(c.objectStorageMetadata.configFilePath, c.objectStorageMetadata.configFileProfile)
+ if c.objectStorageMetadata.ConfigFileAuthentication {
+ c.logger.Debugf("configuration file based authentication is used with configuration file path %s and configuration profile %s. ", c.objectStorageMetadata.ConfigFilePath, c.objectStorageMetadata.ConfigFileProfile)
+ configurationProvider = common.CustomProfileConfigProvider(c.objectStorageMetadata.ConfigFilePath, c.objectStorageMetadata.ConfigFileProfile)
} else {
c.logger.Debugf("identity authentication is used with configuration provided through Dapr component configuration ")
- configurationProvider = common.NewRawConfigurationProvider(c.objectStorageMetadata.tenancyOCID, c.objectStorageMetadata.userOCID, c.objectStorageMetadata.region, c.objectStorageMetadata.fingerPrint, c.objectStorageMetadata.privateKey, nil)
+ configurationProvider = common.NewRawConfigurationProvider(c.objectStorageMetadata.TenancyOCID, c.objectStorageMetadata.UserOCID, c.objectStorageMetadata.Region, c.objectStorageMetadata.FingerPrint, c.objectStorageMetadata.PrivateKey, nil)
}
}
@@ -539,7 +518,7 @@ func (c *ociObjectStorageClient) initOCIObjectStorageClient() (*objectstorage.Ob
return nil, fmt.Errorf("failed to create ObjectStorageClient : %w", cerr)
}
ctx := context.Background()
- c.objectStorageMetadata.namespace, cerr = getNamespace(ctx, objectStorageClient)
+ c.objectStorageMetadata.Namespace, cerr = getNamespace(ctx, objectStorageClient)
if cerr != nil {
return nil, fmt.Errorf("failed to get namespace : %w", cerr)
}
@@ -548,8 +527,8 @@ func (c *ociObjectStorageClient) initOCIObjectStorageClient() (*objectstorage.Ob
func (c *ociObjectStorageClient) pingBucket() error {
req := objectstorage.GetBucketRequest{
- NamespaceName: &c.objectStorageMetadata.namespace,
- BucketName: &c.objectStorageMetadata.bucketName,
+ NamespaceName: &c.objectStorageMetadata.Namespace,
+ BucketName: &c.objectStorageMetadata.BucketName,
}
_, err := c.objectStorageMetadata.OCIObjectStorageClient.GetBucket(context.Background(), req)
if err != nil {
@@ -557,3 +536,10 @@ func (c *ociObjectStorageClient) pingBucket() error {
}
return nil
}
+
+func (r *StateStore) GetComponentMetadata() map[string]string {
+ metadataStruct := objectStoreMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/oci/objectstorage/objectstorage_test.go b/state/oci/objectstorage/objectstorage_test.go
index c766f49e7..47c19130c 100644
--- a/state/oci/objectstorage/objectstorage_test.go
+++ b/state/oci/objectstorage/objectstorage_test.go
@@ -160,7 +160,7 @@ func TestGetObjectStorageMetadata(t *testing.T) {
t.Run("Test getObjectStorageMetadata with full properties map", func(t *testing.T) {
meta, err := getObjectStorageMetadata(getDummyOCIObjectStorageConfiguration())
assert.Nil(t, err, "No error expected in clean property set")
- assert.Equal(t, getDummyOCIObjectStorageConfiguration()["region"], meta.region, "Region in object storage metadata should match region in properties")
+ assert.Equal(t, getDummyOCIObjectStorageConfiguration()["region"], meta.Region, "Region in object storage metadata should match region in properties")
})
t.Run("Test getObjectStorageMetadata with incomplete property set", func(t *testing.T) {
properties := map[string]string{
@@ -382,27 +382,6 @@ func TestDeleteWithMockClient(t *testing.T) {
})
}
-func TestGetValue(t *testing.T) {
- meta := map[string]string{
- "testKey": "theValue",
- }
- t.Parallel()
- t.Run("Existing value", func(t *testing.T) {
- value, _ := getValue(meta, "testKey", true)
- assert.Equal(t, "theValue", value)
- })
- t.Run("Non-existing, required value", func(t *testing.T) {
- value, err := getValue(meta, "noKey", true)
- assert.NotNil(t, err, "Missing required value should result in error")
- assert.Equal(t, "", value, "Empty string should be returned for non-existing value")
- })
- t.Run("Non-existing, optional value", func(t *testing.T) {
- value, err := getValue(meta, "noKey", false)
- assert.Nil(t, err, "Missing optional value should not result in error")
- assert.Equal(t, "", value, "Empty string should be returned for non-existing value")
- })
-}
-
func TestGetFilename(t *testing.T) {
t.Parallel()
t.Run("Valid composite key", func(t *testing.T) {
diff --git a/state/oracledatabase/oracledatabase.go b/state/oracledatabase/oracledatabase.go
index 46d08f3d7..3fe7f8595 100644
--- a/state/oracledatabase/oracledatabase.go
+++ b/state/oracledatabase/oracledatabase.go
@@ -16,7 +16,9 @@ package oracledatabase
import (
"context"
"fmt"
+ "reflect"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
)
@@ -130,3 +132,10 @@ func (o *OracleDatabase) Close() error {
return nil
}
+
+func (o *OracleDatabase) GetComponentMetadata() map[string]string {
+ metadataStruct := oracleDatabaseMetadata{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/oracledatabase/oracledatabaseaccess.go b/state/oracledatabase/oracledatabaseaccess.go
index 133bde306..563a5de1b 100644
--- a/state/oracledatabase/oracledatabaseaccess.go
+++ b/state/oracledatabase/oracledatabaseaccess.go
@@ -24,6 +24,7 @@ import (
"github.com/google/uuid"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/components-contrib/state/utils"
"github.com/dapr/kit/logger"
@@ -43,12 +44,18 @@ const (
// oracleDatabaseAccess implements dbaccess.
type oracleDatabaseAccess struct {
logger logger.Logger
- metadata state.Metadata
+ metadata oracleDatabaseMetadata
db *sql.DB
connectionString string
tx *sql.Tx
}
+type oracleDatabaseMetadata struct {
+ ConnectionString string
+ OracleWalletLocation string
+ TableName string
+}
+
// newOracleDatabaseAccess creates a new instance of oracleDatabaseAccess.
func newOracleDatabaseAccess(logger logger.Logger) *oracleDatabaseAccess {
logger.Debug("Instantiating new Oracle Database state store")
@@ -62,19 +69,31 @@ func (o *oracleDatabaseAccess) Ping() error {
return o.db.Ping()
}
+func parseMetadata(meta map[string]string) (oracleDatabaseMetadata, error) {
+ m := oracleDatabaseMetadata{
+ TableName: "state",
+ }
+ err := metadata.DecodeMetadata(meta, &m)
+ return m, err
+}
+
// Init sets up OracleDatabase connection and ensures that the state table exists.
func (o *oracleDatabaseAccess) Init(metadata state.Metadata) error {
o.logger.Debug("Initializing OracleDatabase state store")
- o.metadata = metadata
- if val, ok := metadata.Properties[connectionStringKey]; ok && val != "" {
- o.connectionString = val
+ meta, err := parseMetadata(metadata.Properties)
+ o.metadata = meta
+ if err != nil {
+ return err
+ }
+ if o.metadata.ConnectionString != "" {
+ o.connectionString = meta.ConnectionString
} else {
o.logger.Error("Missing Oracle Database connection string")
return fmt.Errorf(errMissingConnectionString)
}
- if val, ok := o.metadata.Properties[oracleWalletLocationKey]; ok && val != "" {
- o.connectionString += "?TRACE FILE=trace.log&SSL=enable&SSL Verify=false&WALLET=" + url.QueryEscape(val)
+ if o.metadata.OracleWalletLocation != "" {
+ o.connectionString += "?TRACE FILE=trace.log&SSL=enable&SSL Verify=false&WALLET=" + url.QueryEscape(o.metadata.OracleWalletLocation)
}
db, err := sql.Open("oracle", o.connectionString)
if err != nil {
@@ -96,11 +115,6 @@ func (o *oracleDatabaseAccess) Init(metadata state.Metadata) error {
return nil
}
-// Set makes an insert or update to the database.
-func (o *oracleDatabaseAccess) Set(ctx context.Context, req *state.SetRequest) error {
- return state.SetWithOptions(ctx, o.setValue, req)
-}
-
func parseTTL(requestMetadata map[string]string) (*int, error) {
if val, found := requestMetadata[metadataTTLKey]; found && val != "" {
parsedVal, err := strconv.ParseInt(val, 10, 0)
@@ -115,8 +129,8 @@ func parseTTL(requestMetadata map[string]string) (*int, error) {
return nil, nil
}
-// setValue is an internal implementation of set to enable passing the logic to state.SetWithRetries as a func.
-func (o *oracleDatabaseAccess) setValue(ctx context.Context, req *state.SetRequest) error {
+// Set makes an insert or update to the database.
+func (o *oracleDatabaseAccess) Set(ctx context.Context, req *state.SetRequest) error {
o.logger.Debug("Setting state value in OracleDatabase")
err := state.CheckRequestOptions(req.Options)
if err != nil {
@@ -186,6 +200,7 @@ func (o *oracleDatabaseAccess) setValue(ctx context.Context, req *state.SetReque
result, err = tx.ExecContext(ctx, mergeStatement, req.Key, value, binaryYN, etag, ttlSeconds)
} else {
// when first write policy is indicated, an existing record has to be updated - one that has the etag provided.
+ // TODO: Needs to update ttl_in_seconds
updateStatement := fmt.Sprintf(
`UPDATE %s SET value = :value, binary_yn = :binary_yn, etag = :new_etag
WHERE key = :key AND etag = :etag`,
@@ -255,11 +270,6 @@ func (o *oracleDatabaseAccess) Get(ctx context.Context, req *state.GetRequest) (
// Delete removes an item from the state store.
func (o *oracleDatabaseAccess) Delete(ctx context.Context, req *state.DeleteRequest) error {
- return state.DeleteWithOptions(ctx, o.deleteValue, req)
-}
-
-// deleteValue is an internal implementation of delete to enable passing the logic to state.DeleteWithRetries as a func.
-func (o *oracleDatabaseAccess) deleteValue(ctx context.Context, req *state.DeleteRequest) error {
o.logger.Debug("Deleting state value from OracleDatabase")
if req.Key == "" {
return fmt.Errorf("missing key in delete operation")
@@ -336,7 +346,7 @@ func (o *oracleDatabaseAccess) ExecuteMulti(ctx context.Context, sets []state.Se
return err
}
-// Close implements io.Close.
+// Close implements io.Closer.
func (o *oracleDatabaseAccess) Close() error {
if o.db != nil {
return o.db.Close()
@@ -373,10 +383,3 @@ func tableExists(db *sql.DB, tableName string) (bool, error) {
exists := tblCount > 0
return exists, err
}
-
-// func handleError(msg string, err error) {
-// if err != nil {
-// fmt.Println(msg, err)
-
-// }
-// }
diff --git a/state/postgresql/postgresdbaccess.go b/state/postgresql/postgresdbaccess.go
index ae495f62b..dc3f81939 100644
--- a/state/postgresql/postgresdbaccess.go
+++ b/state/postgresql/postgresdbaccess.go
@@ -18,17 +18,17 @@ import (
"database/sql"
"encoding/base64"
"encoding/json"
+ "errors"
"fmt"
"strconv"
"time"
- "github.com/agrea/ptr"
- "github.com/pkg/errors"
-
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/components-contrib/state/query"
"github.com/dapr/components-contrib/state/utils"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
// Blank import for the underlying PostgreSQL driver.
_ "github.com/jackc/pgx/v5/stdlib"
@@ -37,16 +37,16 @@ import (
const (
connectionStringKey = "connectionString"
errMissingConnectionString = "missing connection string"
- tableName = "state"
- connMaxIdleTimeKey = "connMaxIdleTime"
+ defaultTableName = "state"
)
// postgresDBAccess implements dbaccess.
type postgresDBAccess struct {
logger logger.Logger
- metadata state.Metadata
+ metadata postgresMetadataStruct
db *sql.DB
connectionString string
+ tableName string
}
// newPostgresDBAccess creates a new instance of postgresAccess.
@@ -58,18 +58,30 @@ func newPostgresDBAccess(logger logger.Logger) *postgresDBAccess {
}
}
-// Init sets up PostgreSQL connection and ensures that the state table exists.
-func (p *postgresDBAccess) Init(metadata state.Metadata) error {
- p.logger.Debug("Initializing PostgreSQL state store")
- p.metadata = metadata
+type postgresMetadataStruct struct {
+ ConnectionString string
+ ConnectionMaxIdleTime time.Duration
+ TableName string
+}
- if val, ok := metadata.Properties[connectionStringKey]; ok && val != "" {
- p.connectionString = val
- } else {
+// Init sets up PostgreSQL connection and ensures that the state table exists.
+func (p *postgresDBAccess) Init(meta state.Metadata) error {
+ p.logger.Debug("Initializing PostgreSQL state store")
+ m := postgresMetadataStruct{
+ TableName: defaultTableName,
+ }
+ err := metadata.DecodeMetadata(meta.Properties, &m)
+ if err != nil {
+ return err
+ }
+ p.metadata = m
+
+ if m.ConnectionString == "" {
p.logger.Error("Missing postgreSQL connection string")
- return fmt.Errorf(errMissingConnectionString)
+ return errors.New(errMissingConnectionString)
}
+ p.connectionString = m.ConnectionString
db, err := sql.Open("pgx", p.connectionString)
if err != nil {
@@ -85,26 +97,22 @@ func (p *postgresDBAccess) Init(metadata state.Metadata) error {
return pingErr
}
- err = propertyToDuration(p.metadata.Properties, connMaxIdleTimeKey, p.db.SetConnMaxIdleTime)
+ p.db.SetConnMaxIdleTime(m.ConnectionMaxIdleTime)
if err != nil {
return err
}
- err = p.ensureStateTable(tableName)
+ err = p.ensureStateTable(m.TableName)
if err != nil {
return err
}
+ p.tableName = m.TableName
return nil
}
// Set makes an insert or update to the database.
func (p *postgresDBAccess) Set(ctx context.Context, req *state.SetRequest) error {
- return state.SetWithOptions(ctx, p.setValue, req)
-}
-
-// setValue is an internal implementation of set to enable passing the logic to state.SetWithRetries as a func.
-func (p *postgresDBAccess) setValue(ctx context.Context, req *state.SetRequest) error {
p.logger.Debug("Setting state value in PostgreSQL")
err := state.CheckRequestOptions(req.Options)
@@ -113,11 +121,11 @@ func (p *postgresDBAccess) setValue(ctx context.Context, req *state.SetRequest)
}
if req.Key == "" {
- return fmt.Errorf("missing key in set operation")
+ return errors.New("missing key in set operation")
}
if v, ok := req.Value.(string); ok && v == "" {
- return fmt.Errorf("empty string is not allowed in set operation")
+ return errors.New("empty string is not allowed in set operation")
}
v := req.Value
@@ -134,11 +142,15 @@ func (p *postgresDBAccess) setValue(ctx context.Context, req *state.SetRequest)
// Sprintf is required for table name because sql.DB does not substitute parameters for table names.
// Other parameters use sql.DB parameter substitution.
- if req.ETag == nil {
+ if req.Options.Concurrency == state.FirstWrite && (req.ETag == nil || *req.ETag == "") {
+ result, err = p.db.ExecContext(ctx, fmt.Sprintf(
+ `INSERT INTO %s (key, value, isbinary) VALUES ($1, $2, $3);`,
+ p.tableName), req.Key, value, isBinary)
+ } else if req.ETag == nil || *req.ETag == "" {
result, err = p.db.ExecContext(ctx, fmt.Sprintf(
`INSERT INTO %s (key, value, isbinary) VALUES ($1, $2, $3)
ON CONFLICT (key) DO UPDATE SET value = $2, isbinary = $3, updatedate = NOW();`,
- tableName), req.Key, value, isBinary)
+ p.tableName), req.Key, value, isBinary)
} else {
// Convert req.ETag to uint32 for postgres XID compatibility
var etag64 uint64
@@ -152,7 +164,7 @@ func (p *postgresDBAccess) setValue(ctx context.Context, req *state.SetRequest)
result, err = p.db.ExecContext(ctx, fmt.Sprintf(
`UPDATE %s SET value = $1, isbinary = $2, updatedate = NOW()
WHERE key = $3 AND xmin = $4;`,
- tableName), value, isBinary, req.Key, etag)
+ p.tableName), value, isBinary, req.Key, etag)
}
if err != nil {
@@ -169,7 +181,7 @@ func (p *postgresDBAccess) setValue(ctx context.Context, req *state.SetRequest)
}
if rows != 1 {
- return fmt.Errorf("no item was updated")
+ return errors.New("no item was updated")
}
return nil
@@ -203,27 +215,30 @@ func (p *postgresDBAccess) BulkSet(ctx context.Context, req []state.SetRequest)
func (p *postgresDBAccess) Get(ctx context.Context, req *state.GetRequest) (*state.GetResponse, error) {
p.logger.Debug("Getting state value from PostgreSQL")
if req.Key == "" {
- return nil, fmt.Errorf("missing key in get operation")
+ return nil, errors.New("missing key in get operation")
}
- var value string
- var isBinary bool
- var etag int
- err := p.db.QueryRowContext(ctx, fmt.Sprintf("SELECT value, isbinary, xmin as etag FROM %s WHERE key = $1", tableName), req.Key).Scan(&value, &isBinary, &etag)
+ var (
+ value []byte
+ isBinary bool
+ etag uint64 // Postgres uses uint32, but FormatUint requires uint64, so using uint64 directly to avoid re-allocations
+ )
+ err := p.db.QueryRowContext(ctx, fmt.Sprintf("SELECT value, isbinary, xmin as etag FROM %s WHERE key = $1", p.tableName), req.Key).Scan(&value, &isBinary, &etag)
if err != nil {
// If no rows exist, return an empty response, otherwise return the error.
if err == sql.ErrNoRows {
return &state.GetResponse{}, nil
}
-
return nil, err
}
if isBinary {
- var s string
- var data []byte
+ var (
+ s string
+ data []byte
+ )
- if err = json.Unmarshal([]byte(value), &s); err != nil {
+ if err = json.Unmarshal(value, &s); err != nil {
return nil, err
}
@@ -233,34 +248,28 @@ func (p *postgresDBAccess) Get(ctx context.Context, req *state.GetRequest) (*sta
return &state.GetResponse{
Data: data,
- ETag: ptr.String(strconv.Itoa(etag)),
+ ETag: ptr.Of(strconv.FormatUint(etag, 10)),
Metadata: req.Metadata,
}, nil
}
return &state.GetResponse{
- Data: []byte(value),
- ETag: ptr.String(strconv.Itoa(etag)),
+ Data: value,
+ ETag: ptr.Of(strconv.FormatUint(etag, 10)),
Metadata: req.Metadata,
}, nil
}
// Delete removes an item from the state store.
-func (p *postgresDBAccess) Delete(ctx context.Context, req *state.DeleteRequest) error {
- return state.DeleteWithOptions(ctx, p.deleteValue, req)
-}
-
-// deleteValue is an internal implementation of delete to enable passing the logic to state.DeleteWithRetries as a func.
-func (p *postgresDBAccess) deleteValue(ctx context.Context, req *state.DeleteRequest) error {
+func (p *postgresDBAccess) Delete(ctx context.Context, req *state.DeleteRequest) (err error) {
p.logger.Debug("Deleting state value from PostgreSQL")
if req.Key == "" {
- return fmt.Errorf("missing key in delete operation")
+ return errors.New("missing key in delete operation")
}
var result sql.Result
- var err error
- if req.ETag == nil {
+ if req.ETag == nil || *req.ETag == "" {
result, err = p.db.ExecContext(ctx, "DELETE FROM state WHERE key = $1", req.Key)
} else {
// Convert req.ETag to uint32 for postgres XID compatibility
@@ -298,12 +307,10 @@ func (p *postgresDBAccess) BulkDelete(ctx context.Context, req []state.DeleteReq
}
if len(req) > 0 {
- for _, d := range req {
- da := d // Fix for gosec G601: Implicit memory aliasing in for loop.
- err = p.Delete(ctx, &da)
+ for i := range req {
+ err = p.Delete(ctx, &req[i])
if err != nil {
tx.Rollback()
-
return err
}
}
@@ -369,8 +376,9 @@ func (p *postgresDBAccess) ExecuteMulti(ctx context.Context, request *state.Tran
func (p *postgresDBAccess) Query(ctx context.Context, req *state.QueryRequest) (*state.QueryResponse, error) {
p.logger.Debug("Getting query value from PostgreSQL")
q := &Query{
- query: "",
- params: []interface{}{},
+ query: "",
+ params: []interface{}{},
+ tableName: p.tableName,
}
qbuilder := query.NewQueryBuilder(q)
if err := qbuilder.BuildQuery(&req.Query); err != nil {
@@ -430,11 +438,11 @@ func tableExists(db *sql.DB, tableName string) (bool, error) {
func getSet(req state.TransactionalStateOperation) (state.SetRequest, error) {
setReq, ok := req.Request.(state.SetRequest)
if !ok {
- return setReq, fmt.Errorf("expecting set request")
+ return setReq, errors.New("expecting set request")
}
if setReq.Key == "" {
- return setReq, fmt.Errorf("missing key in upsert operation")
+ return setReq, errors.New("missing key in upsert operation")
}
return setReq, nil
@@ -444,24 +452,12 @@ func getSet(req state.TransactionalStateOperation) (state.SetRequest, error) {
func getDelete(req state.TransactionalStateOperation) (state.DeleteRequest, error) {
delReq, ok := req.Request.(state.DeleteRequest)
if !ok {
- return delReq, fmt.Errorf("expecting delete request")
+ return delReq, errors.New("expecting delete request")
}
if delReq.Key == "" {
- return delReq, fmt.Errorf("missing key in upsert operation")
+ return delReq, errors.New("missing key in upsert operation")
}
return delReq, nil
}
-
-func propertyToDuration(props map[string]string, key string, setter func(time.Duration)) error {
- if v, ok := props[key]; ok {
- if d, err := time.ParseDuration(v); err == nil {
- setter(d)
- } else {
- return errors.Wrapf(err, "error converitng %s:%s to time duration", key, v)
- }
- }
-
- return nil
-}
diff --git a/state/postgresql/postgresql.go b/state/postgresql/postgresql.go
index f37aa564c..337486bf9 100644
--- a/state/postgresql/postgresql.go
+++ b/state/postgresql/postgresql.go
@@ -15,7 +15,9 @@ package postgresql
import (
"context"
+ "reflect"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
)
@@ -103,3 +105,10 @@ func (p *PostgreSQL) Close() error {
return nil
}
+
+func (p *PostgreSQL) GetComponentMetadata() map[string]string {
+ metadataStruct := postgresMetadataStruct{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/postgresql/postgresql_integration_test.go b/state/postgresql/postgresql_integration_test.go
index 2297776ee..a682bfdcd 100644
--- a/state/postgresql/postgresql_integration_test.go
+++ b/state/postgresql/postgresql_integration_test.go
@@ -561,7 +561,7 @@ func storeItemExists(t *testing.T, key string) bool {
defer db.Close()
exists := false
- statement := fmt.Sprintf(`SELECT EXISTS (SELECT FROM %s WHERE key = $1)`, tableName)
+ statement := fmt.Sprintf(`SELECT EXISTS (SELECT FROM %s WHERE key = $1)`, defaultTableName)
err = db.QueryRow(statement, key).Scan(&exists)
assert.Nil(t, err)
@@ -573,7 +573,7 @@ func getRowData(t *testing.T, key string) (returnValue string, insertdate sql.Nu
assert.Nil(t, err)
defer db.Close()
- err = db.QueryRow(fmt.Sprintf("SELECT value, insertdate, updatedate FROM %s WHERE key = $1", tableName), key).Scan(&returnValue, &insertdate, &updatedate)
+ err = db.QueryRow(fmt.Sprintf("SELECT value, insertdate, updatedate FROM %s WHERE key = $1", defaultTableName), key).Scan(&returnValue, &insertdate, &updatedate)
assert.Nil(t, err)
return returnValue, insertdate, updatedate
diff --git a/state/postgresql/postgresql_query.go b/state/postgresql/postgresql_query.go
index 09530c0a0..0b02e6095 100644
--- a/state/postgresql/postgresql_query.go
+++ b/state/postgresql/postgresql_query.go
@@ -21,18 +21,18 @@ import (
"strconv"
"strings"
- "github.com/agrea/ptr"
-
"github.com/dapr/components-contrib/state"
"github.com/dapr/components-contrib/state/query"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
type Query struct {
- query string
- params []interface{}
- limit int
- skip *int64
+ query string
+ params []interface{}
+ limit int
+ skip *int64
+ tableName string
}
func (q *Query) VisitEQ(f *query.EQ) (string, error) {
@@ -89,9 +89,9 @@ func (q *Query) visitFilters(op string, filters []query.Filter) (string, error)
}
}
- sep := fmt.Sprintf(" %s ", op)
+ sep := " " + op + " "
- return fmt.Sprintf("(%s)", strings.Join(arr, sep)), nil
+ return "(" + strings.Join(arr, sep) + ")", nil
}
func (q *Query) VisitAND(f *query.AND) (string, error) {
@@ -103,10 +103,10 @@ func (q *Query) VisitOR(f *query.OR) (string, error) {
}
func (q *Query) Finalize(filters string, qq *query.Query) error {
- q.query = fmt.Sprintf("SELECT key, value, xmin as etag FROM %s", tableName)
+ q.query = "SELECT key, value, xmin as etag FROM " + q.tableName
if filters != "" {
- q.query += fmt.Sprintf(" WHERE %s", filters)
+ q.query += " WHERE " + filters
}
if len(qq.Sort) > 0 {
@@ -118,13 +118,13 @@ func (q *Query) Finalize(filters string, qq *query.Query) error {
}
q.query += translateFieldToFilter(sortItem.Key)
if sortItem.Order != "" {
- q.query += fmt.Sprintf(" %s", sortItem.Order)
+ q.query += " " + sortItem.Order
}
}
}
if qq.Page.Limit > 0 {
- q.query += fmt.Sprintf(" LIMIT %d", qq.Page.Limit)
+ q.query += " LIMIT " + strconv.Itoa(qq.Page.Limit)
q.limit = qq.Page.Limit
}
@@ -133,7 +133,7 @@ func (q *Query) Finalize(filters string, qq *query.Query) error {
if err != nil {
return err
}
- q.query += fmt.Sprintf(" OFFSET %d", skip)
+ q.query += " OFFSET " + strconv.FormatInt(skip, 10)
q.skip = &skip
}
@@ -152,7 +152,7 @@ func (q *Query) execute(ctx context.Context, logger logger.Logger, db *sql.DB) (
var (
key string
data []byte
- etag int
+ etag uint64 // Postgres uses uint32, but FormatUint requires uint64, so using uint64 directly to avoid re-allocations
)
if err = rows.Scan(&key, &data, &etag); err != nil {
return nil, "", err
@@ -160,7 +160,7 @@ func (q *Query) execute(ctx context.Context, logger logger.Logger, db *sql.DB) (
result := state.QueryItem{
Key: key,
Data: data,
- ETag: ptr.String(strconv.Itoa(etag)),
+ ETag: ptr.Of(strconv.FormatUint(etag, 10)),
}
ret = append(ret, result)
}
@@ -201,7 +201,7 @@ func translateFieldToFilter(key string) string {
filterField += ">"
}
- filterField += fmt.Sprintf("'%s'", fieldPart)
+ filterField += "'" + fieldPart + "'"
}
return filterField
@@ -210,6 +210,6 @@ func translateFieldToFilter(key string) string {
func (q *Query) whereFieldEqual(key string, value interface{}) string {
position := q.addParamValueAndReturnPosition(value)
filterField := translateFieldToFilter(key)
- query := fmt.Sprintf("%s=$%v", filterField, position)
+ query := filterField + "=$" + strconv.Itoa(position)
return query
}
diff --git a/state/postgresql/postgresql_query_test.go b/state/postgresql/postgresql_query_test.go
index 260d3d570..e576ce6ff 100644
--- a/state/postgresql/postgresql_query_test.go
+++ b/state/postgresql/postgresql_query_test.go
@@ -60,7 +60,9 @@ func TestPostgresqlQueryBuildQuery(t *testing.T) {
err = json.Unmarshal(data, &qq)
assert.NoError(t, err)
- q := &Query{}
+ q := &Query{
+ tableName: defaultTableName,
+ }
qbuilder := query.NewQueryBuilder(q)
err = qbuilder.BuildQuery(&qq)
assert.NoError(t, err)
diff --git a/state/redis/redis.go b/state/redis/redis.go
index 2f9edfbfc..96d616c29 100644
--- a/state/redis/redis.go
+++ b/state/redis/redis.go
@@ -16,10 +16,10 @@ package redis
import (
"context"
"fmt"
+ "reflect"
"strconv"
"strings"
- "github.com/agrea/ptr"
"github.com/go-redis/redis/v8"
jsoniter "github.com/json-iterator/go"
@@ -30,6 +30,7 @@ import (
"github.com/dapr/components-contrib/state/query"
"github.com/dapr/components-contrib/state/utils"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
const (
@@ -195,7 +196,13 @@ func (r *StateStore) parseConnectedSlaves(res string) int {
return 0
}
-func (r *StateStore) deleteValue(ctx context.Context, req *state.DeleteRequest) error {
+// Delete performs a delete operation.
+func (r *StateStore) Delete(ctx context.Context, req *state.DeleteRequest) error {
+ err := state.CheckRequestOptions(req.Options)
+ if err != nil {
+ return err
+ }
+
if req.ETag == nil {
etag := "0"
req.ETag = &etag
@@ -207,7 +214,7 @@ func (r *StateStore) deleteValue(ctx context.Context, req *state.DeleteRequest)
} else {
delQuery = delDefaultQuery
}
- _, err := r.client.Do(ctx, "EVAL", delQuery, 1, req.Key, *req.ETag).Result()
+ _, err = r.client.Do(ctx, "EVAL", delQuery, 1, req.Key, *req.ETag).Result()
if err != nil {
return state.NewETagError(state.ETagMismatch, err)
}
@@ -216,17 +223,8 @@ func (r *StateStore) deleteValue(ctx context.Context, req *state.DeleteRequest)
}
// Delete performs a delete operation.
-func (r *StateStore) Delete(ctx context.Context, req *state.DeleteRequest) error {
- err := state.CheckRequestOptions(req.Options)
- if err != nil {
- return err
- }
-
- return state.DeleteWithOptions(ctx, r.deleteValue, req)
-}
-
func (r *StateStore) directGet(ctx context.Context, req *state.GetRequest) (*state.GetResponse, error) {
- res, err := r.client.Do(ctx, "GET", req.Key).Result()
+ res, err := r.client.Do(r.ctx, "GET", req.Key).Result()
if err != nil {
return nil, err
}
@@ -317,7 +315,8 @@ type jsonEntry struct {
Version *int `json:"version,omitempty"`
}
-func (r *StateStore) setValue(ctx context.Context, req *state.SetRequest) error {
+// Set saves state into redis.
+func (r *StateStore) Set(ctx context.Context, req *state.SetRequest) error {
err := state.CheckRequestOptions(req.Options)
if err != nil {
return err
@@ -383,11 +382,6 @@ func (r *StateStore) setValue(ctx context.Context, req *state.SetRequest) error
return nil
}
-// Set saves state into redis.
-func (r *StateStore) Set(ctx context.Context, req *state.SetRequest) error {
- return state.SetWithOptions(ctx, r.setValue, req)
-}
-
// Multi performs a transactional operation. succeeds only if all operations succeed, and fails if one or more operations fail.
func (r *StateStore) Multi(ctx context.Context, request *state.TransactionalStateRequest) error {
var setQuery, delQuery string
@@ -476,7 +470,7 @@ func (r *StateStore) getKeyVersion(vals []interface{}) (data string, version *st
seenData = true
case "version":
versionVal, _ := strconv.Unquote(fmt.Sprintf("%q", vals[i+1]))
- version = ptr.String(versionVal)
+ version = ptr.Of(versionVal)
seenVersion = true
}
}
@@ -545,3 +539,10 @@ func (r *StateStore) Close() error {
return r.client.Close()
}
+
+func (r *StateStore) GetComponentMetadata() map[string]string {
+ metadataStruct := rediscomponent.Settings{}
+ metadataInfo := map[string]string{}
+ daprmetadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/redis/redis_test.go b/state/redis/redis_test.go
index 8151db6a7..dfa32f58e 100644
--- a/state/redis/redis_test.go
+++ b/state/redis/redis_test.go
@@ -19,7 +19,6 @@ import (
"testing"
"time"
- "github.com/agrea/ptr"
miniredis "github.com/alicebob/miniredis/v2"
redis "github.com/go-redis/redis/v8"
jsoniter "github.com/json-iterator/go"
@@ -28,6 +27,7 @@ import (
rediscomponent "github.com/dapr/components-contrib/internal/component/redis"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
func TestGetKeyVersion(t *testing.T) {
@@ -36,7 +36,7 @@ func TestGetKeyVersion(t *testing.T) {
key, ver, err := store.getKeyVersion([]interface{}{"data", "TEST_KEY", "version", "TEST_VER"})
assert.Equal(t, nil, err, "failed to read all fields")
assert.Equal(t, "TEST_KEY", key, "failed to read key")
- assert.Equal(t, ptr.String("TEST_VER"), ver, "failed to read version")
+ assert.Equal(t, ptr.Of("TEST_VER"), ver, "failed to read version")
})
t.Run("With missing data", func(t *testing.T) {
_, _, err := store.getKeyVersion([]interface{}{"version", "TEST_VER"})
@@ -50,7 +50,7 @@ func TestGetKeyVersion(t *testing.T) {
key, ver, err := store.getKeyVersion([]interface{}{"version", "TEST_VER", "dragon", "TEST_DRAGON", "data", "TEST_KEY"})
assert.Equal(t, nil, err, "failed to read all fields")
assert.Equal(t, "TEST_KEY", key, "failed to read key")
- assert.Equal(t, ptr.String("TEST_VER"), ver, "failed to read version")
+ assert.Equal(t, ptr.Of("TEST_VER"), ver, "failed to read version")
})
t.Run("With no fields", func(t *testing.T) {
_, _, err := store.getKeyVersion([]interface{}{})
@@ -245,7 +245,7 @@ func TestTransactionalUpsert(t *testing.T) {
vals := res.([]interface{})
data, version, err := ss.getKeyVersion(vals)
assert.Equal(t, nil, err)
- assert.Equal(t, ptr.String("1"), version)
+ assert.Equal(t, ptr.Of("1"), version)
assert.Equal(t, `"deathstar"`, data)
res, err = c.Do(context.Background(), "TTL", "weapon").Result()
@@ -394,7 +394,7 @@ func TestRequestsWithGlobalTTL(t *testing.T) {
vals := res.([]interface{})
data, version, err := ss.getKeyVersion(vals)
assert.Equal(t, nil, err)
- assert.Equal(t, ptr.String("1"), version)
+ assert.Equal(t, ptr.Of("1"), version)
assert.Equal(t, `"deathstar"`, data)
res, err = c.Do(context.Background(), "TTL", "weapon").Result()
@@ -515,6 +515,23 @@ func TestTransactionalDeleteNoEtag(t *testing.T) {
assert.Equal(t, 0, len(vals))
}
+func TestGetMetadata(t *testing.T) {
+ s, c := setupMiniredis()
+ defer s.Close()
+
+ ss := &StateStore{
+ client: c,
+ json: jsoniter.ConfigFastest,
+ logger: logger.NewLogger("test"),
+ }
+
+ metadataInfo := ss.GetComponentMetadata()
+ assert.Contains(t, metadataInfo, "redisHost")
+ assert.Contains(t, metadataInfo, "idleCheckFrequency")
+ assert.Equal(t, metadataInfo["redisHost"], "string")
+ assert.Equal(t, metadataInfo["idleCheckFrequency"], "redis.Duration")
+}
+
func setupMiniredis() (*miniredis.Miniredis, *redis.Client) {
s, err := miniredis.Run()
if err != nil {
diff --git a/state/request_options.go b/state/request_options.go
index 3e1d9b5c8..140783244 100644
--- a/state/request_options.go
+++ b/state/request_options.go
@@ -14,7 +14,6 @@ limitations under the License.
package state
import (
- "context"
"fmt"
)
@@ -67,13 +66,3 @@ func validateConsistencyOption(c string) error {
return nil
}
-
-// SetWithOptions handles SetRequest with request options.
-func SetWithOptions(ctx context.Context, method func(ctx context.Context, req *SetRequest) error, req *SetRequest) error {
- return method(ctx, req)
-}
-
-// DeleteWithOptions handles DeleteRequest with options.
-func DeleteWithOptions(ctx context.Context, method func(ctx context.Context, req *DeleteRequest) error, req *DeleteRequest) error {
- return method(ctx, req)
-}
diff --git a/state/request_options_test.go b/state/request_options_test.go
index a8e28ff47..2853fea6b 100644
--- a/state/request_options_test.go
+++ b/state/request_options_test.go
@@ -14,37 +14,11 @@ limitations under the License.
package state
import (
- "context"
"testing"
"github.com/stretchr/testify/assert"
)
-// TestSetRequestWithOptions is used to test request options.
-func TestSetRequestWithOptions(t *testing.T) {
- t.Run("set with default options", func(t *testing.T) {
- counter := 0
- SetWithOptions(context.Background(), func(ctx context.Context, req *SetRequest) error {
- counter++
-
- return nil
- }, &SetRequest{})
- assert.Equal(t, 1, counter, "should execute only once")
- })
-
- t.Run("set with no explicit options", func(t *testing.T) {
- counter := 0
- SetWithOptions(context.Background(), func(ctx context.Context, req *SetRequest) error {
- counter++
-
- return nil
- }, &SetRequest{
- Options: SetStateOption{},
- })
- assert.Equal(t, 1, counter, "should execute only once")
- })
-}
-
// TestCheckRequestOptions is used to validate request options.
func TestCheckRequestOptions(t *testing.T) {
t.Run("set state options", func(t *testing.T) {
diff --git a/state/rethinkdb/rethinkdb.go b/state/rethinkdb/rethinkdb.go
index c36db6341..58ac66c65 100644
--- a/state/rethinkdb/rethinkdb.go
+++ b/state/rethinkdb/rethinkdb.go
@@ -17,16 +17,16 @@ import (
"context"
"encoding/json"
"io"
- "strconv"
- "strings"
+ "reflect"
"time"
- "github.com/agrea/ptr"
r "github.com/dancannon/gorethink"
"github.com/pkg/errors"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
const (
@@ -45,9 +45,9 @@ type RethinkDB struct {
}
type stateConfig struct {
- r.ConnectOpts
- Archive bool `json:"archive"`
- Table string `json:"table"`
+ r.ConnectOpts `mapstructure:",squash"`
+ Archive bool `json:"archive"`
+ Table string `json:"table"`
}
type stateRecord struct {
@@ -172,7 +172,7 @@ func (s *RethinkDB) Get(ctx context.Context, req *state.GetRequest) (*state.GetR
return nil, errors.Wrap(err, "error parsing database content")
}
- resp := &state.GetResponse{ETag: ptr.String(doc.Hash)}
+ resp := &state.GetResponse{ETag: ptr.Of(doc.Hash)}
b, ok := doc.Data.([]byte)
if ok {
resp.Data = b
@@ -324,87 +324,17 @@ func metadataToConfig(cfg map[string]string, logger logger.Logger) (*stateConfig
Table: stateTableNameDefault,
}
- // runtime
- for k, v := range cfg {
- switch k {
- case "table": // string
- c.Table = v
- case "address": // string
- c.Address = v
- case "addresses": // []string
- c.Addresses = strings.Split(v, ",")
- case "database": // string
- c.Database = v
- case "username": // string
- c.Username = v
- case "password": // string
- c.Password = v
- case "authkey": // string
- c.AuthKey = v
- case "timeout": // time.Duration
- d, err := time.ParseDuration(v)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid timeout format: %v", v)
- }
- c.Timeout = d
- case "write_timeout": // time.Duration
- d, err := time.ParseDuration(v)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid write timeout format: %v", v)
- }
- c.WriteTimeout = d
- case "read_timeout": // time.Duration
- d, err := time.ParseDuration(v)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid read timeout format: %v", v)
- }
- c.ReadTimeout = d
- case "keep_alive_timeout": // time.Duration
- d, err := time.ParseDuration(v)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid keep alive timeout format: %v", v)
- }
- c.KeepAlivePeriod = d
- case "initial_cap": // int
- i, err := strconv.Atoi(v)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid keep initial cap format: %v", v)
- }
- c.InitialCap = i
- case "max_open": // int
- i, err := strconv.Atoi(v)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid keep max open format: %v", v)
- }
- c.MaxOpen = i
- case "discover_hosts": // bool
- b, err := strconv.ParseBool(v)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid discover hosts format: %v", v)
- }
- c.DiscoverHosts = b
- case "use-open-tracing": // bool
- b, err := strconv.ParseBool(v)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid use open tracing format: %v", v)
- }
- c.UseOpentracing = b
- case "archive": // bool
- b, err := strconv.ParseBool(v)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid use open tracing format: %v", v)
- }
- c.Archive = b
- case "max_idle": // int
- i, err := strconv.Atoi(v)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid keep max idle format: %v", v)
- }
- c.InitialCap = i
- default:
- logger.Infof("unrecognized metadata: %s", k)
- }
+ err := metadata.DecodeMetadata(cfg, &c)
+ if err != nil {
+ return nil, err
}
return &c, nil
}
+
+func (s *RethinkDB) GetComponentMetadata() map[string]string {
+ metadataStruct := stateConfig{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/rethinkdb/rethinkdb_test.go b/state/rethinkdb/rethinkdb_test.go
index cf0a08821..4d3ebb878 100644
--- a/state/rethinkdb/rethinkdb_test.go
+++ b/state/rethinkdb/rethinkdb_test.go
@@ -47,10 +47,10 @@ func TestGetRethinkDBMetadata(t *testing.T) {
p["timeout"] = fmt.Sprintf("%v", timeout)
maxOpen := 30
- p["max_open"] = fmt.Sprintf("%v", maxOpen)
+ p["maxOpen"] = fmt.Sprintf("%v", maxOpen)
discoverHosts := true
- p["discover_hosts"] = fmt.Sprintf("%v", discoverHosts)
+ p["discoverHosts"] = fmt.Sprintf("%v", discoverHosts)
m, err := metadataToConfig(p, testLogger)
assert.Nil(t, err)
diff --git a/state/sqlserver/migration.go b/state/sqlserver/migration.go
index 06ab76bc4..a56019906 100644
--- a/state/sqlserver/migration.go
+++ b/state/sqlserver/migration.go
@@ -277,6 +277,7 @@ func (m *migration) createStoredProcedureIfNotExists(db *sql.DB, name string, es
}
/* #nosec. */
+//nolint:dupword
func (m *migration) ensureUpsertStoredProcedureExists(db *sql.DB, mr migrationResult) error {
tsql := fmt.Sprintf(`
CREATE PROCEDURE %s (
diff --git a/state/sqlserver/sqlserver.go b/state/sqlserver/sqlserver.go
index f8d117760..62b9599f4 100644
--- a/state/sqlserver/sqlserver.go
+++ b/state/sqlserver/sqlserver.go
@@ -20,15 +20,15 @@ import (
"encoding/json"
"errors"
"fmt"
- "strconv"
"unicode"
- "github.com/agrea/ptr"
mssql "github.com/denisenkom/go-mssqldb"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/components-contrib/state/utils"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
// KeyType defines type of the table identifier.
@@ -120,6 +120,16 @@ type SQLServer struct {
db *sql.DB
}
+type sqlServerMetadata struct {
+ ConnectionString string
+ DatabaseName string
+ TableName string
+ Schema string
+ KeyType string
+ KeyLength int
+ IndexedProperties string
+}
+
func isLetterOrNumber(c rune) bool {
return unicode.IsNumber(c) || unicode.IsLetter(c)
}
@@ -156,29 +166,8 @@ func isValidIndexedPropertyType(s string) bool {
// Init initializes the SQL server state store.
func (s *SQLServer) Init(metadata state.Metadata) error {
- if val, ok := metadata.Properties[connectionStringKey]; ok && val != "" {
- s.connectionString = val
- } else {
- return fmt.Errorf("missing connection string")
- }
-
- if err := s.getTable(metadata); err != nil {
- return err
- }
-
- if err := s.getDatabase(metadata); err != nil {
- return err
- }
-
- if err := s.getKeyType(metadata); err != nil {
- return err
- }
-
- if err := s.getSchema(metadata); err != nil {
- return err
- }
-
- if err := s.getIndexedProperties(metadata); err != nil {
+ err := s.parseMetadata(metadata.Properties)
+ if err != nil {
return err
}
@@ -203,11 +192,50 @@ func (s *SQLServer) Init(metadata state.Metadata) error {
return nil
}
+func (s *SQLServer) parseMetadata(meta map[string]string) error {
+ m := sqlServerMetadata{
+ TableName: defaultTable,
+ Schema: defaultSchema,
+ DatabaseName: defaultDatabase,
+ KeyLength: defaultKeyLength,
+ }
+ err := metadata.DecodeMetadata(meta, &m)
+ if err != nil {
+ return err
+ }
+ if m.ConnectionString == "" {
+ return fmt.Errorf("missing connection string")
+ }
+ s.connectionString = m.ConnectionString
+
+ if err := s.setTable(m.TableName); err != nil {
+ return err
+ }
+
+ if err := s.setDatabase(m.DatabaseName); err != nil {
+ return err
+ }
+
+ if err := s.setKeyType(m.KeyType, m.KeyLength); err != nil {
+ return err
+ }
+
+ if err := s.setSchema(m.Schema); err != nil {
+ return err
+ }
+
+ if err := s.setIndexedProperties(m.IndexedProperties); err != nil {
+ return err
+ }
+
+ return nil
+}
+
// Returns validated index properties.
-func (s *SQLServer) getIndexedProperties(metadata state.Metadata) error {
- if val, ok := metadata.Properties[indexedPropertiesKey]; ok && val != "" {
+func (s *SQLServer) setIndexedProperties(indexedPropertiesString string) error {
+ if indexedPropertiesString != "" {
var indexedProperties []IndexedProperty
- err := json.Unmarshal([]byte(val), &indexedProperties)
+ err := json.Unmarshal([]byte(indexedPropertiesString), &indexedProperties)
if err != nil {
return err
}
@@ -256,9 +284,9 @@ func (s *SQLServer) validateIndexedProperties(indexedProperties []IndexedPropert
}
// Validates and returns the key type.
-func (s *SQLServer) getKeyType(metadata state.Metadata) error {
- if val, ok := metadata.Properties[keyTypeKey]; ok && val != "" {
- kt, err := KeyTypeFromString(val)
+func (s *SQLServer) setKeyType(keyType string, keyLength int) error {
+ if keyType != "" {
+ kt, err := KeyTypeFromString(keyType)
if err != nil {
return err
}
@@ -272,64 +300,44 @@ func (s *SQLServer) getKeyType(metadata state.Metadata) error {
return nil
}
- if val, ok := metadata.Properties[keyLengthKey]; ok && val != "" {
- var err error
- s.keyLength, err = strconv.Atoi(val)
- if err != nil {
- return err
- }
-
- if s.keyLength <= 0 {
- return fmt.Errorf("invalid key length value of %d", s.keyLength)
- }
+ if keyLength <= 0 {
+ return fmt.Errorf("invalid key length value of %d", keyLength)
} else {
- s.keyLength = defaultKeyLength
+ s.keyLength = keyLength
}
return nil
}
// Returns the schema name if set or the default value otherwise.
-func (s *SQLServer) getSchema(metadata state.Metadata) error {
- if val, ok := metadata.Properties[schemaKey]; ok && val != "" {
- if !isValidSQLName(val) {
- return fmt.Errorf("invalid schema name, accepted characters are (A-Z, a-z, 0-9, _)")
- }
- s.schema = val
- } else {
- s.schema = defaultSchema
+func (s *SQLServer) setSchema(schemaName string) error {
+ if !isValidSQLName(schemaName) {
+ return fmt.Errorf("invalid schema name, accepted characters are (A-Z, a-z, 0-9, _)")
}
+ s.schema = schemaName
return nil
}
// Returns the database name if set or the default value otherwise.
-func (s *SQLServer) getDatabase(metadata state.Metadata) error {
- if val, ok := metadata.Properties[databaseNameKey]; ok && val != "" {
- if !isValidSQLName(val) {
- return fmt.Errorf("invalid database name, accepted characters are (A-Z, a-z, 0-9, _)")
- }
-
- s.databaseName = val
- } else {
- s.databaseName = defaultDatabase
+func (s *SQLServer) setDatabase(databaseName string) error {
+ if !isValidSQLName(databaseName) {
+ return fmt.Errorf("invalid database name, accepted characters are (A-Z, a-z, 0-9, _)")
}
+ s.databaseName = databaseName
+
return nil
}
// Returns the table name if set or the default value otherwise.
-func (s *SQLServer) getTable(metadata state.Metadata) error {
- if val, ok := metadata.Properties[tableNameKey]; ok && val != "" {
- if !isValidSQLName(val) {
- return fmt.Errorf("invalid table name, accepted characters are (A-Z, a-z, 0-9, _)")
- }
-
- s.tableName = val
- } else {
- s.tableName = defaultTable
+func (s *SQLServer) setTable(tableName string) error {
+ if !isValidSQLName(tableName) {
+ return fmt.Errorf("invalid table name, accepted characters are (A-Z, a-z, 0-9, _)")
}
+ s.tableName = tableName
+
return nil
}
@@ -541,7 +549,7 @@ func (s *SQLServer) Get(ctx context.Context, req *state.GetRequest) (*state.GetR
return &state.GetResponse{
Data: []byte(data),
- ETag: ptr.String(etag),
+ ETag: ptr.Of(etag),
}, nil
}
@@ -624,3 +632,7 @@ func (s *SQLServer) BulkSet(ctx context.Context, req []state.SetRequest) error {
return err
}
+
+func (s *SQLServer) GetComponentMetadata() map[string]string {
+ return map[string]string{}
+}
diff --git a/state/sqlserver/sqlserver_test.go b/state/sqlserver/sqlserver_test.go
index 6233e382f..cacaf4eb0 100644
--- a/state/sqlserver/sqlserver_test.go
+++ b/state/sqlserver/sqlserver_test.go
@@ -229,11 +229,6 @@ func TestInvalidConfiguration(t *testing.T) {
props: map[string]string{connectionStringKey: ""},
expectedErr: "missing connection string",
},
- {
- name: "Invalid maxKeyLength value",
- props: map[string]string{connectionStringKey: sampleConnectionString, tableNameKey: "test", keyLengthKey: "aa"},
- expectedErr: "parsing \"aa\"",
- },
{
name: "Negative maxKeyLength value",
props: map[string]string{connectionStringKey: sampleConnectionString, tableNameKey: "test", keyLengthKey: "-1"},
diff --git a/state/store.go b/state/store.go
index 592ffeb34..803052bbe 100644
--- a/state/store.go
+++ b/state/store.go
@@ -28,6 +28,7 @@ type Store interface {
Delete(ctx context.Context, req *DeleteRequest) error
Get(ctx context.Context, req *GetRequest) (*GetResponse, error)
Set(ctx context.Context, req *SetRequest) error
+ GetComponentMetadata() map[string]string
}
func Ping(store Store) error {
diff --git a/state/store_test.go b/state/store_test.go
index 5657bd40d..0face2e2c 100644
--- a/state/store_test.go
+++ b/state/store_test.go
@@ -129,6 +129,10 @@ func (s *Store1) Set(ctx context.Context, req *SetRequest) error {
return nil
}
+func (s *Store1) GetComponentMetadata() map[string]string {
+ return map[string]string{}
+}
+
// example of store which supports bulk method.
type Store2 struct {
// DefaultBulkStore
@@ -187,3 +191,7 @@ func (s *Store2) BulkDelete(ctx context.Context, req []DeleteRequest) error {
return nil
}
+
+func (s *Store2) GetComponentMetadata() map[string]string {
+ return map[string]string{}
+}
diff --git a/state/zookeeper/zk.go b/state/zookeeper/zk.go
index 69b368469..f80691185 100644
--- a/state/zookeeper/zk.go
+++ b/state/zookeeper/zk.go
@@ -17,17 +17,19 @@ import (
"context"
"errors"
"path"
+ reflect "reflect"
"strconv"
"strings"
"time"
- "github.com/agrea/ptr"
"github.com/hashicorp/go-multierror"
jsoniter "github.com/json-iterator/go"
"github.com/samuel/go-zookeeper/zk"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
)
const (
@@ -57,16 +59,11 @@ type config struct {
keyPrefixPath string
}
-func newConfig(metadata map[string]string) (c *config, err error) {
- var buf []byte
-
- if buf, err = jsoniter.ConfigFastest.Marshal(metadata); err != nil {
- return
- }
-
+func newConfig(meta map[string]string) (c *config, err error) {
var props properties
- if err = jsoniter.ConfigFastest.Unmarshal(buf, &props); err != nil {
- return
+ errDecode := metadata.DecodeMetadata(meta, &props)
+ if errDecode != nil {
+ return nil, errDecode
}
return props.parse()
@@ -174,7 +171,7 @@ func (s *StateStore) Get(ctx context.Context, req *state.GetRequest) (*state.Get
return &state.GetResponse{
Data: value,
- ETag: ptr.String(strconv.Itoa(int(stat.Version))),
+ ETag: ptr.Of(strconv.Itoa(int(stat.Version))),
}, nil
}
@@ -191,22 +188,20 @@ func (s *StateStore) Delete(ctx context.Context, req *state.DeleteRequest) error
return err
}
- return state.DeleteWithOptions(ctx, func(ctx context.Context, req *state.DeleteRequest) error {
- err := s.conn.Delete(r.Path, r.Version)
- if errors.Is(err, zk.ErrNoNode) {
- return nil
- }
-
- if err != nil {
- if req.ETag != nil {
- return state.NewETagError(state.ETagMismatch, err)
- }
-
- return err
- }
-
+ err = s.conn.Delete(r.Path, r.Version)
+ if errors.Is(err, zk.ErrNoNode) {
return nil
- }, req)
+ }
+
+ if err != nil {
+ if req.ETag != nil {
+ return state.NewETagError(state.ETagMismatch, err)
+ }
+
+ return err
+ }
+
+ return nil
}
// BulkDelete performs a bulk delete operation.
@@ -243,23 +238,20 @@ func (s *StateStore) Set(ctx context.Context, req *state.SetRequest) error {
return err
}
- return state.SetWithOptions(ctx, func(ctx context.Context, req *state.SetRequest) error {
- _, err = s.conn.Set(r.Path, r.Data, r.Version)
+ _, err = s.conn.Set(r.Path, r.Data, r.Version)
+ if errors.Is(err, zk.ErrNoNode) {
+ _, err = s.conn.Create(r.Path, r.Data, 0, nil)
+ }
- if errors.Is(err, zk.ErrNoNode) {
- _, err = s.conn.Create(r.Path, r.Data, 0, nil)
+ if err != nil {
+ if req.ETag != nil {
+ return state.NewETagError(state.ETagMismatch, err)
}
- if err != nil {
- if req.ETag != nil {
- return state.NewETagError(state.ETagMismatch, err)
- }
+ return err
+ }
- return err
- }
-
- return nil
- }, req)
+ return nil
}
// BulkSet performs a bulks save operation.
@@ -391,3 +383,10 @@ func (s *StateStore) marshalData(v interface{}) ([]byte, error) {
return jsoniter.ConfigFastest.Marshal(v)
}
+
+func (s *StateStore) GetComponentMetadata() map[string]string {
+ metadataStruct := properties{}
+ metadataInfo := map[string]string{}
+ metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo)
+ return metadataInfo
+}
diff --git a/state/zookeeper/zk_test.go b/state/zookeeper/zk_test.go
index 8bfe52fee..b3cc9d9a8 100644
--- a/state/zookeeper/zk_test.go
+++ b/state/zookeeper/zk_test.go
@@ -19,13 +19,13 @@ import (
"testing"
"time"
- "github.com/agrea/ptr"
gomock "github.com/golang/mock/gomock"
"github.com/hashicorp/go-multierror"
"github.com/samuel/go-zookeeper/zk"
"github.com/stretchr/testify/assert"
"github.com/dapr/components-contrib/state"
+ "github.com/dapr/kit/ptr"
)
//go:generate mockgen -package zookeeper -source zk.go -destination zk_mock.go
@@ -84,7 +84,7 @@ func TestGet(t *testing.T) {
res, err := s.Get(context.Background(), &state.GetRequest{Key: "foo"})
assert.NotNil(t, res, "Key must be exists")
assert.Equal(t, "bar", string(res.Data), "Value must be equals")
- assert.Equal(t, ptr.String("123"), res.ETag, "ETag must be equals")
+ assert.Equal(t, ptr.Of("123"), res.ETag, "ETag must be equals")
assert.NoError(t, err, "Key must be exists")
})
diff --git a/tests/certification/bindings/alicloud/dubbo/go.mod b/tests/certification/bindings/alicloud/dubbo/go.mod
index cacc7577c..c48901b1d 100644
--- a/tests/certification/bindings/alicloud/dubbo/go.mod
+++ b/tests/certification/bindings/alicloud/dubbo/go.mod
@@ -7,9 +7,9 @@ require (
github.com/apache/dubbo-go-hessian2 v1.11.3
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211026011813-36b75e9ae272
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -29,7 +29,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.2.0 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/creasty/defaults v1.5.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
@@ -103,6 +103,7 @@ require (
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -138,14 +139,14 @@ require (
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/bindings/alicloud/dubbo/go.sum b/tests/certification/bindings/alicloud/dubbo/go.sum
index 7074cdfce..4d7d55671 100644
--- a/tests/certification/bindings/alicloud/dubbo/go.sum
+++ b/tests/certification/bindings/alicloud/dubbo/go.sum
@@ -112,8 +112,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72H
github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk=
github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g=
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
-github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
+github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -127,8 +127,8 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@@ -174,8 +174,8 @@ github.com/creasty/defaults v1.5.2 h1:/VfB6uxpyp6h0fr7SPp7n8WJBoV8jfxQXPCnkVSjyl
github.com/creasty/defaults v1.5.2/go.mod h1:FPZ+Y0WNrbqOVw+c6av63eyHUAl6pMHZwqLPvXUZGfY=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -697,6 +697,7 @@ github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhEC
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
@@ -811,7 +812,7 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
+github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
@@ -981,7 +982,7 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@@ -1005,8 +1006,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1252,8 +1253,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/bindings/alicloud/nacos/go.mod b/tests/certification/bindings/alicloud/nacos/go.mod
index 53607282f..3006d7ef4 100644
--- a/tests/certification/bindings/alicloud/nacos/go.mod
+++ b/tests/certification/bindings/alicloud/nacos/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211026011813-36b75e9ae272
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/nacos-group/nacos-sdk-go/v2 v2.1.2
github.com/stretchr/testify v1.8.1
)
@@ -23,7 +23,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
@@ -78,6 +78,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -107,7 +108,7 @@ require (
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sync v0.1.0 // indirect
@@ -115,7 +116,7 @@ require (
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/bindings/alicloud/nacos/go.sum b/tests/certification/bindings/alicloud/nacos/go.sum
index 95ef94b4f..a06986b3e 100644
--- a/tests/certification/bindings/alicloud/nacos/go.sum
+++ b/tests/certification/bindings/alicloud/nacos/go.sum
@@ -66,8 +66,8 @@ github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJ
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
-github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
+github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -77,8 +77,8 @@ github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMU
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -101,8 +101,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -398,6 +398,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -546,7 +547,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -568,8 +569,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -768,8 +769,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/bindings/azure/blobstorage/blobstorage_test.go b/tests/certification/bindings/azure/blobstorage/blobstorage_test.go
index 964b2910d..a775cc53c 100644
--- a/tests/certification/bindings/azure/blobstorage/blobstorage_test.go
+++ b/tests/certification/bindings/azure/blobstorage/blobstorage_test.go
@@ -33,12 +33,16 @@ import (
dapr_testing "github.com/dapr/dapr/pkg/testing"
daprsdk "github.com/dapr/go-sdk/client"
"github.com/dapr/kit/logger"
+ "github.com/dapr/kit/ptr"
"github.com/dapr/components-contrib/tests/certification/embedded"
"github.com/dapr/components-contrib/tests/certification/flow"
"github.com/dapr/components-contrib/tests/certification/flow/sidecar"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/bloberror"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container"
)
const (
@@ -104,10 +108,12 @@ func listBlobRequest(ctx flow.Context, client daprsdk.Client, prefix string, mar
}
// deleteBlobRequest is used to make a common binding request for the delete operation.
-func deleteBlobRequest(ctx flow.Context, client daprsdk.Client, name string, deleteSnapshotsOption string) (out *daprsdk.BindingEvent, err error) {
+func deleteBlobRequest(ctx flow.Context, client daprsdk.Client, name string, deleteSnapshotsOption *string) (out *daprsdk.BindingEvent, err error) {
invokeDeleteMetadata := map[string]string{
- "blobName": name,
- "deleteSnapshots": deleteSnapshotsOption,
+ "blobName": name,
+ }
+ if deleteSnapshotsOption != nil {
+ invokeDeleteMetadata["deleteSnapshots"] = *deleteSnapshotsOption
}
invokeGetRequest := &daprsdk.InvokeBindingRequest{
@@ -185,19 +191,19 @@ func TestBlobStorage(t *testing.T) {
assert.Equal(t, newString, input2)
// cleanup.
- out, invokeDeleteErr := deleteBlobRequest(ctx, client, blobName, "")
+ out, invokeDeleteErr := deleteBlobRequest(ctx, client, blobName, nil)
assert.NoError(t, invokeDeleteErr)
assert.Empty(t, out.Data)
// confirm the deletion.
_, invokeSecondGetErr := getBlobRequest(ctx, client, blobName, false)
assert.Error(t, invokeSecondGetErr)
- assert.Contains(t, invokeSecondGetErr.Error(), "ServiceCode=BlobNotFound")
+ assert.Contains(t, invokeSecondGetErr.Error(), bloberror.BlobNotFound)
// deleting the key again should fail.
- _, invokeDeleteErr2 := deleteBlobRequest(ctx, client, blobName, "")
+ _, invokeDeleteErr2 := deleteBlobRequest(ctx, client, blobName, nil)
assert.Error(t, invokeDeleteErr2)
- assert.Contains(t, invokeDeleteErr2.Error(), "ServiceCode=BlobNotFound")
+ assert.Contains(t, invokeDeleteErr2.Error(), bloberror.BlobNotFound)
return nil
}
@@ -230,7 +236,7 @@ func TestBlobStorage(t *testing.T) {
_, invokeCreateErr := client.InvokeBinding(ctx, invokeCreateRequest)
assert.Error(t, invokeCreateErr)
- assert.Contains(t, invokeCreateErr.Error(), "ServiceCode=Md5Mismatch")
+ assert.Contains(t, invokeCreateErr.Error(), bloberror.MD5Mismatch)
return nil
}
@@ -272,14 +278,14 @@ func TestBlobStorage(t *testing.T) {
assert.Equal(t, responseData, dataBytes)
assert.Empty(t, out.Metadata)
- out, invokeDeleteErr := deleteBlobRequest(ctx, client, blobName, "")
+ out, invokeDeleteErr := deleteBlobRequest(ctx, client, blobName, nil)
assert.NoError(t, invokeDeleteErr)
assert.Empty(t, out.Data)
// confirm the deletion.
_, invokeSecondGetErr := getBlobRequest(ctx, client, blobName, false)
assert.Error(t, invokeSecondGetErr)
- assert.Contains(t, invokeSecondGetErr.Error(), "ServiceCode=BlobNotFound")
+ assert.Contains(t, invokeSecondGetErr.Error(), bloberror.BlobNotFound)
return nil
}
@@ -327,7 +333,7 @@ func TestBlobStorage(t *testing.T) {
}
// cleanup.
- _, invokeDeleteErr := deleteBlobRequest(ctx, client, blobName, "")
+ _, invokeDeleteErr := deleteBlobRequest(ctx, client, blobName, nil)
assert.NoError(t, invokeDeleteErr)
return nil
@@ -384,9 +390,9 @@ func TestBlobStorage(t *testing.T) {
out, invokeGetErr := client.InvokeBinding(ctx, invokeGetRequest)
assert.NoError(t, invokeGetErr)
- assert.Equal(t, string(out.Data), input)
- assert.Contains(t, out.Metadata, "custom")
- assert.Equal(t, out.Metadata["custom"], "hello-world")
+ assert.Equal(t, input, string(out.Data))
+ assert.Contains(t, out.Metadata, "Custom")
+ assert.Equal(t, "hello-world", out.Metadata["Custom"])
out, invokeErr := listBlobRequest(ctx, client, "", "", -1, true, false, false, false, false)
assert.NoError(t, invokeErr)
@@ -412,14 +418,14 @@ func TestBlobStorage(t *testing.T) {
}
assert.True(t, found)
- out, invokeDeleteErr := deleteBlobRequest(ctx, client, "filename.txt", "")
+ out, invokeDeleteErr := deleteBlobRequest(ctx, client, "filename.txt", nil)
assert.NoError(t, invokeDeleteErr)
assert.Empty(t, out.Data)
// confirm the deletion.
_, invokeSecondGetErr := getBlobRequest(ctx, client, "filename.txt", false)
assert.Error(t, invokeSecondGetErr)
- assert.Contains(t, invokeSecondGetErr.Error(), "ServiceCode=BlobNotFound")
+ assert.Contains(t, invokeSecondGetErr.Error(), bloberror.BlobNotFound)
return nil
}
@@ -505,8 +511,8 @@ func TestBlobStorage(t *testing.T) {
unmarshalErr := json.Unmarshal(out.Data, &output)
assert.NoError(t, unmarshalErr)
- assert.Equal(t, len(output), 1)
- assert.Equal(t, output[0]["Name"], "prefixA/filename.txt")
+ assert.Equal(t, 1, len(output))
+ assert.Contains(t, output[0]["Name"], "prefixA")
nextMarker := out.Metadata["marker"]
@@ -518,27 +524,27 @@ func TestBlobStorage(t *testing.T) {
err2 := json.Unmarshal(out2.Data, &output2)
assert.NoError(t, err2)
- assert.Equal(t, len(output2), 1)
- assert.Equal(t, output2[0]["Name"], "prefixAfilename.txt")
+ assert.Equal(t, 1, len(output2))
+ assert.Contains(t, output2[0]["Name"], "prefixA")
// cleanup.
- _, invokeDeleteErr1 := deleteBlobRequest(ctx, client, "prefixA/filename.txt", "")
+ _, invokeDeleteErr1 := deleteBlobRequest(ctx, client, "prefixA/filename.txt", nil)
assert.NoError(t, invokeDeleteErr1)
- _, invokeDeleteErr2 := deleteBlobRequest(ctx, client, "prefixAfilename.txt", "")
+ _, invokeDeleteErr2 := deleteBlobRequest(ctx, client, "prefixAfilename.txt", nil)
assert.NoError(t, invokeDeleteErr2)
- _, invokeDeleteErr3 := deleteBlobRequest(ctx, client, "prefixB/filename.txt", "")
+ _, invokeDeleteErr3 := deleteBlobRequest(ctx, client, "prefixB/filename.txt", nil)
assert.NoError(t, invokeDeleteErr3)
// list deleted items with prefix.
- out3, listErr3 := listBlobRequest(ctx, client, "prefixA", "", -1, false, false, false, false, true)
+ out3, listErr3 := listBlobRequest(ctx, client, "prefixA/", "", -1, false, false, false, false, true)
assert.NoError(t, listErr3)
// this will only return the deleted items if soft delete policy is enabled for the blob service.
- assert.Equal(t, out3.Metadata["number"], "2")
+ assert.Equal(t, "1", out3.Metadata["number"])
var output3 []map[string]interface{}
err3 := json.Unmarshal(out3.Data, &output3)
assert.NoError(t, err3)
- assert.Equal(t, len(output3), 2)
+ assert.Equal(t, len(output3), 1)
return nil
}
@@ -553,17 +559,15 @@ func TestBlobStorage(t *testing.T) {
defer client.Close()
cred, _ := azblob.NewSharedKeyCredential(os.Getenv("AzureBlobStorageAccount"), os.Getenv("AzureBlobStorageAccessKey"))
- service, _ := azblob.NewServiceClientWithSharedKey(fmt.Sprintf("https://%s.blob.core.windows.net/", os.Getenv("AzureBlobStorageAccount")), cred, nil)
- containerClient, _ := service.NewContainerClient(os.Getenv("AzureBlobStorageContainer"))
+ containerClient, _ := container.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.blob.core.windows.net/%s", os.Getenv("AzureBlobStorageAccount"), os.Getenv("AzureBlobStorageContainer")), cred, nil)
- blobClient, _ := containerClient.NewBlockBlobClient("snapshotthis.txt")
- uploadResp, uploadErr := blobClient.UploadBuffer(
+ blobClient := containerClient.NewBlockBlobClient("snapshotthis.txt")
+ _, uploadErr := blobClient.UploadBuffer(
ctx, []byte("some example content"),
- azblob.UploadOption{}) //nolint:exhaustivestruct
+ &azblob.UploadBufferOptions{}) //nolint:exhaustivestruct
assert.NoError(t, uploadErr)
- uploadResp.Body.Close()
_, createSnapshotErr := blobClient.CreateSnapshot(
- ctx, &azblob.BlobCreateSnapshotOptions{}) //nolint:exhaustivestruct
+ ctx, &blob.CreateSnapshotOptions{}) //nolint:exhaustivestruct
assert.NoError(t, createSnapshotErr)
// list the contents of the container including snapshots for the specific blob only.
@@ -572,27 +576,27 @@ func TestBlobStorage(t *testing.T) {
assert.Equal(t, out.Metadata["number"], "2")
// delete snapshots.
- _, invokeDeleteErr := deleteBlobRequest(ctx, client, "snapshotthis.txt", "only")
+ _, invokeDeleteErr := deleteBlobRequest(ctx, client, "snapshotthis.txt", ptr.Of(string(blob.DeleteSnapshotsOptionTypeOnly)))
assert.NoError(t, invokeDeleteErr)
// verify snapshot is deleted.
out2, listErr2 := listBlobRequest(ctx, client, "snapshotthis.txt", "", -1, false, true, false, false, false)
assert.NoError(t, listErr2)
- assert.Equal(t, out2.Metadata["number"], "1")
+ assert.Equal(t, "1", out2.Metadata["number"])
// create another snapshot.
_, createSnapshotErr2 := blobClient.CreateSnapshot(
- ctx, &azblob.BlobCreateSnapshotOptions{}) //nolint:exhaustivestruct
+ ctx, &blob.CreateSnapshotOptions{}) //nolint:exhaustivestruct
assert.NoError(t, createSnapshotErr2)
// delete base blob and snapshots all at once.
- _, invokeDeleteErr2 := deleteBlobRequest(ctx, client, "snapshotthis.txt", "include")
+ _, invokeDeleteErr2 := deleteBlobRequest(ctx, client, "snapshotthis.txt", ptr.Of(string(blob.DeleteSnapshotsOptionTypeInclude)))
assert.NoError(t, invokeDeleteErr2)
// verify base blob and snapshots are deleted.
out3, listErr3 := listBlobRequest(ctx, client, "snapshotthis.txt", "", -1, false, true, false, false, false)
assert.NoError(t, listErr3)
- assert.Equal(t, out3.Metadata["number"], "0")
+ assert.Equal(t, "0", out3.Metadata["number"])
return nil
}
diff --git a/tests/certification/bindings/azure/blobstorage/go.mod b/tests/certification/bindings/azure/blobstorage/go.mod
index 3f4bba8b8..6ecad066c 100644
--- a/tests/certification/bindings/azure/blobstorage/go.mod
+++ b/tests/certification/bindings/azure/blobstorage/go.mod
@@ -3,12 +3,12 @@ module github.com/dapr/components-contrib/tests/certification/bindings/azure/blo
go 1.19
require (
- github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.4.1
+ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.5.1
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211130185200-4918900c09e1
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -19,7 +19,7 @@ require (
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
github.com/Azure/azure-storage-blob-go v0.10.0 // indirect
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
@@ -37,7 +37,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
@@ -96,6 +96,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -125,14 +126,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/bindings/azure/blobstorage/go.sum b/tests/certification/bindings/azure/blobstorage/go.sum
index 7fe5f186a..3597e1e34 100644
--- a/tests/certification/bindings/azure/blobstorage/go.sum
+++ b/tests/certification/bindings/azure/blobstorage/go.sum
@@ -47,10 +47,10 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 h1:pqrAR74b6EoR4kcxF7L7Wg2B8
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
-github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.4.1 h1:QSdcrd/UFJv6Bp/CfoVf2SrENpFn9P6Yh8yb+xNhYMM=
-github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.4.1/go.mod h1:eZ4g6GUvXiGulfIbbhh1Xr4XwUYaYaWMqzGD/284wCA=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 h1:XUNQ4mw+zJmaA2KXzP9JlQiecy1SI+Eog7xVkPiqIbg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.5.1 h1:BMTdr+ib5ljLa9MxTJK8x/Ds0MbBb4MfuW5BL0zMJnI=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.5.1/go.mod h1:c6WvOhtmjNUWbLfOG1qxM/q0SPvQNSVJvolm+C52dIU=
github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs=
github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE=
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd h1:b3wyxBl3vvr15tUAziPBPK354y+LSdfPCpex5oBttHo=
@@ -124,8 +124,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -147,8 +147,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -455,6 +455,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -607,7 +608,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -629,8 +630,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -826,8 +827,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/bindings/azure/cosmosdb/go.mod b/tests/certification/bindings/azure/cosmosdb/go.mod
index e84584836..a2073f186 100644
--- a/tests/certification/bindings/azure/cosmosdb/go.mod
+++ b/tests/certification/bindings/azure/cosmosdb/go.mod
@@ -6,9 +6,9 @@ require (
github.com/a8m/documentdb v1.3.1-0.20220405205223-5b41ba0aaeb1
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211130185200-4918900c09e1
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/google/uuid v1.3.0
github.com/stretchr/testify v1.8.1
)
@@ -22,7 +22,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.2 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
github.com/Azure/azure-storage-blob-go v0.10.0 // indirect
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
@@ -40,7 +40,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
@@ -98,6 +98,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -127,14 +128,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/bindings/azure/cosmosdb/go.sum b/tests/certification/bindings/azure/cosmosdb/go.sum
index 3c52369f6..be14c5cd8 100644
--- a/tests/certification/bindings/azure/cosmosdb/go.sum
+++ b/tests/certification/bindings/azure/cosmosdb/go.sum
@@ -51,8 +51,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4Sath
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.2 h1:yJegJqjhrMJ3Oe5s43jOTGL2AsE7pJyx+7Yqls/65tw=
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.2/go.mod h1:Fy3bbChFm4cZn6oIxYYqKB2FG3rBDxk3NZDLDJCHl+Q=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 h1:XUNQ4mw+zJmaA2KXzP9JlQiecy1SI+Eog7xVkPiqIbg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs=
github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE=
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd h1:b3wyxBl3vvr15tUAziPBPK354y+LSdfPCpex5oBttHo=
@@ -128,8 +128,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -151,8 +151,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -460,6 +460,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -612,7 +613,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -634,8 +635,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -831,8 +832,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/bindings/azure/eventhubs/go.mod b/tests/certification/bindings/azure/eventhubs/go.mod
index bf4e97ca4..6efe2a3de 100644
--- a/tests/certification/bindings/azure/eventhubs/go.mod
+++ b/tests/certification/bindings/azure/eventhubs/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211026011813-36b75e9ae272
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/google/uuid v1.3.0
github.com/stretchr/testify v1.8.1
go.uber.org/multierr v1.8.0
@@ -22,7 +22,7 @@ require (
github.com/Azure/azure-sdk-for-go v67.0.0+incompatible // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
github.com/Azure/azure-storage-blob-go v0.10.0 // indirect
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
github.com/Azure/go-amqp v0.17.5 // indirect
@@ -43,7 +43,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/devigned/tab v0.1.1 // indirect
@@ -104,6 +104,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -134,14 +135,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/bindings/azure/eventhubs/go.sum b/tests/certification/bindings/azure/eventhubs/go.sum
index 493e5d175..cfd080dbc 100644
--- a/tests/certification/bindings/azure/eventhubs/go.sum
+++ b/tests/certification/bindings/azure/eventhubs/go.sum
@@ -53,8 +53,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 h1:pqrAR74b6EoR4kcxF7L7Wg2B8
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 h1:XUNQ4mw+zJmaA2KXzP9JlQiecy1SI+Eog7xVkPiqIbg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-storage-blob-go v0.6.0/go.mod h1:oGfmITT1V6x//CswqY2gtAHND+xIP64/qL7a5QJix0Y=
github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs=
github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE=
@@ -140,8 +140,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -163,8 +163,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -480,6 +480,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -636,7 +637,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -658,8 +659,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -855,8 +856,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/bindings/azure/servicebusqueues/go.mod b/tests/certification/bindings/azure/servicebusqueues/go.mod
index 8882c17e6..7fab64cb9 100644
--- a/tests/certification/bindings/azure/servicebusqueues/go.mod
+++ b/tests/certification/bindings/azure/servicebusqueues/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211026011813-36b75e9ae272
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
go.uber.org/multierr v1.8.0
)
@@ -19,7 +19,7 @@ require (
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.1 // indirect
github.com/Azure/azure-storage-blob-go v0.10.0 // indirect
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
@@ -40,7 +40,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
@@ -100,6 +100,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -131,14 +132,14 @@ require (
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/ratelimit v0.2.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/bindings/azure/servicebusqueues/go.sum b/tests/certification/bindings/azure/servicebusqueues/go.sum
index 8e42a6c41..8135dcf87 100644
--- a/tests/certification/bindings/azure/servicebusqueues/go.sum
+++ b/tests/certification/bindings/azure/servicebusqueues/go.sum
@@ -47,8 +47,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 h1:pqrAR74b6EoR4kcxF7L7Wg2B8
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 h1:XUNQ4mw+zJmaA2KXzP9JlQiecy1SI+Eog7xVkPiqIbg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.1 h1:Zm7A6yKHT3evC/0lquPWJ9hrkRGVIeZOmIvHPv6xV9Q=
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.1/go.mod h1:LH9XQnMr2ZYxQdVdCrzLO9mxeDyrDFa6wbSI3x5zCZk=
github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs=
@@ -128,8 +128,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -151,8 +151,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -463,6 +463,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -621,7 +622,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -643,8 +644,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -840,8 +841,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/bindings/azure/storagequeues/components/decode/azure_queue_storage.yaml b/tests/certification/bindings/azure/storagequeues/components/decode/azure_queue_storage.yaml
index 1e02a5a42..02a99f0bd 100644
--- a/tests/certification/bindings/azure/storagequeues/components/decode/azure_queue_storage.yaml
+++ b/tests/certification/bindings/azure/storagequeues/components/decode/azure_queue_storage.yaml
@@ -17,6 +17,8 @@ spec:
key: AzureBlobStorageAccessKey
- name: decodeBase64
value: true
+ - name: encodeBase64
+ value: true
- name: queue
value: "decodequeue"
auth:
diff --git a/tests/certification/bindings/azure/storagequeues/components/visibilityTimeout/azure_queue_storage.yaml b/tests/certification/bindings/azure/storagequeues/components/visibilityTimeout/azure_queue_storage.yaml
new file mode 100644
index 000000000..0209c247b
--- /dev/null
+++ b/tests/certification/bindings/azure/storagequeues/components/visibilityTimeout/azure_queue_storage.yaml
@@ -0,0 +1,23 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: visibilityBinding
+ namespace: default
+spec:
+ type: bindings.azure.storagequeues
+ version: v1
+ metadata:
+ - name: storageAccount
+ secretKeyRef:
+ name: AzureBlobStorageAccount
+ key: AzureBlobStorageAccount
+ - name: storageAccessKey
+ secretKeyRef:
+ name: AzureBlobStorageAccessKey
+ key: AzureBlobStorageAccessKey
+ - name: queue
+ value: "visibility"
+ - name: visibilityTimeout
+ value: "20s"
+auth:
+ secretStore: envvar-secret-store
diff --git a/tests/certification/bindings/azure/storagequeues/components/visibilityTimeout/localsecrets.yaml b/tests/certification/bindings/azure/storagequeues/components/visibilityTimeout/localsecrets.yaml
new file mode 100644
index 000000000..94bb7a264
--- /dev/null
+++ b/tests/certification/bindings/azure/storagequeues/components/visibilityTimeout/localsecrets.yaml
@@ -0,0 +1,9 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: envvar-secret-store
+ namespace: default
+spec:
+ type: secretstores.local.env
+ version: v1
+ metadata:
diff --git a/tests/certification/bindings/azure/storagequeues/go.mod b/tests/certification/bindings/azure/storagequeues/go.mod
index bbea3a0d2..559589d1b 100644
--- a/tests/certification/bindings/azure/storagequeues/go.mod
+++ b/tests/certification/bindings/azure/storagequeues/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211026011813-36b75e9ae272
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
go.uber.org/multierr v1.8.0
)
@@ -19,7 +19,7 @@ require (
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
github.com/Azure/azure-storage-blob-go v0.10.0 // indirect
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
@@ -37,7 +37,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
@@ -97,6 +97,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -127,14 +128,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/bindings/azure/storagequeues/go.sum b/tests/certification/bindings/azure/storagequeues/go.sum
index b973a6009..c3d066376 100644
--- a/tests/certification/bindings/azure/storagequeues/go.sum
+++ b/tests/certification/bindings/azure/storagequeues/go.sum
@@ -47,8 +47,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 h1:pqrAR74b6EoR4kcxF7L7Wg2B8
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 h1:XUNQ4mw+zJmaA2KXzP9JlQiecy1SI+Eog7xVkPiqIbg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs=
github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE=
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd h1:b3wyxBl3vvr15tUAziPBPK354y+LSdfPCpex5oBttHo=
@@ -122,8 +122,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -145,8 +145,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -455,6 +455,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -611,7 +612,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -633,8 +634,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -830,8 +831,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/bindings/azure/storagequeues/storagequeue_test.go b/tests/certification/bindings/azure/storagequeues/storagequeue_test.go
index f550b6b3f..12516b2ec 100644
--- a/tests/certification/bindings/azure/storagequeues/storagequeue_test.go
+++ b/tests/certification/bindings/azure/storagequeues/storagequeue_test.go
@@ -16,8 +16,8 @@ package storagequeue_test
import (
"context"
- "encoding/base64"
"fmt"
+ "strings"
"testing"
"time"
@@ -27,17 +27,6 @@ import (
"github.com/dapr/components-contrib/bindings"
binding_asq "github.com/dapr/components-contrib/bindings/azure/storagequeues"
secretstore_env "github.com/dapr/components-contrib/secretstores/local/env"
-
- bindings_loader "github.com/dapr/dapr/pkg/components/bindings"
- secretstores_loader "github.com/dapr/dapr/pkg/components/secretstores"
- "github.com/dapr/dapr/pkg/runtime"
- dapr_testing "github.com/dapr/dapr/pkg/testing"
-
- daprClient "github.com/dapr/go-sdk/client"
- "github.com/dapr/go-sdk/service/common"
-
- "github.com/dapr/kit/logger"
-
"github.com/dapr/components-contrib/tests/certification/embedded"
"github.com/dapr/components-contrib/tests/certification/flow"
"github.com/dapr/components-contrib/tests/certification/flow/app"
@@ -45,6 +34,13 @@ import (
"github.com/dapr/components-contrib/tests/certification/flow/sidecar"
"github.com/dapr/components-contrib/tests/certification/flow/simulate"
"github.com/dapr/components-contrib/tests/certification/flow/watcher"
+ bindings_loader "github.com/dapr/dapr/pkg/components/bindings"
+ secretstores_loader "github.com/dapr/dapr/pkg/components/secretstores"
+ "github.com/dapr/dapr/pkg/runtime"
+ dapr_testing "github.com/dapr/dapr/pkg/testing"
+ daprClient "github.com/dapr/go-sdk/client"
+ "github.com/dapr/go-sdk/service/common"
+ "github.com/dapr/kit/logger"
)
const (
@@ -132,6 +128,7 @@ func TestStorageQueue(t *testing.T) {
componentRuntimeOptions(),
)).
Step("send and wait", test).
+ Step("wait for messages to be deleted", flow.Sleep(time.Second*3)).
Run()
}
@@ -170,9 +167,6 @@ func TestAzureStorageQueueTTLs(t *testing.T) {
err = client.InvokeOutputBinding(ctx, mixedTTLReq)
require.NoError(ctx, err, "error publishing message")
}
-
- // Wait for double the TTL after sending the last message.
- time.Sleep(time.Second * 20)
return nil
}
@@ -201,10 +195,8 @@ func TestAzureStorageQueueTTLs(t *testing.T) {
freshPorts, _ := dapr_testing.GetFreePorts(2)
flow.New(t, "storagequeue ttl certification").
- // Run the application logic above.
- Step(app.Run("ttlApp", fmt.Sprintf(":%d", appPort), ttlApplication)).
Step(sidecar.Run("ttlSidecar",
- embedded.WithAppProtocol(runtime.HTTPProtocol, appPort),
+ embedded.WithoutApp(),
embedded.WithDaprGRPCPort(grpcPort),
embedded.WithDaprHTTPPort(httpPort),
embedded.WithComponentsPath("./components/ttl"),
@@ -212,6 +204,7 @@ func TestAzureStorageQueueTTLs(t *testing.T) {
)).
Step("send ttl messages", ttlTest).
Step("stop initial sidecar", sidecar.Stop("ttlSidecar")).
+ Step("wait for messages to expire", flow.Sleep(time.Second*20)).
Step(app.Run("ttlApp", fmt.Sprintf(":%d", appPort), ttlApplication)).
Step(sidecar.Run("appSidecar",
embedded.WithAppProtocol(runtime.HTTPProtocol, appPort),
@@ -224,6 +217,7 @@ func TestAzureStorageQueueTTLs(t *testing.T) {
ttlMessages.Assert(t, time.Minute)
return nil
}).
+ Step("wait for messages to be deleted", flow.Sleep(time.Second*3)).
Run()
}
@@ -251,9 +245,6 @@ func TestAzureStorageQueueTTLsWithLessSleepTime(t *testing.T) {
err = client.InvokeOutputBinding(ctx, messageTTLReq)
require.NoError(ctx, err, "error publishing message")
}
-
- // Wait for double the TTL after sending the last message.
- time.Sleep(time.Second * 1)
return nil
}
@@ -281,6 +272,7 @@ func TestAzureStorageQueueTTLsWithLessSleepTime(t *testing.T) {
componentRuntimeOptions(),
)).
Step("send ttl messages", ttlTest).
+ Step("wait a brief moment - messages will not have expired", flow.Sleep(time.Second*1)).
Step("stop initial sidecar", sidecar.Stop("ttlSidecar")).
Step(app.Run("ttlApp", fmt.Sprintf(":%d", appPort), ttlApplication)).
Step(sidecar.Run("appSidecar",
@@ -294,6 +286,7 @@ func TestAzureStorageQueueTTLsWithLessSleepTime(t *testing.T) {
ttlMessages.Assert(t, time.Minute)
return nil
}).
+ Step("wait for messages to be deleted", flow.Sleep(time.Second*3)).
Run()
}
@@ -312,7 +305,7 @@ func TestAzureStorageQueueForDecode(t *testing.T) {
// Declare the expected data.
msgs := make([]string, numOfMessages)
for i := 0; i < numOfMessages; i++ {
- msgs[i] = fmt.Sprintf("Message %03d", i)
+ msgs[i] = fmt.Sprintf("Message 新 %03d", i) // the chinese character is part of the test for UTF-8 characters
}
messages.ExpectStrings(msgs...)
@@ -323,7 +316,6 @@ func TestAzureStorageQueueForDecode(t *testing.T) {
for _, msg := range msgs {
ctx.Logf("Sending: %q", msg)
dataBytes := []byte(msg)
- dataBytes = []byte(base64.StdEncoding.EncodeToString(dataBytes))
req := &daprClient.InvokeBindingRequest{Name: "decode-binding", Operation: "create", Data: dataBytes, Metadata: metadata}
err := client.InvokeOutputBinding(ctx, req)
require.NoError(ctx, err, "error publishing message")
@@ -356,6 +348,92 @@ func TestAzureStorageQueueForDecode(t *testing.T) {
componentRuntimeOptions(),
)).
Step("send and wait", testDecode).
+ Step("wait for messages to be deleted", flow.Sleep(time.Second*3)).
+ Run()
+}
+
+func TestAzureStorageQueueForVisibility(t *testing.T) {
+ allmessages := watcher.NewOrdered()
+
+ ports, _ := dapr_testing.GetFreePorts(3)
+ grpcPort := ports[0]
+ httpPort := ports[1]
+ appPort := ports[2]
+
+ messageRetryMap := make(map[string]bool)
+
+ testVisibility := func(ctx flow.Context) error {
+ client, err := daprClient.NewClientWithPort(fmt.Sprintf("%d", grpcPort))
+ require.NoError(t, err, "Could not initialize dapr client.")
+
+ numMessages := 3
+ // Declare the expected data.
+ msgs := make([]string, numMessages)
+ for i := 0; i < 3; i++ {
+ msgs[i] = fmt.Sprintf("Message %d", i)
+ }
+
+ retryMessages := make([]string, numMessages)
+ for i := 0; i < 3; i++ {
+ retryMessages[i] = fmt.Sprintf("Retry Message %d", i)
+ }
+ // combine retryMessages and msgs
+ combineMessages := make([]string, 0)
+ combineMessages = append(combineMessages, msgs...)
+ combineMessages = append(combineMessages, retryMessages...)
+ allmessages.ExpectStrings(combineMessages...)
+
+ metadata := make(map[string]string)
+
+ ctx.Log("Invoking output binding!")
+ for i := 0; i < numMessages; i++ {
+ dataBytes := []byte(msgs[i])
+ req := &daprClient.InvokeBindingRequest{Name: "visibilityBinding", Operation: "create", Data: dataBytes, Metadata: metadata}
+ err := client.InvokeOutputBinding(ctx, req)
+ require.NoError(ctx, err, "error publishing message")
+ // we alternate between message we will accept and message we will intentionally reject / fail just once for visibility testing
+ dataBytes = []byte(retryMessages[i])
+ req = &daprClient.InvokeBindingRequest{Name: "visibilityBinding", Operation: "create", Data: dataBytes, Metadata: metadata}
+ err = client.InvokeOutputBinding(ctx, req)
+ require.NoError(ctx, err, "error publishing message")
+ }
+
+ // check that we eventually got all messages
+ // this verifies that the retried messages were delivered after the other messages
+ allmessages.Assert(ctx, time.Second*60)
+
+ return nil
+ }
+
+ visibilityApplication := func(ctx flow.Context, s common.Service) (err error) {
+ // Setup the input binding endpoints.
+ err = multierr.Combine(err,
+ s.AddBindingInvocationHandler("visibilityBinding", func(_ context.Context, in *common.BindingEvent) ([]byte, error) {
+ ctx.Logf("Reading message: %s", string(in.Data))
+ if strings.HasPrefix(string(in.Data), "Retry") && !messageRetryMap[string(in.Data)] {
+ ctx.Logf("Intentionally retrying message: %s", string(in.Data))
+ messageRetryMap[string(in.Data)] = true
+ return nil, fmt.Errorf("retry")
+ }
+ allmessages.Observe(string(in.Data))
+ ctx.Logf("Successfully handled message: %s", string(in.Data))
+ return []byte("{}"), nil
+ }))
+ return err
+ }
+
+ flow.New(t, "storagequeue visibilityTimeout certification").
+ // Run the application logic above.
+ Step(app.Run("standardApp", fmt.Sprintf(":%d", appPort), visibilityApplication)).
+ Step(sidecar.Run("standardSidecar",
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort),
+ embedded.WithDaprGRPCPort(grpcPort),
+ embedded.WithDaprHTTPPort(httpPort),
+ embedded.WithComponentsPath("./components/visibilityTimeout"),
+ componentRuntimeOptions(),
+ )).
+ Step("send and wait", testVisibility).
+ Step("wait for messages to be deleted", flow.Sleep(time.Second*3)).
Run()
}
@@ -428,6 +506,7 @@ func TestAzureStorageQueueRetriesOnError(t *testing.T) {
)).
Step("interrupt network", network.InterruptNetwork(time.Minute, []string{}, []string{}, "443")).
Step("send and wait", testRetry).
+ Step("wait for messages to be deleted", flow.Sleep(time.Second*3)).
Run()
}
diff --git a/tests/certification/bindings/cron/README.md b/tests/certification/bindings/cron/README.md
new file mode 100644
index 000000000..c2f9f7f53
--- /dev/null
+++ b/tests/certification/bindings/cron/README.md
@@ -0,0 +1,15 @@
+# Cron certification testing
+
+This project aims to test the cron component under various conditions.
+
+## Test plan
+
+* Test cron triggers with different schedules and written in different cron formats within deadline limits
+> Example: a cron trigger with a schedule `@every 1s` should trigger 10 times in the next 10 seconds
+> Test cron triggers with schedule written in the standard crontab format `*/15 * * * *`, non-standard format `*/3 * * * * *`, quartz format `0 0 */6 ?* *` and macro format `@every 3s`
+* Test cron triggers having same route
+> Check if two cron triggers having different schedules of `@every 1s` and `@every 3s` respectively and having same app route `/cron` should both trigger the app correctly
+* Test cron trigger on app restart
+> Check if cron will still trigger the app in case the app listening to cron trigger crashes and restarts
+* Test cron trigger on sidecar restart
+> Check if the app is still triggered by cron in case of dapr sidecar restart.
\ No newline at end of file
diff --git a/tests/certification/bindings/cron/components/cron15m.yaml b/tests/certification/bindings/cron/components/cron15m.yaml
new file mode 100644
index 000000000..1b7deb72d
--- /dev/null
+++ b/tests/certification/bindings/cron/components/cron15m.yaml
@@ -0,0 +1,11 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: cron15m
+spec:
+ type: bindings.cron
+ version: v1
+ metadata:
+ - name: schedule
+ # test standard crontab format
+ value: "*/15 * * * *"
\ No newline at end of file
diff --git a/tests/certification/bindings/cron/components/cron1s.yaml b/tests/certification/bindings/cron/components/cron1s.yaml
new file mode 100644
index 000000000..1b41d60da
--- /dev/null
+++ b/tests/certification/bindings/cron/components/cron1s.yaml
@@ -0,0 +1,12 @@
+
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: cron1s
+spec:
+ type: bindings.cron
+ version: v1
+ metadata:
+ - name: schedule
+ # test non-standard macro format
+ value: "@every 1s"
\ No newline at end of file
diff --git a/tests/certification/bindings/cron/components/cron3s.yaml b/tests/certification/bindings/cron/components/cron3s.yaml
new file mode 100644
index 000000000..1ff513a76
--- /dev/null
+++ b/tests/certification/bindings/cron/components/cron3s.yaml
@@ -0,0 +1,12 @@
+
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: cron3s
+spec:
+ type: bindings.cron
+ version: v1
+ metadata:
+ - name: schedule
+ # test non-standard crontab format
+ value: "*/3 * * * * *"
\ No newline at end of file
diff --git a/tests/certification/bindings/cron/components/cron6h.yaml b/tests/certification/bindings/cron/components/cron6h.yaml
new file mode 100644
index 000000000..7f6b1a85f
--- /dev/null
+++ b/tests/certification/bindings/cron/components/cron6h.yaml
@@ -0,0 +1,11 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: cron6h
+spec:
+ type: bindings.cron
+ version: v1
+ metadata:
+ - name: schedule
+ # test quartz crontab format
+ value: "0 0 */6 ? * *"
\ No newline at end of file
diff --git a/tests/certification/bindings/cron/components/cronMonthly.yaml b/tests/certification/bindings/cron/components/cronMonthly.yaml
new file mode 100644
index 000000000..3cfc31fa0
--- /dev/null
+++ b/tests/certification/bindings/cron/components/cronMonthly.yaml
@@ -0,0 +1,11 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: cronMonthly
+spec:
+ type: bindings.cron
+ version: v1
+ metadata:
+ - name: schedule
+ # test standard crontab format
+ value: "0 0 1 * *"
\ No newline at end of file
diff --git a/tests/certification/bindings/cron/components_sameroute/cron.yaml b/tests/certification/bindings/cron/components_sameroute/cron.yaml
new file mode 100644
index 000000000..d08ca6101
--- /dev/null
+++ b/tests/certification/bindings/cron/components_sameroute/cron.yaml
@@ -0,0 +1,15 @@
+
+# Testing two cron bindings with different schedule and same route
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: cron
+spec:
+ type: bindings.cron
+ version: v1
+ metadata:
+ - name: schedule
+ # test non-standard macro format
+ value: "@every 1s"
+ - name: route
+ value: /cron
\ No newline at end of file
diff --git a/tests/certification/bindings/cron/components_sameroute/cron3s.yaml b/tests/certification/bindings/cron/components_sameroute/cron3s.yaml
new file mode 100644
index 000000000..3ff25799f
--- /dev/null
+++ b/tests/certification/bindings/cron/components_sameroute/cron3s.yaml
@@ -0,0 +1,15 @@
+
+# Testing two cron bindings with different schedule and same route
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: cron3s
+spec:
+ type: bindings.cron
+ version: v1
+ metadata:
+ - name: schedule
+ # test non-standard crontab format
+ value: "*/3 * * * * *"
+ - name: route
+ value: /cron
\ No newline at end of file
diff --git a/tests/certification/bindings/cron/config.yaml b/tests/certification/bindings/cron/config.yaml
new file mode 100644
index 000000000..3a2e2b30c
--- /dev/null
+++ b/tests/certification/bindings/cron/config.yaml
@@ -0,0 +1,4 @@
+apiVersion: dapr.io/v1alpha1
+kind: Configuration
+metadata:
+ name: cronbindingconfig
\ No newline at end of file
diff --git a/tests/certification/bindings/cron/cron_test.go b/tests/certification/bindings/cron/cron_test.go
new file mode 100644
index 000000000..6c1381468
--- /dev/null
+++ b/tests/certification/bindings/cron/cron_test.go
@@ -0,0 +1,298 @@
+/*
+Copyright 2021 The Dapr Authors
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package cron_test
+
+import (
+ "context"
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/benbjohnson/clock"
+ "github.com/stretchr/testify/require"
+
+ "github.com/dapr/components-contrib/bindings"
+ "github.com/dapr/components-contrib/bindings/cron"
+ "github.com/dapr/dapr/pkg/runtime"
+ "github.com/dapr/go-sdk/service/common"
+ "github.com/dapr/kit/logger"
+
+ // Certification testing runnables
+ "github.com/dapr/components-contrib/tests/certification/embedded"
+ "github.com/dapr/components-contrib/tests/certification/flow"
+ "github.com/dapr/components-contrib/tests/certification/flow/app"
+ "github.com/dapr/components-contrib/tests/certification/flow/sidecar"
+
+ bindings_loader "github.com/dapr/dapr/pkg/components/bindings"
+ dapr_testing "github.com/dapr/dapr/pkg/testing"
+)
+
+type cronTest struct {
+ cronName string // name of the cron binding
+ schedule string // cron schedule
+ expectedTriggerCount int // expected number of triggers within the deadline
+ timeoutToObserveTriggers time.Duration // time to add to the mock clock to observe triggers
+ clk *clock.Mock // mock clock
+}
+
+// starting time for the mock clock
+var startTime = time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC)
+
+// Test cron triggers with different schedules
+//
+//nolint:dupword
+func TestCronBindingTrigger(t *testing.T) {
+ appName := "cronapp"
+ sidecarName := "cron-sidecar"
+
+ testMatrix := []cronTest{
+ {
+ cronName: "cron1s",
+ schedule: "@every 1s", // Test macro cron format
+ expectedTriggerCount: 10,
+ timeoutToObserveTriggers: time.Second * 10,
+ },
+ {
+ cronName: "cron3s",
+ schedule: "*/3 * * * * *", // Test non-standard crontab format
+ expectedTriggerCount: 10,
+ timeoutToObserveTriggers: time.Second * 30,
+ },
+ {
+ cronName: "cron15m",
+ schedule: "*/15 * * * *", // Test standard crontab format
+ expectedTriggerCount: 12,
+ timeoutToObserveTriggers: time.Hour * 3,
+ },
+ {
+ cronName: "cron6h",
+ schedule: "0 0 */6 ? * *", // Test quartz cron format
+ expectedTriggerCount: 12,
+ timeoutToObserveTriggers: time.Hour * 24 * 3,
+ },
+ {
+ cronName: "cronMonthly",
+ schedule: "0 0 1 * *", // Test standard cron format
+ expectedTriggerCount: 10,
+ timeoutToObserveTriggers: time.Hour * 24 * 31 * 10, // Add 10 months to the mock clock
+ },
+ }
+
+ for _, cronTest := range testMatrix {
+ cronTest.clk = clock.NewMock()
+ cronTest.clk.Set(startTime)
+
+ ports, _ := dapr_testing.GetFreePorts(3)
+ grpcPort := ports[0]
+ httpPort := ports[1]
+ appPort := ports[2]
+
+ // total times cron is triggered
+ observedTriggerCount := 0
+
+ flow.New(t, "test cron trigger with different schedules").
+ Step(app.Run(appName, fmt.Sprintf(":%d", appPort), appWithTriggerCounter(t, cronTest.clk, cronTest.cronName, &observedTriggerCount))).
+ Step(sidecar.Run(sidecarName,
+ embedded.WithComponentsPath("./components"),
+ embedded.WithDaprGRPCPort(grpcPort),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort),
+ embedded.WithDaprHTTPPort(httpPort),
+ componentRuntimeOptions(cronTest.clk),
+ )).
+ Step("advance the clock time", addTimeToMockClock(cronTest.clk, cronTest.timeoutToObserveTriggers)).
+ Step("assert cron triggered within deadline", assertTriggerCount(t, cronTest.expectedTriggerCount, &observedTriggerCount)).
+ Step("stop sidecar", sidecar.Stop(sidecarName)).
+ Step("stop app", app.Stop(appName)).
+ Run()
+ }
+}
+
+// Test two cron bindings having different schedules @every 1s and @every 3s triggering the same app route
+func TestCronBindingsWithSameRoute(t *testing.T) {
+ ports, _ := dapr_testing.GetFreePorts(3)
+ grpcPort := ports[0]
+ httpPort := ports[1]
+ appPort := ports[2]
+
+ cronName := "cron"
+ appName := "cronapp"
+ sidecarName := "cron-sidecar"
+
+ // check if cron triggers 20 times within 15 seconds (15 times from @every 1s binding and 5 times from @every 3s binding)
+ expectedTriggerCount := 20
+ // total times cron is triggered
+ observedTriggerCount := 0
+ // total time for all triggers to be observed
+ timeoutToObserveTriggers := time.Second * 15
+
+ clk := clock.NewMock()
+ clk.Set(startTime)
+
+ flow.New(t, "test cron bindings with different schedules and same route").
+ Step(app.Run(appName, fmt.Sprintf(":%d", appPort), appWithTriggerCounter(t, clk, cronName, &observedTriggerCount))).
+ Step(sidecar.Run(sidecarName,
+ embedded.WithComponentsPath("./components_sameroute"),
+ embedded.WithDaprGRPCPort(grpcPort),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort),
+ embedded.WithDaprHTTPPort(httpPort),
+ componentRuntimeOptions(clk),
+ )).
+ Step("advance the clock time", addTimeToMockClock(clk, timeoutToObserveTriggers)).
+ Step("assert cron triggered within deadline", assertTriggerCount(t, expectedTriggerCount, &observedTriggerCount)).
+ Step("stop sidecar", sidecar.Stop(sidecarName)).
+ Step("stop app", app.Stop(appName)).
+ Run()
+}
+
+// For cron component with trigger @every 3s, check if the app is invoked correctly on app restart
+func TestCronBindingWithAppRestart(t *testing.T) {
+ ports, _ := dapr_testing.GetFreePorts(3)
+ grpcPort := ports[0]
+ httpPort := ports[1]
+ appPort := ports[2]
+
+ cronName := "cron3s"
+ appName := "cronapp3s"
+ sidecarName := "cron-sidecar"
+
+ // check if cron triggers 5 times within 15 seconds
+ expectedTriggerCount := 5
+ // total times cron is triggered
+ observedTriggerCount := 0
+ // total time for all triggers to be observed
+ timeoutToObserveTriggers := time.Second * 15
+ // allow cron to trigger once before stopping the app
+ waitBeforeAppStop := time.Second * 5
+ // wait for some time after the app has stopped, before restarting the app
+ waitBeforeAppRestart := time.Second * 5
+
+ clk := clock.NewMock()
+ clk.Set(startTime)
+
+ flow.New(t, "test cron trigger schedule @every3s with app restart").
+ Step(app.Run(appName, fmt.Sprintf(":%d", appPort), appWithTriggerCounter(t, clk, cronName, &observedTriggerCount))).
+ Step(sidecar.Run(sidecarName,
+ embedded.WithComponentsPath("./components"),
+ embedded.WithDaprGRPCPort(grpcPort),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort),
+ embedded.WithDaprHTTPPort(httpPort),
+ componentRuntimeOptions(clk),
+ )).
+ Step("allow cron to trigger once", addTimeToMockClock(clk, waitBeforeAppStop), flow.Sleep(waitBeforeAppStop)).
+ Step("stop app", app.Stop(appName)).
+ Step("wait before app restart", flow.Sleep(waitBeforeAppRestart)).
+ Step(app.Run(appName, fmt.Sprintf(":%d", appPort), appWithTriggerCounter(t, clk, cronName, &observedTriggerCount))).
+ Step("advance the clock time", addTimeToMockClock(clk, timeoutToObserveTriggers)).
+ Step("assert cron triggered within deadline", assertTriggerCount(t, expectedTriggerCount, &observedTriggerCount)).
+ Step("stop sidecar", sidecar.Stop(sidecarName)).
+ Step("stop app", app.Stop(appName)).
+ Run()
+}
+
+// For cron component with trigger @every 3s, check if the app is invoked correctly on sidecar restart
+func TestCronBindingWithSidecarRestart(t *testing.T) {
+ ports, _ := dapr_testing.GetFreePorts(3)
+ grpcPort := ports[0]
+ httpPort := ports[1]
+ appPort := ports[2]
+
+ cronName := "cron3s"
+ appName := "cronapp3s"
+ sidecarName := "cron-sidecar"
+
+ // check if cron triggers 5 times within 15 seconds
+ expectedTriggerCount := 5
+ // total times cron is triggered
+ observedTriggerCount := 0
+ // total time for all triggers to be observed
+ timeoutToObserveTriggers := time.Second * 15
+ // allow cron to trigger once before stopping the sidecar
+ waitBeforeSidecarStop := time.Second * 5
+ // wait for some time after the app has stopped, before restarting the sidecar
+ waitBeforeSidecarRestart := time.Second * 5
+
+ clk := clock.NewMock()
+ clk.Set(startTime)
+
+ flow.New(t, "test cron trigger schedule @every 3s with sidecar restart").
+ Step(app.Run(appName, fmt.Sprintf(":%d", appPort), appWithTriggerCounter(t, clk, cronName, &observedTriggerCount))).
+ Step(sidecar.Run(sidecarName,
+ embedded.WithComponentsPath("./components"),
+ embedded.WithDaprGRPCPort(grpcPort),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort),
+ embedded.WithDaprHTTPPort(httpPort),
+ componentRuntimeOptions(clk),
+ )).
+ Step("allow cron to trigger once", addTimeToMockClock(clk, waitBeforeSidecarStop), flow.Sleep(waitBeforeSidecarStop)).
+ Step("stop sidecar", sidecar.Stop(sidecarName)).
+ Step("wait before sidecar restart", flow.Sleep(waitBeforeSidecarRestart)).
+ Step(sidecar.Run(sidecarName,
+ embedded.WithComponentsPath("./components"),
+ embedded.WithDaprGRPCPort(grpcPort),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort),
+ embedded.WithDaprHTTPPort(httpPort),
+ componentRuntimeOptions(clk),
+ )).
+ Step("advance the clock time", addTimeToMockClock(clk, timeoutToObserveTriggers)).
+ Step("assert cron triggered within deadline", assertTriggerCount(t, expectedTriggerCount, &observedTriggerCount)).
+ Step("stop sidecar", sidecar.Stop(sidecarName)).
+ Step("stop app", app.Stop(appName)).
+ Run()
+}
+
+func appWithTriggerCounter(t *testing.T, clk *clock.Mock, cronName string, triggeredCount *int) func(ctx flow.Context, s common.Service) error {
+ return func(ctx flow.Context, s common.Service) error {
+ // Setup the input binding endpoint
+ err := s.AddBindingInvocationHandler(cronName, func(_ context.Context, in *common.BindingEvent) ([]byte, error) {
+ ctx.Logf("Cron triggered at %s", clk.Now().String())
+ (*triggeredCount)++
+ return []byte("{}"), nil
+ })
+ require.NoError(t, err)
+ return err
+ }
+}
+
+func addTimeToMockClock(clk *clock.Mock, timeToAdd time.Duration) func(ctx flow.Context) error {
+ return func(ctx flow.Context) error {
+ clk.Add(timeToAdd)
+ // Wait for 1 second after adding time to mock clock to allow cron goroutine to run
+ time.Sleep(time.Second)
+ return nil
+ }
+}
+
+func assertTriggerCount(t *testing.T, expectedTriggerCount int, observedTriggerCount *int) func(ctx flow.Context) error {
+ return func(ctx flow.Context) error {
+ // allow up to 1 less or extra trigger to account for additional timeout(@schedule interval of cron trigger) provided in the tests or if unable to observe up to 1 trigger during app or sidecar restart
+ if !(*observedTriggerCount >= expectedTriggerCount-1 && *observedTriggerCount <= expectedTriggerCount+1) {
+ t.Errorf("expected %d triggers, got %d", expectedTriggerCount, *observedTriggerCount)
+ }
+ return nil
+ }
+}
+
+func componentRuntimeOptions(clk clock.Clock) []runtime.Option {
+ log := logger.NewLogger("dapr.components")
+
+ bindingsRegistry := bindings_loader.NewRegistry()
+ bindingsRegistry.Logger = log
+
+ bindingsRegistry.RegisterInputBinding(func(l logger.Logger) bindings.InputBinding {
+ return cron.NewCronWithClock(l, clk)
+ }, "cron")
+ return []runtime.Option{
+ runtime.WithBindings(bindingsRegistry),
+ }
+}
diff --git a/tests/certification/bindings/cron/go.mod b/tests/certification/bindings/cron/go.mod
new file mode 100644
index 000000000..297f23e1c
--- /dev/null
+++ b/tests/certification/bindings/cron/go.mod
@@ -0,0 +1,150 @@
+module github.com/dapr/components-contrib/tests/certification/bindings/cron
+
+go 1.19
+
+require (
+ github.com/benbjohnson/clock v1.3.0
+ github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
+ github.com/dapr/components-contrib/tests/certification v0.0.0-20220519061249-c2cb1dad5bb0
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
+ github.com/dapr/go-sdk v1.6.0
+ github.com/dapr/kit v0.0.3
+ github.com/stretchr/testify v1.8.1
+)
+
+require (
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
+ github.com/emicklei/go-restful/v3 v3.9.0 // indirect
+ github.com/evanphx/json-patch/v5 v5.6.0 // indirect
+ github.com/go-openapi/jsonpointer v0.19.5 // indirect
+ github.com/go-openapi/jsonreference v0.20.0 // indirect
+ github.com/go-openapi/swag v0.22.3 // indirect
+ github.com/google/gnostic v0.6.9 // indirect
+ github.com/google/uuid v1.3.0 // indirect
+ github.com/jhump/protoreflect v1.13.0 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
+ github.com/tidwall/transform v0.0.0-20201103190739-32f242e2dbde // indirect
+)
+
+require (
+ contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect
+ github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
+ github.com/PuerkitoBio/purell v1.2.0 // indirect
+ github.com/andybalholm/brotli v1.0.4 // indirect
+ github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed // indirect
+ github.com/armon/go-metrics v0.4.1 // indirect
+ github.com/beorn7/perks v1.0.1 // indirect
+ github.com/cenkalti/backoff v2.2.1+incompatible // indirect
+ github.com/cespare/xxhash/v2 v2.1.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fasthttp/router v1.4.12 // indirect
+ github.com/fatih/color v1.13.0 // indirect
+ github.com/fsnotify/fsnotify v1.6.0 // indirect
+ github.com/ghodss/yaml v1.0.0 // indirect
+ github.com/go-kit/log v0.2.1 // indirect
+ github.com/go-logfmt/logfmt v0.5.1 // indirect
+ github.com/go-logr/logr v1.2.3 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
+ github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+ github.com/golang/mock v1.6.0 // indirect
+ github.com/golang/protobuf v1.5.2 // indirect
+ github.com/google/cel-go v0.12.5 // indirect
+ github.com/google/go-cmp v0.5.9 // indirect
+ github.com/google/gofuzz v1.2.0 // indirect
+ github.com/gorilla/mux v1.8.0 // indirect
+ github.com/grandcat/zeroconf v1.0.0 // indirect
+ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
+ github.com/hashicorp/consul/api v1.15.2 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+ github.com/hashicorp/go-hclog v1.3.1 // indirect
+ github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/hashicorp/go-rootcerts v1.0.2 // indirect
+ github.com/hashicorp/golang-lru v0.5.4 // indirect
+ github.com/hashicorp/serf v0.10.1 // indirect
+ github.com/imdario/mergo v0.3.13 // indirect
+ github.com/json-iterator/go v1.1.12 // indirect
+ github.com/klauspost/compress v1.15.11 // indirect
+ github.com/kr/pretty v0.3.0 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.16 // indirect
+ github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect
+ github.com/miekg/dns v1.1.50 // indirect
+ github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
+ github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+ github.com/modern-go/reflect2 v1.0.2 // indirect
+ github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/prometheus/client_golang v1.13.0 // indirect
+ github.com/prometheus/client_model v0.3.0 // indirect
+ github.com/prometheus/common v0.37.0 // indirect
+ github.com/prometheus/procfs v0.8.0 // indirect
+ github.com/prometheus/statsd_exporter v0.22.8 // indirect
+ github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d // indirect
+ github.com/sirupsen/logrus v1.9.0 // indirect
+ github.com/sony/gobreaker v0.5.0 // indirect
+ github.com/spf13/pflag v1.0.5 // indirect
+ github.com/stoewer/go-strcase v1.2.0 // indirect
+ github.com/stretchr/objx v0.5.0 // indirect; indirec
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.41.0 // indirect
+ go.opencensus.io v0.23.0 // indirect
+ go.opentelemetry.io/otel v1.11.1 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1 // indirect
+ go.opentelemetry.io/otel/exporters/zipkin v1.11.1 // indirect
+ go.opentelemetry.io/otel/sdk v1.11.1 // indirect
+ go.opentelemetry.io/otel/trace v1.11.1 // indirect
+ go.opentelemetry.io/proto/otlp v0.19.0 // indirect
+ go.uber.org/atomic v1.10.0 // indirect
+ golang.org/x/mod v0.6.0 // indirect
+ golang.org/x/net v0.1.0 // indirect
+ golang.org/x/oauth2 v0.1.0 // indirect
+ golang.org/x/sys v0.1.0 // indirect
+ golang.org/x/term v0.1.0 // indirect
+ golang.org/x/text v0.4.0 // indirect
+ golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
+ golang.org/x/tools v0.2.0 // indirect
+ gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
+ google.golang.org/appengine v1.6.7 // indirect
+ google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
+ google.golang.org/grpc v1.50.1 // indirect
+ google.golang.org/protobuf v1.28.1 // indirect
+ gopkg.in/inf.v0 v0.9.1 // indirect
+ gopkg.in/yaml.v2 v2.4.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+ k8s.io/api v0.25.3 // indirect
+ k8s.io/apiextensions-apiserver v0.25.3 // indirect
+ k8s.io/apimachinery v0.25.3 // indirect
+ k8s.io/client-go v0.25.3 // indirect
+ k8s.io/component-base v0.25.3 // indirect
+ k8s.io/klog/v2 v2.80.1 // indirect
+ k8s.io/kube-openapi v0.0.0-20220928191237-829ce0c27909 // indirect
+ k8s.io/utils v0.0.0-20221012122500-cfd413dd9e85 // indirect
+ sigs.k8s.io/controller-runtime v0.13.0 // indirect
+ sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
+ sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
+ sigs.k8s.io/yaml v1.3.0 // indirect
+)
+
+replace github.com/dapr/dapr => github.com/1046102779/dapr v0.0.0-20221021130037-635b70c24259
+
+replace github.com/dapr/components-contrib/tests/certification => ../../
+
+replace github.com/dapr/components-contrib => ../../../../
+
+// Uncomment for local development for testing with changes
+// in the Dapr runtime. Don't commit with this uncommented!
+//
+// replace github.com/dapr/dapr => ../../../../../dapr
diff --git a/tests/certification/bindings/cron/go.sum b/tests/certification/bindings/cron/go.sum
new file mode 100644
index 000000000..969444ac9
--- /dev/null
+++ b/tests/certification/bindings/cron/go.sum
@@ -0,0 +1,924 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
+cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
+cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
+cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
+cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
+cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
+cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
+cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg=
+contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/1046102779/dapr v0.0.0-20221021130037-635b70c24259 h1:r3xaidxNIHmRnLrHmgdug8kPunYA8V3OrObr+KbyNOw=
+github.com/1046102779/dapr v0.0.0-20221021130037-635b70c24259/go.mod h1:WBbYLjYoq/kPzdTODWM1mR3IOfxE3+8bw8O3XQiJfio=
+github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a h1:XVdatQFSP2YhJGjqLLIfW8QBk4loz/SCe/PxkXDiW+s=
+github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a/go.mod h1:C0A1KeiVHs+trY6gUTPhhGammbrZ30ZfXRW/nuT7HLw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
+github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/PuerkitoBio/purell v1.2.0 h1:/Jdm5QfyM8zdlqT6WVZU4cfP23sot6CEHA4CS49Ezig=
+github.com/PuerkitoBio/purell v1.2.0/go.mod h1:OhLRTaaIzhvIyofkJfB24gokC7tM42Px5UhoT32THBk=
+github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b h1:WMhlIaJkDgEQSVJQM06YV+cYUl1r5OY5//ijMXJNqtA=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
+github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
+github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
+github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed h1:ue9pVfIcP+QMEjfgo/Ez4ZjNZfonGgR6NgjMaJMu1Cg=
+github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
+github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
+github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
+github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
+github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
+github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
+github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
+github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
+github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
+github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
+github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
+github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
+github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/dapr/go-sdk v1.6.0 h1:jg5A2khSCHF8bGZsig5RWN/gD0jjitszc2V6Uq2pPdY=
+github.com/dapr/go-sdk v1.6.0/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
+github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE=
+github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
+github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
+github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
+github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
+github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
+github.com/fasthttp/router v1.4.12 h1:QEgK+UKARaC1bAzJgnIhdUMay6nwp+YFq6VGPlyKN1o=
+github.com/fasthttp/router v1.4.12/go.mod h1:41Qdc4Z4T2pWVVtATHCnoUnOtxdBoeKEYJTXhHwbxCQ=
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
+github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
+github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
+github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0=
+github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
+github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
+github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
+github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
+github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
+github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
+github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
+github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A=
+github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
+github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
+github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
+github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
+github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
+github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
+github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
+github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
+github.com/google/cel-go v0.12.5 h1:DmzaiSgoaqGCjtpPQWl26/gND+yRpim56H1jCVev6d8=
+github.com/google/cel-go v0.12.5/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw=
+github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0=
+github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
+github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+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/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
+github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE=
+github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs=
+github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
+github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
+github.com/hashicorp/consul/api v1.15.2 h1:3Q/pDqvJ7udgt/60QOOW/p/PeKioQN+ncYzzCdN2av0=
+github.com/hashicorp/consul/api v1.15.2/go.mod h1:v6nvB10borjOuIwNRZYPZiHKrTM/AyrGtd0WVVodKM8=
+github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4=
+github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
+github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
+github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
+github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo=
+github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
+github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
+github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs=
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
+github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
+github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
+github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
+github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
+github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
+github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
+github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
+github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
+github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
+github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
+github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
+github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
+github.com/hashicorp/memberlist v0.3.1/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
+github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM=
+github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0=
+github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
+github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
+github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
+github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
+github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
+github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI=
+github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI=
+github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ=
+github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E=
+github.com/jhump/protoreflect v1.13.0 h1:zrrZqa7JAc2YGgPSzZZkmUXJ5G6NRPdxOg/9t7ISImA=
+github.com/jhump/protoreflect v1.13.0/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
+github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
+github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
+github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM=
+github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
+github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
+github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
+github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
+github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
+github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
+github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
+github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
+github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
+github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
+github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
+github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU=
+github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
+github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/openzipkin/zipkin-go v0.4.1 h1:kNd/ST2yLLWhaWrkgchya40TJabe8Hioj9udfPcEO5A=
+github.com/openzipkin/zipkin-go v0.4.1/go.mod h1:qY0VqDSN1pOBN94dBc6w2GJlWLiovAyg7Qt6/I9HecM=
+github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
+github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
+github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
+github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
+github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
+github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
+github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU=
+github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
+github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
+github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
+github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
+github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
+github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
+github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
+github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
+github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
+github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
+github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
+github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI=
+github.com/prometheus/statsd_exporter v0.22.8 h1:Qo2D9ZzaQG+id9i5NYNGmbf1aa/KxKbB9aKfMS+Yib0=
+github.com/prometheus/statsd_exporter v0.22.8/go.mod h1:/DzwbTEaFTE0Ojz5PqcSk6+PFHOPWGxdXVr6yC8eFOM=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
+github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d h1:Q+gqLBOPkFGHyCJxXMRqtUgUbTjI8/Ze8vu8GGyNFwo=
+github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
+github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg=
+github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+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/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
+github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/tidwall/transform v0.0.0-20201103190739-32f242e2dbde h1:AMNpJRc7P+GTwVbl8DkK2I9I8BBUzNiHuH/tlxrpan0=
+github.com/tidwall/transform v0.0.0-20201103190739-32f242e2dbde/go.mod h1:MvrEmduDUz4ST5pGZ7CABCnOU5f3ZiOAZzT6b1A6nX8=
+github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
+github.com/valyala/fasthttp v1.41.0 h1:zeR0Z1my1wDHTRiamBCXVglQdbUwgb9uWG3k1HQz6jY=
+github.com/valyala/fasthttp v1.41.0/go.mod h1:f6VbjjoI3z1NDOZOv17o6RvtRSWxC77seBFc2uWtgiY=
+github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
+github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
+github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
+go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
+go.opentelemetry.io/otel v1.11.1 h1:4WLLAmcfkmDk2ukNXJyq3/kiz/3UzCaYq6PskJsaou4=
+go.opentelemetry.io/otel v1.11.1/go.mod h1:1nNhXBbWSD0nsL38H6btgnFN2k4i0sNLHNNMZMSbUGE=
+go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 h1:X2GndnMCsUPh6CiY2a+frAbNsXaPLbB0soHRYhAZ5Ig=
+go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1/go.mod h1:i8vjiSzbiUC7wOQplijSXMYUpNM93DtlS5CbUT+C6oQ=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1 h1:MEQNafcNCB0uQIti/oHgU7CZpUMYQ7qigBwMVKycHvc=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1/go.mod h1:19O5I2U5iys38SsmT2uDJja/300woyzE1KPIQxEUBUc=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1 h1:LYyG/f1W/jzAix16jbksJfMQFpOH/Ma6T639pVPMgfI=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1/go.mod h1:QrRRQiY3kzAoYPNLP0W/Ikg0gR6V3LMc+ODSxr7yyvg=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1 h1:tFl63cpAAcD9TOU6U8kZU7KyXuSRYAZlbx1C61aaB74=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1/go.mod h1:X620Jww3RajCJXw/unA+8IRTgxkdS7pi+ZwK9b7KUJk=
+go.opentelemetry.io/otel/exporters/zipkin v1.11.1 h1:JlJ3/oQoyqlrPDCfsSVFcHgGeHvZq+hr1VPWtiYCXTo=
+go.opentelemetry.io/otel/exporters/zipkin v1.11.1/go.mod h1:T4S6aVwIS1+MHA+dJHCcPROtZe6ORwnv5vMKPRapsFw=
+go.opentelemetry.io/otel/sdk v1.11.1 h1:F7KmQgoHljhUuJyA+9BiU+EkJfyX5nVVF4wyzWZpKxs=
+go.opentelemetry.io/otel/sdk v1.11.1/go.mod h1:/l3FE4SupHJ12TduVjUkZtlfFqDCQJlOlithYrdktys=
+go.opentelemetry.io/otel/trace v1.11.1 h1:ofxdnzsNrGBYXbP7t7zpUK281+go5rF7dvdIZXF8gdQ=
+go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk=
+go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
+go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw=
+go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
+go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
+go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
+golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
+golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
+golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
+golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y=
+golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
+golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
+golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y=
+golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY=
+gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
+google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
+google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c h1:QgY/XxIAIeccR+Ca/rDdKubLIU9rcJ3xfy1DC/Wd2Oo=
+google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
+google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
+google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
+google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+k8s.io/api v0.25.3 h1:Q1v5UFfYe87vi5H7NU0p4RXC26PPMT8KOpr1TLQbCMQ=
+k8s.io/api v0.25.3/go.mod h1:o42gKscFrEVjHdQnyRenACrMtbuJsVdP+WVjqejfzmI=
+k8s.io/apiextensions-apiserver v0.25.3 h1:bfI4KS31w2f9WM1KLGwnwuVlW3RSRPuIsfNF/3HzR0k=
+k8s.io/apiextensions-apiserver v0.25.3/go.mod h1:ZJqwpCkxIx9itilmZek7JgfUAM0dnTsA48I4krPqRmo=
+k8s.io/apimachinery v0.25.3 h1:7o9ium4uyUOM76t6aunP0nZuex7gDf8VGwkR5RcJnQc=
+k8s.io/apimachinery v0.25.3/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo=
+k8s.io/client-go v0.25.3 h1:oB4Dyl8d6UbfDHD8Bv8evKylzs3BXzzufLiO27xuPs0=
+k8s.io/client-go v0.25.3/go.mod h1:t39LPczAIMwycjcXkVc+CB+PZV69jQuNx4um5ORDjQA=
+k8s.io/component-base v0.25.3 h1:UrsxciGdrCY03ULT1h/S/gXFCOPnLhUVwSyx+hM/zq4=
+k8s.io/component-base v0.25.3/go.mod h1:WYoS8L+IlTZgU7rhAl5Ctpw0WdMxDfCC5dkxcEFa/TI=
+k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
+k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
+k8s.io/kube-openapi v0.0.0-20220928191237-829ce0c27909 h1:q/70bz7C1/LGuQu/JBX7Fpi55CwcCts/wbvlehe0RRo=
+k8s.io/kube-openapi v0.0.0-20220928191237-829ce0c27909/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
+k8s.io/utils v0.0.0-20221012122500-cfd413dd9e85 h1:cTdVh7LYu82xeClmfzGtgyspNh6UxpwLWGi8R4sspNo=
+k8s.io/utils v0.0.0-20221012122500-cfd413dd9e85/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ=
+sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI=
+sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
+sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
+sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
+sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
+sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
+sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
diff --git a/tests/certification/bindings/kafka/go.mod b/tests/certification/bindings/kafka/go.mod
index f5bf8a29c..6c04fe04d 100644
--- a/tests/certification/bindings/kafka/go.mod
+++ b/tests/certification/bindings/kafka/go.mod
@@ -4,12 +4,12 @@ go 1.19
require (
github.com/Shopify/sarama v1.37.2
- github.com/cenkalti/backoff/v4 v4.1.3
+ github.com/cenkalti/backoff/v4 v4.2.0
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20220519061249-c2cb1dad5bb0
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/google/uuid v1.3.0
github.com/stretchr/testify v1.8.1
go.uber.org/multierr v1.8.0
@@ -87,6 +87,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -121,14 +122,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/bindings/kafka/go.sum b/tests/certification/bindings/kafka/go.sum
index 16f89f0e0..5bbf3ee84 100644
--- a/tests/certification/bindings/kafka/go.sum
+++ b/tests/certification/bindings/kafka/go.sum
@@ -73,8 +73,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -96,8 +96,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -410,6 +410,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc=
github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -571,7 +572,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -593,8 +594,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -790,8 +791,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/bindings/localstorage/README.md b/tests/certification/bindings/localstorage/README.md
index a15fc774f..f9b52c4d0 100644
--- a/tests/certification/bindings/localstorage/README.md
+++ b/tests/certification/bindings/localstorage/README.md
@@ -1,8 +1,8 @@
-# LocalStorage certifcation testing
+# LocalStorage certification testing
This project aims to test the LocalStorage component under various conditions.
-## Test plain
+## Test plan
- Invocation
- create file and get data success
diff --git a/tests/certification/bindings/localstorage/go.mod b/tests/certification/bindings/localstorage/go.mod
index 34ec6ef1f..611b46f3b 100644
--- a/tests/certification/bindings/localstorage/go.mod
+++ b/tests/certification/bindings/localstorage/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-00010101000000-000000000000
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -20,7 +20,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
@@ -75,6 +75,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -102,14 +103,14 @@ require (
go.opentelemetry.io/otel/trace v1.11.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/bindings/localstorage/go.sum b/tests/certification/bindings/localstorage/go.sum
index 9f007f927..1303cbf87 100644
--- a/tests/certification/bindings/localstorage/go.sum
+++ b/tests/certification/bindings/localstorage/go.sum
@@ -70,8 +70,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -95,8 +95,8 @@ github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -382,6 +382,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -525,7 +526,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -547,8 +548,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -742,8 +743,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/bindings/postgres/go.mod b/tests/certification/bindings/postgres/go.mod
index 06456483b..4f127b145 100644
--- a/tests/certification/bindings/postgres/go.mod
+++ b/tests/certification/bindings/postgres/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20220526162429-d03aeba3e0d6
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/lib/pq v1.10.7
github.com/stretchr/testify v1.8.1
)
@@ -21,7 +21,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
@@ -79,6 +79,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -108,14 +109,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/bindings/postgres/go.sum b/tests/certification/bindings/postgres/go.sum
index 39ce5937f..4ea034818 100644
--- a/tests/certification/bindings/postgres/go.sum
+++ b/tests/certification/bindings/postgres/go.sum
@@ -70,8 +70,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -93,8 +93,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -390,6 +390,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -538,7 +539,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -560,8 +561,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -755,8 +756,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/bindings/rabbitmq/go.mod b/tests/certification/bindings/rabbitmq/go.mod
index 6e94cc8c9..cf7300063 100644
--- a/tests/certification/bindings/rabbitmq/go.mod
+++ b/tests/certification/bindings/rabbitmq/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211130185200-4918900c09e1
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/rabbitmq/amqp091-go v1.5.0
github.com/stretchr/testify v1.8.1
go.uber.org/multierr v1.8.0
@@ -22,7 +22,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
@@ -77,6 +77,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -105,14 +106,14 @@ require (
go.opentelemetry.io/otel/trace v1.11.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/bindings/rabbitmq/go.sum b/tests/certification/bindings/rabbitmq/go.sum
index 00cb81252..205afe275 100644
--- a/tests/certification/bindings/rabbitmq/go.sum
+++ b/tests/certification/bindings/rabbitmq/go.sum
@@ -70,8 +70,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -93,8 +93,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -382,6 +382,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -532,7 +533,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -554,8 +555,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -750,8 +751,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/bindings/redis/README.md b/tests/certification/bindings/redis/README.md
index c5d48a21f..29a4a5f26 100644
--- a/tests/certification/bindings/redis/README.md
+++ b/tests/certification/bindings/redis/README.md
@@ -1,4 +1,4 @@
-# RabbitMQ Binding Certification
+# Redis Binding Certification
The purpose of this module is to provide tests that certify the Redis Binding as a stable component.
diff --git a/tests/certification/bindings/redis/go.mod b/tests/certification/bindings/redis/go.mod
index a862a7fa7..1c955bb46 100644
--- a/tests/certification/bindings/redis/go.mod
+++ b/tests/certification/bindings/redis/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20220908221803-2b5650c2faa4
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/go-redis/redis/v8 v8.11.5
github.com/stretchr/testify v1.8.1
)
@@ -21,7 +21,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
@@ -76,6 +76,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -104,14 +105,14 @@ require (
go.opentelemetry.io/otel/trace v1.11.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/bindings/redis/go.sum b/tests/certification/bindings/redis/go.sum
index e192c66d8..93cf9a7b6 100644
--- a/tests/certification/bindings/redis/go.sum
+++ b/tests/certification/bindings/redis/go.sum
@@ -72,8 +72,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -95,8 +95,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -386,6 +386,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -532,7 +533,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -554,8 +555,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -749,8 +750,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/embedded/embedded.go b/tests/certification/embedded/embedded.go
index 4a66187a7..071cafb57 100644
--- a/tests/certification/embedded/embedded.go
+++ b/tests/certification/embedded/embedded.go
@@ -22,13 +22,13 @@ import (
global_config "github.com/dapr/dapr/pkg/config"
env "github.com/dapr/dapr/pkg/config/env"
"github.com/dapr/dapr/pkg/cors"
- "github.com/dapr/dapr/pkg/grpc"
"github.com/dapr/dapr/pkg/modes"
"github.com/dapr/dapr/pkg/operator/client"
"github.com/dapr/dapr/pkg/resiliency"
"github.com/dapr/dapr/pkg/runtime"
"github.com/dapr/dapr/pkg/runtime/security"
"github.com/dapr/kit/logger"
+ "github.com/phayes/freeport"
)
const (
@@ -138,7 +138,7 @@ func NewRuntime(appID string, opts ...Option) (*runtime.DaprRuntime, *runtime.Co
}
if runtimeConfig.InternalGRPCPort == 0 {
- if runtimeConfig.InternalGRPCPort, err = grpc.GetFreePort(); err != nil {
+ if runtimeConfig.InternalGRPCPort, err = freeport.GetFreePort(); err != nil {
return nil, nil, err
}
}
diff --git a/tests/certification/flow/watcher/watcher.go b/tests/certification/flow/watcher/watcher.go
index 161b4b8cd..75b044c71 100644
--- a/tests/certification/flow/watcher/watcher.go
+++ b/tests/certification/flow/watcher/watcher.go
@@ -15,6 +15,7 @@ package watcher
import (
"errors"
+ "fmt"
"sync"
"time"
@@ -344,8 +345,10 @@ func (w *Watcher) FailIfNotExpected(t TestingT, data ...interface{}) {
defer w.mu.Unlock()
for _, item := range data {
- val, ok := w.remaining[item]
- assert.False(t, ok, "Encountered an unexpected item: %v", val)
+ _, ok := w.remaining[item]
+ if !ok {
+ assert.Fail(t, fmt.Sprintf("Encountered an unexpected item: %v", item), item)
+ }
}
}
diff --git a/tests/certification/go.mod b/tests/certification/go.mod
index 44d9bdde1..a272094c7 100644
--- a/tests/certification/go.mod
+++ b/tests/certification/go.mod
@@ -4,9 +4,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/google/go-cmp v0.5.9
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.8.1
@@ -100,14 +100,14 @@ require (
go.opentelemetry.io/otel/trace v1.11.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
@@ -131,7 +131,8 @@ require (
)
require (
- github.com/cenkalti/backoff/v4 v4.1.3
+ github.com/cenkalti/backoff/v4 v4.2.0
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5
github.com/tylertreat/comcast v1.0.1
)
diff --git a/tests/certification/go.sum b/tests/certification/go.sum
index d0058fac4..ac437efa4 100644
--- a/tests/certification/go.sum
+++ b/tests/certification/go.sum
@@ -70,8 +70,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -93,8 +93,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -382,6 +382,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -527,7 +528,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -549,8 +550,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -744,8 +745,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/pubsub/azure/eventhubs/go.mod b/tests/certification/pubsub/azure/eventhubs/go.mod
index 53b20c93c..dbeb1ea38 100644
--- a/tests/certification/pubsub/azure/eventhubs/go.mod
+++ b/tests/certification/pubsub/azure/eventhubs/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v1.4.0-rc2
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/google/uuid v1.3.0
github.com/stretchr/testify v1.8.1
go.uber.org/multierr v1.8.0
@@ -22,7 +22,7 @@ require (
github.com/Azure/azure-sdk-for-go v67.0.0+incompatible // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
github.com/Azure/azure-storage-blob-go v0.10.0 // indirect
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
github.com/Azure/go-amqp v0.17.5 // indirect
@@ -43,7 +43,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/devigned/tab v0.1.1 // indirect
@@ -104,6 +104,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -133,14 +134,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/pubsub/azure/eventhubs/go.sum b/tests/certification/pubsub/azure/eventhubs/go.sum
index 15e417cdc..5bf683af0 100644
--- a/tests/certification/pubsub/azure/eventhubs/go.sum
+++ b/tests/certification/pubsub/azure/eventhubs/go.sum
@@ -53,8 +53,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 h1:pqrAR74b6EoR4kcxF7L7Wg2B8
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 h1:XUNQ4mw+zJmaA2KXzP9JlQiecy1SI+Eog7xVkPiqIbg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-storage-blob-go v0.6.0/go.mod h1:oGfmITT1V6x//CswqY2gtAHND+xIP64/qL7a5QJix0Y=
github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs=
github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE=
@@ -140,8 +140,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -163,8 +163,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -480,6 +480,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -634,7 +635,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -656,8 +657,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -853,8 +854,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/pubsub/azure/servicebus/topics/go.mod b/tests/certification/pubsub/azure/servicebus/topics/go.mod
index b3aa0d674..6e5a189fc 100644
--- a/tests/certification/pubsub/azure/servicebus/topics/go.mod
+++ b/tests/certification/pubsub/azure/servicebus/topics/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211026011813-36b75e9ae272
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/google/uuid v1.3.0
github.com/stretchr/testify v1.8.1
go.uber.org/multierr v1.8.0
@@ -20,7 +20,7 @@ require (
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.1 // indirect
github.com/Azure/azure-storage-blob-go v0.10.0 // indirect
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
@@ -41,7 +41,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
@@ -100,6 +100,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -131,14 +132,14 @@ require (
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/ratelimit v0.2.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/pubsub/azure/servicebus/topics/go.sum b/tests/certification/pubsub/azure/servicebus/topics/go.sum
index 8e42a6c41..8135dcf87 100644
--- a/tests/certification/pubsub/azure/servicebus/topics/go.sum
+++ b/tests/certification/pubsub/azure/servicebus/topics/go.sum
@@ -47,8 +47,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 h1:pqrAR74b6EoR4kcxF7L7Wg2B8
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 h1:XUNQ4mw+zJmaA2KXzP9JlQiecy1SI+Eog7xVkPiqIbg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.1 h1:Zm7A6yKHT3evC/0lquPWJ9hrkRGVIeZOmIvHPv6xV9Q=
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.1/go.mod h1:LH9XQnMr2ZYxQdVdCrzLO9mxeDyrDFa6wbSI3x5zCZk=
github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs=
@@ -128,8 +128,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -151,8 +151,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -463,6 +463,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -621,7 +622,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -643,8 +644,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -840,8 +841,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/pubsub/azure/servicebus/topics/servicebus_test.go b/tests/certification/pubsub/azure/servicebus/topics/servicebus_test.go
index 1c00a432c..f971ee5c3 100644
--- a/tests/certification/pubsub/azure/servicebus/topics/servicebus_test.go
+++ b/tests/certification/pubsub/azure/servicebus/topics/servicebus_test.go
@@ -902,8 +902,6 @@ func TestServicebusDefaultTtl(t *testing.T) {
}
require.NoError(ctx, err, "error publishing message")
}
- // Wait for double the TTL after sending the last message.
- time.Sleep(time.Second * 20)
return nil
}
}
@@ -926,16 +924,25 @@ func TestServicebusDefaultTtl(t *testing.T) {
subscriberApplication(appID1, topicActiveName, consumerGroup1))).
// Run the Dapr sidecar with the component entitymanagement
- Step(sidecar.Run(sidecarName1,
+ Step(sidecar.Run("initalSidecar",
embedded.WithComponentsPath("./components/default_ttl"),
- embedded.WithAppProtocol(runtime.HTTPProtocol, appPort+portOffset),
+ embedded.WithoutApp(),
embedded.WithDaprGRPCPort(runtime.DefaultDaprAPIGRPCPort+portOffset),
embedded.WithDaprHTTPPort(runtime.DefaultDaprHTTPPort+portOffset),
embedded.WithProfilePort(runtime.DefaultProfilePort+portOffset),
componentRuntimeOptions(),
)).
- Step(fmt.Sprintf("publish messages to topicToBeCreated: %s", topicActiveName), testTtlPublishMessages(metadata, sidecarName1, topicActiveName, consumerGroup1)).
+ Step(fmt.Sprintf("publish messages to topicToBeCreated: %s", topicActiveName), testTtlPublishMessages(metadata, "initalSidecar", topicActiveName, consumerGroup1)).
+ Step("stop initial sidecar", sidecar.Stop("initialSidecar")).
Step("wait", flow.Sleep(20*time.Second)).
+ Step(sidecar.Run(sidecarName1,
+ embedded.WithComponentsPath("./components/default_ttl"),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort+portOffset),
+ embedded.WithDaprGRPCPort(runtime.DefaultDaprAPIGRPCPort+portOffset*2),
+ embedded.WithDaprHTTPPort(runtime.DefaultDaprHTTPPort+portOffset*2),
+ embedded.WithProfilePort(runtime.DefaultProfilePort+portOffset*2),
+ componentRuntimeOptions(),
+ )).
Step("verify if app6 has recevied messages published to newly created topic", assertMessages(10*time.Second, consumerGroup1)).
Run()
}
diff --git a/tests/certification/pubsub/kafka/go.mod b/tests/certification/pubsub/kafka/go.mod
index 36b176933..9ec2b7b63 100644
--- a/tests/certification/pubsub/kafka/go.mod
+++ b/tests/certification/pubsub/kafka/go.mod
@@ -4,12 +4,12 @@ go 1.19
require (
github.com/Shopify/sarama v1.37.2
- github.com/cenkalti/backoff/v4 v4.1.3
+ github.com/cenkalti/backoff/v4 v4.2.0
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20220519061249-c2cb1dad5bb0
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/google/uuid v1.3.0
github.com/stretchr/testify v1.8.1
go.uber.org/multierr v1.8.0
@@ -87,6 +87,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -121,14 +122,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/pubsub/kafka/go.sum b/tests/certification/pubsub/kafka/go.sum
index 16f89f0e0..5bbf3ee84 100644
--- a/tests/certification/pubsub/kafka/go.sum
+++ b/tests/certification/pubsub/kafka/go.sum
@@ -73,8 +73,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -96,8 +96,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -410,6 +410,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc=
github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -571,7 +572,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -593,8 +594,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -790,8 +791,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/pubsub/mqtt/go.mod b/tests/certification/pubsub/mqtt/go.mod
index d0ed658f2..a416b0bb2 100644
--- a/tests/certification/pubsub/mqtt/go.mod
+++ b/tests/certification/pubsub/mqtt/go.mod
@@ -3,12 +3,12 @@ module github.com/dapr/components-contrib/tests/certification/pubsub/mqtt
go 1.19
require (
- github.com/cenkalti/backoff/v4 v4.1.3
+ github.com/cenkalti/backoff/v4 v4.2.0
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v1.4.0-rc2
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/eclipse/paho.mqtt.golang v1.4.2
github.com/stretchr/testify v1.8.1
go.uber.org/multierr v1.8.0
@@ -79,6 +79,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -108,7 +109,7 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/ratelimit v0.2.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sync v0.1.0 // indirect
@@ -116,7 +117,7 @@ require (
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/pubsub/mqtt/go.sum b/tests/certification/pubsub/mqtt/go.sum
index 18213fd1d..5686deb5b 100644
--- a/tests/certification/pubsub/mqtt/go.sum
+++ b/tests/certification/pubsub/mqtt/go.sum
@@ -72,8 +72,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -95,8 +95,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -389,6 +389,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -538,7 +539,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -560,8 +561,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -757,8 +758,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/pubsub/rabbitmq/README.md b/tests/certification/pubsub/rabbitmq/README.md
index f07d26962..bc4699365 100644
--- a/tests/certification/pubsub/rabbitmq/README.md
+++ b/tests/certification/pubsub/rabbitmq/README.md
@@ -27,3 +27,11 @@ This project aims to test the RabbitMQ Pub/Sub component under various condition
* the total number of the messages received by subscribers "B"
* App: Simulates periodic errors
* Component: Retries on error
+* Test TTL is regarded.
+ * Setting a large TTL only at the message level but not component level, wait for a small period, and verify that the message is received.
+ * Setting a TTL only at the message level but not component level expires messages correctly
+ * Setting a default TTL at the component level expires messages correctly
+ * Create component spec with the field `ttlInSeconds`.
+ * Run dapr application with component.
+ * Send a message, wait TTL seconds, and verify the message is deleted/expired.
+ * Setting a TTL at the component level and message level ignores the default component level TTL and always uses the message level TTL specified
diff --git a/tests/certification/pubsub/rabbitmq/components/ttl/rabbitmq_msg_ttl.yaml b/tests/certification/pubsub/rabbitmq/components/ttl/rabbitmq_msg_ttl.yaml
new file mode 100644
index 000000000..121bbe192
--- /dev/null
+++ b/tests/certification/pubsub/rabbitmq/components/ttl/rabbitmq_msg_ttl.yaml
@@ -0,0 +1,19 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: msg-ttl-pubsub
+ namespace: default
+spec:
+ type: pubsub.rabbitmq
+ version: v1
+ metadata:
+ - name: consumerID
+ value: msg
+ - name: host
+ value: "amqp://test:test@localhost:5672"
+ - name: durable
+ value: true
+ - name: deletedWhenUnused
+ value: false
+ - name: requeueInFailure
+ value: true
diff --git a/tests/certification/pubsub/rabbitmq/components/ttl/rabbitmq_overwrite_ttl.yaml b/tests/certification/pubsub/rabbitmq/components/ttl/rabbitmq_overwrite_ttl.yaml
new file mode 100644
index 000000000..9b7ebd2ff
--- /dev/null
+++ b/tests/certification/pubsub/rabbitmq/components/ttl/rabbitmq_overwrite_ttl.yaml
@@ -0,0 +1,21 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: overwrite-ttl-pubsub
+ namespace: default
+spec:
+ type: pubsub.rabbitmq
+ version: v1
+ metadata:
+ - name: consumerID
+ value: overwrite
+ - name: host
+ value: "amqp://test:test@localhost:5672"
+ - name: durable
+ value: true
+ - name: deletedWhenUnused
+ value: false
+ - name: requeueInFailure
+ value: true
+ - name: ttlInSeconds
+ value: 30 # Short TTL for easier testing
\ No newline at end of file
diff --git a/tests/certification/pubsub/rabbitmq/components/ttl/rabbitmq_queue_ttl.yaml b/tests/certification/pubsub/rabbitmq/components/ttl/rabbitmq_queue_ttl.yaml
new file mode 100644
index 000000000..06a0a223d
--- /dev/null
+++ b/tests/certification/pubsub/rabbitmq/components/ttl/rabbitmq_queue_ttl.yaml
@@ -0,0 +1,21 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: queue-ttl-pubsub
+ namespace: default
+spec:
+ type: pubsub.rabbitmq
+ version: v1
+ metadata:
+ - name: consumerID
+ value: queue
+ - name: host
+ value: "amqp://test:test@localhost:5672"
+ - name: durable
+ value: true
+ - name: deletedWhenUnused
+ value: false
+ - name: requeueInFailure
+ value: true
+ - name: ttlInSeconds
+ value: 10 # Short TTL for easier testing
\ No newline at end of file
diff --git a/tests/certification/pubsub/rabbitmq/go.mod b/tests/certification/pubsub/rabbitmq/go.mod
index 5c1b3c978..503abc8f3 100644
--- a/tests/certification/pubsub/rabbitmq/go.mod
+++ b/tests/certification/pubsub/rabbitmq/go.mod
@@ -3,12 +3,12 @@ module github.com/dapr/components-contrib/tests/certification/pubsub/rabbitmq
go 1.19
require (
- github.com/cenkalti/backoff/v4 v4.1.3
+ github.com/cenkalti/backoff/v4 v4.2.0
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211130185200-4918900c09e1
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/rabbitmq/amqp091-go v1.5.0
github.com/stretchr/testify v1.8.1
go.uber.org/multierr v1.8.0
@@ -77,6 +77,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -105,14 +106,14 @@ require (
go.opentelemetry.io/otel/trace v1.11.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/pubsub/rabbitmq/go.sum b/tests/certification/pubsub/rabbitmq/go.sum
index 00cb81252..205afe275 100644
--- a/tests/certification/pubsub/rabbitmq/go.sum
+++ b/tests/certification/pubsub/rabbitmq/go.sum
@@ -70,8 +70,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -93,8 +93,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -382,6 +382,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -532,7 +533,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -554,8 +555,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -750,8 +751,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/pubsub/rabbitmq/rabbitmq_test.go b/tests/certification/pubsub/rabbitmq/rabbitmq_test.go
index 3d14ff465..146325d81 100644
--- a/tests/certification/pubsub/rabbitmq/rabbitmq_test.go
+++ b/tests/certification/pubsub/rabbitmq/rabbitmq_test.go
@@ -17,24 +17,27 @@ import (
"context"
"fmt"
"math/rand"
+ "strconv"
"sync"
"testing"
"time"
"github.com/cenkalti/backoff/v4"
+ daprClient "github.com/dapr/go-sdk/client"
amqp "github.com/rabbitmq/amqp091-go"
"github.com/stretchr/testify/require"
"go.uber.org/multierr"
// Pub/Sub.
- pubsub_rabbitmq "github.com/dapr/components-contrib/pubsub/rabbitmq"
pubsub_loader "github.com/dapr/dapr/pkg/components/pubsub"
"github.com/dapr/dapr/pkg/runtime"
"github.com/dapr/go-sdk/service/common"
"github.com/dapr/kit/logger"
kit_retry "github.com/dapr/kit/retry"
+ pubsub_rabbitmq "github.com/dapr/components-contrib/pubsub/rabbitmq"
+
"github.com/dapr/components-contrib/tests/certification/embedded"
"github.com/dapr/components-contrib/tests/certification/flow"
"github.com/dapr/components-contrib/tests/certification/flow/app"
@@ -47,26 +50,34 @@ import (
)
const (
- sidecarName1 = "dapr-1"
- sidecarName2 = "dapr-2"
- sidecarName3 = "dapr-3"
- appID1 = "app-1"
- appID2 = "app-2"
- appID3 = "app-3"
- clusterName = "rabbitmqcertification"
- dockerComposeYAML = "docker-compose.yml"
- numMessages = 1000
- errFrequency = 100
- appPort = 8000
+ sidecarName1 = "dapr-1"
+ sidecarName2 = "dapr-2"
+ sidecarName3 = "dapr-3"
+ sidecarNameTTLClient = "dapr-ttl-client"
+ appID1 = "app-1"
+ appID2 = "app-2"
+ appID3 = "app-3"
+ clusterName = "rabbitmqcertification"
+ dockerComposeYAML = "docker-compose.yml"
+ numMessages = 1000
+ errFrequency = 100
+ appPort = 8000
rabbitMQURL = "amqp://test:test@localhost:5672"
- pubsubAlpha = "mq-alpha"
- pubsubBeta = "mq-beta"
+ pubsubAlpha = "mq-alpha"
+ pubsubBeta = "mq-beta"
+ pubsubMessageOnlyTTL = "msg-ttl-pubsub"
+ pubsubQueueOnlyTTL = "overwrite-ttl-pubsub"
+ pubsubOverwriteTTL = "queue-ttl-pubsub"
topicRed = "red"
topicBlue = "blue"
topicGreen = "green"
+
+ topicTTL1 = "ttl1"
+ topicTTL2 = "ttl2"
+ topicTTL3 = "ttl3"
)
type Consumer struct {
@@ -325,6 +336,212 @@ func TestRabbitMQ(t *testing.T) {
Run()
}
+func TestRabbitMQTTL(t *testing.T) {
+ rand.Seed(time.Now().UTC().UnixNano())
+ log := logger.NewLogger("dapr.components")
+ // log.SetOutputLevel(logger.DebugLevel)
+
+ MessageOnlyMessages, QueueOnlyMessages, OverwriteMessages := watcher.NewUnordered(), watcher.NewUnordered(), watcher.NewUnordered()
+ fullMessages := watcher.NewUnordered()
+ // Application logic that tracks messages from a topic.
+ application := func(pubsubName, topic string, w *watcher.Watcher) app.SetupFn {
+ return func(ctx flow.Context, s common.Service) (err error) {
+ // Simulate periodic errors.
+ sim := simulate.PeriodicError(ctx, errFrequency)
+ err = multierr.Combine(
+ err,
+ s.AddTopicEventHandler(&common.Subscription{
+ PubsubName: pubsubName,
+ Topic: topic,
+ Route: fmt.Sprintf("/%s", topic),
+ }, func(_ context.Context, e *common.TopicEvent) (retry bool, err error) {
+ if err := sim(); err != nil {
+ log.Debugf("Simulated error - pubsub: %s, topic: %s, id: %s, data: %s", e.PubsubName, e.Topic, e.ID, e.Data)
+ return true, err
+ }
+
+ // Track/Observe the data of the event.
+ w.Observe(e.Data)
+ log.Debugf("Event - pubsub: %s, topic: %s, id: %s, data: %s", e.PubsubName, e.Topic, e.ID, e.Data)
+ return false, nil
+ }),
+ )
+
+ return err
+ }
+ }
+
+ sendMessage := func(sidecarName, pubsubName, topic string, ttlInSeconds int) func(ctx flow.Context) error {
+ fullMessages.Reset()
+ return func(ctx flow.Context) error {
+ // Declare what is expected BEFORE performing any steps
+ // that will satisfy the test.
+ msgs := make([]string, numMessages)
+ for i := range msgs {
+ msgs[i] = fmt.Sprintf("Hello, Messages %03d", i)
+ }
+
+ sc := sidecar.GetClient(ctx, sidecarName)
+
+ // Send events that the application above will observe.
+ log.Infof("Sending messages on topic '%s'", topic)
+
+ var err error
+ for _, msg := range msgs {
+ log.Debugf("Sending: '%s' on topic '%s'", msg, topic)
+ if ttlInSeconds > 0 {
+ err = sc.PublishEvent(ctx, pubsubName, topic, msg, daprClient.PublishEventWithMetadata(map[string]string{"ttlInSeconds": strconv.Itoa(ttlInSeconds)}))
+ } else {
+ err = sc.PublishEvent(ctx, pubsubName, topic, msg)
+ }
+ require.NoError(ctx, err, "error publishing message")
+ fullMessages.Add(msg)
+ fullMessages.Prepare(msg)
+ }
+
+ return nil
+ }
+ }
+
+ flow.New(t, "rabbitmq ttl certification").
+ // Run RabbitMQ using Docker Compose.
+ Step(dockercompose.Run(clusterName, dockerComposeYAML)).
+ Step("wait for rabbitmq readiness",
+ retry.Do(time.Second, 30, amqpReady(rabbitMQURL))).
+ // Start dapr and app to precreate all 3 queue in rabbitmq,
+ // if topic is not subscribed, then the message will be lost.
+ // Sidecar will block to wait app, so we need to start app first.
+ Step(app.Run(appID1, fmt.Sprintf(":%d", appPort+1),
+ application(pubsubMessageOnlyTTL, topicTTL1, fullMessages))).
+ Step(sidecar.Run(sidecarName1,
+ embedded.WithComponentsPath("./components/ttl"),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort+1),
+ embedded.WithDaprGRPCPort(runtime.DefaultDaprAPIGRPCPort+1),
+ embedded.WithDaprHTTPPort(runtime.DefaultDaprHTTPPort+1),
+ embedded.WithProfilePort(runtime.DefaultProfilePort+1),
+ componentRuntimeOptions(),
+ )).
+ Step(app.Run(appID2, fmt.Sprintf(":%d", appPort+2),
+ application(pubsubQueueOnlyTTL, topicTTL2, QueueOnlyMessages))).
+ Step(sidecar.Run(sidecarName2,
+ embedded.WithComponentsPath("./components/ttl"),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort+2),
+ embedded.WithDaprGRPCPort(runtime.DefaultDaprAPIGRPCPort+2),
+ embedded.WithDaprHTTPPort(runtime.DefaultDaprHTTPPort+2),
+ embedded.WithProfilePort(runtime.DefaultProfilePort+2),
+ componentRuntimeOptions(),
+ )).
+ Step(app.Run(appID3, fmt.Sprintf(":%d", appPort+4),
+ application(pubsubOverwriteTTL, topicTTL3, OverwriteMessages))).
+ Step(sidecar.Run(sidecarName3,
+ embedded.WithComponentsPath("./components/ttl"),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort+4),
+ embedded.WithDaprGRPCPort(runtime.DefaultDaprAPIGRPCPort+4),
+ embedded.WithDaprHTTPPort(runtime.DefaultDaprHTTPPort+4),
+ embedded.WithProfilePort(runtime.DefaultProfilePort+4),
+ componentRuntimeOptions(),
+ )).
+ // Wait for all queue crated and then stop.
+ Step("wait", flow.Sleep(10*time.Second)).
+ Step("stop sidecar1", sidecar.Stop(sidecarName1)).
+ Step("stop app1", app.Stop(appID1)).
+ Step("stop sidecar2", sidecar.Stop(sidecarName2)).
+ Step("stop app2", app.Stop(appID2)).
+ Step("stop sidecar3", sidecar.Stop(sidecarName3)).
+ Step("stop app3", app.Stop(appID3)).
+ // Run publishing sidecars and send to RabbitMQ.
+ Step(sidecar.Run(sidecarNameTTLClient,
+ embedded.WithComponentsPath("./components/ttl"),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, 0),
+ embedded.WithDaprGRPCPort(runtime.DefaultDaprAPIGRPCPort),
+ embedded.WithDaprHTTPPort(runtime.DefaultDaprHTTPPort),
+ embedded.WithProfilePort(runtime.DefaultProfilePort),
+ componentRuntimeOptions(),
+ )).
+ Step("wait", flow.Sleep(5*time.Second)).
+ // base test case, send message with large ttl and check messages are received.
+ Step("send message only ttl messages", sendMessage(sidecarNameTTLClient, pubsubMessageOnlyTTL, topicTTL1, 100)).
+ Step("wait", flow.Sleep(5*time.Second)).
+ // Run the application1 logic above.
+ Step(app.Run(appID1, fmt.Sprintf(":%d", appPort+1),
+ application(pubsubMessageOnlyTTL, topicTTL1, fullMessages))).
+ // Run the Dapr sidecar with the RabbitMQ component.
+ Step(sidecar.Run(sidecarName1,
+ embedded.WithComponentsPath("./components/ttl"),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort+1),
+ embedded.WithDaprGRPCPort(runtime.DefaultDaprAPIGRPCPort+1),
+ embedded.WithDaprHTTPPort(runtime.DefaultDaprHTTPPort+1),
+ embedded.WithProfilePort(runtime.DefaultProfilePort+1),
+ componentRuntimeOptions(),
+ )).
+ Step("verify full messages", func(ctx flow.Context) error {
+ // Assertion on the data.
+ fullMessages.Assert(t, 3*time.Minute)
+ return nil
+ }).
+ Step("stop sidecar", sidecar.Stop(sidecarName1)).
+ Step("stop app", app.Stop(appID1)).
+ // test case 1, send message with ttl and check messages are expired.
+ Step("send message only ttl messages", sendMessage(sidecarNameTTLClient, pubsubMessageOnlyTTL, topicTTL1, 10)).
+ Step("wait", flow.Sleep(10*time.Second)).
+ Step(app.Run(appID1, fmt.Sprintf(":%d", appPort+1),
+ application(pubsubMessageOnlyTTL, topicTTL1, MessageOnlyMessages))).
+ Step(sidecar.Run(sidecarName1,
+ embedded.WithComponentsPath("./components/ttl"),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort+1),
+ embedded.WithDaprGRPCPort(runtime.DefaultDaprAPIGRPCPort+1),
+ embedded.WithDaprHTTPPort(runtime.DefaultDaprHTTPPort+1),
+ embedded.WithProfilePort(runtime.DefaultProfilePort+1),
+ componentRuntimeOptions(),
+ )).
+ Step("verify messages only ttl", func(ctx flow.Context) error {
+ // Assertion on the data.
+ MessageOnlyMessages.Assert(t, 3*time.Minute)
+ return nil
+ }).
+ // test case 2, send message without ttl to a queue with ttl, check messages are expired.
+ Step("send message without ttl to queue with ttl", sendMessage(sidecarNameTTLClient, pubsubQueueOnlyTTL, topicTTL2, 0)).
+ Step("wait", flow.Sleep(10*time.Second)).
+ // Run the application2 logic above.
+ Step(app.Run(appID2, fmt.Sprintf(":%d", appPort+2),
+ application(pubsubQueueOnlyTTL, topicTTL2, QueueOnlyMessages))).
+ // Run the Dapr sidecar with the RabbitMQ component.
+ Step(sidecar.Run(sidecarName2,
+ embedded.WithComponentsPath("./components/ttl"),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort+2),
+ embedded.WithDaprGRPCPort(runtime.DefaultDaprAPIGRPCPort+2),
+ embedded.WithDaprHTTPPort(runtime.DefaultDaprHTTPPort+2),
+ embedded.WithProfilePort(runtime.DefaultProfilePort+2),
+ componentRuntimeOptions(),
+ )).
+ Step("verify messages only ttl", func(ctx flow.Context) error {
+ // Assertion on the data.
+ QueueOnlyMessages.Assert(t, 3*time.Minute)
+ return nil
+ }).
+ Step("send message with ttl 10 to queue with ttl 30",
+ sendMessage(sidecarNameTTLClient, pubsubOverwriteTTL, topicTTL3, 10)).
+ Step("wait", flow.Sleep(10*time.Second)).
+ // test case 3, send message with ttl 10s to a queue with ttl 30s, wait for 10s, check messages are expired.
+ Step(app.Run(appID3, fmt.Sprintf(":%d", appPort+4),
+ application(pubsubOverwriteTTL, topicTTL3, OverwriteMessages))).
+ // Run the Dapr sidecar with the RabbitMQ component.
+ Step(sidecar.Run(sidecarName3,
+ embedded.WithComponentsPath("./components/ttl"),
+ embedded.WithAppProtocol(runtime.HTTPProtocol, appPort+4),
+ embedded.WithDaprGRPCPort(runtime.DefaultDaprAPIGRPCPort+4),
+ embedded.WithDaprHTTPPort(runtime.DefaultDaprHTTPPort+4),
+ embedded.WithProfilePort(runtime.DefaultProfilePort+4),
+ componentRuntimeOptions(),
+ )).
+ Step("verify messages only ttl", func(ctx flow.Context) error {
+ // Assertion on the data.
+ OverwriteMessages.Assert(t, 3*time.Minute)
+ return nil
+ }).
+ Run()
+}
+
func componentRuntimeOptions() []runtime.Option {
log := logger.NewLogger("dapr.components")
diff --git a/tests/certification/secretstores/azure/keyvault/go.mod b/tests/certification/secretstores/azure/keyvault/go.mod
index 02714c56b..5125728dd 100644
--- a/tests/certification/secretstores/azure/keyvault/go.mod
+++ b/tests/certification/secretstores/azure/keyvault/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211130185200-4918900c09e1
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -18,7 +18,7 @@ require (
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.10.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0 // indirect
github.com/Azure/azure-storage-blob-go v0.10.0 // indirect
@@ -38,7 +38,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
@@ -97,6 +97,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -126,14 +127,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/secretstores/azure/keyvault/go.sum b/tests/certification/secretstores/azure/keyvault/go.sum
index aac4d5e4c..af3d75dff 100644
--- a/tests/certification/secretstores/azure/keyvault/go.sum
+++ b/tests/certification/secretstores/azure/keyvault/go.sum
@@ -47,8 +47,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 h1:pqrAR74b6EoR4kcxF7L7Wg2B8
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 h1:XUNQ4mw+zJmaA2KXzP9JlQiecy1SI+Eog7xVkPiqIbg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.10.1 h1:AhZnZn4kUKz36bHJ8AK/FH2tH/q3CAkG+Gme+2ibuak=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.10.1/go.mod h1:S78i9yTr4o/nXlH76bKjGUye9Z2wSxO5Tz7GoDr4vfI=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0 h1:Lg6BW0VPmCwcMlvOviL3ruHFO+H9tZNqscK0AeuFjGM=
@@ -126,8 +126,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -149,8 +149,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -457,6 +457,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -609,7 +610,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -631,8 +632,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -828,8 +829,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/secretstores/hashicorp/vault/README.md b/tests/certification/secretstores/hashicorp/vault/README.md
index 480417e4b..9f4f9c2f3 100644
--- a/tests/certification/secretstores/hashicorp/vault/README.md
+++ b/tests/certification/secretstores/hashicorp/vault/README.md
@@ -16,17 +16,118 @@ This secret store [supports the following features][features]:
## Test network instability
1. Vault component does not expose a time out configuration option. For this test, let's assume a 1 minute timeout.
2. Retrieve a key to show the connection is fine.
-3. Interrupt the network (Vault port, 8200) for longer than the established timeout value.
+3. Interrupt the network on Vault's port (8200) for longer than the established timeout value.
4. Wait a few seconds (less than the timeout value).
5. Try to read the key from step 2 and assert it is still there.
## Test support for multiple keys under the same secret
-1. Test retrieval of secrets with multiple keys under it
+1. Test retrieval of secrets with multiple keys under it.
+
+## Tests for metadata fields
+
+### Tests for `vaultKVPrefix`, `vaultKVUsePrefix` and `vaultValueTypeText`
+
+1. Verify `vaultKVPrefix` is used
+ * set field to to non default value
+ * run dapr application with component
+ * component should successfully initialize
+ * component should advertise `multipleKeyValuesPerSecret` feature
+ * retrieval of key under registered under new prefix should succeed
+ * keys under default and empty prefixes should be missing
+1. Verify `vaultKVUsePrefix` is used
+ * set field to `false` (non default value)
+ * run dapr application with component
+ * component should successfully initialize
+ * component should advertise `multipleKeyValuesPerSecret` feature
+ * retrieval of key registered without (empty) prefix should succeed
+ * keys under default and non-default prefix from step above should be missing
+1. Verify `vaultValueTypeText` is used
+ * set field to to non default value `text`
+ * run dapr application with component
+ * component should successfully initialize
+ * component should **not** advertise `multipleKeyValuesPerSecret` feature
+ * retrieval of key under registered under new prefix should succeed
+ * keys under default and empty prefixes should be missing
+
+
+### Tests for `vaultToken` and `vaultTokenMountPath`
+
+1. Verify `vaultToken` is used (happy case)
+ * The baseline fo this test is all the previous test are using a known-to-work value that matches what our docker-compose environment sets up.
+1. Verify failure when we use a `vaultToken` value that does not match what our environment sets up
+1. Verify `vaultTokenMountPath` is used (happy case)
+1. Verify failure when `vaultTokenMountPath` points to a broken path
+1. Verify failure when both `vaultToken` and `vaultTokenMountPath` are missing
+1. Verify failure when both `vaultToken` and `vaultTokenMountPath` are present
+
+
+### Tests for vaultAddr
+
+1. Verify `vaultAddr` is used (happy case)
+ * The baseline fo this test is all the previous test are using this flag with a known-to-work value that matches what our docker-compose environment sets up and is **not the default**.
+1. Verify initialization and operation success when `vaultAddr` is missing `skipVerify` is `true`
+ * Start a vault instance using a self-signed HTTPS certificate.
+ * Component configuration lacks `vaultAddr` and defaults to address `https://127.0.0.1:8200`
+ * Due to `skipVerify` the component accepts the self-signed certificate
+1. Verify initialization success but operation failure when `vaultAddr` is missing `skipVerify` is `false`
+ * Start a vault instance using a self-signed HTTPS certificate.
+ * Component configuration lacks `vaultAddr` and defaults to address `https://127.0.0.1:8200`
+ * Since `skipVerify` is disable the component requires a valid TLS certificate and refuses to connect to our vault instance, failing requests.
+1. Verify `vaultAddr` is used when it points to a non-std port
+ * Start a vault instance in dev-mode (HTTP) but listening on a non-std port
+ * Modify component configuration to use this non-std port
+ * Ensure component initialization success and successful retrieval of secrets
+1. Verify successful initialization but secret retrieval failure when `vaultAddr` points to an address not served by a Vault
+ * Start a vault instance in dev-mode (HTTP) listening on std port
+ * Modify component configuration to use a distinct (non-std) port
+ * Ensure component initialization success but secret retrieval failure
+
+
+### Tests for enginePath
+
+1. Verify that setting `enginePath` to an explicit default value works
+1. Verify that setting `enginePath` to a custom value (`TestEnginePathCustomSecretsPath`) works
+ * Start a vault instance in dev-mode
+ * In the companion shell script that seeds the vault instance with secrets,
+ 1. Create a new **path** named `customSecretsPath` that uses the KV engine version 2 (`-version=2 kv` or `kv-v2`)
+ * We cannot use version 1 as the vault component lacks support for non-versioned engines.
+ 2. Seeds this path with a secret specific for this test (to avoid the risk of false-positive tests)
+ * Verify that the custom path has secrets under it using BulkList (this is a sanity check)
+ * Verify that the custom path-specific secret is found
+
+
+### Tests for CA and other certificate-related parameters
+
+TODO: Should we add code to enforce that only one of these is provided?
+
+1. Verify happy-case behavior when `caPem` is set to valid CA certificate and `tlsServerName` matches the server name and `skipVerify` is false.
+1. Verify happy-case behavior when `caPath` is set to valid CA certificate and `tlsServerName` matches the server name and `skipVerify` is false.
+1. Verify happy-case behavior when `caCert` is set to valid CA certificate and `tlsServerName` matches the server name and `skipVerify` is false.
+1. Verify successful initialization but secret retrieval failure when `caPem` is set to a valid server certificate (baseline) but `tlsServerName` does not match the server name and `skipVerify` is false.
+1. Verify successful initialization but secret retrieval failure when `caPem` is set to an invalid server certificate (flag under test) despite `tlsServerName` matching the server name and `skipVerify` is false.
+
+1. Same as the one above but `skipVerify` is true and we should observe happy-case behavior.
+
+1. skipVerify
+ * We also tested before with the vault-generated self-signed cert while testing for `vaultAddr`
+
+
+#### Versioning
+
+1. Verify success on retrieval of a past version of a secret
+ * Start a vault instance in dev-mode (HTTP)
+ * Seed vault instance with multiple versions of a single secret
+ * Use standard component configuration
+ * Ensure component initialization success
+ * Ensure successful retrieval of latest version of the secret
+ * Ensure successful retrieval of an specific version of the secret
## Out of scope
+1. Verifying how vault component handles engines that do not support versioning, like KV version 1
+ * Vault component only handles engines with version support (Bug?)
1. Tests verifying writing and updating a secret since secret stores do not expose this functionality.
@@ -34,8 +135,24 @@ This secret store [supports the following features][features]:
Under the current directory run:
+```shell
+GOLANG_PROTOBUF_REGISTRATION_CONFLICT=warn go test -v .
```
-go test -v vault_test.go
+
+To run an specific test run (replacing `TestVersioning` with the name of the test method):
+
+```shell
+GOLANG_PROTOBUF_REGISTRATION_CONFLICT=warn go test -run TestVersioning -v .
+```
+
+### Docker-compose
+
+You might need to verify if docker-compose is doing what you think it is doing: seeding the right secrets or even booting up properly.
+
+Head to the directory hosting the `docker-compose-hashicorp-vault.yml` file and run:
+
+```shell
+docker-compose -f docker-compose-hashicorp-vault.yml up --remove-orphans
```
# References:
@@ -44,7 +161,10 @@ go test -v vault_test.go
* [List of secret store components and their features][features]
* [PR with Conformance tests for Hashicorp Vault][conformance]
* [HashiCorp Vault API reference](https://www.vaultproject.io/api-docs)
+* [Vault Official Docker image documentation][vault-docker]
+
[HashiCorp Vault Secret Store]: https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/
[features]: https://docs.dapr.io/reference/components-reference/supported-secret-stores/
-[conformance]: https://github.com/dapr/components-contrib/pull/2031
\ No newline at end of file
+[conformance]: https://github.com/dapr/components-contrib/pull/2031
+[vault-docker]: https://hub.docker.com/_/vault/
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/capture_logs.go b/tests/certification/secretstores/hashicorp/vault/capture_logs.go
new file mode 100644
index 000000000..3a44d288c
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/capture_logs.go
@@ -0,0 +1,109 @@
+/*
+Copyright 2021 The Dapr Authors
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package vault_test
+
+import (
+ "bufio"
+ "bytes"
+ "io"
+ "os"
+ "strings"
+
+ "github.com/dapr/components-contrib/tests/certification/flow"
+ "github.com/dapr/kit/logger"
+ "github.com/stretchr/testify/assert"
+)
+
+//
+// Helper functions for asserting error messages during component initialization
+//
+// These can be exported to their own module.
+// Do notice that they have side effects: using more than one in a single
+// flow will cause only the latest to work. Perhaps this functionality
+// (dapr.runtime log capture) could be baked into flows themselves?
+//
+// Also: this is not thread-safe nor concurrent safe: only one test
+// can be run at a time to ensure deterministic capture of dapr.runtime output.
+
+type InitErrorChecker func(ctx flow.Context, errorLine string) error
+
+func CaptureLogsAndCheckInitErrors(checker InitErrorChecker) flow.Runnable {
+ // Setup log capture
+ logCaptor := &bytes.Buffer{}
+ runtimeLogger := logger.NewLogger("dapr.runtime")
+ runtimeLogger.SetOutput(io.MultiWriter(os.Stdout, logCaptor))
+
+ // Stop log capture, reset buffer just for good mesure
+ cleanup := func() {
+ logCaptor.Reset()
+ runtimeLogger.SetOutput(os.Stdout)
+ }
+
+ grepInitErrorFromLogs := func() (string, error) {
+ errorMarker := []byte("INIT_COMPONENT_FAILURE")
+ scanner := bufio.NewScanner(logCaptor)
+ for scanner.Scan() {
+ if err := scanner.Err(); err != nil {
+ return "", err
+ }
+ if bytes.Contains(scanner.Bytes(), errorMarker) {
+ return scanner.Text(), nil
+ }
+ }
+ return "", scanner.Err()
+ }
+
+ // Wraps our InitErrorChecker with cleanup and error-grepping logic so we only care about the
+ // log error
+ return func(ctx flow.Context) error {
+ defer cleanup()
+
+ errorLine, err := grepInitErrorFromLogs()
+ if err != nil {
+ return err
+ }
+ ctx.Logf("captured errorLine: %s", errorLine)
+
+ return checker(ctx, errorLine)
+ }
+}
+
+func AssertNoInitializationErrorsForComponent(componentName string) flow.Runnable {
+ checker := func(ctx flow.Context, errorLine string) error {
+ componentFailedToInitialize := strings.Contains(errorLine, componentName)
+ assert.False(ctx.T, componentFailedToInitialize,
+ "Found component name mentioned in an component initialization error message: %s", errorLine)
+
+ return nil
+ }
+
+ return CaptureLogsAndCheckInitErrors(checker)
+}
+
+func AssertInitializationFailedWithErrorsForComponent(componentName string, additionalSubStringsToMatch ...string) flow.Runnable {
+ checker := func(ctx flow.Context, errorLine string) error {
+ assert.NotEmpty(ctx.T, errorLine, "Expected a component initialization error message but none found")
+ assert.Contains(ctx.T, errorLine, componentName,
+ "Expected to find component '%s' mentioned in error message but found none: %s", componentName, errorLine)
+
+ for _, subString := range additionalSubStringsToMatch {
+ assert.Contains(ctx.T, errorLine, subString,
+ "Expected to find '%s' mentioned in error message but found none: %s", componentName, errorLine)
+ }
+
+ return nil
+ }
+
+ return CaptureLogsAndCheckInitErrors(checker)
+}
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/Makefile b/tests/certification/secretstores/hashicorp/vault/components/caFamily/Makefile
new file mode 100644
index 000000000..58e877255
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/Makefile
@@ -0,0 +1,53 @@
+
+TARGETS = certificates/key.pem certificates/cert.pem caPem/hashicorp-vault.yml certificates/incorrect-ca-key.pem certificates/incorrect-ca-cert.pem
+
+all: $(TARGETS)
+
+# Create cert and key lasting 10 years, no password, no prompt for
+# subject details. Also set subjectAltName so we avoid the
+# "x509: certificate relies on legacy Common Name field" errors
+
+certificates/key.pem certificates/cert.pem:
+ set -e; \
+ mkdir -v -p certificates; \
+ openssl req -x509 -newkey rsa:4096 \
+ -keyout certificates/key.pem \
+ -out certificates/cert.pem \
+ -sha256 -days 3650 \
+ -nodes \
+ -addext "subjectAltName = DNS:hashicorp_vault,DNS:localhost,IP:127.0.0.1" \
+ -subj "/C=CA/ST=BC/L=Vancouver/O=Dapr Testing/OU=Org/CN=www.dapr.io"; \
+ chmod -v 644 certificates/key.pem certificates/cert.pem
+
+# We use this for negative tests that ensure we reject connecting to
+# a server using a distinct Certificate Authority -- despite the server certificate
+# having all the right identifiers
+certificates/incorrect-ca-key.pem certificates/incorrect-ca-cert.pem:
+ set -e; \
+ mkdir -v -p certificates; \
+ openssl req -x509 -newkey rsa:4096 \
+ -keyout certificates/incorrect-ca-key.pem \
+ -out certificates/incorrect-ca-cert.pem \
+ -sha256 -days 3650 \
+ -nodes \
+ -addext "subjectAltName = DNS:hashicorp_vault,DNS:localhost,IP:127.0.0.1" \
+ -subj "/C=CA/ST=BC/L=Vancouver/O=Dapr Testing/OU=Org/CN=www.dapr.io" ; \
+ chmod -v 644 certificates/incorrect-ca-key.pem certificates/incorrect-ca-cert.pem
+
+
+caPem/hashicorp-vault.yml: caPem/hashicorp-vault.yml.template certificates/cert.pem
+ set -e; \
+ echo "#\n# THIS FILE IS AUTO-GENERATED - DO NOT EDIT\n#\n\n" > $@.tmp; \
+ cat caPem/hashicorp-vault.yml.template >> $@.tmp;\
+ sed 's/^/ /' certificates/cert.pem >> $@.tmp; \
+ mv -f $@.tmp $@
+
+# %: .tmp.%
+# mv $< $@
+
+clean:
+ rm -f -v $(TARGETS)
+ rmdir certificates
+
+.PHONY: clean
+.PHONY: all
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/README.md b/tests/certification/secretstores/hashicorp/vault/components/caFamily/README.md
new file mode 100644
index 000000000..830a668ba
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/README.md
@@ -0,0 +1,27 @@
+# Certificate-related tests
+
+These tests are particularly tricky to setup- so a little README in case you decide to change
+this in the future and things break.
+
+# vault, `-dev-tls` and its default port
+
+To make our testing easier we start vault with `-dev-tls`. We do this:
+* to keep the development behavior on,
+* to force vault to start with a default TLS listener with its own self-signed TLS cert. We will
+ use this listener for our negative tests (for `skipValidation` and `tlsServerName`).
+
+To keep the rest of the test setup consistent and similar to other tests, we move this listener to a non-default port.
+
+
+# Using and generating our very own certificate and key
+
+Besides `-dev-tls`, we also instruct vault to use a configuration that defines another listener using `-config /vault/config/vault_server.hcl`. This listener, defined in the `config/vault_server.hcl` is configured use a certificate-key pair we generated ourselves. It also binds this listener to the default vault port - to make the keep some sort of consistency in the test setup.
+
+We use this certificate we generated to assist with the validation of `caPem`, `caCert`, `caPath`, `skipValidate` and `tlsServerName` flags. All of these refer to the same certificate. Testing `caPem` is a bit special in that it needs the certificate inlined in the component YAML file.
+
+A Makefile is included here in order to document and to ease re-generation of the certificate and keys. It will also re-generate the `caPem`-dependent component YAML, so one does not have to remember updating it whenever the certificate is updated or regenerated.
+As a matter of fact, our code does not ship with any of these certificates. Instead, this Makefile is invoked at the begging on `TestCaFamilyOfFields` test.
+
+# Misc. references
+
+For how to configure the vault docker image we are using check https://hub.docker.com/_/vault/
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/badCaCert/docker-compose-hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/caFamily/badCaCert/docker-compose-hashicorp-vault.yml
new file mode 100644
index 000000000..50f41bee7
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/badCaCert/docker-compose-hashicorp-vault.yml
@@ -0,0 +1,46 @@
+version: '3.9'
+
+# Use a YAML reference to define VAULT_TOKEN and DOCKER_IMAGE only once
+x-common-values:
+ # This should match tests/config/secrestore/hashicorp/vault/hashicorp-vault.yaml
+ # This should match .github/infrastructure/conformance/hashicorp/vault_token_file.txt
+ vault_token: &VAULT_TOKEN "vault-dev-root-token-id"
+ # Reuse the same docker image to save on resources and because the base vault image
+ # has everything we need for seeding the initial key values too.
+ vault_docker_image: &VAULT_DOCKER_IMAGE vault:1.12.1
+
+services:
+ hashicorp_vault:
+ image: *VAULT_DOCKER_IMAGE
+ ports:
+ - '8200:8200'
+ cap_add:
+ - IPC_LOCK
+ environment:
+ # Move vault's dev-mode self-signed TLS listener to another port so we can use the default one for
+ # our own listener with our own self-signed certificate.
+ VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:7200"
+ VAULT_DEV_ROOT_TOKEN_ID: *VAULT_TOKEN
+ volumes:
+ - ../vaultConfig:/vault/config/:ro
+ - ../certificates:/certificates:ro
+ # Force vault to use TLS/HTTPS in dev mode
+ entrypoint: vault server -dev-tls -config /vault/config/vault_server.hcl
+
+ # We define a aux. service to seed the expected conformance secrets to vault
+ seed_conformance_secrets:
+ image: *VAULT_DOCKER_IMAGE
+ depends_on:
+ - hashicorp_vault
+ environment:
+ VAULT_TOKEN : *VAULT_TOKEN
+ # We are using HTTPS
+ VAULT_ADDR: https://hashicorp_vault:8200/
+ # Force the server to use our own certificate
+ VAULT_SKIP_VERIFY: 'false'
+ VAULT_CACERT: /certificates/cert.pem
+ volumes:
+ - ../../../../../../../../.github/infrastructure/conformance/hashicorp:/setup:ro
+ - ../certificates:/certificates:ro
+ entrypoint: /setup/setup-hashicorp-vault-secrets.sh
+
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/badCaCert/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/caFamily/badCaCert/hashicorp-vault.yml
new file mode 100644
index 000000000..8b734f73f
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/badCaCert/hashicorp-vault.yml
@@ -0,0 +1,20 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestCaFamilyOfFields-badCaCert
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ - name: vaultAddr
+ value: "https://127.0.0.1:8200"
+ # Enforce TLS verification because this test is all about this
+ - name: skipVerify
+ value: false
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
+ - name: tlsServerName
+ value: hashicorp_vault
+ - name: caCert
+ value: components/caFamily/certificates/incorrect-ca-cert.pem # <<<<< We should fail authentication
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/badCaCertAndSkipVerify/docker-compose-hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/caFamily/badCaCertAndSkipVerify/docker-compose-hashicorp-vault.yml
new file mode 100644
index 000000000..50f41bee7
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/badCaCertAndSkipVerify/docker-compose-hashicorp-vault.yml
@@ -0,0 +1,46 @@
+version: '3.9'
+
+# Use a YAML reference to define VAULT_TOKEN and DOCKER_IMAGE only once
+x-common-values:
+ # This should match tests/config/secrestore/hashicorp/vault/hashicorp-vault.yaml
+ # This should match .github/infrastructure/conformance/hashicorp/vault_token_file.txt
+ vault_token: &VAULT_TOKEN "vault-dev-root-token-id"
+ # Reuse the same docker image to save on resources and because the base vault image
+ # has everything we need for seeding the initial key values too.
+ vault_docker_image: &VAULT_DOCKER_IMAGE vault:1.12.1
+
+services:
+ hashicorp_vault:
+ image: *VAULT_DOCKER_IMAGE
+ ports:
+ - '8200:8200'
+ cap_add:
+ - IPC_LOCK
+ environment:
+ # Move vault's dev-mode self-signed TLS listener to another port so we can use the default one for
+ # our own listener with our own self-signed certificate.
+ VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:7200"
+ VAULT_DEV_ROOT_TOKEN_ID: *VAULT_TOKEN
+ volumes:
+ - ../vaultConfig:/vault/config/:ro
+ - ../certificates:/certificates:ro
+ # Force vault to use TLS/HTTPS in dev mode
+ entrypoint: vault server -dev-tls -config /vault/config/vault_server.hcl
+
+ # We define a aux. service to seed the expected conformance secrets to vault
+ seed_conformance_secrets:
+ image: *VAULT_DOCKER_IMAGE
+ depends_on:
+ - hashicorp_vault
+ environment:
+ VAULT_TOKEN : *VAULT_TOKEN
+ # We are using HTTPS
+ VAULT_ADDR: https://hashicorp_vault:8200/
+ # Force the server to use our own certificate
+ VAULT_SKIP_VERIFY: 'false'
+ VAULT_CACERT: /certificates/cert.pem
+ volumes:
+ - ../../../../../../../../.github/infrastructure/conformance/hashicorp:/setup:ro
+ - ../certificates:/certificates:ro
+ entrypoint: /setup/setup-hashicorp-vault-secrets.sh
+
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/badCaCertAndSkipVerify/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/caFamily/badCaCertAndSkipVerify/hashicorp-vault.yml
new file mode 100644
index 000000000..480d33284
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/badCaCertAndSkipVerify/hashicorp-vault.yml
@@ -0,0 +1,20 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestCaFamilyOfFields-badCaCertAndSkipVerify
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ - name: vaultAddr
+ value: "https://127.0.0.1:8200"
+ # Enforce TLS verification because this test is all about this
+ - name: skipVerify
+ value: true # <<< flag under test
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
+ - name: tlsServerName
+ value: hashicorp_vault
+ - name: caCert
+ value: components/caFamily/certificates/incorrect-ca-cert.pem # <<<<< We would fail authentication if it wasn't for skipVerify
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/badTlsServerName/docker-compose-hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/caFamily/badTlsServerName/docker-compose-hashicorp-vault.yml
new file mode 100644
index 000000000..50f41bee7
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/badTlsServerName/docker-compose-hashicorp-vault.yml
@@ -0,0 +1,46 @@
+version: '3.9'
+
+# Use a YAML reference to define VAULT_TOKEN and DOCKER_IMAGE only once
+x-common-values:
+ # This should match tests/config/secrestore/hashicorp/vault/hashicorp-vault.yaml
+ # This should match .github/infrastructure/conformance/hashicorp/vault_token_file.txt
+ vault_token: &VAULT_TOKEN "vault-dev-root-token-id"
+ # Reuse the same docker image to save on resources and because the base vault image
+ # has everything we need for seeding the initial key values too.
+ vault_docker_image: &VAULT_DOCKER_IMAGE vault:1.12.1
+
+services:
+ hashicorp_vault:
+ image: *VAULT_DOCKER_IMAGE
+ ports:
+ - '8200:8200'
+ cap_add:
+ - IPC_LOCK
+ environment:
+ # Move vault's dev-mode self-signed TLS listener to another port so we can use the default one for
+ # our own listener with our own self-signed certificate.
+ VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:7200"
+ VAULT_DEV_ROOT_TOKEN_ID: *VAULT_TOKEN
+ volumes:
+ - ../vaultConfig:/vault/config/:ro
+ - ../certificates:/certificates:ro
+ # Force vault to use TLS/HTTPS in dev mode
+ entrypoint: vault server -dev-tls -config /vault/config/vault_server.hcl
+
+ # We define a aux. service to seed the expected conformance secrets to vault
+ seed_conformance_secrets:
+ image: *VAULT_DOCKER_IMAGE
+ depends_on:
+ - hashicorp_vault
+ environment:
+ VAULT_TOKEN : *VAULT_TOKEN
+ # We are using HTTPS
+ VAULT_ADDR: https://hashicorp_vault:8200/
+ # Force the server to use our own certificate
+ VAULT_SKIP_VERIFY: 'false'
+ VAULT_CACERT: /certificates/cert.pem
+ volumes:
+ - ../../../../../../../../.github/infrastructure/conformance/hashicorp:/setup:ro
+ - ../certificates:/certificates:ro
+ entrypoint: /setup/setup-hashicorp-vault-secrets.sh
+
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/badTlsServerName/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/caFamily/badTlsServerName/hashicorp-vault.yml
new file mode 100644
index 000000000..b366f7047
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/badTlsServerName/hashicorp-vault.yml
@@ -0,0 +1,20 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestCaFamilyOfFields-badTlsServerName
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ - name: vaultAddr
+ value: "https://127.0.0.1:8200"
+ # Enforce TLS verification because this test is all about this
+ - name: skipVerify
+ value: false
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
+ - name: tlsServerName
+ value: badTlsServerName # <<<<< Ooops, this won't match our cert.
+ - name: caCert
+ value: components/caFamily/certificates/cert.pem
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/caCert/docker-compose-hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/caFamily/caCert/docker-compose-hashicorp-vault.yml
new file mode 100644
index 000000000..50f41bee7
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/caCert/docker-compose-hashicorp-vault.yml
@@ -0,0 +1,46 @@
+version: '3.9'
+
+# Use a YAML reference to define VAULT_TOKEN and DOCKER_IMAGE only once
+x-common-values:
+ # This should match tests/config/secrestore/hashicorp/vault/hashicorp-vault.yaml
+ # This should match .github/infrastructure/conformance/hashicorp/vault_token_file.txt
+ vault_token: &VAULT_TOKEN "vault-dev-root-token-id"
+ # Reuse the same docker image to save on resources and because the base vault image
+ # has everything we need for seeding the initial key values too.
+ vault_docker_image: &VAULT_DOCKER_IMAGE vault:1.12.1
+
+services:
+ hashicorp_vault:
+ image: *VAULT_DOCKER_IMAGE
+ ports:
+ - '8200:8200'
+ cap_add:
+ - IPC_LOCK
+ environment:
+ # Move vault's dev-mode self-signed TLS listener to another port so we can use the default one for
+ # our own listener with our own self-signed certificate.
+ VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:7200"
+ VAULT_DEV_ROOT_TOKEN_ID: *VAULT_TOKEN
+ volumes:
+ - ../vaultConfig:/vault/config/:ro
+ - ../certificates:/certificates:ro
+ # Force vault to use TLS/HTTPS in dev mode
+ entrypoint: vault server -dev-tls -config /vault/config/vault_server.hcl
+
+ # We define a aux. service to seed the expected conformance secrets to vault
+ seed_conformance_secrets:
+ image: *VAULT_DOCKER_IMAGE
+ depends_on:
+ - hashicorp_vault
+ environment:
+ VAULT_TOKEN : *VAULT_TOKEN
+ # We are using HTTPS
+ VAULT_ADDR: https://hashicorp_vault:8200/
+ # Force the server to use our own certificate
+ VAULT_SKIP_VERIFY: 'false'
+ VAULT_CACERT: /certificates/cert.pem
+ volumes:
+ - ../../../../../../../../.github/infrastructure/conformance/hashicorp:/setup:ro
+ - ../certificates:/certificates:ro
+ entrypoint: /setup/setup-hashicorp-vault-secrets.sh
+
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/caCert/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/caFamily/caCert/hashicorp-vault.yml
new file mode 100644
index 000000000..50c53eec2
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/caCert/hashicorp-vault.yml
@@ -0,0 +1,20 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestCaFamilyOfFields-caCert
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ - name: vaultAddr
+ value: "https://127.0.0.1:8200"
+ # Enforce TLS verification because this test is all about this
+ - name: skipVerify
+ value: false
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
+ - name: tlsServerName
+ value: hashicorp_vault
+ - name: caCert
+ value: components/caFamily/certificates/cert.pem
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/caPath/docker-compose-hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/caFamily/caPath/docker-compose-hashicorp-vault.yml
new file mode 100644
index 000000000..50f41bee7
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/caPath/docker-compose-hashicorp-vault.yml
@@ -0,0 +1,46 @@
+version: '3.9'
+
+# Use a YAML reference to define VAULT_TOKEN and DOCKER_IMAGE only once
+x-common-values:
+ # This should match tests/config/secrestore/hashicorp/vault/hashicorp-vault.yaml
+ # This should match .github/infrastructure/conformance/hashicorp/vault_token_file.txt
+ vault_token: &VAULT_TOKEN "vault-dev-root-token-id"
+ # Reuse the same docker image to save on resources and because the base vault image
+ # has everything we need for seeding the initial key values too.
+ vault_docker_image: &VAULT_DOCKER_IMAGE vault:1.12.1
+
+services:
+ hashicorp_vault:
+ image: *VAULT_DOCKER_IMAGE
+ ports:
+ - '8200:8200'
+ cap_add:
+ - IPC_LOCK
+ environment:
+ # Move vault's dev-mode self-signed TLS listener to another port so we can use the default one for
+ # our own listener with our own self-signed certificate.
+ VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:7200"
+ VAULT_DEV_ROOT_TOKEN_ID: *VAULT_TOKEN
+ volumes:
+ - ../vaultConfig:/vault/config/:ro
+ - ../certificates:/certificates:ro
+ # Force vault to use TLS/HTTPS in dev mode
+ entrypoint: vault server -dev-tls -config /vault/config/vault_server.hcl
+
+ # We define a aux. service to seed the expected conformance secrets to vault
+ seed_conformance_secrets:
+ image: *VAULT_DOCKER_IMAGE
+ depends_on:
+ - hashicorp_vault
+ environment:
+ VAULT_TOKEN : *VAULT_TOKEN
+ # We are using HTTPS
+ VAULT_ADDR: https://hashicorp_vault:8200/
+ # Force the server to use our own certificate
+ VAULT_SKIP_VERIFY: 'false'
+ VAULT_CACERT: /certificates/cert.pem
+ volumes:
+ - ../../../../../../../../.github/infrastructure/conformance/hashicorp:/setup:ro
+ - ../certificates:/certificates:ro
+ entrypoint: /setup/setup-hashicorp-vault-secrets.sh
+
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/caPath/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/caFamily/caPath/hashicorp-vault.yml
new file mode 100644
index 000000000..5d2e51e81
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/caPath/hashicorp-vault.yml
@@ -0,0 +1,20 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestCaFamilyOfFields-caPath
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ - name: vaultAddr
+ value: "https://127.0.0.1:8200"
+ # Enforce TLS verification because this test is all about this
+ - name: skipVerify
+ value: false
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
+ - name: tlsServerName
+ value: hashicorp_vault
+ - name: caPath
+ value: components/caFamily/certificates/
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/caPem/docker-compose-hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/caFamily/caPem/docker-compose-hashicorp-vault.yml
new file mode 100644
index 000000000..50f41bee7
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/caPem/docker-compose-hashicorp-vault.yml
@@ -0,0 +1,46 @@
+version: '3.9'
+
+# Use a YAML reference to define VAULT_TOKEN and DOCKER_IMAGE only once
+x-common-values:
+ # This should match tests/config/secrestore/hashicorp/vault/hashicorp-vault.yaml
+ # This should match .github/infrastructure/conformance/hashicorp/vault_token_file.txt
+ vault_token: &VAULT_TOKEN "vault-dev-root-token-id"
+ # Reuse the same docker image to save on resources and because the base vault image
+ # has everything we need for seeding the initial key values too.
+ vault_docker_image: &VAULT_DOCKER_IMAGE vault:1.12.1
+
+services:
+ hashicorp_vault:
+ image: *VAULT_DOCKER_IMAGE
+ ports:
+ - '8200:8200'
+ cap_add:
+ - IPC_LOCK
+ environment:
+ # Move vault's dev-mode self-signed TLS listener to another port so we can use the default one for
+ # our own listener with our own self-signed certificate.
+ VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:7200"
+ VAULT_DEV_ROOT_TOKEN_ID: *VAULT_TOKEN
+ volumes:
+ - ../vaultConfig:/vault/config/:ro
+ - ../certificates:/certificates:ro
+ # Force vault to use TLS/HTTPS in dev mode
+ entrypoint: vault server -dev-tls -config /vault/config/vault_server.hcl
+
+ # We define a aux. service to seed the expected conformance secrets to vault
+ seed_conformance_secrets:
+ image: *VAULT_DOCKER_IMAGE
+ depends_on:
+ - hashicorp_vault
+ environment:
+ VAULT_TOKEN : *VAULT_TOKEN
+ # We are using HTTPS
+ VAULT_ADDR: https://hashicorp_vault:8200/
+ # Force the server to use our own certificate
+ VAULT_SKIP_VERIFY: 'false'
+ VAULT_CACERT: /certificates/cert.pem
+ volumes:
+ - ../../../../../../../../.github/infrastructure/conformance/hashicorp:/setup:ro
+ - ../certificates:/certificates:ro
+ entrypoint: /setup/setup-hashicorp-vault-secrets.sh
+
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/caPem/hashicorp-vault.yml.template b/tests/certification/secretstores/hashicorp/vault/components/caFamily/caPem/hashicorp-vault.yml.template
new file mode 100644
index 000000000..2e41d366f
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/caPem/hashicorp-vault.yml.template
@@ -0,0 +1,20 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestCaFamilyOfFields-caPem
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ - name: vaultAddr
+ value: "https://127.0.0.1:8200"
+ # Enforce TLS verification because this test is all about this
+ - name: skipVerify
+ value: false
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
+ - name: tlsServerName
+ value: hashicorp_vault
+ - name: caPem
+ value: |-
diff --git a/tests/certification/secretstores/hashicorp/vault/components/caFamily/vaultConfig/vault_server.hcl b/tests/certification/secretstores/hashicorp/vault/components/caFamily/vaultConfig/vault_server.hcl
new file mode 100644
index 000000000..8d18bad85
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/caFamily/vaultConfig/vault_server.hcl
@@ -0,0 +1,6 @@
+listener "tcp" {
+ address = "0.0.0.0:8200"
+ tls_disable = "false"
+ tls_cert_file = "/certificates/cert.pem"
+ tls_key_file = "/certificates/key.pem"
+}
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/enginePath/customSecretsPath/docker-compose-hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/enginePath/customSecretsPath/docker-compose-hashicorp-vault.yml
new file mode 100644
index 000000000..ef4244434
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/enginePath/customSecretsPath/docker-compose-hashicorp-vault.yml
@@ -0,0 +1,35 @@
+version: '3.9'
+
+# Use a YAML reference to define VAULT_TOKEN and DOCKER_IMAGE only once
+x-common-values:
+ # This should match tests/config/secrestore/hashicorp/vault/hashicorp-vault.yaml
+ # This should match .github/infrastructure/conformance/hashicorp/vault_token_file.txt
+ vault_token: &VAULT_TOKEN "vault-dev-root-token-id"
+ # Reuse the same docker image to save on resources and because the base vault image
+ # has everything we need for seeding the initial key values too.
+ vault_docker_image: &VAULT_DOCKER_IMAGE vault:1.12.1
+
+services:
+ hashicorp_vault:
+ image: *VAULT_DOCKER_IMAGE
+ ports:
+ - '8200:8200'
+ cap_add:
+ - IPC_LOCK
+ environment:
+ VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:8200"
+ VAULT_DEV_ROOT_TOKEN_ID: *VAULT_TOKEN
+
+
+ # We define a aux. service to seed the expected conformance secrets to vault
+ seed_conformance_secrets:
+ image: *VAULT_DOCKER_IMAGE
+ depends_on:
+ - hashicorp_vault
+ environment:
+ VAULT_TOKEN : *VAULT_TOKEN
+ VAULT_ADDR: http://hashicorp_vault:8200/
+ volumes:
+ - .:/setup:ro
+ entrypoint: /setup/setup-hashicorp-vault-secrets.sh # <<< Use our custom secret seeder for the enginePath/customSecretsPath
+
diff --git a/tests/certification/secretstores/hashicorp/vault/components/enginePath/customSecretsPath/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/enginePath/customSecretsPath/hashicorp-vault.yml
new file mode 100644
index 000000000..d35fc0ee7
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/enginePath/customSecretsPath/hashicorp-vault.yml
@@ -0,0 +1,15 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestEnginePath-customSecretsPath
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ - name: vaultAddr
+ value: "http://127.0.0.1:8200"
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
+ - name: enginePath
+ value: customSecretsPath
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/enginePath/customSecretsPath/setup-hashicorp-vault-secrets.sh b/tests/certification/secretstores/hashicorp/vault/components/enginePath/customSecretsPath/setup-hashicorp-vault-secrets.sh
new file mode 100755
index 000000000..546dae349
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/enginePath/customSecretsPath/setup-hashicorp-vault-secrets.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+# Notice that while hashicorp supports multiple keys in a secret,
+# our confirmance tests needs to go for the common demominator
+# which is a secret store that only has name/value semantic.
+# Hence we setup secret containing a single key with the their
+# same name.
+
+set -eu
+
+MAX_ATTEMPTS=30
+
+for attempt in `seq $MAX_ATTEMPTS`; do
+ # Test connectivity to vault server and create secrets to match
+ # conformance tests / contents from tests/conformance/secrets.json
+ if vault status &&
+ vault secrets enable -path=customSecretsPath kv-v2 && # Enable this path with kv/version2 engine
+ vault kv put customSecretsPath/dapr/secretUnderCustomPath the=trick was=the path=parameter &&
+ vault kv get customSecretsPath/dapr/secretUnderCustomPath ;
+ then
+ echo ✅ secrets set;
+ sleep 1;
+ exit 0;
+ else
+ echo "⏰ vault not available, waiting... - attempt $attempt of $MAX_ATTEMPTS";
+ sleep 1;
+ fi
+done;
+
+echo ❌ Failed to set secrets;
+exit 1
diff --git a/tests/certification/secretstores/hashicorp/vault/components/enginePath/secret/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/enginePath/secret/hashicorp-vault.yml
new file mode 100644
index 000000000..aa953d973
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/enginePath/secret/hashicorp-vault.yml
@@ -0,0 +1,15 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestEnginePath-secret
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ - name: vaultAddr
+ value: "http://127.0.0.1:8200"
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
+ - name: enginePath
+ value: secret
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/missing/docker-compose-hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/missing/docker-compose-hashicorp-vault.yml
new file mode 100644
index 000000000..90f3992be
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/missing/docker-compose-hashicorp-vault.yml
@@ -0,0 +1,38 @@
+version: '3.9'
+
+# Use a YAML reference to define VAULT_TOKEN and DOCKER_IMAGE only once
+x-common-values:
+ # This should match tests/config/secrestore/hashicorp/vault/hashicorp-vault.yaml
+ # This should match .github/infrastructure/conformance/hashicorp/vault_token_file.txt
+ vault_token: &VAULT_TOKEN "vault-dev-root-token-id"
+ # Reuse the same docker image to save on resources and because the base vault image
+ # has everything we need for seeding the initial key values too.
+ vault_docker_image: &VAULT_DOCKER_IMAGE vault:1.12.1
+
+services:
+ hashicorp_vault:
+ image: *VAULT_DOCKER_IMAGE
+ ports:
+ - '8200:8200'
+ cap_add:
+ - IPC_LOCK
+ environment:
+ VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:8200"
+ VAULT_DEV_ROOT_TOKEN_ID: *VAULT_TOKEN
+ # Force vault to use TLS/HTTPS in dev mode
+ entrypoint: vault server -dev-tls=true
+
+ # We define a aux. service to seed the expected conformance secrets to vault
+ seed_conformance_secrets:
+ image: *VAULT_DOCKER_IMAGE
+ depends_on:
+ - hashicorp_vault
+ environment:
+ VAULT_TOKEN : *VAULT_TOKEN
+ # We are using HTTPS
+ VAULT_ADDR: https://hashicorp_vault:8200/
+ VAULT_SKIP_VERIFY: 'true'
+ volumes:
+ - ../../../../../../../../.github/infrastructure/conformance/hashicorp:/setup:ro
+ entrypoint: /setup/setup-hashicorp-vault-secrets.sh
+
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/missing/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/missing/hashicorp-vault.yml
new file mode 100644
index 000000000..d60a34d05
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/missing/hashicorp-vault.yml
@@ -0,0 +1,19 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestVaultAddr-missing
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ # Yes, we commented out vaultAddr.
+ # Default value should kick in: https://127.0.0.1:8200. Notice: HTTPS (TLS)
+ # - name: vaultAddr
+ # value: "http://127.0.0.1:8200"
+ # Do not perform TLS verification since e are starting vault in development
+ # mode with a self-signed certificate
+ - name: skipVerify
+ value: true
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/missingSkipVerifyFalse/docker-compose-hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/missingSkipVerifyFalse/docker-compose-hashicorp-vault.yml
new file mode 100644
index 000000000..90f3992be
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/missingSkipVerifyFalse/docker-compose-hashicorp-vault.yml
@@ -0,0 +1,38 @@
+version: '3.9'
+
+# Use a YAML reference to define VAULT_TOKEN and DOCKER_IMAGE only once
+x-common-values:
+ # This should match tests/config/secrestore/hashicorp/vault/hashicorp-vault.yaml
+ # This should match .github/infrastructure/conformance/hashicorp/vault_token_file.txt
+ vault_token: &VAULT_TOKEN "vault-dev-root-token-id"
+ # Reuse the same docker image to save on resources and because the base vault image
+ # has everything we need for seeding the initial key values too.
+ vault_docker_image: &VAULT_DOCKER_IMAGE vault:1.12.1
+
+services:
+ hashicorp_vault:
+ image: *VAULT_DOCKER_IMAGE
+ ports:
+ - '8200:8200'
+ cap_add:
+ - IPC_LOCK
+ environment:
+ VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:8200"
+ VAULT_DEV_ROOT_TOKEN_ID: *VAULT_TOKEN
+ # Force vault to use TLS/HTTPS in dev mode
+ entrypoint: vault server -dev-tls=true
+
+ # We define a aux. service to seed the expected conformance secrets to vault
+ seed_conformance_secrets:
+ image: *VAULT_DOCKER_IMAGE
+ depends_on:
+ - hashicorp_vault
+ environment:
+ VAULT_TOKEN : *VAULT_TOKEN
+ # We are using HTTPS
+ VAULT_ADDR: https://hashicorp_vault:8200/
+ VAULT_SKIP_VERIFY: 'true'
+ volumes:
+ - ../../../../../../../../.github/infrastructure/conformance/hashicorp:/setup:ro
+ entrypoint: /setup/setup-hashicorp-vault-secrets.sh
+
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/missingSkipVerifyFalse/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/missingSkipVerifyFalse/hashicorp-vault.yml
new file mode 100644
index 000000000..83b5d7fdf
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/missingSkipVerifyFalse/hashicorp-vault.yml
@@ -0,0 +1,19 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestVaultAddr-missingSkipVerifyFalse
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ # Yes, we commented out vaultAddr.
+ # Default value should kick in: https://127.0.0.1:8200. Notice: HTTPS (TLS)
+ # - name: vaultAddr
+ # value: "http://127.0.0.1:8200"
+ # Do not perform TLS verification since e are starting vault in development
+ # mode with a self-signed certificate
+ - name: skipVerify
+ value: false
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/nonStdPort/docker-compose-hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/nonStdPort/docker-compose-hashicorp-vault.yml
new file mode 100644
index 000000000..0a8514409
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/nonStdPort/docker-compose-hashicorp-vault.yml
@@ -0,0 +1,36 @@
+version: '3.9'
+
+# Use a YAML reference to define VAULT_TOKEN and DOCKER_IMAGE only once
+x-common-values:
+ # This should match tests/config/secrestore/hashicorp/vault/hashicorp-vault.yaml
+ # This should match .github/infrastructure/conformance/hashicorp/vault_token_file.txt
+ vault_token: &VAULT_TOKEN "vault-dev-root-token-id"
+ # Reuse the same docker image to save on resources and because the base vault image
+ # has everything we need for seeding the initial key values too.
+ vault_docker_image: &VAULT_DOCKER_IMAGE vault:1.12.1
+
+services:
+ hashicorp_vault:
+ image: *VAULT_DOCKER_IMAGE
+ ports:
+ - '11200:11200'
+ cap_add:
+ - IPC_LOCK
+ environment:
+ VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:11200"
+ VAULT_DEV_ROOT_TOKEN_ID: *VAULT_TOKEN
+
+ # We define a aux. service to seed the expected conformance secrets to vault
+ seed_conformance_secrets:
+ image: *VAULT_DOCKER_IMAGE
+ depends_on:
+ - hashicorp_vault
+ environment:
+ VAULT_TOKEN : *VAULT_TOKEN
+ # We are using HTTPS
+ VAULT_ADDR: http://hashicorp_vault:11200/
+ VAULT_SKIP_VERIFY: 'true'
+ volumes:
+ - ../../../../../../../../.github/infrastructure/conformance/hashicorp:/setup:ro
+ entrypoint: /setup/setup-hashicorp-vault-secrets.sh
+
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/nonStdPort/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/nonStdPort/hashicorp-vault.yml
new file mode 100644
index 000000000..f5c3d3264
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/nonStdPort/hashicorp-vault.yml
@@ -0,0 +1,14 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestVaultAddr-nonStdPort
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ # Use non-standard port
+ - name: vaultAddr
+ value: "http://127.0.0.1:11200"
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/wrongAddress/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/wrongAddress/hashicorp-vault.yml
new file mode 100644
index 000000000..5c4a548a9
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultAddr/wrongAddress/hashicorp-vault.yml
@@ -0,0 +1,13 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestVaultAddr-wrongAddress
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ - name: vaultAddr
+ value: "http://127.0.0.1:28234" # yeah.. let's hope no one starts a Vault here
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultKVPrefix/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultKVPrefix/hashicorp-vault.yml
new file mode 100644
index 000000000..7d0b663e6
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultKVPrefix/hashicorp-vault.yml
@@ -0,0 +1,15 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ - name: vaultAddr
+ value: "http://127.0.0.1:8200"
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
+ - name: vaultKVPrefix
+ value: alternativePrefix
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultKVUsePrefixFalse/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultKVUsePrefixFalse/hashicorp-vault.yml
new file mode 100644
index 000000000..8179b6ee2
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultKVUsePrefixFalse/hashicorp-vault.yml
@@ -0,0 +1,15 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ - name: vaultAddr
+ value: "http://127.0.0.1:8200"
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
+ - name: vaultKVUsePrefix
+ value: false
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/badVaultToken/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/badVaultToken/hashicorp-vault.yml
new file mode 100644
index 000000000..34bfb0c29
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/badVaultToken/hashicorp-vault.yml
@@ -0,0 +1,14 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestTokenAndTokenMountPath-badVaultToken
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ ignoreErrors: true # This component will fail to load but we don't want Dapr to FATAL because of it.
+ metadata:
+ - name: vaultAddr
+ value: "http://127.0.0.1:8200"
+ - name: vaultToken
+ value: "this-is-not-the-correct-vault-token-to-talk-to-our-server"
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/both/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/both/hashicorp-vault.yml
new file mode 100644
index 000000000..b747c743c
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/both/hashicorp-vault.yml
@@ -0,0 +1,16 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestTokenAndTokenMountPath-both
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ ignoreErrors: true # This component will fail to load but we don't want Dapr to FATAL because of it.
+ metadata:
+ - name: vaultAddr
+ value: "http://127.0.0.1:8200"
+ - name: vaultToken
+ value: "vault-dev-root-token-id"
+ - name: vaultTokenMountPath
+ value: /tmp/vaultToken.txt
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/neither/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/neither/hashicorp-vault.yml
new file mode 100644
index 000000000..08e74811f
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/neither/hashicorp-vault.yml
@@ -0,0 +1,13 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestTokenAndTokenMountPath-neither
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ ignoreErrors: true # This component will fail to load but we don't want Dapr to FATAL because of it.
+ metadata:
+ - name: vaultAddr
+ value: "http://127.0.0.1:8200"
+ # no vaultToken or vaultTokenMountPath
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/tokenMountPathHappyCase/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/tokenMountPathHappyCase/hashicorp-vault.yml
new file mode 100644
index 000000000..cf26809b2
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/tokenMountPathHappyCase/hashicorp-vault.yml
@@ -0,0 +1,15 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestTokenAndTokenMountPath-tokenMountPathHappyCase
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ ignoreErrors: true # This component will fail to load but we don't want Dapr to FATAL because of it.
+ metadata:
+ - name: vaultAddr
+ value: "http://127.0.0.1:8200"
+ - name: vaultTokenMountPath
+ # This is a long path but this file is in current directory ;)
+ value: components/vaultTokenAndTokenMountPath/tokenMountPathHappyCase/vault_token_file.txt
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/tokenMountPathHappyCase/vault_token_file.txt b/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/tokenMountPathHappyCase/vault_token_file.txt
new file mode 100644
index 000000000..0fc2ab7bd
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/tokenMountPathHappyCase/vault_token_file.txt
@@ -0,0 +1 @@
+vault-dev-root-token-id
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/tokenMountPathPointsToBrokenPath/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/tokenMountPathPointsToBrokenPath/hashicorp-vault.yml
new file mode 100644
index 000000000..9f0b65be2
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultTokenAndTokenMountPath/tokenMountPathPointsToBrokenPath/hashicorp-vault.yml
@@ -0,0 +1,14 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestTokenAndTokenMountPath-tokenMountPathPointsToBrokenPath
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ ignoreErrors: true # This component will fail to load but we don't want Dapr to FATAL because of it.
+ metadata:
+ - name: vaultAddr
+ value: "http://127.0.0.1:8200"
+ - name: vaultTokenMountPath
+ value: /this/path/does/not/exist/vaultToken.txt
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/vaultValueTypeText/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/vaultValueTypeText/hashicorp-vault.yml
new file mode 100644
index 000000000..94362ca78
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/vaultValueTypeText/hashicorp-vault.yml
@@ -0,0 +1,15 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ - name: vaultAddr
+ value: "http://127.0.0.1:8200"
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
+ - name: vaultValueType
+ value: text # Turns Vault into a secret store with name/value semantics.
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/versioning/docker-compose-hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/versioning/docker-compose-hashicorp-vault.yml
new file mode 100644
index 000000000..bdcf03479
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/versioning/docker-compose-hashicorp-vault.yml
@@ -0,0 +1,34 @@
+version: '3.9'
+
+# Use a YAML reference to define VAULT_TOKEN and DOCKER_IMAGE only once
+x-common-values:
+ # This should match tests/config/secrestore/hashicorp/vault/hashicorp-vault.yaml
+ # This should match .github/infrastructure/conformance/hashicorp/vault_token_file.txt
+ vault_token: &VAULT_TOKEN "vault-dev-root-token-id"
+ # Reuse the same docker image to save on resources and because the base vault image
+ # has everything we need for seeding the initial key values too.
+ vault_docker_image: &VAULT_DOCKER_IMAGE vault:1.12.1
+
+services:
+ hashicorp_vault:
+ image: *VAULT_DOCKER_IMAGE
+ ports:
+ - '8200:8200'
+ cap_add:
+ - IPC_LOCK
+ environment:
+ VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:8200"
+ VAULT_DEV_ROOT_TOKEN_ID: *VAULT_TOKEN
+
+ # We define a aux. service to seed the expected conformance secrets to vault
+ seed_conformance_secrets:
+ image: *VAULT_DOCKER_IMAGE
+ depends_on:
+ - hashicorp_vault
+ environment:
+ VAULT_TOKEN : *VAULT_TOKEN
+ VAULT_ADDR: http://hashicorp_vault:8200/
+ volumes:
+ - .:/setup:ro
+ entrypoint: /setup/seed-secret-with-multiple-versions.sh # <<< Use our custom secret seeder for the versioning test
+
diff --git a/tests/certification/secretstores/hashicorp/vault/components/versioning/hashicorp-vault.yml b/tests/certification/secretstores/hashicorp/vault/components/versioning/hashicorp-vault.yml
new file mode 100644
index 000000000..74ce6249a
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/versioning/hashicorp-vault.yml
@@ -0,0 +1,13 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: my-hashicorp-vault-TestVersioning
+ namespace: default
+spec:
+ type: secretstores.hashicorp.vault
+ version: v1
+ metadata:
+ - name: vaultAddr
+ value: "http://127.0.0.1:8200"
+ - name: vaultToken # Matches docker compose VAULT_DEV_ROOT_TOKEN_ID env. var.
+ value: "vault-dev-root-token-id"
\ No newline at end of file
diff --git a/tests/certification/secretstores/hashicorp/vault/components/versioning/seed-secret-with-multiple-versions.sh b/tests/certification/secretstores/hashicorp/vault/components/versioning/seed-secret-with-multiple-versions.sh
new file mode 100755
index 000000000..50a6f280d
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/components/versioning/seed-secret-with-multiple-versions.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# Notice that while hashicorp supports multiple keys in a secret,
+# our confirmance tests needs to go for the common demominator
+# which is a secret store that only has name/value semantic.
+# Hence we setup secret containing a single key with the their
+# same name.
+
+set -eu
+
+MAX_ATTEMPTS=30
+
+for attempt in `seq $MAX_ATTEMPTS`; do
+ # Test connectivity to vault server and create secrets to match
+ # conformance tests / contents from tests/conformance/secrets.json
+ if vault status &&
+ vault kv put secret/dapr/secretUnderTest versionedKey=initialVersion &&
+ vault kv put secret/dapr/secretUnderTest versionedKey=secondVersion &&
+ vault kv put secret/dapr/secretUnderTest versionedKey=v3 &&
+ vault kv put secret/dapr/secretUnderTest versionedKey=v4 &&
+ vault kv put secret/dapr/secretUnderTest versionedKey=latestValue &&
+ vault kv get secret/dapr/secretUnderTest ;
+ then
+ echo ✅ secrets set;
+ sleep 1;
+ exit 0;
+ else
+ echo "⏰ vault not available, waiting... - attempt $attempt of $MAX_ATTEMPTS";
+ sleep 1;
+ fi
+done;
+
+echo ❌ Failed to set secrets;
+exit 1
diff --git a/tests/certification/secretstores/hashicorp/vault/flow_helpers.go b/tests/certification/secretstores/hashicorp/vault/flow_helpers.go
new file mode 100644
index 000000000..62034e384
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/flow_helpers.go
@@ -0,0 +1,157 @@
+/*
+Copyright 2021 The Dapr Authors
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package vault_test
+
+import (
+ "path/filepath"
+ "testing"
+ "time"
+
+ "github.com/dapr/components-contrib/secretstores/hashicorp/vault"
+ "github.com/dapr/components-contrib/tests/certification/embedded"
+ "github.com/dapr/components-contrib/tests/certification/flow"
+ "github.com/dapr/components-contrib/tests/certification/flow/dockercompose"
+ "github.com/dapr/components-contrib/tests/certification/flow/sidecar"
+ secretstores_loader "github.com/dapr/dapr/pkg/components/secretstores"
+ "github.com/dapr/dapr/pkg/runtime"
+ dapr_testing "github.com/dapr/dapr/pkg/testing"
+ "github.com/dapr/kit/logger"
+ "github.com/stretchr/testify/assert"
+)
+
+//
+// Flow and test setup helpers
+//
+
+func componentRuntimeOptions() []runtime.Option {
+ log := logger.NewLogger("dapr.components")
+
+ secretStoreRegistry := secretstores_loader.NewRegistry()
+ secretStoreRegistry.Logger = log
+ secretStoreRegistry.RegisterComponent(vault.NewHashiCorpVaultSecretStore, "hashicorp.vault")
+
+ return []runtime.Option{
+ runtime.WithSecretStores(secretStoreRegistry),
+ }
+}
+
+func GetCurrentGRPCAndHTTPPort(t *testing.T) (int, int) {
+ ports, err := dapr_testing.GetFreePorts(2)
+ assert.NoError(t, err)
+
+ currentGrpcPort := ports[0]
+ currentHttpPort := ports[1]
+
+ return currentGrpcPort, currentHttpPort
+}
+
+//
+// Helper functions for common tests for happy case, init-but-does-not-work and fails-initialization tests
+// These test re-use the same seed secrets. They aim to check how certain flags break or keep vault working
+// instead of verifying some specific tha change key retrieval behavior.
+//
+// Those tests require a `/` structure.
+
+type commonFlowSettings struct {
+ t *testing.T
+ currentGrpcPort int
+ currentHttpPort int
+ secretStoreComponentPathBase string
+ componentNamePrefix string
+}
+
+func NewFlowSettings(t *testing.T) *commonFlowSettings {
+ res := commonFlowSettings{}
+ res.t = t
+ res.currentGrpcPort, res.currentHttpPort = GetCurrentGRPCAndHTTPPort(t)
+ return &res
+}
+
+func createPositiveTestFlow(fs *commonFlowSettings, flowDescription string, componentSuffix string, useCustomDockerCompose bool) {
+ componentPath := filepath.Join(fs.secretStoreComponentPathBase, componentSuffix)
+ componentName := fs.componentNamePrefix + componentSuffix
+
+ dockerComposeClusterYAML := defaultDockerComposeClusterYAML
+ if useCustomDockerCompose {
+ dockerComposeClusterYAML = filepath.Join(componentPath, "docker-compose-hashicorp-vault.yml")
+ }
+
+ flow.New(fs.t, flowDescription).
+ Step(dockercompose.Run(dockerComposeProjectName, dockerComposeClusterYAML)).
+ Step("Waiting for component to start...", flow.Sleep(5*time.Second)).
+ Step(sidecar.Run(sidecarName,
+ embedded.WithoutApp(),
+ embedded.WithComponentsPath(componentPath),
+ embedded.WithDaprGRPCPort(fs.currentGrpcPort),
+ embedded.WithDaprHTTPPort(fs.currentHttpPort),
+ componentRuntimeOptions(),
+ )).
+ Step("Waiting for component to load...", flow.Sleep(5*time.Second)).
+ Step("Verify component is registered", testComponentFound(componentName, fs.currentGrpcPort)).
+ Step("Verify no errors regarding component initialization", AssertNoInitializationErrorsForComponent(componentPath)).
+ Step("Test that the default secret is found", testDefaultSecretIsFound(fs.currentGrpcPort, componentName)).
+ Step("Stop HashiCorp Vault server", dockercompose.Stop(dockerComposeProjectName, dockerComposeClusterYAML)).
+ Run()
+}
+
+func createInitSucceedsButComponentFailsFlow(fs *commonFlowSettings, flowDescription string, componentSuffix string, useCustomDockerCompose bool, initErrorCodes ...string) {
+ componentPath := filepath.Join(fs.secretStoreComponentPathBase, componentSuffix)
+ componentName := fs.componentNamePrefix + componentSuffix
+
+ dockerComposeClusterYAML := defaultDockerComposeClusterYAML
+ if useCustomDockerCompose {
+ dockerComposeClusterYAML = filepath.Join(componentPath, "docker-compose-hashicorp-vault.yml")
+ }
+
+ flow.New(fs.t, flowDescription).
+ Step(dockercompose.Run(dockerComposeProjectName, dockerComposeClusterYAML)).
+ Step("Waiting for component to start...", flow.Sleep(5*time.Second)).
+ Step(sidecar.Run(sidecarName,
+ embedded.WithoutApp(),
+ embedded.WithComponentsPath(componentPath),
+ embedded.WithDaprGRPCPort(fs.currentGrpcPort),
+ embedded.WithDaprHTTPPort(fs.currentHttpPort),
+ componentRuntimeOptions(),
+ )).
+ Step("Waiting for component to load...", flow.Sleep(5*time.Second)).
+ Step("Verify component is registered", testComponentFound(componentName, fs.currentGrpcPort)).
+ Step("Verify no errors regarding component initialization", AssertNoInitializationErrorsForComponent(componentPath)).
+ Step("Verify component does not work", testComponentIsNotWorking(componentName, fs.currentGrpcPort)).
+ Step("Stop HashiCorp Vault server", dockercompose.Stop(dockerComposeProjectName, dockerComposeClusterYAML)).
+ Run()
+}
+
+func createNegativeTestFlow(fs *commonFlowSettings, flowDescription string, componentSuffix string, initErrorCodes ...string) {
+ componentPath := filepath.Join(fs.secretStoreComponentPathBase, componentSuffix)
+ componentName := fs.componentNamePrefix + componentSuffix
+ dockerComposeClusterYAML := defaultDockerComposeClusterYAML
+
+ flow.New(fs.t, flowDescription).
+ Step(dockercompose.Run(dockerComposeProjectName, dockerComposeClusterYAML)).
+ Step("Waiting for component to start...", flow.Sleep(5*time.Second)).
+ Step(sidecar.Run(sidecarName,
+ embedded.WithoutApp(),
+ embedded.WithComponentsPath(componentPath),
+ embedded.WithDaprGRPCPort(fs.currentGrpcPort),
+ embedded.WithDaprHTTPPort(fs.currentHttpPort),
+ componentRuntimeOptions(),
+ )).
+ Step("Waiting for component to load...", flow.Sleep(5*time.Second)).
+ // TODO(tmacam) FIX https://github.com/dapr/dapr/issues/5487
+ Step("Verify component is NOT registered", testComponentNotFound(componentName, fs.currentGrpcPort)).
+ Step("Verify initialization error reported for component", AssertInitializationFailedWithErrorsForComponent(componentName, initErrorCodes...)).
+ Step(" Bug dependant behavior - test component is actually registered", testComponentFound(componentName, fs.currentGrpcPort)).
+ Step("Stop HashiCorp Vault server", dockercompose.Stop(dockerComposeProjectName, dockerComposeClusterYAML)).
+ Run()
+}
diff --git a/tests/certification/secretstores/hashicorp/vault/go.mod b/tests/certification/secretstores/hashicorp/vault/go.mod
index e1dfe0cac..d6b8c536e 100644
--- a/tests/certification/secretstores/hashicorp/vault/go.mod
+++ b/tests/certification/secretstores/hashicorp/vault/go.mod
@@ -5,9 +5,9 @@ go 1.18
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20220526162429-d03aeba3e0d6
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e // We require dapr/dapr#5208 merged
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4 // We require dapr/dapr#5208 merged
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/golang/protobuf v1.5.2
github.com/stretchr/testify v1.8.1
)
@@ -21,7 +21,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
@@ -74,6 +74,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -102,14 +103,14 @@ require (
go.opentelemetry.io/otel/trace v1.11.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/secretstores/hashicorp/vault/go.sum b/tests/certification/secretstores/hashicorp/vault/go.sum
index cea71190d..59d959bda 100644
--- a/tests/certification/secretstores/hashicorp/vault/go.sum
+++ b/tests/certification/secretstores/hashicorp/vault/go.sum
@@ -70,8 +70,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -93,8 +93,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -380,6 +380,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -525,7 +526,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -547,8 +548,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -742,8 +743,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/secretstores/hashicorp/vault/metadata_helpers.go b/tests/certification/secretstores/hashicorp/vault/metadata_helpers.go
new file mode 100644
index 000000000..29b3b4160
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/metadata_helpers.go
@@ -0,0 +1,105 @@
+/*
+Copyright 2021 The Dapr Authors
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package vault_test
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/dapr/components-contrib/secretstores"
+ "github.com/dapr/components-contrib/tests/certification/flow"
+ "github.com/dapr/go-sdk/client"
+ "github.com/golang/protobuf/ptypes/empty"
+ "github.com/stretchr/testify/assert"
+)
+
+//
+// Helper methods for checking component registration and availability of its features
+//
+
+func testComponentFound(targetComponentName string, currentGrpcPort int) flow.Runnable {
+ return func(ctx flow.Context) error {
+ componentFound, _ := getComponentCapabilities(ctx, currentGrpcPort, targetComponentName)
+ assert.True(ctx.T, componentFound, "Component was expected to be found but it was missing.")
+ return nil
+ }
+}
+
+// Due to https://github.com/dapr/dapr/issues/5487 we cannot perform negative tests
+// for the component presence against the metadata registry.
+// Instead, we turned testComponentNotFound into a simpler negative test that ensures a good key cannot be found
+func testComponentNotFound(targetComponentName string, currentGrpcPort int) flow.Runnable {
+ // TODO(tmacam) once https://github.com/dapr/dapr/issues/5487 is fixed, uncomment the code bellow
+ return testSecretIsNotFound(currentGrpcPort, targetComponentName, "multiplekeyvaluessecret")
+
+ //return func(ctx flow.Context) error {
+ // // Find the component
+ // componentFound, _ := getComponentCapabilities(ctx, currentGrpcPort, targetComponentName)
+ // assert.False(ctx.T, componentFound, "Component was expected to be missing but it was found.")
+ // return nil
+ //}
+}
+
+func testComponentDoesNotHaveFeature(currentGrpcPort int, targetComponentName string, targetCapability secretstores.Feature) flow.Runnable {
+ return testComponentAndFeaturePresence(currentGrpcPort, targetComponentName, targetCapability, false)
+}
+
+func testComponentHasFeature(currentGrpcPort int, targetComponentName string, targetCapability secretstores.Feature) flow.Runnable {
+ return testComponentAndFeaturePresence(currentGrpcPort, targetComponentName, targetCapability, true)
+}
+
+func testComponentAndFeaturePresence(currentGrpcPort int, targetComponentName string, targetCapability secretstores.Feature, expectedToBeFound bool) flow.Runnable {
+ return func(ctx flow.Context) error {
+ componentFound, capabilities := getComponentCapabilities(ctx, currentGrpcPort, targetComponentName)
+
+ assert.True(ctx.T, componentFound, "Component was expected to be found but it was missing.")
+
+ targetCapabilityAsString := string(targetCapability)
+ // Find capability
+ capabilityFound := false
+ for _, cap := range capabilities {
+ if cap == targetCapabilityAsString {
+ capabilityFound = true
+ break
+ }
+ }
+ assert.Equal(ctx.T, expectedToBeFound, capabilityFound)
+
+ return nil
+ }
+}
+
+func getComponentCapabilities(ctx flow.Context, currentGrpcPort int, targetComponentName string) (found bool, capabilities []string) {
+ daprClient, err := client.NewClientWithPort(fmt.Sprint(currentGrpcPort))
+ if err != nil {
+ panic(err)
+ }
+ defer daprClient.Close()
+
+ clientCtx := context.Background()
+
+ resp, err := daprClient.GrpcClient().GetMetadata(clientCtx, &empty.Empty{})
+ assert.NoError(ctx.T, err)
+ assert.NotNil(ctx.T, resp)
+ assert.NotNil(ctx.T, resp.GetRegisteredComponents())
+
+ // Find the component
+ for _, component := range resp.GetRegisteredComponents() {
+ if component.GetName() == targetComponentName {
+ ctx.Logf("component found=%s", component)
+ return true, component.GetCapabilities()
+ }
+ }
+ return false, []string{}
+}
diff --git a/tests/certification/secretstores/hashicorp/vault/secret_helpers.go b/tests/certification/secretstores/hashicorp/vault/secret_helpers.go
new file mode 100644
index 000000000..94435f7fd
--- /dev/null
+++ b/tests/certification/secretstores/hashicorp/vault/secret_helpers.go
@@ -0,0 +1,107 @@
+/*
+Copyright 2021 The Dapr Authors
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package vault_test
+
+import (
+ "fmt"
+
+ "github.com/dapr/components-contrib/tests/certification/flow"
+ "github.com/dapr/go-sdk/client"
+ "github.com/stretchr/testify/assert"
+)
+
+//
+// Aux. functions for testing key presence
+//
+
+func testKeyValuesInSecret(currentGrpcPort int, secretStoreName string, secretName string, keyValueMap map[string]string, maybeVersionID ...string) flow.Runnable {
+ return func(ctx flow.Context) error {
+ daprClient, err := client.NewClientWithPort(fmt.Sprint(currentGrpcPort))
+ if err != nil {
+ panic(err)
+ }
+ defer daprClient.Close()
+
+ metadata := map[string]string{}
+ if len(maybeVersionID) > 0 {
+ metadata["version_id"] = maybeVersionID[0]
+ }
+
+ res, err := daprClient.GetSecret(ctx, secretStoreName, secretName, metadata)
+ assert.NoError(ctx.T, err)
+ assert.NotNil(ctx.T, res)
+
+ for key, valueExpected := range keyValueMap {
+ valueInSecret, exists := res[key]
+ assert.True(ctx.T, exists, "expected key not found in key")
+ assert.Equal(ctx.T, valueExpected, valueInSecret)
+ }
+ return nil
+ }
+}
+
+func testSecretIsNotFound(currentGrpcPort int, secretStoreName string, secretName string) flow.Runnable {
+ return func(ctx flow.Context) error {
+ daprClient, err := client.NewClientWithPort(fmt.Sprint(currentGrpcPort))
+ if err != nil {
+ panic(err)
+ }
+ defer daprClient.Close()
+
+ emptyOpt := map[string]string{}
+
+ _, err = daprClient.GetSecret(ctx, secretStoreName, secretName, emptyOpt)
+ assert.Error(ctx.T, err)
+
+ return nil
+ }
+}
+
+func testDefaultSecretIsFound(currentGrpcPort int, secretStoreName string) flow.Runnable {
+ return testKeyValuesInSecret(currentGrpcPort, secretStoreName, "multiplekeyvaluessecret", map[string]string{
+ "first": "1",
+ "second": "2",
+ "third": "3",
+ })
+}
+
+func testComponentIsNotWorking(targetComponentName string, currentGrpcPort int) flow.Runnable {
+ return testSecretIsNotFound(currentGrpcPort, targetComponentName, "multiplekeyvaluessecret")
+}
+
+func testGetBulkSecretsWorksAndFoundKeys(currentGrpcPort int, secretStoreName string) flow.Runnable {
+ return func(ctx flow.Context) error {
+ client, err := client.NewClientWithPort(fmt.Sprint(currentGrpcPort))
+ if err != nil {
+ panic(err)
+ }
+ defer client.Close()
+
+ emptyOpt := map[string]string{}
+
+ res, err := client.GetBulkSecret(ctx, secretStoreName, emptyOpt)
+ assert.NoError(ctx.T, err)
+ assert.NotNil(ctx.T, res)
+ assert.NotEmpty(ctx.T, res)
+
+ for k, v := range res {
+ ctx.Logf("Secret %s", k)
+ for i, j := range v {
+ ctx.Logf("\t key-value pair: %s : %s", i, j)
+ }
+ }
+
+ return nil
+ }
+}
diff --git a/tests/certification/secretstores/hashicorp/vault/vault_test.go b/tests/certification/secretstores/hashicorp/vault/vault_test.go
index 148416a28..467e8a8a2 100644
--- a/tests/certification/secretstores/hashicorp/vault/vault_test.go
+++ b/tests/certification/secretstores/hashicorp/vault/vault_test.go
@@ -15,33 +15,24 @@ package vault_test
import (
"context"
- "fmt"
+ "os/exec"
+ "path/filepath"
"testing"
"time"
"github.com/dapr/components-contrib/secretstores"
- "github.com/dapr/components-contrib/secretstores/hashicorp/vault"
"github.com/dapr/components-contrib/tests/certification/embedded"
"github.com/dapr/components-contrib/tests/certification/flow"
"github.com/dapr/components-contrib/tests/certification/flow/dockercompose"
"github.com/dapr/components-contrib/tests/certification/flow/network"
"github.com/dapr/components-contrib/tests/certification/flow/sidecar"
- secretstores_loader "github.com/dapr/dapr/pkg/components/secretstores"
- "github.com/dapr/dapr/pkg/runtime"
- dapr_testing "github.com/dapr/dapr/pkg/testing"
- "github.com/dapr/go-sdk/client"
- "github.com/dapr/kit/logger"
- "github.com/stretchr/testify/assert"
-
- "github.com/golang/protobuf/ptypes/empty"
)
const (
- sidecarName = "hashicorp-vault-sidecar"
- dockerComposeClusterYAML = "../../../../../.github/infrastructure/docker-compose-hashicorp-vault.yml"
- dockerComposeProjectName = "hashicorp-vault"
- secretStoreComponentPath = "./components/default"
- secretStoreName = "my-hashicorp-vault" // as set in the component YAML
+ sidecarName = "hashicorp-vault-sidecar"
+ defaultDockerComposeClusterYAML = "../../../../../.github/infrastructure/docker-compose-hashicorp-vault.yml"
+ dockerComposeProjectName = "hashicorp-vault"
+ // secretStoreName = "my-hashicorp-vault" // as set in the component YAML
networkInstabilityTime = 1 * time.Minute
waitAfterInstabilityTime = networkInstabilityTime / 4
@@ -49,47 +40,25 @@ const (
)
func TestBasicSecretRetrieval(t *testing.T) {
- ports, err := dapr_testing.GetFreePorts(2)
- assert.NoError(t, err)
+ const (
+ secretStoreComponentPath = "./components/default"
+ secretStoreName = "my-hashicorp-vault" // as set in the component YAML
+ )
- currentGrpcPort := ports[0]
- currentHttpPort := ports[1]
+ currentGrpcPort, currentHttpPort := GetCurrentGRPCAndHTTPPort(t)
- testGetKnownSecret := func(ctx flow.Context) error {
- client, err := client.NewClientWithPort(fmt.Sprint(currentGrpcPort))
- if err != nil {
- panic(err)
- }
- defer client.Close()
+ // This test reuses the HashiCorp Vault's conformance test resources created using
+ // .github/infrastructure/docker-compose-hashicorp-vault.yml,
+ // so it reuses the tests/conformance/secretstores/secretstores.go test secrets.
+ testGetKnownSecret := testKeyValuesInSecret(currentGrpcPort, secretStoreName,
+ "secondsecret", map[string]string{
+ "secondsecret": "efgh",
+ })
- emptyOpt := map[string]string{}
-
- // This test reuses the HashiCorp Vault's conformance test resources created using
- // .github/infrastructure/docker-compose-hashicorp-vault.yml,
- // so it reuses the tests/conformance/secretstores/secretstores.go test secrets.
- res, err := client.GetSecret(ctx, secretStoreName, "secondsecret", emptyOpt)
- assert.NoError(t, err)
- assert.Equal(t, "efgh", res["secondsecret"])
- return nil
- }
-
- testGetMissingSecret := func(ctx flow.Context) error {
- client, err := client.NewClientWithPort(fmt.Sprint(currentGrpcPort))
- if err != nil {
- panic(err)
- }
- defer client.Close()
-
- emptyOpt := map[string]string{}
-
- _, getErr := client.GetSecret(ctx, secretStoreName, "this_secret_is_not_there", emptyOpt)
- assert.Error(t, getErr)
-
- return nil
- }
+ testGetMissingSecret := testSecretIsNotFound(currentGrpcPort, secretStoreName, "this_secret_is_not_there")
flow.New(t, "Test component is up and we can retrieve some secrets").
- Step(dockercompose.Run(dockerComposeProjectName, dockerComposeClusterYAML)).
+ Step(dockercompose.Run(dockerComposeProjectName, defaultDockerComposeClusterYAML)).
Step("Waiting for component to start...", flow.Sleep(5*time.Second)).
Step(sidecar.Run(sidecarName,
embedded.WithoutApp(),
@@ -99,47 +68,28 @@ func TestBasicSecretRetrieval(t *testing.T) {
componentRuntimeOptions(),
)).
Step("Waiting for component to load...", flow.Sleep(5*time.Second)).
- Step("Verify component is registered", testComponentFound(t, secretStoreName, currentGrpcPort)).
+ Step("Verify component is registered", testComponentFound(secretStoreName, currentGrpcPort)).
+ Step("Verify no errors regarding component initialization", AssertNoInitializationErrorsForComponent(secretStoreComponentPath)).
Step("Run basic secret retrieval test", testGetKnownSecret).
Step("Test retrieval of secret that does not exist", testGetMissingSecret).
Step("Interrupt network for 1 minute",
network.InterruptNetwork(networkInstabilityTime, nil, nil, servicePortToInterrupt)).
Step("Wait for component to recover", flow.Sleep(waitAfterInstabilityTime)).
Step("Run basic test again to verify reconnection occurred", testGetKnownSecret).
- Step("Stop HashiCorp Vault server", dockercompose.Stop(dockerComposeProjectName, dockerComposeClusterYAML)).
+ Step("Stop HashiCorp Vault server", dockercompose.Stop(dockerComposeProjectName, defaultDockerComposeClusterYAML)).
Run()
}
func TestMultipleKVRetrieval(t *testing.T) {
- ports, err := dapr_testing.GetFreePorts(2)
- assert.NoError(t, err)
+ const (
+ secretStoreComponentPath = "./components/default"
+ secretStoreName = "my-hashicorp-vault" // as set in the component YAML
+ )
- currentGrpcPort := ports[0]
- currentHttpPort := ports[1]
-
- testGetMultipleKeyValuesFromSecret := func(ctx flow.Context) error {
- client, err := client.NewClientWithPort(fmt.Sprint(currentGrpcPort))
- if err != nil {
- panic(err)
- }
- defer client.Close()
-
- emptyOpt := map[string]string{}
-
- // This test reuses the HashiCorp Vault's conformance test resources created using
- // .github/infrastructure/docker-compose-hashicorp-vault.yml,
- // so it reuses the tests/conformance/secretstores/secretstores.go test secrets.
- res, err := client.GetSecret(ctx, secretStoreName, "multiplekeyvaluessecret", emptyOpt)
- assert.NoError(t, err)
- assert.NotNil(t, res)
- assert.Equal(t, "1", res["first"])
- assert.Equal(t, "2", res["second"])
- assert.Equal(t, "3", res["third"])
- return nil
- }
+ currentGrpcPort, currentHttpPort := GetCurrentGRPCAndHTTPPort(t)
flow.New(t, "Test retrieving multiple key values from a secret").
- Step(dockercompose.Run(dockerComposeProjectName, dockerComposeClusterYAML)).
+ Step(dockercompose.Run(dockerComposeProjectName, defaultDockerComposeClusterYAML)).
Step("Waiting for component to start...", flow.Sleep(5*time.Second)).
Step(sidecar.Run(sidecarName,
embedded.WithoutApp(),
@@ -149,90 +99,305 @@ func TestMultipleKVRetrieval(t *testing.T) {
componentRuntimeOptions(),
)).
Step("Waiting for component to load...", flow.Sleep(5*time.Second)).
- Step("Verify component is registered", testComponentFound(t, secretStoreName, currentGrpcPort)).
+ Step("Verify component is registered", testComponentFound(secretStoreName, currentGrpcPort)).
+ Step("Verify no errors regarding component initialization", AssertNoInitializationErrorsForComponent(secretStoreComponentPath)).
Step("Verify component has support for multiple key-values under the same secret",
- testComponentHasFeature(t, secretStoreName, string(secretstores.FeatureMultipleKeyValuesPerSecret), currentGrpcPort)).
- Step("Test retrieval of a secret with multiple key-values", testGetMultipleKeyValuesFromSecret).
+ testComponentHasFeature(currentGrpcPort, secretStoreName, secretstores.FeatureMultipleKeyValuesPerSecret)).
+ Step("Test retrieval of a secret with multiple key-values",
+ testKeyValuesInSecret(currentGrpcPort, secretStoreName, "multiplekeyvaluessecret", map[string]string{
+ "first": "1",
+ "second": "2",
+ "third": "3",
+ })).
+ Step("Test secret registered under a non-default vaultKVPrefix cannot be found",
+ testSecretIsNotFound(currentGrpcPort, secretStoreName, "secretUnderAlternativePrefix")).
+ Step("Test secret registered with no prefix cannot be found", testSecretIsNotFound(currentGrpcPort, secretStoreName, "secretWithNoPrefix")).
+ Step("Stop HashiCorp Vault server", dockercompose.Stop(dockerComposeProjectName, defaultDockerComposeClusterYAML)).
+ Run()
+}
+
+func TestVaultKVPrefix(t *testing.T) {
+ const (
+ secretStoreComponentPath = "./components/vaultKVPrefix"
+ secretStoreName = "my-hashicorp-vault" // as set in the component YAML
+ )
+
+ currentGrpcPort, currentHttpPort := GetCurrentGRPCAndHTTPPort(t)
+
+ flow.New(t, "Test setting a non-default vaultKVPrefix value").
+ Step(dockercompose.Run(dockerComposeProjectName, defaultDockerComposeClusterYAML)).
+ Step("Waiting for component to start...", flow.Sleep(5*time.Second)).
+ Step(sidecar.Run(sidecarName,
+ embedded.WithoutApp(),
+ embedded.WithComponentsPath(secretStoreComponentPath),
+ embedded.WithDaprGRPCPort(currentGrpcPort),
+ embedded.WithDaprHTTPPort(currentHttpPort),
+ componentRuntimeOptions(),
+ )).
+ Step("Waiting for component to load...", flow.Sleep(5*time.Second)).
+ Step("Verify component is registered", testComponentFound(secretStoreName, currentGrpcPort)).
+ Step("Verify no errors regarding component initialization", AssertNoInitializationErrorsForComponent(secretStoreComponentPath)).
+ Step("Verify component has support for multiple key-values under the same secret",
+ testComponentHasFeature(currentGrpcPort, secretStoreName, secretstores.FeatureMultipleKeyValuesPerSecret)).
+ Step("Test retrieval of a secret under a non-default vaultKVPrefix",
+ testKeyValuesInSecret(currentGrpcPort, secretStoreName, "secretUnderAlternativePrefix", map[string]string{
+ "altPrefixKey": "altPrefixValue",
+ })).
+ Step("Test secret registered with no prefix cannot be found", testSecretIsNotFound(currentGrpcPort, secretStoreName, "secretWithNoPrefix")).
+ Step("Stop HashiCorp Vault server", dockercompose.Stop(dockerComposeProjectName, defaultDockerComposeClusterYAML)).
+ Run()
+}
+
+func TestVaultKVUsePrefixFalse(t *testing.T) {
+ const (
+ secretStoreComponentPath = "./components/vaultKVUsePrefixFalse"
+ secretStoreName = "my-hashicorp-vault" // as set in the component YAML
+ )
+
+ currentGrpcPort, currentHttpPort := GetCurrentGRPCAndHTTPPort(t)
+
+ flow.New(t, "Test using an empty vaultKVPrefix value").
+ Step(dockercompose.Run(dockerComposeProjectName, defaultDockerComposeClusterYAML)).
+ Step("Waiting for component to start...", flow.Sleep(5*time.Second)).
+ Step(sidecar.Run(sidecarName,
+ embedded.WithoutApp(),
+ embedded.WithComponentsPath(secretStoreComponentPath),
+ embedded.WithDaprGRPCPort(currentGrpcPort),
+ embedded.WithDaprHTTPPort(currentHttpPort),
+ componentRuntimeOptions(),
+ )).
+ Step("Waiting for component to load...", flow.Sleep(5*time.Second)).
+ Step("Verify component is registered", testComponentFound(secretStoreName, currentGrpcPort)).
+ Step("Verify no errors regarding component initialization", AssertNoInitializationErrorsForComponent(secretStoreComponentPath)).
+ Step("Verify component has support for multiple key-values under the same secret",
+ testComponentHasFeature(currentGrpcPort, secretStoreName, secretstores.FeatureMultipleKeyValuesPerSecret)).
+ Step("Test retrieval of a secret registered with no prefix and assuming vaultKVUsePrefix=false",
+ testKeyValuesInSecret(currentGrpcPort, secretStoreName, "secretWithNoPrefix", map[string]string{
+ "noPrefixKey": "noProblem",
+ })).
+ Step("Test secret registered under the default vaultKVPrefix cannot be found",
+ testSecretIsNotFound(currentGrpcPort, secretStoreName, "multiplekeyvaluessecret")).
+ Step("Test secret registered under a non-default vaultKVPrefix cannot be found",
+ testSecretIsNotFound(currentGrpcPort, secretStoreName, "secretUnderAlternativePrefix")).
+ Step("Stop HashiCorp Vault server", dockercompose.Stop(dockerComposeProjectName, defaultDockerComposeClusterYAML)).
+ Run()
+}
+
+func TestVaultValueTypeText(t *testing.T) {
+ const (
+ secretStoreComponentPath = "./components/vaultValueTypeText"
+ secretStoreName = "my-hashicorp-vault" // as set in the component YAML
+ )
+
+ currentGrpcPort, currentHttpPort := GetCurrentGRPCAndHTTPPort(t)
+
+ flow.New(t, "Test setting vaultValueType=text should cause it to behave with single-value semantics").
+ Step(dockercompose.Run(dockerComposeProjectName, defaultDockerComposeClusterYAML)).
+ Step("Waiting for component to start...", flow.Sleep(5*time.Second)).
+ Step(sidecar.Run(sidecarName,
+ embedded.WithoutApp(),
+ embedded.WithComponentsPath(secretStoreComponentPath),
+ embedded.WithDaprGRPCPort(currentGrpcPort),
+ embedded.WithDaprHTTPPort(currentHttpPort),
+ componentRuntimeOptions(),
+ )).
+ Step("Waiting for component to load...", flow.Sleep(5*time.Second)).
+ Step("Verify component is registered", testComponentFound(secretStoreName, currentGrpcPort)).
+ Step("Verify no errors regarding component initialization", AssertNoInitializationErrorsForComponent(secretStoreComponentPath)).
+ Step("Verify component DOES NOT support multiple key-values under the same secret",
+ testComponentDoesNotHaveFeature(currentGrpcPort, secretStoreName, secretstores.FeatureMultipleKeyValuesPerSecret)).
+ Step("Test secret store presents name/value semantics for secrets",
+ // result has a single key with tha same name as the secret and a JSON-like content
+ testKeyValuesInSecret(currentGrpcPort, secretStoreName, "secondsecret", map[string]string{
+ "secondsecret": "{\"secondsecret\":\"efgh\"}",
+ })).
+ Step("Test secret registered under a non-default vaultKVPrefix cannot be found",
+ testSecretIsNotFound(currentGrpcPort, secretStoreName, "secretUnderAlternativePrefix")).
+ Step("Test secret registered with no prefix cannot be found", testSecretIsNotFound(currentGrpcPort, secretStoreName, "secretWithNoPrefix")).
+ Step("Stop HashiCorp Vault server", dockercompose.Stop(dockerComposeProjectName, defaultDockerComposeClusterYAML)).
+ Run()
+}
+
+func TestTokenAndTokenMountPath(t *testing.T) {
+ fs := NewFlowSettings(t)
+ fs.secretStoreComponentPathBase = "./components/vaultTokenAndTokenMountPath/"
+ fs.componentNamePrefix = "my-hashicorp-vault-TestTokenAndTokenMountPath-"
+
+ createNegativeTestFlow(fs,
+ "Verify component initialization failure when BOTH vaultToken and vaultTokenMountPath are present",
+ "both",
+ "token mount path and token both set")
+
+ createNegativeTestFlow(fs,
+ "Verify component initialization failure when NEITHER vaultToken nor vaultTokenMountPath are present",
+ "neither",
+ "token mount path and token not set")
+
+ createNegativeTestFlow(fs,
+ "Verify component initialization failure when vaultTokenPath points to a non-existing file",
+ "tokenMountPathPointsToBrokenPath",
+ "couldn't read vault token from mount path")
+
+ createInitSucceedsButComponentFailsFlow(fs,
+ "Verify failure when vaultToken value does not match our servers's value",
+ "badVaultToken",
+ false)
+
+ createPositiveTestFlow(fs,
+ "Verify success when vaultTokenPath points to an existing file matching the configured secret we have for our secret seeder",
+ "tokenMountPathHappyCase",
+ false)
+}
+
+func TestVaultAddr(t *testing.T) {
+ fs := NewFlowSettings(t)
+ fs.secretStoreComponentPathBase = "./components/vaultAddr/"
+ fs.componentNamePrefix = "my-hashicorp-vault-TestVaultAddr-"
+
+ createInitSucceedsButComponentFailsFlow(fs,
+ "Verify initialization success but use failure when vaultAddr does not point to a valid vault server address",
+ "wrongAddress",
+ false)
+
+ createPositiveTestFlow(fs,
+ "Verify success when vaultAddr is missing and skipVerify is true and vault is using a self-signed certificate",
+ "missing",
+ true)
+
+ createPositiveTestFlow(fs,
+ "Verify success when vaultAddr points to a non-standard port",
+ "nonStdPort",
+ true)
+
+ createInitSucceedsButComponentFailsFlow(fs,
+ "Verify initialization success but use failure when vaultAddr is missing and skipVerify is true and vault is using its own self-signed certificate",
+ "missingSkipVerifyFalse",
+ true)
+}
+
+func TestEnginePathCustomSecretsPath(t *testing.T) {
+ const (
+ secretStoreComponentPathBase = "./components/enginePath/"
+ componentNamePrefix = "my-hashicorp-vault-TestEnginePath-"
+ componentSuffix = "customSecretsPath"
+ componentName = componentNamePrefix + componentSuffix
+ )
+
+ currentGrpcPort, currentHttpPort := GetCurrentGRPCAndHTTPPort(t)
+
+ componentPath := filepath.Join(secretStoreComponentPathBase, componentSuffix)
+ dockerComposeClusterYAML := filepath.Join(componentPath, "docker-compose-hashicorp-vault.yml")
+
+ flow.New(t, "Verify success when we set enginePath to a non-std value").
+ Step(dockercompose.Run(dockerComposeProjectName, dockerComposeClusterYAML)).
+ Step("Waiting for component to start...", flow.Sleep(5*time.Second)).
+ Step(sidecar.Run(sidecarName,
+ embedded.WithoutApp(),
+ embedded.WithComponentsPath(componentPath),
+ embedded.WithDaprGRPCPort(currentGrpcPort),
+ embedded.WithDaprHTTPPort(currentHttpPort),
+ // Dapr log-level debug?
+ componentRuntimeOptions(),
+ )).
+ Step("Waiting for component to load...", flow.Sleep(5*time.Second)).
+ Step("Verify component is registered", testComponentFound(componentName, currentGrpcPort)).
+ Step("Verify no errors regarding component initialization", AssertNoInitializationErrorsForComponent(componentPath)).
+ Step("Verify that the custom path has secrets under it", testGetBulkSecretsWorksAndFoundKeys(currentGrpcPort, componentName)).
+ Step("Verify that the custom path-specific secret is found", testKeyValuesInSecret(currentGrpcPort, componentName,
+ "secretUnderCustomPath", map[string]string{
+ "the": "trick",
+ "was": "the",
+ "path": "parameter",
+ })).
Step("Stop HashiCorp Vault server", dockercompose.Stop(dockerComposeProjectName, dockerComposeClusterYAML)).
Run()
}
-func testComponentFound(t *testing.T, targetComponentName string, currentGrpcPort int) flow.Runnable {
- return func(ctx flow.Context) error {
- client, err := client.NewClientWithPort(fmt.Sprint(currentGrpcPort))
- if err != nil {
- panic(err)
- }
- defer client.Close()
+func TestEnginePathSecrets(t *testing.T) {
+ fs := NewFlowSettings(t)
+ fs.secretStoreComponentPathBase = "./components/enginePath/"
+ fs.componentNamePrefix = "my-hashicorp-vault-TestEnginePath-"
- clientCtx := context.Background()
-
- resp, err := client.GrpcClient().GetMetadata(clientCtx, &empty.Empty{})
- assert.NoError(t, err)
- assert.NotNil(t, resp)
- assert.NotNil(t, resp.GetRegisteredComponents())
-
- // Find the component
- componentFound := false
- for _, component := range resp.GetRegisteredComponents() {
- if component.GetName() == targetComponentName {
- componentFound = true
- break
- }
- }
- assert.True(t, componentFound)
-
- return nil
- }
+ createPositiveTestFlow(fs,
+ "Verify success when vaultEngine explicitly uses the secrets engine",
+ "secret", false)
}
-func testComponentHasFeature(t *testing.T, targetComponentName string, targetCapability string, currentGrpcPort int) flow.Runnable {
- return func(ctx flow.Context) error {
- client, err := client.NewClientWithPort(fmt.Sprint(currentGrpcPort))
- if err != nil {
- panic(err)
- }
- defer client.Close()
+func TestCaFamilyOfFields(t *testing.T) {
+ fs := NewFlowSettings(t)
+ fs.secretStoreComponentPathBase = "./components/caFamily/"
+ fs.componentNamePrefix = "my-hashicorp-vault-TestCaFamilyOfFields-"
- clientCtx := context.Background()
+ // Generate certificates and caPem/hashicorp-vault.yml
+ ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
+ defer cancel()
+ makeCmd := exec.CommandContext(ctx, "make",
+ // Change to components/caFamily directory so files are generated relative to that directory
+ "-C", fs.secretStoreComponentPathBase,
+ )
- resp, err := client.GrpcClient().GetMetadata(clientCtx, &empty.Empty{})
- assert.NoError(t, err)
- assert.NotNil(t, resp)
- assert.NotNil(t, resp.GetRegisteredComponents())
-
- // Find the component
- var capabilities []string = []string{}
- for _, component := range resp.GetRegisteredComponents() {
- if component.GetName() == targetComponentName {
- capabilities = component.GetCapabilities()
- break
- }
- }
- assert.NotEmpty(t, capabilities)
-
- // Find capability
- capabilityFound := false
- for _, cap := range capabilities {
- if cap == targetCapability {
- capabilityFound = true
- break
- }
- }
- assert.True(t, capabilityFound)
-
- return nil
+ if out, err := makeCmd.CombinedOutput(); err != nil {
+ t.Logf("Make exited with error %s", out)
+ t.Fatal(err)
}
+
+ createPositiveTestFlow(fs,
+ "Verify success when using a caCert to talk to vault with tlsServerName and enforceVerify",
+ "caCert", true)
+
+ createPositiveTestFlow(fs,
+ "Verify success when using a caPath to talk to vault with tlsServerName and enforceVerify",
+ "caCert", true)
+
+ createPositiveTestFlow(fs,
+ "Verify success when using a caPem to talk to vault with tlsServerName and enforceVerify",
+ "caPem", true)
+
+ createInitSucceedsButComponentFailsFlow(fs,
+ "Verify successful initialization but secret retrieval failure when `caPem` is set to a valid server certificate (baseline) but `tlsServerName` does not match the server name",
+ "badTlsServerName", true)
+
+ createInitSucceedsButComponentFailsFlow(fs,
+ "Verify successful initialization but secret retrieval failure when `caPem` is set to an invalid server certificate (flag under test) despite `tlsServerName` matching the server name ",
+ "badCaCert", true)
+
+ createPositiveTestFlow(fs,
+ "Verify success when using a caPem is invalid but skipVerify is on",
+ "badCaCertAndSkipVerify", true)
}
-func componentRuntimeOptions() []runtime.Option {
- log := logger.NewLogger("dapr.components")
+func TestVersioning(t *testing.T) {
+ const (
+ componentPath = "./components/versioning/"
+ componentName = "my-hashicorp-vault-TestVersioning"
+ )
+ dockerComposeClusterYAML := filepath.Join(componentPath, "docker-compose-hashicorp-vault.yml")
- secretStoreRegistry := secretstores_loader.NewRegistry()
- secretStoreRegistry.Logger = log
- secretStoreRegistry.RegisterComponent(vault.NewHashiCorpVaultSecretStore, "hashicorp.vault")
+ currentGrpcPort, currentHttpPort := GetCurrentGRPCAndHTTPPort(t)
- return []runtime.Option{
- runtime.WithSecretStores(secretStoreRegistry),
- }
+ flow.New(t, "Verify success on retrieval of a past version of a secret").
+ Step(dockercompose.Run(dockerComposeProjectName, dockerComposeClusterYAML)).
+ Step("Waiting for component to start...", flow.Sleep(5*time.Second)).
+ Step(sidecar.Run(sidecarName,
+ embedded.WithoutApp(),
+ embedded.WithComponentsPath(componentPath),
+ embedded.WithDaprGRPCPort(currentGrpcPort),
+ embedded.WithDaprHTTPPort(currentHttpPort),
+ // Dapr log-level debug?
+ componentRuntimeOptions(),
+ )).
+ Step("Waiting for component to load...", flow.Sleep(5*time.Second)).
+ Step("Verify component is registered", testComponentFound(componentName, currentGrpcPort)).
+ Step("Verify no errors regarding component initialization", AssertNoInitializationErrorsForComponent(componentPath)).
+ Step("Verify that we can list secrets", testGetBulkSecretsWorksAndFoundKeys(currentGrpcPort, componentName)).
+ Step("Verify that the latest version of the secret is there", testKeyValuesInSecret(currentGrpcPort, componentName,
+ "secretUnderTest", map[string]string{
+ "versionedKey": "latestValue",
+ })).
+ Step("Verify that a past version of the secret is there", testKeyValuesInSecret(currentGrpcPort, componentName,
+ "secretUnderTest", map[string]string{
+ "versionedKey": "secondVersion",
+ }, "2")).
+ Step("Stop HashiCorp Vault server", dockercompose.Stop(dockerComposeProjectName, dockerComposeClusterYAML)).
+ Run()
}
diff --git a/tests/certification/secretstores/local/env/go.mod b/tests/certification/secretstores/local/env/go.mod
index 9d628a13e..2b4f3bacf 100644
--- a/tests/certification/secretstores/local/env/go.mod
+++ b/tests/certification/secretstores/local/env/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211130185200-4918900c09e1
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -20,7 +20,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
@@ -74,6 +74,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -101,14 +102,14 @@ require (
go.opentelemetry.io/otel/trace v1.11.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/secretstores/local/env/go.sum b/tests/certification/secretstores/local/env/go.sum
index 7ec7d23db..3cf74a82e 100644
--- a/tests/certification/secretstores/local/env/go.sum
+++ b/tests/certification/secretstores/local/env/go.sum
@@ -70,8 +70,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -93,8 +93,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -380,6 +380,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -523,7 +524,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -545,8 +546,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -740,8 +741,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/secretstores/local/file/go.mod b/tests/certification/secretstores/local/file/go.mod
index 0ce6f21a9..0748097f1 100644
--- a/tests/certification/secretstores/local/file/go.mod
+++ b/tests/certification/secretstores/local/file/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211130185200-4918900c09e1
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -20,7 +20,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
@@ -74,6 +74,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -101,14 +102,14 @@ require (
go.opentelemetry.io/otel/trace v1.11.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/secretstores/local/file/go.sum b/tests/certification/secretstores/local/file/go.sum
index 7ec7d23db..3cf74a82e 100644
--- a/tests/certification/secretstores/local/file/go.sum
+++ b/tests/certification/secretstores/local/file/go.sum
@@ -70,8 +70,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -93,8 +93,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -380,6 +380,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -523,7 +524,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -545,8 +546,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -740,8 +741,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/state/azure/blobstorage/go.mod b/tests/certification/state/azure/blobstorage/go.mod
index d083aec4a..2d48295ce 100644
--- a/tests/certification/state/azure/blobstorage/go.mod
+++ b/tests/certification/state/azure/blobstorage/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211026011813-36b75e9ae272
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -18,7 +18,8 @@ require (
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.5.1 // indirect
github.com/Azure/azure-storage-blob-go v0.10.0 // indirect
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
@@ -31,13 +32,12 @@ require (
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 // indirect
github.com/PuerkitoBio/purell v1.2.0 // indirect
- github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
@@ -96,6 +96,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -125,14 +126,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/state/azure/blobstorage/go.sum b/tests/certification/state/azure/blobstorage/go.sum
index 1f77cc478..3597e1e34 100644
--- a/tests/certification/state/azure/blobstorage/go.sum
+++ b/tests/certification/state/azure/blobstorage/go.sum
@@ -47,8 +47,10 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 h1:pqrAR74b6EoR4kcxF7L7Wg2B8
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 h1:XUNQ4mw+zJmaA2KXzP9JlQiecy1SI+Eog7xVkPiqIbg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.5.1 h1:BMTdr+ib5ljLa9MxTJK8x/Ds0MbBb4MfuW5BL0zMJnI=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.5.1/go.mod h1:c6WvOhtmjNUWbLfOG1qxM/q0SPvQNSVJvolm+C52dIU=
github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs=
github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE=
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd h1:b3wyxBl3vvr15tUAziPBPK354y+LSdfPCpex5oBttHo=
@@ -98,7 +100,6 @@ github.com/PuerkitoBio/purell v1.2.0 h1:/Jdm5QfyM8zdlqT6WVZU4cfP23sot6CEHA4CS49E
github.com/PuerkitoBio/purell v1.2.0/go.mod h1:OhLRTaaIzhvIyofkJfB24gokC7tM42Px5UhoT32THBk=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b h1:WMhlIaJkDgEQSVJQM06YV+cYUl1r5OY5//ijMXJNqtA=
-github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b/go.mod h1:Tie46d3UWzXpj+Fh9+DQTyaUxEpFBPOLXrnx7nxlKRo=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -123,8 +124,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -146,8 +147,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -454,6 +455,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -606,7 +608,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -628,8 +630,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -825,8 +827,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/state/azure/cosmosdb/cosmosdb_test.go b/tests/certification/state/azure/cosmosdb/cosmosdb_test.go
index ade9638b8..fcc77ab5a 100644
--- a/tests/certification/state/azure/cosmosdb/cosmosdb_test.go
+++ b/tests/certification/state/azure/cosmosdb/cosmosdb_test.go
@@ -23,12 +23,12 @@ import (
"github.com/dapr/go-sdk/client"
secretstore_env "github.com/dapr/components-contrib/secretstores/local/env"
- secretstores_loader "github.com/dapr/dapr/pkg/components/secretstores"
-
"github.com/dapr/components-contrib/tests/certification/flow/sidecar"
+ secretstores_loader "github.com/dapr/dapr/pkg/components/secretstores"
state_loader "github.com/dapr/dapr/pkg/components/state"
"github.com/dapr/dapr/pkg/runtime"
dapr_testing "github.com/dapr/dapr/pkg/testing"
+ daprClient "github.com/dapr/go-sdk/client"
"github.com/dapr/kit/logger"
"github.com/stretchr/testify/assert"
)
@@ -73,6 +73,34 @@ func TestAzureCosmosDBStorage(t *testing.T) {
}
}
+ transactionsTest := func(statestore string) func(ctx flow.Context) error {
+ return func(ctx flow.Context) error {
+ client, err := client.NewClientWithPort(fmt.Sprint(currentGrpcPort))
+ if err != nil {
+ panic(err)
+ }
+ defer client.Close()
+
+ err = client.ExecuteStateTransaction(ctx, statestore, nil, []*daprClient.StateOperation{
+ {
+ Type: daprClient.StateOperationTypeUpsert,
+ Item: &daprClient.SetStateItem{
+ Key: "reqKey1",
+ Value: []byte("reqVal1"),
+ Etag: &daprClient.ETag{
+ Value: "test",
+ },
+ Metadata: map[string]string{
+ "ttlInSeconds": "-1",
+ },
+ },
+ },
+ })
+ assert.NoError(t, err)
+
+ return nil
+ }
+ }
partitionTest := func(statestore string) flow.Runnable {
return func(ctx flow.Context) error {
client, err := client.NewClientWithPort(fmt.Sprint(currentGrpcPort))
@@ -133,6 +161,17 @@ func TestAzureCosmosDBStorage(t *testing.T) {
Step("Run basic test with master key", basicTest("statestore-basic")).
Run()
+ flow.New(t, "Test transaction operations").
+ // Run the Dapr sidecar with azure CosmosDB storage.
+ Step(sidecar.Run(sidecarNamePrefix,
+ embedded.WithoutApp(),
+ embedded.WithDaprGRPCPort(currentGrpcPort),
+ embedded.WithDaprHTTPPort(currentHTTPPort),
+ embedded.WithComponentsPath("./components/basictest"),
+ componentRuntimeOptions())).
+ Step("Run transaction test with etag present", transactionsTest("statestore-basic")).
+ Run()
+
flow.New(t, "Test basic operations with different partition keys").
// Run the Dapr sidecar with azure CosmosDB storage.
Step(sidecar.Run(sidecarNamePrefix,
diff --git a/tests/certification/state/azure/cosmosdb/go.mod b/tests/certification/state/azure/cosmosdb/go.mod
index b7db76a3d..b747cb313 100644
--- a/tests/certification/state/azure/cosmosdb/go.mod
+++ b/tests/certification/state/azure/cosmosdb/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211026011813-36b75e9ae272
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -20,7 +20,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.2 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
github.com/Azure/azure-storage-blob-go v0.10.0 // indirect
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
@@ -38,7 +38,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
@@ -97,6 +97,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -126,14 +127,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/state/azure/cosmosdb/go.sum b/tests/certification/state/azure/cosmosdb/go.sum
index bf35f7a7a..93efec478 100644
--- a/tests/certification/state/azure/cosmosdb/go.sum
+++ b/tests/certification/state/azure/cosmosdb/go.sum
@@ -51,8 +51,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4Sath
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.2 h1:yJegJqjhrMJ3Oe5s43jOTGL2AsE7pJyx+7Yqls/65tw=
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.2/go.mod h1:Fy3bbChFm4cZn6oIxYYqKB2FG3rBDxk3NZDLDJCHl+Q=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 h1:XUNQ4mw+zJmaA2KXzP9JlQiecy1SI+Eog7xVkPiqIbg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs=
github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE=
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd h1:b3wyxBl3vvr15tUAziPBPK354y+LSdfPCpex5oBttHo=
@@ -126,8 +126,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -149,8 +149,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -457,6 +457,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -609,7 +610,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -631,8 +632,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -828,8 +829,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/state/azure/tablestorage/go.mod b/tests/certification/state/azure/tablestorage/go.mod
index 66cb2d933..b2bae4cfb 100644
--- a/tests/certification/state/azure/tablestorage/go.mod
+++ b/tests/certification/state/azure/tablestorage/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211026011813-36b75e9ae272
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -19,7 +19,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.4 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/data/aztables v1.0.1 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
github.com/Azure/azure-storage-blob-go v0.10.0 // indirect
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
@@ -37,7 +37,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
@@ -96,6 +96,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -125,14 +126,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/state/azure/tablestorage/go.sum b/tests/certification/state/azure/tablestorage/go.sum
index cabac65c2..ab2103a54 100644
--- a/tests/certification/state/azure/tablestorage/go.sum
+++ b/tests/certification/state/azure/tablestorage/go.sum
@@ -49,8 +49,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4Sath
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
github.com/Azure/azure-sdk-for-go/sdk/data/aztables v1.0.1 h1:bFa9IcjvrCber6gGgDAUZ+I2bO8J7s8JxXmu9fhi2ss=
github.com/Azure/azure-sdk-for-go/sdk/data/aztables v1.0.1/go.mod h1:l3wvZkG9oW07GLBW5Cd0WwG5asOfJ8aqE8raUvNzLpk=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 h1:XUNQ4mw+zJmaA2KXzP9JlQiecy1SI+Eog7xVkPiqIbg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs=
github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE=
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd h1:b3wyxBl3vvr15tUAziPBPK354y+LSdfPCpex5oBttHo=
@@ -124,8 +124,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -147,8 +147,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -455,6 +455,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -607,7 +608,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -629,8 +630,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -826,8 +827,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/state/cassandra/go.mod b/tests/certification/state/cassandra/go.mod
index a9b61f811..4e7c21eaa 100644
--- a/tests/certification/state/cassandra/go.mod
+++ b/tests/certification/state/cassandra/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211026011813-36b75e9ae272
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -20,7 +20,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
@@ -77,6 +77,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -105,14 +106,14 @@ require (
go.opentelemetry.io/otel/trace v1.11.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/state/cassandra/go.sum b/tests/certification/state/cassandra/go.sum
index 8344f9bf3..4200def81 100644
--- a/tests/certification/state/cassandra/go.sum
+++ b/tests/certification/state/cassandra/go.sum
@@ -74,8 +74,8 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4Yn
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -97,8 +97,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -392,6 +392,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -537,7 +538,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -559,8 +560,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -754,8 +755,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/state/cockroachdb/README.md b/tests/certification/state/cockroachdb/README.md
new file mode 100644
index 000000000..41fc558a8
--- /dev/null
+++ b/tests/certification/state/cockroachdb/README.md
@@ -0,0 +1,42 @@
+# CockroachDB State Store Certification
+
+The purpose of this module is to provide tests that certify the CockroachDB State Store as a stable component.
+
+## Test plan
+
+## Connection Test
+* Verify the connection is established to CockroachDB.
+ * Create component spec.
+ * Run the component with docker-compose
+ * Run dapr application with component.
+ * Ensure that you have access to the queue and connection to the queue is established.
+
+## Basic Operations Test
+* Verify that cockroachDB can save, retrieve, and delete states
+ * Save basic state information with a specified key
+ * Perform a Get Operation with that same key and ensure the the data previously written is retrieved
+ * Delete the state item
+ * Perform another Get Operation and verify that the data retreived is a nil byte array
+
+
+## ETAG Test
+* Verify cockroachDB Etag behavior
+ * Save state without an etag and ensure default etag (value of 1) is created
+ * Save state with a new, previously unsused etag and ensure that no item is updated
+ * Get state with etag of 1 and verify that our first written data is retrieved
+ * Overwrite the initial data through a Set operation with an etag value of 1
+ * Run a Get Operation and verify that the previous Set operation was successful
+
+## Transactions Test
+* Verify that cockroachDB can handle multiple opperations in a single request
+ * Save basic state information with a specified key
+ * Perform a Get Operation with that same key and ensure the the data previously written is retrieved
+ * Run a suite of set and delete requests
+ * Run a Get Operation on the data that should've been deleted from the Delete operation in the multi command and verify that the data no longer exists
+ * Retrieve data written from set requests and verify the data was correctly written
+
+## Restart Test
+* Verify that cockroachDB can have state data persist after a restart
+ * Stop cockroachDB by calling a dockercompose stop command
+ * Start cockroachDB by calling a dockercompose start command
+ * Perform a Get Operation using a previously inserted key and verify that the data previously saved before the restart is returned
\ No newline at end of file
diff --git a/tests/certification/state/cockroachdb/cockroachdb_test.go b/tests/certification/state/cockroachdb/cockroachdb_test.go
new file mode 100644
index 000000000..fbb7cda18
--- /dev/null
+++ b/tests/certification/state/cockroachdb/cockroachdb_test.go
@@ -0,0 +1,271 @@
+/*
+Copyright 2021 The Dapr Authors
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package cockroachdb_test
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/dapr/components-contrib/state"
+ state_cockroach "github.com/dapr/components-contrib/state/cockroachdb"
+ "github.com/dapr/components-contrib/tests/certification/embedded"
+ "github.com/dapr/components-contrib/tests/certification/flow"
+ "github.com/dapr/components-contrib/tests/certification/flow/dockercompose"
+ "github.com/dapr/components-contrib/tests/certification/flow/sidecar"
+ state_loader "github.com/dapr/dapr/pkg/components/state"
+ "github.com/dapr/dapr/pkg/runtime"
+ dapr_testing "github.com/dapr/dapr/pkg/testing"
+ goclient "github.com/dapr/go-sdk/client"
+ "github.com/dapr/kit/logger"
+ "github.com/google/uuid"
+ "github.com/stretchr/testify/assert"
+)
+
+const (
+ sidecarNamePrefix = "cockroach-sidecar-"
+ dockerComposeYAML = "docker-compose.yml"
+ stateStoreName = "statestore"
+ certificationTestPrefix = "stable-certification-"
+ stateStoreNoConfigError = "error saving state: rpc error: code = FailedPrecondition desc = state store is not configured"
+)
+
+func TestCockroach(t *testing.T) {
+ log := logger.NewLogger("dapr.components")
+
+ stateStore := state_cockroach.New(log).(*state_cockroach.CockroachDB)
+ ports, err := dapr_testing.GetFreePorts(3)
+ assert.NoError(t, err)
+
+ stateRegistry := state_loader.NewRegistry()
+ stateRegistry.Logger = log
+ stateRegistry.RegisterComponent(func(l logger.Logger) state.Store {
+ return stateStore
+ }, "cockroachdb")
+
+ currentGrpcPort := ports[0]
+ currentHTTPPort := ports[1]
+
+ // Generate a unique value for the key being inserted to ensure no conflicts occur
+ keyOne := uuid.New()
+ keyOneString := strings.Replace(keyOne.String(), "-", "", -1)
+
+ basicTest := func(ctx flow.Context) error {
+ client, err := goclient.NewClientWithPort(fmt.Sprint(currentGrpcPort))
+ if err != nil {
+ panic(err)
+ }
+ defer client.Close()
+
+ err = stateStore.Ping()
+ assert.Equal(t, nil, err)
+
+ err = client.SaveState(ctx, stateStoreName, certificationTestPrefix+"key1", []byte("certificationdata"), nil)
+ assert.NoError(t, err)
+
+ // get state
+ item, err := client.GetState(ctx, stateStoreName, certificationTestPrefix+"key1", nil)
+ assert.NoError(t, err)
+ assert.Equal(t, "certificationdata", string(item.Value))
+
+ errUpdate := client.SaveState(ctx, stateStoreName, certificationTestPrefix+"key1", []byte("cockroachCertUpdate"), nil)
+ assert.NoError(t, errUpdate)
+ item, errUpdatedGet := client.GetState(ctx, stateStoreName, certificationTestPrefix+"key1", nil)
+ assert.NoError(t, errUpdatedGet)
+ assert.Equal(t, "cockroachCertUpdate", string(item.Value))
+
+ // delete state
+ err = client.DeleteState(ctx, stateStoreName, certificationTestPrefix+"key1", nil)
+ assert.NoError(t, err)
+
+ // get state
+ item, errUpdatedGet = client.GetState(ctx, stateStoreName, certificationTestPrefix+"key1", nil)
+ assert.NoError(t, errUpdatedGet)
+ assert.Equal(t, []byte(nil), item.Value)
+ return nil
+ }
+
+ // Check if TCP port is actually open
+ testGetAfterCockroachdbRestart := func(ctx flow.Context) error {
+ client, err := goclient.NewClientWithPort(fmt.Sprint(currentGrpcPort))
+ if err != nil {
+ panic(err)
+ }
+ defer client.Close()
+
+ err = stateStore.Ping()
+ assert.Equal(t, nil, err)
+
+ resp, err := stateStore.Get(&state.GetRequest{
+ Key: keyOneString,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, "2", *resp.ETag) // 2 is returned since the previous etag value of "1" was incremented by 1 when the update occurred
+ assert.Equal(t, "\"Overwrite Success\"", string(resp.Data))
+
+ return nil
+ }
+
+ //ETag test
+ eTagTest := func(ctx flow.Context) error {
+ etag1 := "1"
+ etag100 := "100"
+
+ // Setting with nil etag will insert an item with an etag value of 1 unless there is a conflict
+ err := stateStore.Set(&state.SetRequest{
+ Key: keyOneString,
+ Value: "v1",
+ })
+ assert.NoError(t, err)
+
+ // Setting with an etag wil do an update, not an insert so an error is expected since the etag of 100 is not present
+ err = stateStore.Set(&state.SetRequest{
+ Key: keyOneString,
+ Value: "v3",
+ ETag: &etag100,
+ })
+ assert.Equal(t, fmt.Errorf("no item was updated"), err)
+
+ resp, err := stateStore.Get(&state.GetRequest{
+ Key: keyOneString,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, etag1, *resp.ETag) //1 is returned since the default when the new data is written is a value of 1
+ assert.Equal(t, "\"v1\"", string(resp.Data)) //v1 is returned since it was the only item successfully inserted with the key of keyOneString
+
+ // This will update the value stored in key K with "Overwrite Success" since the previously created etag has a value of 1
+ // It will also increment the etag stored by a value of 1
+ err = stateStore.Set(&state.SetRequest{
+ Key: keyOneString,
+ Value: "Overwrite Success",
+ ETag: &etag1,
+ })
+ assert.NoError(t, err)
+
+ resp, err = stateStore.Get(&state.GetRequest{
+ Key: keyOneString,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, "2", *resp.ETag) //2 is returned since the previous etag value of "1" was incremented by 1 when the update occurred
+ assert.Equal(t, "\"Overwrite Success\"", string(resp.Data))
+
+ return nil
+ }
+
+ // Transaction related test - also for Multi
+ transactionsTest := func(ctx flow.Context) error {
+
+ // Set state to allow for a delete operation inside the multi list
+ err = stateStore.Set(&state.SetRequest{Key: certificationTestPrefix + "key1", Value: []byte("certificationdata")})
+ assert.NoError(t, err)
+
+ // get state
+ item, errUpdatedGet := stateStore.Get(&state.GetRequest{Key: certificationTestPrefix + "key1"})
+ assert.NoError(t, errUpdatedGet)
+ assert.Equal(t, []byte("certificationdata"), item.Data)
+
+ err = stateStore.Multi(&state.TransactionalStateRequest{
+ Operations: []state.TransactionalStateOperation{
+ {
+ Operation: state.Upsert,
+ Request: state.SetRequest{
+ Key: "reqKey1",
+ Value: "reqVal1",
+ Metadata: map[string]string{},
+ },
+ },
+ {
+ Operation: state.Upsert,
+ Request: state.SetRequest{
+ Key: "reqKey2",
+ Value: "reqVal2",
+ Metadata: map[string]string{},
+ },
+ },
+ {
+ Operation: state.Upsert,
+ Request: state.SetRequest{
+ Key: "reqKey3",
+ Value: "reqVal3",
+ },
+ },
+ {
+ Operation: state.Upsert,
+ Request: state.SetRequest{
+ Key: "reqKey1",
+ Value: "reqVal101",
+ Metadata: map[string]string{},
+ },
+ },
+ {
+ Operation: state.Upsert,
+ Request: state.SetRequest{
+ Key: "reqKey3",
+ Value: "reqVal103",
+ Metadata: map[string]string{},
+ },
+ },
+ {
+ Operation: state.Delete,
+ Request: state.DeleteRequest{
+ Key: certificationTestPrefix + "key1",
+ Metadata: map[string]string{},
+ },
+ },
+ },
+ })
+ assert.Equal(t, nil, err)
+
+ // get state
+ item, errUpdatedGet = stateStore.Get(&state.GetRequest{Key: certificationTestPrefix + "key1"})
+ assert.NoError(t, errUpdatedGet)
+ assert.Equal(t, []byte(nil), item.Data)
+
+ resp1, err := stateStore.Get(&state.GetRequest{
+ Key: "reqKey1",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, "2", *resp1.ETag)
+ assert.Equal(t, "\"reqVal101\"", string(resp1.Data))
+
+ resp3, err := stateStore.Get(&state.GetRequest{
+ Key: "reqKey3",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, "2", *resp3.ETag)
+ assert.Equal(t, "\"reqVal103\"", string(resp3.Data))
+ return nil
+ }
+
+ flow.New(t, "Connecting cockroachdb And Verifying majority of the tests here").
+ Step(dockercompose.Run("cockroachdb", dockerComposeYAML)).
+ Step("Waiting for cockroachdb readiness", flow.Sleep(30*time.Second)).
+ Step(sidecar.Run(sidecarNamePrefix+"dockerDefault",
+ embedded.WithoutApp(),
+ embedded.WithDaprGRPCPort(currentGrpcPort),
+ embedded.WithDaprHTTPPort(currentHTTPPort),
+ embedded.WithComponentsPath("components/standard"),
+ runtime.WithStates(stateRegistry),
+ )).
+ Step("Run basic test", basicTest).
+ Step("Run eTag test", eTagTest).
+ Step("Run transactions test", transactionsTest).
+ Step("Stop cockroachdb server", dockercompose.Stop("cockroachdb", dockerComposeYAML, "cockroachdb")).
+ Step("Sleep after dockercompose stop", flow.Sleep(10*time.Second)).
+ Step("Start cockroachdb server", dockercompose.Start("cockroachdb", dockerComposeYAML, "cockroachdb")).
+ Step("wait for component to start", flow.Sleep(10*time.Second)).
+ Step("Get Values Saved Earlier And Not Expired, after cockroachdb restart", testGetAfterCockroachdbRestart).
+ Run()
+}
diff --git a/tests/certification/state/cockroachdb/components/standard/cockroachdb.yaml b/tests/certification/state/cockroachdb/components/standard/cockroachdb.yaml
new file mode 100644
index 000000000..a1087752e
--- /dev/null
+++ b/tests/certification/state/cockroachdb/components/standard/cockroachdb.yaml
@@ -0,0 +1,17 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: statestore
+spec:
+ type: state.cockroachdb
+ metadata:
+ - name: cockroachdbHost
+ value: localhost:26257
+ - name: cockroachdbPassword
+ value: ""
+ - name: initTimeout
+ value: 5m
+ - name: timeout
+ value: 20s
+ - name: connectionString
+ value: "host=localhost user=root port=26257 connect_timeout=10 database=dapr_test"
\ No newline at end of file
diff --git a/tests/certification/state/cockroachdb/config.yaml b/tests/certification/state/cockroachdb/config.yaml
new file mode 100644
index 000000000..6c95e632f
--- /dev/null
+++ b/tests/certification/state/cockroachdb/config.yaml
@@ -0,0 +1,6 @@
+apiVersion: dapr.io/v1alpha1
+kind: Configuration
+metadata:
+ name: keyvaultconfig
+spec:
+ features:
diff --git a/tests/certification/state/cockroachdb/docker-compose.yml b/tests/certification/state/cockroachdb/docker-compose.yml
new file mode 100644
index 000000000..b8f3a7d27
--- /dev/null
+++ b/tests/certification/state/cockroachdb/docker-compose.yml
@@ -0,0 +1,21 @@
+version: '3.5'
+services:
+ cockroachdb:
+ image: cockroachdb/cockroach:v21.2.3
+ hostname: cockroachdb
+ command: start-single-node --cluster-name=single-node --logtostderr=WARNING --log-file-verbosity=WARNING --insecure
+ restart: always
+ security_opt:
+ - no-new-privileges
+ ports:
+ - "26257:26257"
+
+ cockroachdb-init:
+ hostname: cockroachdb-init
+ image: timveil/cockroachdb-remote-client:latest
+ environment:
+ - COCKROACH_HOST=cockroachdb:26257
+ - COCKROACH_INSECURE=true
+ - DATABASE_NAME=dapr_test
+ depends_on:
+ - cockroachdb
diff --git a/tests/certification/state/cockroachdb/go.mod b/tests/certification/state/cockroachdb/go.mod
new file mode 100644
index 000000000..61433b097
--- /dev/null
+++ b/tests/certification/state/cockroachdb/go.mod
@@ -0,0 +1,145 @@
+module github.com/dapr/components-contrib/tests/certification/state/cockroachdb
+
+go 1.19
+
+require (
+ github.com/dapr/components-contrib v1.9.1
+ github.com/dapr/components-contrib/tests/certification v0.0.0-20221111215803-c92827c3defc
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
+ github.com/dapr/go-sdk v1.6.0
+ github.com/dapr/kit v0.0.3
+ github.com/google/uuid v1.3.0
+ github.com/stretchr/testify v1.8.1
+)
+
+require (
+ contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect
+ github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
+ github.com/PuerkitoBio/purell v1.2.0 // indirect
+ github.com/andybalholm/brotli v1.0.4 // indirect
+ github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed // indirect
+ github.com/armon/go-metrics v0.4.1 // indirect
+ github.com/beorn7/perks v1.0.1 // indirect
+ github.com/cenkalti/backoff v2.2.1+incompatible // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
+ github.com/cespare/xxhash/v2 v2.1.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/emicklei/go-restful/v3 v3.8.0 // indirect
+ github.com/evanphx/json-patch/v5 v5.6.0 // indirect
+ github.com/fasthttp/router v1.4.12 // indirect
+ github.com/fatih/color v1.13.0 // indirect
+ github.com/fsnotify/fsnotify v1.6.0 // indirect
+ github.com/ghodss/yaml v1.0.0 // indirect
+ github.com/go-kit/log v0.2.1 // indirect
+ github.com/go-logfmt/logfmt v0.5.1 // indirect
+ github.com/go-logr/logr v1.2.3 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
+ github.com/go-openapi/jsonpointer v0.19.5 // indirect
+ github.com/go-openapi/jsonreference v0.19.5 // indirect
+ github.com/go-openapi/swag v0.19.14 // indirect
+ github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+ github.com/golang/mock v1.6.0 // indirect
+ github.com/golang/protobuf v1.5.2 // indirect
+ github.com/google/cel-go v0.12.5 // indirect
+ github.com/google/gnostic v0.5.7-v3refs // indirect
+ github.com/google/go-cmp v0.5.9 // indirect
+ github.com/google/gofuzz v1.2.0 // indirect
+ github.com/grandcat/zeroconf v1.0.0 // indirect
+ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
+ github.com/hashicorp/consul/api v1.13.0 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+ github.com/hashicorp/go-hclog v1.3.1 // indirect
+ github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/hashicorp/go-rootcerts v1.0.2 // indirect
+ github.com/hashicorp/golang-lru v0.5.4 // indirect
+ github.com/hashicorp/serf v0.9.7 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jackc/pgpassfile v1.0.0 // indirect
+ github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
+ github.com/jackc/pgx/v5 v5.0.4 // indirect
+ github.com/jhump/protoreflect v1.13.0 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
+ github.com/json-iterator/go v1.1.12 // indirect
+ github.com/klauspost/compress v1.15.11 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.16 // indirect
+ github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
+ github.com/miekg/dns v1.1.50 // indirect
+ github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
+ github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+ github.com/modern-go/reflect2 v1.0.2 // indirect
+ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/prometheus/client_golang v1.13.0 // indirect
+ github.com/prometheus/client_model v0.3.0 // indirect
+ github.com/prometheus/common v0.37.0 // indirect
+ github.com/prometheus/procfs v0.8.0 // indirect
+ github.com/prometheus/statsd_exporter v0.22.7 // indirect
+ github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d // indirect
+ github.com/sirupsen/logrus v1.9.0 // indirect
+ github.com/sony/gobreaker v0.5.0 // indirect
+ github.com/spf13/pflag v1.0.5 // indirect
+ github.com/stoewer/go-strcase v1.2.0 // indirect
+ github.com/stretchr/objx v0.5.0 // indirect
+ github.com/tidwall/transform v0.0.0-20201103190739-32f242e2dbde // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.41.0 // indirect
+ go.opencensus.io v0.23.0 // indirect
+ go.opentelemetry.io/otel v1.11.1 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1 // indirect
+ go.opentelemetry.io/otel/exporters/zipkin v1.11.1 // indirect
+ go.opentelemetry.io/otel/sdk v1.11.1 // indirect
+ go.opentelemetry.io/otel/trace v1.11.1 // indirect
+ go.opentelemetry.io/proto/otlp v0.19.0 // indirect
+ go.uber.org/atomic v1.10.0 // indirect
+ golang.org/x/crypto v0.1.0 // indirect
+ golang.org/x/mod v0.6.0 // indirect
+ golang.org/x/net v0.1.0 // indirect
+ golang.org/x/oauth2 v0.1.0 // indirect
+ golang.org/x/sys v0.1.0 // indirect
+ golang.org/x/term v0.1.0 // indirect
+ golang.org/x/text v0.4.0 // indirect
+ golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
+ golang.org/x/tools v0.2.0 // indirect
+ gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
+ google.golang.org/appengine v1.6.7 // indirect
+ google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
+ google.golang.org/grpc v1.50.1 // indirect
+ google.golang.org/protobuf v1.28.1 // indirect
+ gopkg.in/inf.v0 v0.9.1 // indirect
+ gopkg.in/yaml.v2 v2.4.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+ k8s.io/api v0.25.3 // indirect
+ k8s.io/apiextensions-apiserver v0.25.3 // indirect
+ k8s.io/apimachinery v0.25.3 // indirect
+ k8s.io/client-go v0.25.3 // indirect
+ k8s.io/component-base v0.25.3 // indirect
+ k8s.io/klog/v2 v2.80.1 // indirect
+ k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
+ k8s.io/utils v0.0.0-20221012122500-cfd413dd9e85 // indirect
+ sigs.k8s.io/controller-runtime v0.13.0 // indirect
+ sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
+ sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
+ sigs.k8s.io/yaml v1.3.0 // indirect
+)
+
+replace github.com/dapr/components-contrib/tests/certification => ../../
+
+// replace github.com/dapr/dapr => github.com/berndverst/dapr v1.1.3-0.20221105062638-159383e4fac0
+
+replace github.com/dapr/components-contrib => ../../../../
+
+replace github.com/dapr/dapr => github.com/1046102779/dapr v0.0.0-20221021130037-635b70c24259
diff --git a/tests/certification/state/cockroachdb/go.sum b/tests/certification/state/cockroachdb/go.sum
new file mode 100644
index 000000000..f6c4f9a9c
--- /dev/null
+++ b/tests/certification/state/cockroachdb/go.sum
@@ -0,0 +1,914 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
+cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
+cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
+cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
+cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
+cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
+cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
+cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg=
+contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/1046102779/dapr v0.0.0-20221021130037-635b70c24259 h1:r3xaidxNIHmRnLrHmgdug8kPunYA8V3OrObr+KbyNOw=
+github.com/1046102779/dapr v0.0.0-20221021130037-635b70c24259/go.mod h1:WBbYLjYoq/kPzdTODWM1mR3IOfxE3+8bw8O3XQiJfio=
+github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a h1:XVdatQFSP2YhJGjqLLIfW8QBk4loz/SCe/PxkXDiW+s=
+github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a/go.mod h1:C0A1KeiVHs+trY6gUTPhhGammbrZ30ZfXRW/nuT7HLw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
+github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
+github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/purell v1.2.0 h1:/Jdm5QfyM8zdlqT6WVZU4cfP23sot6CEHA4CS49Ezig=
+github.com/PuerkitoBio/purell v1.2.0/go.mod h1:OhLRTaaIzhvIyofkJfB24gokC7tM42Px5UhoT32THBk=
+github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
+github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b h1:WMhlIaJkDgEQSVJQM06YV+cYUl1r5OY5//ijMXJNqtA=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
+github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
+github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
+github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed h1:ue9pVfIcP+QMEjfgo/Ez4ZjNZfonGgR6NgjMaJMu1Cg=
+github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
+github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
+github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
+github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
+github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
+github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
+github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
+github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
+github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
+github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/dapr/go-sdk v1.6.0 h1:jg5A2khSCHF8bGZsig5RWN/gD0jjitszc2V6Uq2pPdY=
+github.com/dapr/go-sdk v1.6.0/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
+github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw=
+github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
+github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
+github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
+github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
+github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
+github.com/fasthttp/router v1.4.12 h1:QEgK+UKARaC1bAzJgnIhdUMay6nwp+YFq6VGPlyKN1o=
+github.com/fasthttp/router v1.4.12/go.mod h1:41Qdc4Z4T2pWVVtATHCnoUnOtxdBoeKEYJTXhHwbxCQ=
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
+github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
+github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
+github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
+github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
+github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
+github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
+github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
+github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
+github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
+github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A=
+github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
+github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
+github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
+github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
+github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
+github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
+github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
+github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
+github.com/google/cel-go v0.12.5 h1:DmzaiSgoaqGCjtpPQWl26/gND+yRpim56H1jCVev6d8=
+github.com/google/cel-go v0.12.5/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw=
+github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
+github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
+github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+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/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE=
+github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs=
+github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
+github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
+github.com/hashicorp/consul/api v1.13.0 h1:2hnLQ0GjQvw7f3O61jMO8gbasZviZTrt9R8WzgiirHc=
+github.com/hashicorp/consul/api v1.13.0/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ=
+github.com/hashicorp/consul/sdk v0.8.0 h1:OJtKBtEjboEZvG6AOUdh4Z1Zbyu0WcxQ0qatRrZHTVU=
+github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
+github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
+github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
+github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo=
+github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
+github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
+github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs=
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
+github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
+github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
+github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
+github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
+github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs=
+github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
+github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
+github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
+github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
+github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
+github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA=
+github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
+github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
+github.com/hashicorp/serf v0.9.7 h1:hkdgbqizGQHuU5IPqYM1JdSMV8nKfpuOnZYXssk9muY=
+github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
+github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
+github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
+github.com/jackc/pgx/v5 v5.0.4 h1:r5O6y84qHX/z/HZV40JBdx2obsHz7/uRj5b+CcYEdeY=
+github.com/jackc/pgx/v5 v5.0.4/go.mod h1:U0ynklHtgg43fue9Ly30w3OCSTDPlXjig9ghrNGaguQ=
+github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
+github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI=
+github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI=
+github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ=
+github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E=
+github.com/jhump/protoreflect v1.13.0 h1:zrrZqa7JAc2YGgPSzZZkmUXJ5G6NRPdxOg/9t7ISImA=
+github.com/jhump/protoreflect v1.13.0/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
+github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
+github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
+github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
+github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
+github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
+github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
+github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
+github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
+github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
+github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
+github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
+github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
+github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
+github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
+github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU=
+github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
+github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/openzipkin/zipkin-go v0.4.1 h1:kNd/ST2yLLWhaWrkgchya40TJabe8Hioj9udfPcEO5A=
+github.com/openzipkin/zipkin-go v0.4.1/go.mod h1:qY0VqDSN1pOBN94dBc6w2GJlWLiovAyg7Qt6/I9HecM=
+github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
+github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
+github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
+github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
+github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
+github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
+github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU=
+github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
+github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
+github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
+github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
+github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
+github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
+github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
+github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
+github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
+github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
+github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
+github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0=
+github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
+github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d h1:Q+gqLBOPkFGHyCJxXMRqtUgUbTjI8/Ze8vu8GGyNFwo=
+github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
+github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg=
+github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+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/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
+github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/tidwall/transform v0.0.0-20201103190739-32f242e2dbde h1:AMNpJRc7P+GTwVbl8DkK2I9I8BBUzNiHuH/tlxrpan0=
+github.com/tidwall/transform v0.0.0-20201103190739-32f242e2dbde/go.mod h1:MvrEmduDUz4ST5pGZ7CABCnOU5f3ZiOAZzT6b1A6nX8=
+github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
+github.com/valyala/fasthttp v1.41.0 h1:zeR0Z1my1wDHTRiamBCXVglQdbUwgb9uWG3k1HQz6jY=
+github.com/valyala/fasthttp v1.41.0/go.mod h1:f6VbjjoI3z1NDOZOv17o6RvtRSWxC77seBFc2uWtgiY=
+github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
+github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
+go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
+go.opentelemetry.io/otel v1.11.1 h1:4WLLAmcfkmDk2ukNXJyq3/kiz/3UzCaYq6PskJsaou4=
+go.opentelemetry.io/otel v1.11.1/go.mod h1:1nNhXBbWSD0nsL38H6btgnFN2k4i0sNLHNNMZMSbUGE=
+go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 h1:X2GndnMCsUPh6CiY2a+frAbNsXaPLbB0soHRYhAZ5Ig=
+go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1/go.mod h1:i8vjiSzbiUC7wOQplijSXMYUpNM93DtlS5CbUT+C6oQ=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1 h1:MEQNafcNCB0uQIti/oHgU7CZpUMYQ7qigBwMVKycHvc=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1/go.mod h1:19O5I2U5iys38SsmT2uDJja/300woyzE1KPIQxEUBUc=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1 h1:LYyG/f1W/jzAix16jbksJfMQFpOH/Ma6T639pVPMgfI=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1/go.mod h1:QrRRQiY3kzAoYPNLP0W/Ikg0gR6V3LMc+ODSxr7yyvg=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1 h1:tFl63cpAAcD9TOU6U8kZU7KyXuSRYAZlbx1C61aaB74=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1/go.mod h1:X620Jww3RajCJXw/unA+8IRTgxkdS7pi+ZwK9b7KUJk=
+go.opentelemetry.io/otel/exporters/zipkin v1.11.1 h1:JlJ3/oQoyqlrPDCfsSVFcHgGeHvZq+hr1VPWtiYCXTo=
+go.opentelemetry.io/otel/exporters/zipkin v1.11.1/go.mod h1:T4S6aVwIS1+MHA+dJHCcPROtZe6ORwnv5vMKPRapsFw=
+go.opentelemetry.io/otel/sdk v1.11.1 h1:F7KmQgoHljhUuJyA+9BiU+EkJfyX5nVVF4wyzWZpKxs=
+go.opentelemetry.io/otel/sdk v1.11.1/go.mod h1:/l3FE4SupHJ12TduVjUkZtlfFqDCQJlOlithYrdktys=
+go.opentelemetry.io/otel/trace v1.11.1 h1:ofxdnzsNrGBYXbP7t7zpUK281+go5rF7dvdIZXF8gdQ=
+go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk=
+go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
+go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw=
+go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
+go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
+go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
+golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
+golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
+golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
+golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
+golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y=
+golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
+golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
+golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y=
+golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY=
+gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
+google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
+google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c h1:QgY/XxIAIeccR+Ca/rDdKubLIU9rcJ3xfy1DC/Wd2Oo=
+google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
+google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
+google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
+google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+k8s.io/api v0.25.3 h1:Q1v5UFfYe87vi5H7NU0p4RXC26PPMT8KOpr1TLQbCMQ=
+k8s.io/api v0.25.3/go.mod h1:o42gKscFrEVjHdQnyRenACrMtbuJsVdP+WVjqejfzmI=
+k8s.io/apiextensions-apiserver v0.25.3 h1:bfI4KS31w2f9WM1KLGwnwuVlW3RSRPuIsfNF/3HzR0k=
+k8s.io/apiextensions-apiserver v0.25.3/go.mod h1:ZJqwpCkxIx9itilmZek7JgfUAM0dnTsA48I4krPqRmo=
+k8s.io/apimachinery v0.25.3 h1:7o9ium4uyUOM76t6aunP0nZuex7gDf8VGwkR5RcJnQc=
+k8s.io/apimachinery v0.25.3/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo=
+k8s.io/client-go v0.25.3 h1:oB4Dyl8d6UbfDHD8Bv8evKylzs3BXzzufLiO27xuPs0=
+k8s.io/client-go v0.25.3/go.mod h1:t39LPczAIMwycjcXkVc+CB+PZV69jQuNx4um5ORDjQA=
+k8s.io/component-base v0.25.3 h1:UrsxciGdrCY03ULT1h/S/gXFCOPnLhUVwSyx+hM/zq4=
+k8s.io/component-base v0.25.3/go.mod h1:WYoS8L+IlTZgU7rhAl5Ctpw0WdMxDfCC5dkxcEFa/TI=
+k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
+k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
+k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=
+k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=
+k8s.io/utils v0.0.0-20221012122500-cfd413dd9e85 h1:cTdVh7LYu82xeClmfzGtgyspNh6UxpwLWGi8R4sspNo=
+k8s.io/utils v0.0.0-20221012122500-cfd413dd9e85/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ=
+sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI=
+sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
+sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
+sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
+sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
+sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
+sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
diff --git a/tests/certification/state/memcached/go.mod b/tests/certification/state/memcached/go.mod
index 25239b978..170018fb7 100644
--- a/tests/certification/state/memcached/go.mod
+++ b/tests/certification/state/memcached/go.mod
@@ -5,9 +5,9 @@ go 1.18
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20220526162429-d03aeba3e0d6
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -21,7 +21,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20221031212613-62deef7fc822 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
@@ -75,6 +75,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -103,14 +104,14 @@ require (
go.opentelemetry.io/otel/trace v1.11.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/state/memcached/go.sum b/tests/certification/state/memcached/go.sum
index c6ca77277..645b5031f 100644
--- a/tests/certification/state/memcached/go.sum
+++ b/tests/certification/state/memcached/go.sum
@@ -72,8 +72,8 @@ github.com/bradfitz/gomemcache v0.0.0-20221031212613-62deef7fc822 h1:hjXJeBcAMS1
github.com/bradfitz/gomemcache v0.0.0-20221031212613-62deef7fc822/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -95,8 +95,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -382,6 +382,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -527,7 +528,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -549,8 +550,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -744,8 +745,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/state/mongodb/go.mod b/tests/certification/state/mongodb/go.mod
index 2d3d2e132..075f40659 100644
--- a/tests/certification/state/mongodb/go.mod
+++ b/tests/certification/state/mongodb/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20220526162429-d03aeba3e0d6
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -15,13 +15,12 @@ require (
contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
github.com/PuerkitoBio/purell v1.2.0 // indirect
- github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
@@ -77,6 +76,7 @@ require (
github.com/montanaflynn/stats v0.6.6 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -111,7 +111,7 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sync v0.1.0 // indirect
@@ -119,7 +119,7 @@ require (
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/state/mongodb/go.sum b/tests/certification/state/mongodb/go.sum
index a6186f562..c04917097 100644
--- a/tests/certification/state/mongodb/go.sum
+++ b/tests/certification/state/mongodb/go.sum
@@ -46,7 +46,6 @@ github.com/PuerkitoBio/purell v1.2.0 h1:/Jdm5QfyM8zdlqT6WVZU4cfP23sot6CEHA4CS49E
github.com/PuerkitoBio/purell v1.2.0/go.mod h1:OhLRTaaIzhvIyofkJfB24gokC7tM42Px5UhoT32THBk=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b h1:WMhlIaJkDgEQSVJQM06YV+cYUl1r5OY5//ijMXJNqtA=
-github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b/go.mod h1:Tie46d3UWzXpj+Fh9+DQTyaUxEpFBPOLXrnx7nxlKRo=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -71,8 +70,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -94,8 +93,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -389,6 +388,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -549,7 +549,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -571,8 +571,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -767,8 +767,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/state/mysql/go.mod b/tests/certification/state/mysql/go.mod
index 6bd75cb71..802980d17 100644
--- a/tests/certification/state/mysql/go.mod
+++ b/tests/certification/state/mysql/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20220526162429-d03aeba3e0d6
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -20,7 +20,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
@@ -75,6 +75,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -102,16 +103,14 @@ require (
go.opentelemetry.io/otel/trace v1.11.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
- golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
- golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
@@ -136,4 +135,6 @@ require (
replace github.com/dapr/components-contrib/tests/certification => ../../
+replace github.com/dapr/dapr => github.com/1046102779/dapr v0.0.0-20221021130037-635b70c24259
+
replace github.com/dapr/components-contrib => ../../../../
diff --git a/tests/certification/state/mysql/go.sum b/tests/certification/state/mysql/go.sum
index 52ef44dc2..402e2858f 100644
--- a/tests/certification/state/mysql/go.sum
+++ b/tests/certification/state/mysql/go.sum
@@ -33,6 +33,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg=
contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/1046102779/dapr v0.0.0-20221021130037-635b70c24259 h1:r3xaidxNIHmRnLrHmgdug8kPunYA8V3OrObr+KbyNOw=
+github.com/1046102779/dapr v0.0.0-20221021130037-635b70c24259/go.mod h1:WBbYLjYoq/kPzdTODWM1mR3IOfxE3+8bw8O3XQiJfio=
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a h1:XVdatQFSP2YhJGjqLLIfW8QBk4loz/SCe/PxkXDiW+s=
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a/go.mod h1:C0A1KeiVHs+trY6gUTPhhGammbrZ30ZfXRW/nuT7HLw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -69,8 +71,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -90,12 +92,10 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e h1:Ieid1nWDFssDXrXIdRakN/jAcHMA1x3Rq0joFXGaMM0=
-github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e/go.mod h1:mGNQLZnlzH8HX7GcQv3u4YNE432gs1CYC8NLbOf65SE=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -383,6 +383,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -526,8 +527,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -549,8 +549,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -617,7 +617,6 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -745,8 +744,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/state/postgresql/go.mod b/tests/certification/state/postgresql/go.mod
index d21b174ed..5c5c7fe95 100644
--- a/tests/certification/state/postgresql/go.mod
+++ b/tests/certification/state/postgresql/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20220526162429-d03aeba3e0d6
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -15,13 +15,12 @@ require (
contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
github.com/PuerkitoBio/purell v1.2.0 // indirect
- github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
@@ -78,6 +77,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -106,14 +106,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/state/postgresql/go.sum b/tests/certification/state/postgresql/go.sum
index d6d5565ab..0a70364d0 100644
--- a/tests/certification/state/postgresql/go.sum
+++ b/tests/certification/state/postgresql/go.sum
@@ -47,7 +47,6 @@ github.com/PuerkitoBio/purell v1.2.0 h1:/Jdm5QfyM8zdlqT6WVZU4cfP23sot6CEHA4CS49E
github.com/PuerkitoBio/purell v1.2.0/go.mod h1:OhLRTaaIzhvIyofkJfB24gokC7tM42Px5UhoT32THBk=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b h1:WMhlIaJkDgEQSVJQM06YV+cYUl1r5OY5//ijMXJNqtA=
-github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b/go.mod h1:Tie46d3UWzXpj+Fh9+DQTyaUxEpFBPOLXrnx7nxlKRo=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -72,8 +71,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -95,8 +94,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -388,6 +387,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -534,7 +534,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -556,8 +556,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -751,8 +751,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/state/postgresql/postgresql_test.go b/tests/certification/state/postgresql/postgresql_test.go
index 28020d30e..a9bc80c2d 100644
--- a/tests/certification/state/postgresql/postgresql_test.go
+++ b/tests/certification/state/postgresql/postgresql_test.go
@@ -184,7 +184,8 @@ func TestPostgreSQL(t *testing.T) {
},
},
})
- assert.Equal(t, nil, err)
+ require.NoError(t, err)
+
resp1, err := stateStore.Get(context.Background(), &state.GetRequest{
Key: "reqKey1",
})
@@ -206,7 +207,7 @@ func TestPostgreSQL(t *testing.T) {
// save state
_, err = client.GetState(ctx, stateStoreName, certificationTestPrefix+"key1", nil)
- assert.NoError(t, err)
+ require.NoError(t, err)
return nil
}
diff --git a/tests/certification/state/redis/go.mod b/tests/certification/state/redis/go.mod
index 187bc34e2..986f865c6 100644
--- a/tests/certification/state/redis/go.mod
+++ b/tests/certification/state/redis/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20220526162429-d03aeba3e0d6
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -17,13 +17,12 @@ require (
contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
github.com/PuerkitoBio/purell v1.2.0 // indirect
- github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
@@ -78,6 +77,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -106,14 +106,14 @@ require (
go.opentelemetry.io/otel/trace v1.11.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/state/redis/go.sum b/tests/certification/state/redis/go.sum
index 5aa21b312..93cf9a7b6 100644
--- a/tests/certification/state/redis/go.sum
+++ b/tests/certification/state/redis/go.sum
@@ -46,7 +46,6 @@ github.com/PuerkitoBio/purell v1.2.0 h1:/Jdm5QfyM8zdlqT6WVZU4cfP23sot6CEHA4CS49E
github.com/PuerkitoBio/purell v1.2.0/go.mod h1:OhLRTaaIzhvIyofkJfB24gokC7tM42Px5UhoT32THBk=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b h1:WMhlIaJkDgEQSVJQM06YV+cYUl1r5OY5//ijMXJNqtA=
-github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b/go.mod h1:Tie46d3UWzXpj+Fh9+DQTyaUxEpFBPOLXrnx7nxlKRo=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -73,8 +72,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -96,8 +95,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -387,6 +386,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -533,7 +533,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -555,8 +555,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -750,8 +750,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/certification/state/sqlserver/go.mod b/tests/certification/state/sqlserver/go.mod
index d06d917b9..439dbbac9 100644
--- a/tests/certification/state/sqlserver/go.mod
+++ b/tests/certification/state/sqlserver/go.mod
@@ -5,9 +5,9 @@ go 1.19
require (
github.com/dapr/components-contrib v1.9.1-0.20221025205611-e38369028650
github.com/dapr/components-contrib/tests/certification v0.0.0-20211130185200-4918900c09e1
- github.com/dapr/dapr v1.9.1-0.20221101183153-7e3635f1491e
+ github.com/dapr/dapr v1.9.4-0.20221121055721-6683f7582ac4
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721
- github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5
+ github.com/dapr/kit v0.0.3
github.com/stretchr/testify v1.8.1
)
@@ -15,13 +15,12 @@ require (
contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
github.com/PuerkitoBio/purell v1.2.0 // indirect
- github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/denisenkom/go-mssqldb v0.12.3 // indirect
@@ -78,6 +77,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
+ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
@@ -107,14 +107,14 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
- golang.org/x/tools v0.1.12 // indirect
+ golang.org/x/tools v0.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
diff --git a/tests/certification/state/sqlserver/go.sum b/tests/certification/state/sqlserver/go.sum
index 14ca74987..5908c7714 100644
--- a/tests/certification/state/sqlserver/go.sum
+++ b/tests/certification/state/sqlserver/go.sum
@@ -49,7 +49,6 @@ github.com/PuerkitoBio/purell v1.2.0 h1:/Jdm5QfyM8zdlqT6WVZU4cfP23sot6CEHA4CS49E
github.com/PuerkitoBio/purell v1.2.0/go.mod h1:OhLRTaaIzhvIyofkJfB24gokC7tM42Px5UhoT32THBk=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b h1:WMhlIaJkDgEQSVJQM06YV+cYUl1r5OY5//ijMXJNqtA=
-github.com/agrea/ptr v0.0.0-20180711073057-77a518d99b7b/go.mod h1:Tie46d3UWzXpj+Fh9+DQTyaUxEpFBPOLXrnx7nxlKRo=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -74,8 +73,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -97,8 +96,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721 h1:EXY9Z1GtR0MC3tQzlYsKryT2HcipE79LhF7u/njeOzM=
github.com/dapr/go-sdk v1.5.1-0.20221004175845-b465b1fa0721/go.mod h1:KLQBltoD9K0w5hKTihdcyg9Epob9gypwL5dYcQzPro4=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5 h1:Jx8u3y/BMjUar0Gp+dzZybBo1Kvbj+18XPbiJ28Xa7A=
-github.com/dapr/kit v0.0.3-0.20221009070203-ca4d40d89ed5/go.mod h1:FR+yc0R0szlKnJooVqJvl7FhWf21wzY4/EzmyFQrESw=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -392,6 +391,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -542,7 +542,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -564,8 +564,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
+golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -760,8 +760,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
+golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/config/bindings/cron/bindings.yaml b/tests/config/bindings/cron/bindings.yaml
new file mode 100644
index 000000000..e40149281
--- /dev/null
+++ b/tests/config/bindings/cron/bindings.yaml
@@ -0,0 +1,12 @@
+
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: cron-binding
+ namespace: default
+spec:
+ type: bindings.cron
+ version: v1
+ metadata:
+ - name: schedule
+ value: "@every 1s"
\ No newline at end of file
diff --git a/tests/config/bindings/kubemq/binding.yml b/tests/config/bindings/kubemq/binding.yml
new file mode 100644
index 000000000..cba5b2825
--- /dev/null
+++ b/tests/config/bindings/kubemq/binding.yml
@@ -0,0 +1,13 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: binding-topic
+ namespace: default
+spec:
+ type: bindings.kubemq
+ version: v1
+ metadata:
+ - name: address
+ value: localhost:50000
+ - name: channel
+ value: queue1
diff --git a/tests/config/bindings/tests.yml b/tests/config/bindings/tests.yml
index 1c5b7170c..4898822ea 100644
--- a/tests/config/bindings/tests.yml
+++ b/tests/config/bindings/tests.yml
@@ -33,12 +33,14 @@ components:
operations: ["create", "operations", "read"]
- component: azure.servicebusqueues
operations: ["create", "operations", "read"]
+ - component: cron
+ operations: ["read"]
- component: kafka
profile: wurstmeister
operations: ["create", "operations"]
- component: kafka
profile: confluent
- operations: ["create", "operations"]
+ operations: ["create", "operations"]
- component: http
operations: ["create", "operations"]
config:
@@ -61,6 +63,8 @@ components:
operations: ["create", "operations", "read"]
config:
checkInOrderProcessing: false
+ - component: kubemq
+ operations: [ "create", "operations", "read" ]
- component: postgres
allOperations: false
- operations: [ "exec", "query", "close", "operations" ]
\ No newline at end of file
+ operations: [ "exec", "query", "close", "operations" ]
diff --git a/tests/config/pubsub/kubemq/pubsub.yml b/tests/config/pubsub/kubemq/pubsub.yml
new file mode 100644
index 000000000..18ede65ff
--- /dev/null
+++ b/tests/config/pubsub/kubemq/pubsub.yml
@@ -0,0 +1,12 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: messages
+spec:
+ type: pubsub.kubemq
+ version: v1
+ metadata:
+ - name: address
+ value: localhost:50000
+ - name: store
+ value: false
diff --git a/tests/config/pubsub/tests.yml b/tests/config/pubsub/tests.yml
index bad79d9fb..70ecceff8 100644
--- a/tests/config/pubsub/tests.yml
+++ b/tests/config/pubsub/tests.yml
@@ -80,3 +80,5 @@ components:
operations: ["publish", "subscribe", "multiplehandlers"]
config:
checkInOrderProcessing: false
+ - component: kubemq
+ operations: ["publish", "subscribe", "multiplehandlers"]
diff --git a/tests/config/state/in-memory/statestore.yaml b/tests/config/state/in-memory/statestore.yaml
new file mode 100644
index 000000000..af0008cf5
--- /dev/null
+++ b/tests/config/state/in-memory/statestore.yaml
@@ -0,0 +1,8 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: statestore
+spec:
+ type: state.in-memory
+ version: v1
+ metadata: []
\ No newline at end of file
diff --git a/tests/config/state/tests.yml b/tests/config/state/tests.yml
index e3215c940..17b4548b3 100644
--- a/tests/config/state/tests.yml
+++ b/tests/config/state/tests.yml
@@ -1,13 +1,13 @@
-# Supported operations: set, get, delete, bulkset, bulkdelete, transaction, etag, first-write, query
+# Supported operations: set, get, delete, bulkset, bulkdelete, transaction, etag, first-write, query, ttl
componentType: state
components:
- component: redis
allOperations: true
- component: mongodb
- allOperations: true
+ operations: [ "set", "get", "delete", "bulkset", "bulkdelete", "transaction", "etag", "first-write", "query" ]
- component: memcached
allOperations: false
- operations: [ "set", "get", "delete", "bulkset", "bulkdelete" ]
+ operations: [ "set", "get", "delete", "bulkset", "bulkdelete", "ttl" ]
- component: azure.cosmosdb
allOperations: true
- component: azure.blobstorage
@@ -21,7 +21,7 @@ components:
operations: [ "set", "get", "delete", "bulkset", "bulkdelete", "transaction", "etag", "first-write" ]
- component: postgresql
allOperations: false
- operations: [ "set", "get", "delete", "bulkset", "bulkdelete", "transaction", "etag", "query" ]
+ operations: [ "set", "get", "delete", "bulkset", "bulkdelete", "transaction", "etag", "query", "first-write" ]
- component: mysql.mysql
allOperations: false
operations: [ "set", "get", "delete", "bulkset", "bulkdelete", "transaction", "etag", "first-write" ]
@@ -36,10 +36,13 @@ components:
operations: ["set", "get", "delete", "etag", "bulkset", "bulkdelete", "first-write"]
- component: cassandra
allOperations: false
- operations: [ "set", "get", "delete", "bulkset", "bulkdelete" ]
+ operations: [ "set", "get", "delete", "bulkset", "bulkdelete", "ttl" ]
- component: cockroachdb
allOperations: false
operations: [ "set", "get", "delete", "bulkset", "bulkdelete", "transaction", "etag", "query" ]
- component: rethinkdb
allOperations: false
- operations: [ "set", "get", "delete", "bulkset", "bulkdelete"]
\ No newline at end of file
+ operations: [ "set", "get", "delete", "bulkset", "bulkdelete"]
+ - component: in-memory
+ allOperations: false
+ operations: [ "set", "get", "delete", "bulkset", "bulkdelete", "transaction", "etag", "first-write", "ttl" ]
diff --git a/tests/conformance/common.go b/tests/conformance/common.go
index 9b61aacc0..4faff0db2 100644
--- a/tests/conformance/common.go
+++ b/tests/conformance/common.go
@@ -42,9 +42,11 @@ import (
b_azure_eventhubs "github.com/dapr/components-contrib/bindings/azure/eventhubs"
b_azure_servicebusqueues "github.com/dapr/components-contrib/bindings/azure/servicebusqueues"
b_azure_storagequeues "github.com/dapr/components-contrib/bindings/azure/storagequeues"
+ b_cron "github.com/dapr/components-contrib/bindings/cron"
b_http "github.com/dapr/components-contrib/bindings/http"
b_influx "github.com/dapr/components-contrib/bindings/influx"
b_kafka "github.com/dapr/components-contrib/bindings/kafka"
+ b_kubemq "github.com/dapr/components-contrib/bindings/kubemq"
b_mqtt "github.com/dapr/components-contrib/bindings/mqtt"
b_postgres "github.com/dapr/components-contrib/bindings/postgres"
b_rabbitmq "github.com/dapr/components-contrib/bindings/rabbitmq"
@@ -57,6 +59,7 @@ import (
p_inmemory "github.com/dapr/components-contrib/pubsub/in-memory"
p_jetstream "github.com/dapr/components-contrib/pubsub/jetstream"
p_kafka "github.com/dapr/components-contrib/pubsub/kafka"
+ p_kubemq "github.com/dapr/components-contrib/pubsub/kubemq"
p_mqtt "github.com/dapr/components-contrib/pubsub/mqtt"
p_natsstreaming "github.com/dapr/components-contrib/pubsub/natsstreaming"
p_pulsar "github.com/dapr/components-contrib/pubsub/pulsar"
@@ -72,6 +75,7 @@ import (
s_azuretablestorage "github.com/dapr/components-contrib/state/azure/tablestorage"
s_cassandra "github.com/dapr/components-contrib/state/cassandra"
s_cockroachdb "github.com/dapr/components-contrib/state/cockroachdb"
+ s_inmemory "github.com/dapr/components-contrib/state/in-memory"
s_memcached "github.com/dapr/components-contrib/state/memcached"
s_mongodb "github.com/dapr/components-contrib/state/mongodb"
s_mysql "github.com/dapr/components-contrib/state/mysql"
@@ -397,6 +401,8 @@ func loadPubSub(tc TestComponent) pubsub.PubSub {
pubsub = p_inmemory.New(testLogger)
case "aws.snssqs":
pubsub = p_snssqs.NewSnsSqs(testLogger)
+ case "kubemq":
+ pubsub = p_kubemq.NewKubeMQ(testLogger)
default:
return nil
}
@@ -459,6 +465,8 @@ func loadStateStore(tc TestComponent) state.Store {
store = s_memcached.NewMemCacheStateStore(testLogger)
case "rethinkdb":
store = s_rethinkdb.NewRethinkDBStateStore(testLogger)
+ case "in-memory":
+ store = s_inmemory.NewInMemoryStateStore(testLogger)
default:
return nil
}
@@ -494,6 +502,8 @@ func loadOutputBindings(tc TestComponent) bindings.OutputBinding {
binding = b_mqtt.NewMQTT(testLogger)
case "rabbitmq":
binding = b_rabbitmq.NewRabbitMQ(testLogger)
+ case "kubemq":
+ binding = b_kubemq.NewKubeMQ(testLogger)
case "postgres":
binding = b_postgres.NewPostgres(testLogger)
default:
@@ -513,6 +523,8 @@ func loadInputBindings(tc TestComponent) bindings.InputBinding {
binding = b_azure_storagequeues.NewAzureStorageQueues(testLogger)
case "azure.eventgrid":
binding = b_azure_eventgrid.NewAzureEventGrid(testLogger)
+ case "cron":
+ binding = b_cron.NewCron(testLogger)
case eventhubs:
binding = b_azure_eventhubs.NewAzureEventHubs(testLogger)
case kafka:
@@ -521,6 +533,8 @@ func loadInputBindings(tc TestComponent) bindings.InputBinding {
binding = b_mqtt.NewMQTT(testLogger)
case "rabbitmq":
binding = b_rabbitmq.NewRabbitMQ(testLogger)
+ case "kubemq":
+ binding = b_kubemq.NewKubeMQ(testLogger)
default:
return nil
}
diff --git a/tests/conformance/state/state.go b/tests/conformance/state/state.go
index 9104090e6..d05270be9 100644
--- a/tests/conformance/state/state.go
+++ b/tests/conformance/state/state.go
@@ -20,6 +20,7 @@ import (
"sort"
"strings"
"testing"
+ "time"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
@@ -589,21 +590,20 @@ func ConformanceTests(t *testing.T, props map[string]string, statestore state.St
err := statestore.Delete(context.TODO(), &state.DeleteRequest{
Key: testKey,
})
- require.Nil(t, err)
+ require.NoError(t, err)
// Set an object.
err = statestore.Set(context.TODO(), &state.SetRequest{
Key: testKey,
Value: firstValue,
})
- require.Nil(t, err)
+ require.NoError(t, err)
// Validate the set.
res, err := statestore.Get(context.TODO(), &state.GetRequest{
Key: testKey,
})
-
- require.Nil(t, err)
+ require.NoError(t, err)
assertEquals(t, firstValue, res)
etag := res.ETag
@@ -613,7 +613,7 @@ func ConformanceTests(t *testing.T, props map[string]string, statestore state.St
Value: secondValue,
ETag: &fakeEtag,
})
- require.NotNil(t, err)
+ require.Error(t, err)
// Try and update with corect ETag, expect success.
err = statestore.Set(context.TODO(), &state.SetRequest{
@@ -621,13 +621,13 @@ func ConformanceTests(t *testing.T, props map[string]string, statestore state.St
Value: secondValue,
ETag: etag,
})
- require.Nil(t, err)
+ require.NoError(t, err)
// Validate the set.
res, err = statestore.Get(context.TODO(), &state.GetRequest{
Key: testKey,
})
- require.Nil(t, err)
+ require.NoError(t, err)
assertEquals(t, secondValue, res)
require.NotEqual(t, etag, res.ETag)
etag = res.ETag
@@ -637,14 +637,14 @@ func ConformanceTests(t *testing.T, props map[string]string, statestore state.St
Key: testKey,
ETag: &fakeEtag,
})
- require.NotNil(t, err)
+ require.Error(t, err)
// Try and delete with correct ETag, expect success.
err = statestore.Delete(context.TODO(), &state.DeleteRequest{
Key: testKey,
ETag: etag,
})
- require.Nil(t, err)
+ require.NoError(t, err)
})
} else {
// Check if eTag feature is NOT listed
@@ -702,21 +702,21 @@ func ConformanceTests(t *testing.T, props map[string]string, statestore state.St
err := statestore.Delete(context.TODO(), &state.DeleteRequest{
Key: testKey,
})
- require.Nil(t, err)
+ require.NoError(t, err)
err = statestore.Set(context.TODO(), requestSet[0])
- require.Nil(t, err)
+ require.NoError(t, err)
// Validate the set.
res, err := statestore.Get(context.TODO(), &state.GetRequest{
Key: testKey,
})
- require.Nil(t, err)
+ require.NoError(t, err)
assertEquals(t, firstValue, res)
// Second write expect fail
- err = statestore.Set(context.TODO(), requestSet[1])
- require.NotNil(t, err)
+ err = statestore.Set(context.Background(), requestSet[1])
+ require.Error(t, err)
})
}
})
@@ -732,19 +732,19 @@ func ConformanceTests(t *testing.T, props map[string]string, statestore state.St
}
// Delete any potential object, it's important to start from a clean slate.
- err := statestore.Delete(context.TODO(), &state.DeleteRequest{
+ err := statestore.Delete(context.Background(), &state.DeleteRequest{
Key: testKey,
})
- require.Nil(t, err)
+ require.NoError(t, err)
- err = statestore.Set(context.TODO(), request)
- require.Nil(t, err)
+ err = statestore.Set(context.Background(), request)
+ require.NoError(t, err)
// Validate the set.
res, err := statestore.Get(context.TODO(), &state.GetRequest{
Key: testKey,
})
- require.Nil(t, err)
+ require.NoError(t, err)
assertEquals(t, firstValue, res)
etag := res.ETag
@@ -758,27 +758,55 @@ func ConformanceTests(t *testing.T, props map[string]string, statestore state.St
Consistency: state.Strong,
},
}
- err = statestore.Set(context.TODO(), request)
- require.Nil(t, err)
+ err = statestore.Set(context.Background(), request)
+ require.NoError(t, err)
// Validate the set.
- res, err = statestore.Get(context.TODO(), &state.GetRequest{
+ res, err = statestore.Get(context.Background(), &state.GetRequest{
Key: testKey,
})
- require.Nil(t, err)
+ require.NoError(t, err)
require.NotEqual(t, etag, res.ETag)
assertEquals(t, secondValue, res)
request.ETag = etag
// Second write expect fail
- err = statestore.Set(context.TODO(), request)
- require.NotNil(t, err)
+ err = statestore.Set(context.Background(), request)
+ require.Error(t, err)
+ })
+ }
+
+ if config.HasOperation("ttl") {
+ t.Run("set and get with TTL", func(t *testing.T) {
+ err := statestore.Set(context.Background(), &state.SetRequest{
+ Key: key + "-ttl",
+ Value: "⏱️",
+ Metadata: map[string]string{
+ "ttlInSeconds": "2",
+ },
+ })
+ require.NoError(t, err)
+
+ // Request immediately
+ res, err := statestore.Get(context.Background(), &state.GetRequest{
+ Key: key + "-ttl",
+ })
+ require.NoError(t, err)
+ assertEquals(t, "⏱️", res)
+
+ // Wait for the object to expire and request again
+ time.Sleep(3 * time.Second)
+ res, err = statestore.Get(context.Background(), &state.GetRequest{
+ Key: key + "-ttl",
+ })
+ require.NoError(t, err)
+ assert.Nil(t, res.Data)
})
}
}
-func assertEquals(t *testing.T, value interface{}, res *state.GetResponse) {
+func assertEquals(t *testing.T, value any, res *state.GetResponse) {
switch v := value.(type) {
case intValueType:
// Custom type requires case mapping
diff --git a/tests/conformance/utils/utils.go b/tests/conformance/utils/utils.go
index 01d5c3244..2628ce2b0 100644
--- a/tests/conformance/utils/utils.go
+++ b/tests/conformance/utils/utils.go
@@ -104,9 +104,9 @@ func appRouter() *mux.Router {
func handleCall(w http.ResponseWriter, r *http.Request) {
switch r.Method {
- case "POST":
+ case http.MethodPost:
s.handlePost(r)
- case "GET":
+ case http.MethodGet:
w.Write(s.handleGet())
default:
w.WriteHeader(http.StatusInternalServerError)
diff --git a/tests/conformance/workflows/workflows.go b/tests/conformance/workflows/workflows.go
index 5232c7a00..2c876c717 100644
--- a/tests/conformance/workflows/workflows.go
+++ b/tests/conformance/workflows/workflows.go
@@ -22,6 +22,7 @@ import (
"github.com/dapr/kit/logger"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/tests/conformance/utils"
"github.com/dapr/components-contrib/workflows"
)
@@ -50,7 +51,7 @@ func ConformanceTests(t *testing.T, props map[string]string, workflowItem workfl
// Test vars
t.Run("init", func(t *testing.T) {
err := workflowItem.Init(workflows.Metadata{
- Properties: props,
+ Base: metadata.Base{Properties: props},
})
assert.NoError(t, err)
})
@@ -60,7 +61,7 @@ func ConformanceTests(t *testing.T, props map[string]string, workflowItem workfl
t.Run("start", func(t *testing.T) {
testLogger.Info("Start test running...")
req := &workflows.StartRequest{
- Parameters: 10, // Time that the activity within the workflow runs for
+ Input: 10, // Time that the activity within the workflow runs for
WorkflowName: "TestWorkflow",
}
req.WorkflowReference.InstanceID = "TestID"
diff --git a/tests/e2e/pubsub/jetstream/go.mod b/tests/e2e/pubsub/jetstream/go.mod
index c940d66bf..b5c58e5df 100644
--- a/tests/e2e/pubsub/jetstream/go.mod
+++ b/tests/e2e/pubsub/jetstream/go.mod
@@ -4,14 +4,14 @@ go 1.19
require (
github.com/dapr/components-contrib v1.5.1
- github.com/dapr/kit v0.0.2
+ github.com/dapr/kit v0.0.3
)
require (
- github.com/cenkalti/backoff/v4 v4.1.3 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect
- github.com/nats-io/nats.go v1.19.0 // indirect
+ github.com/nats-io/nats.go v1.19.1 // indirect
github.com/nats-io/nkeys v0.3.0 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
diff --git a/tests/e2e/pubsub/jetstream/go.sum b/tests/e2e/pubsub/jetstream/go.sum
index 3952483e8..435619a48 100644
--- a/tests/e2e/pubsub/jetstream/go.sum
+++ b/tests/e2e/pubsub/jetstream/go.sum
@@ -1,7 +1,7 @@
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
-github.com/dapr/kit v0.0.2 h1:VNg6RWrBMOdtY0/ZLztyAa/RjyFLaskdO9wt2HIREwk=
-github.com/dapr/kit v0.0.2/go.mod h1:Q4TWm9+vcPZFGehaJUZt2hvA805wJm7FIuoArytWJ8o=
+github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
+github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/dapr/kit v0.0.3 h1:1FCnWjIuAS3OJzJhOlUKNzLxoazYhYIS4oCOOULmWBA=
+github.com/dapr/kit v0.0.3/go.mod h1:+vh2UIRT0KzFm5YJWfj7az4XVSdodys1OCz1WzNe1Eo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -14,8 +14,8 @@ github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmL
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/nats-io/jwt/v2 v2.3.0 h1:z2mA1a7tIf5ShggOFlR1oBPgd6hGqcDYsISxZByUzdI=
github.com/nats-io/nats-server/v2 v2.9.4 h1:GvRgv1936J/zYUwMg/cqtYaJ6L+bgeIOIvPslbesdow=
-github.com/nats-io/nats.go v1.19.0 h1:H6j8aBnTQFoVrTGB6Xjd903UMdE7jz6DS4YkmAqgZ9Q=
-github.com/nats-io/nats.go v1.19.0/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA=
+github.com/nats-io/nats.go v1.19.1 h1:pDQZthDfxRMSJ0ereExAM9ODf3JyS42Exk7iCMdbpec=
+github.com/nats-io/nats.go v1.19.1/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA=
github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
@@ -32,6 +32,7 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
+golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/workflows/metadata.go b/workflows/metadata.go
index 659de3767..c1f6cc02a 100644
--- a/workflows/metadata.go
+++ b/workflows/metadata.go
@@ -13,7 +13,9 @@ limitations under the License.
package workflows
-// Metadata represents a set of binding specific properties.
+import "github.com/dapr/components-contrib/metadata"
+
+// Metadata represents a set of workflow specific properties.
type Metadata struct {
- Properties map[string]string `json:"properties"`
+ metadata.Base `json:",inline"`
}
diff --git a/workflows/requests.go b/workflows/requests.go
index f85d73463..590cb285b 100644
--- a/workflows/requests.go
+++ b/workflows/requests.go
@@ -9,5 +9,5 @@ type StartRequest struct {
Options map[string]string `json:"workflow_options"`
WorkflowReference WorkflowReference `json:"workflow_reference"`
WorkflowName string `json:"function_name"`
- Parameters interface{} `json:"parameters"`
+ Input interface{} `json:"input"`
}
diff --git a/workflows/temporal/temporal.go b/workflows/temporal/temporal.go
index cc98a67c8..81fb7dc87 100644
--- a/workflows/temporal/temporal.go
+++ b/workflows/temporal/temporal.go
@@ -15,7 +15,6 @@ package temporal
import (
"context"
- "encoding/json"
"errors"
"fmt"
"time"
@@ -23,6 +22,7 @@ import (
"go.temporal.io/api/enums/v1"
"go.temporal.io/sdk/client"
+ "github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/workflows"
"github.com/dapr/kit/logger"
)
@@ -33,8 +33,9 @@ type TemporalWF struct {
}
type temporalMetadata struct {
- Identity string `json:"identity"`
- HostPort string `json:"hostport"`
+ Identity string `json:"identity"`
+ HostPort string `json:"hostport"`
+ Namespace string `json:"namespace"`
}
// NewTemporalWorkflow returns a new workflow.
@@ -58,6 +59,9 @@ func (c *TemporalWF) Init(metadata workflows.Metadata) error {
if m.Identity != "" {
cOpt.Identity = m.Identity
}
+ if m.Namespace != "" {
+ cOpt.Namespace = m.Namespace
+ }
// Create the workflow client
newClient, err := client.Dial(cOpt)
if err != nil {
@@ -83,7 +87,7 @@ func (c *TemporalWF) Start(ctx context.Context, req *workflows.StartRequest) (*w
taskQ := req.Options["task_queue"]
opt := client.StartWorkflowOptions{ID: req.WorkflowReference.InstanceID, TaskQueue: taskQ}
- run, err := c.client.ExecuteWorkflow(ctx, opt, req.WorkflowName, req.Parameters)
+ run, err := c.client.ExecuteWorkflow(ctx, opt, req.WorkflowName, req.Input)
if err != nil {
return &workflows.WorkflowReference{}, fmt.Errorf("error executing workflow: %w", err)
}
@@ -124,20 +128,10 @@ func (c *TemporalWF) Close() {
c.client.Close()
}
-func (c *TemporalWF) parseMetadata(metadata workflows.Metadata) (*temporalMetadata, error) {
- connInfo := metadata.Properties
- b, err := json.Marshal(connInfo)
- if err != nil {
- return nil, err
- }
-
- var creds temporalMetadata
- err = json.Unmarshal(b, &creds)
- if err != nil {
- return nil, err
- }
-
- return &creds, nil
+func (c *TemporalWF) parseMetadata(meta workflows.Metadata) (*temporalMetadata, error) {
+ var m temporalMetadata
+ err := metadata.DecodeMetadata(meta.Properties, &m)
+ return &m, err
}
func lookupStatus(status enums.WorkflowExecutionStatus) string {