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 {