diff --git a/.fossa.yml b/.fossa.yml new file mode 100644 index 000000000..f7b984618 --- /dev/null +++ b/.fossa.yml @@ -0,0 +1,6 @@ +version: 3 + +paths: + exclude: + - ./tools + - ./NOTICE diff --git a/.github/dependabot.yml b/.github/dependabot.yml index dbfe995b4..56f5c9da9 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -21,3 +21,18 @@ updates: schedule: interval: "monthly" open-pull-requests-limit: 5 + + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + + - package-ecosystem: docker + directory: /integration-test + schedule: + interval: daily + + - package-ecosystem: gomod + directory: /tools + schedule: + interval: daily diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6208db41a..c4092db59 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -20,6 +20,9 @@ on: schedule: - cron: '30 18 * * 2' +permissions: + contents: read + jobs: analyze: name: Analyze @@ -37,12 +40,17 @@ jobs: # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit + - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +64,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 # ℹī¸ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -69,6 +77,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index dc7a46060..852846e83 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -1,16 +1,24 @@ name: Quality on: [push, pull_request] +permissions: + contents: read + jobs: test: name: Test with Coverage runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit + - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '1.21' - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install dependencies run: | go mod download diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 000000000..10eb78023 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,27 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, +# surfacing known-vulnerable versions of the packages declared or updated in the PR. +# Once installed, if the workflow run is marked as required, +# PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit + + - name: 'Checkout Repository' + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: 'Dependency Review' + uses: actions/dependency-review-action@01bc87099ba56df1e897b6874784491ea6309bc4 # v3.1.4 diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index b7e7da060..ca88d1dd8 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -13,11 +13,16 @@ jobs: runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit + - name: Checkout Repository - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Set up Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 with: node-version: '16' @@ -32,7 +37,7 @@ jobs: yarn build - name: Deploy to S3 - uses: jakejarvis/s3-sync-action@master + uses: jakejarvis/s3-sync-action@7ed8b112447abb09f1da74f3466e4194fc7a6311 # master with: args: --acl public-read --follow-symlinks --delete env: @@ -44,7 +49,7 @@ jobs: DEST_DIR: '' - name: Invalidate CloudFront Distribution - uses: chetan/invalidate-cloudfront-action@master + uses: chetan/invalidate-cloudfront-action@fce6f6f546fae2e9fe55f3bd1411063a908f2557 # master env: DISTRIBUTION: ${{ secrets.DISTRIBUTION }} PATHS: '/*' diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index f28db7797..c21d1f336 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -11,31 +11,36 @@ jobs: goreleaser: runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit + - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: ~1.21.3 - name: Log in to GHCR - uses: docker/login-action@v2 + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GH_TOKEN }} - name: Login to dockerhub - uses: docker/login-action@v1 + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 - name : Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v4 + uses: goreleaser/goreleaser-action@5fdedb94abba051217030cc86d4523cf3f02243d # v4.6.0 with: distribution: goreleaser-pro version: latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 760c02d27..017cd76eb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,31 +11,36 @@ jobs: goreleaser: runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit + - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: ~1.21.3 - name: Log in to GHCR - uses: docker/login-action@v2 + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GH_TOKEN }} - name: Login to dockerhub - uses: docker/login-action@v1 + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v4 + uses: goreleaser/goreleaser-action@5fdedb94abba051217030cc86d4523cf3f02243d # v4.6.0 with: distribution: goreleaser-pro version: latest diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 000000000..af2b5c645 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,78 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '30 18 * * 2' + push: + branches: [ "master" ] + workflow_dispatch: + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + # Uncomment the permissions below if installing in a private repository. + # contents: read + # actions: read + + steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit + + - name: "Checkout code" + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 + with: + sarif_file: results.sarif diff --git a/.github/workflows/shapes.yml b/.github/workflows/shapes.yml index a6d667654..7b26c9010 100644 --- a/.github/workflows/shapes.yml +++ b/.github/workflows/shapes.yml @@ -13,11 +13,16 @@ jobs: runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit + - name: Check out repository - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Sync to S3 - uses: jakejarvis/s3-sync-action@master + uses: jakejarvis/s3-sync-action@7ed8b112447abb09f1da74f3466e4194fc7a6311 # master with: args: --acl public-read --follow-symlinks --no-progress env: diff --git a/.github/workflows/validate-pr-title.yml b/.github/workflows/validate-pr-title.yml new file mode 100644 index 000000000..bddf3a66e --- /dev/null +++ b/.github/workflows/validate-pr-title.yml @@ -0,0 +1,45 @@ +--- +name: "Conventional Commits" +on: + pull_request_target: + types: + - opened + - edited + - synchronize +permissions: + contents: read + +jobs: + validate: + name: Validate PR title + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit + + - uses: amannn/action-semantic-pull-request@e9fabac35e210fea40ca5b14c0da95a099eff26f # v5.4.0 + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + with: + types: | + feat + fix + chore + docs + enhancement + revert + build + ci + style + refactor + perf + test + requireScope: false + subjectPattern: ^(?![A-Z]).+$ + subjectPatternError: | + The subject "{subject}" found in the pull request title "{title}" + didn't match the configured pattern. Please ensure that the subject + doesn't start with an uppercase character. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..7eb1128dd --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,18 @@ +repos: +- repo: https://github.com/gitleaks/gitleaks + rev: v8.16.3 + hooks: + - id: gitleaks +- repo: https://github.com/golangci/golangci-lint + rev: v1.52.2 + hooks: + - id: golangci-lint +- repo: https://github.com/pre-commit/mirrors-eslint + rev: v8.38.0 + hooks: + - id: eslint +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: end-of-file-fixer + - id: trailing-whitespace diff --git a/Dockerfile b/Dockerfile index 757d7ea2c..fe8a98860 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,12 @@ # Step 1: Builder -FROM golang:1.21-alpine3.18 as permify-builder +FROM golang:1.21-alpine3.18@sha256:d8b99943fb0587b79658af03d4d4e8b57769b21dcf08a8401352a9f2a7228754 as permify-builder WORKDIR /go/src/app RUN apk update && apk add --no-cache git COPY . . -RUN CGO_ENABLED=0 go build -v ./cmd/permify/ +RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg/mod CGO_ENABLED=0 go build -v ./cmd/permify/ # Step 2: Final -FROM cgr.dev/chainguard/static:latest +FROM cgr.dev/chainguard/static:latest@sha256:fd59d10894f38ce93eb6e587595ccdd8570bfd9c8f6fde7df4c589a5cefd82e2 COPY --from=ghcr.io/grpc-ecosystem/grpc-health-probe:v0.4.19 /ko-app/grpc-health-probe /usr/local/bin/grpc_health_probe COPY --from=permify-builder /go/src/app/permify /usr/local/bin/permify ENV PATH="$PATH:/usr/local/bin" diff --git a/README.md b/README.md index dfe6937ab..8a1798653 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,10 @@ Coveralls

+

+ +

+ ![Permify - Open source authorization as a service](https://github.com/Permify/permify/assets/39353278/06262e07-84ba-4a1c-b859-870344396600) ## Join Our Team diff --git a/docs/apidocs.swagger.json b/docs/apidocs.swagger.json index 43cc73776..5a63aefc3 100644 --- a/docs/apidocs.swagger.json +++ b/docs/apidocs.swagger.json @@ -3,7 +3,7 @@ "info": { "title": "Permify API", "description": "Permify is an open source authorization service for creating fine-grained and scalable authorization systems.", - "version": "v0.6.5", + "version": "v0.6.9", "contact": { "name": "API Support", "url": "https://github.com/Permify/permify/issues", diff --git a/docs/docs/api-overview/data/write-data.md b/docs/docs/api-overview/data/write-data.md index 0dd3f1989..67e870277 100644 --- a/docs/docs/api-overview/data/write-data.md +++ b/docs/docs/api-overview/data/write-data.md @@ -67,7 +67,7 @@ rr, err: = client.Data.Write(context.Background(), & v1.DataWriteRequest { }, Relation: "admin", Subject: & v1.Subject { - Type: "admin", + Type: "user", Id: "3", }, } diff --git a/docs/docs/reference/configuration.md b/docs/docs/reference/configuration.md index 1244317c0..184366ab3 100644 --- a/docs/docs/reference/configuration.md +++ b/docs/docs/reference/configuration.md @@ -75,7 +75,6 @@ service: cache: number_of_counters: 10_000 max_cost: 10MiB - relationship: # The database section specifies the database engine and connection settings, # including the URI for the database, whether or not to auto-migrate the database, @@ -423,6 +422,59 @@ audits, decision logs, authorization model)

+
service | Service Configurations +

+ +#### Definition + +Configurations for the permify service and how it should behave. You can configure the circuit breaker pattern, configuration watcher, and service specific options for permission and schema services (rate limiting, concurrency limiting, cache size). + +#### Structure + +``` +├── service +| ├── circuit_breaker +| ├── watch: +| | ├── enabled +| ├── schema: +| | ├── cache: +| | | ├── number_of_counters +| | | ├── max_cost +| | permission: +| | | ├── bulk_limit +| | | ├── concurrency_limit +| | | ├── cache: +| | | | ├── number_of_counters +| | | | ├── max_cost +``` + +#### Glossary + +| Required | Argument | Default | Description | +|----------|-------------------------------------|---------|---------------------------------------------------| +| [ ] | circuit_breaker | false | switch option to use the circuit breaker pattern. | +| [ ] | watch | false | switch option for configuration watcher. | +| [ ] | schema.cache.number_of_counters | 1_000 | number of counters for schema service. | +| [ ] | schema.cache.max_cost | 10MiB | max cost for schema cache. | +| [ ] | permission.bulk_limit | 100 | bulk operations limit for permission service. | +| [ ] | permission.concurrency_limit | 100 | concurrency limit for permission service. | +| [ ] | permission.cache.max_cost | 10MiB | max cost for permission service. | + +#### ENV + +| Argument | ENV | Type | +|-----------------------------------------------|--------------------------------------------------------|----------| +| service-circuit-breaker | PERMIFY_SERVICE_CIRCUIT_BREAKER | boolean | +| service-watch-enabled | PERMIFY_SERVICE_WATCH_ENABLED | boolean | +| service-schema-cache-number-of-counters | PERMIFY_SERVICE_SCHEMA_CACHE_NUMBER_OF_COUNTERS | int | +| service-schema-cache-max-cost | PERMIFY_SERVICE_SCHEMA_CACHE_MAX_COST | int | +| service-permission-bulk-limit | PERMIFY_SERVICE_PERMISSION_BULK_LIMIT | int | +| service-permission-concurrency-limit | PERMIFY_SERVICE_PERMISSION_CONCURRENCY_LIMIT | int | +| service-permission-cache-max-cost | PERMIFY_SERVICE_PERMISSION_CACHE_MAX_COST | int | + +

+
+
profiler | Performance Profiler Configurations

diff --git a/example.config.yaml b/example.config.yaml index 8fc17f8a8..36cc832f5 100644 --- a/example.config.yaml +++ b/example.config.yaml @@ -1,3 +1,5 @@ +account_id: "" + # The server section specifies the HTTP and gRPC server settings, # including whether or not TLS is enabled and the certificate and # key file locations. diff --git a/go.mod b/go.mod index e1c9c03e8..2fc8df8e3 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.21 require ( github.com/Masterminds/squirrel v1.5.4 - github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 github.com/cenkalti/backoff/v4 v4.2.1 github.com/cespare/xxhash/v2 v2.2.0 github.com/dgraph-io/ristretto v0.1.1 @@ -18,7 +17,7 @@ require ( github.com/gookit/color v1.5.4 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 github.com/hashicorp/go-memdb v1.3.4 github.com/hashicorp/go-multierror v1.1.1 github.com/jackc/pgio v1.0.0 @@ -33,32 +32,34 @@ require ( github.com/rs/xid v1.5.0 github.com/sercand/kuberesolver/v5 v5.1.1 github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b + github.com/sony/gobreaker v0.5.0 github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.17.0 github.com/stretchr/testify v1.8.4 - github.com/testcontainers/testcontainers-go v0.25.0 + github.com/testcontainers/testcontainers-go v0.27.0 github.com/zitadel/oidc v1.13.5 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 - go.opentelemetry.io/contrib/instrumentation/host v0.46.0 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 + go.opentelemetry.io/contrib/instrumentation/host v0.46.1 go.opentelemetry.io/contrib/instrumentation/runtime v0.46.0 go.opentelemetry.io/otel v1.21.0 go.opentelemetry.io/otel/exporters/jaeger v1.17.0 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.43.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.20.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 go.opentelemetry.io/otel/exporters/zipkin v1.20.0 go.opentelemetry.io/otel/metric v1.21.0 - go.opentelemetry.io/otel/sdk v1.20.0 - go.opentelemetry.io/otel/sdk/metric v1.20.0 + go.opentelemetry.io/otel/sdk v1.21.0 + go.opentelemetry.io/otel/sdk/metric v1.21.0 go.opentelemetry.io/otel/trace v1.21.0 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 - golang.org/x/net v0.17.0 + golang.org/x/net v0.19.0 golang.org/x/sync v0.5.0 - google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb - google.golang.org/grpc v1.59.0 + google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 + google.golang.org/grpc v1.60.1 google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v3 v3.0.1 + resenje.org/singleflight v0.4.1 ) require ( @@ -85,7 +86,7 @@ require ( github.com/golang/glog v1.1.2 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect - github.com/google/uuid v1.3.1 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/gorilla/schema v1.2.0 // indirect github.com/gorilla/securecookie v1.1.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -105,12 +106,12 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/moby/patternmatcher v0.5.0 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc4 // indirect + github.com/opencontainers/image-spec v1.1.0-rc5 // indirect github.com/opencontainers/runc v1.1.7 // indirect github.com/openzipkin/zipkin-go v0.4.2 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect @@ -122,10 +123,9 @@ require ( github.com/prometheus/procfs v0.11.0 // indirect github.com/sagikazarmark/locafero v0.3.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/shirou/gopsutil/v3 v3.23.10 // indirect + github.com/shirou/gopsutil/v3 v3.23.11 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartystreets/goconvey v1.6.4 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.10.0 // indirect github.com/spf13/cast v1.5.1 // indirect @@ -147,8 +147,8 @@ require ( golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.14.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect + google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect ) diff --git a/go.sum b/go.sum index 565751e93..8642ac698 100644 --- a/go.sum +++ b/go.sum @@ -17,15 +17,15 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o= +cloud.google.com/go v0.110.9 h1:e7ITSqGFFk4rbz/JFIqZh3G4VEHguhAL4BQcFlWtU68= 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/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= -cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.2 h1:nWEMDhgbBkBJjfpVySqU4jgWdc22PLR0o4vEexZHers= +cloud.google.com/go/compute v1.23.2/go.mod h1:JJ0atRC0J/oWYiiVBmsSsrRnh92DhZPG4hFDcR04Rns= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -56,8 +56,6 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -212,15 +210,13 @@ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbu github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= 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.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.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/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= @@ -231,8 +227,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDa github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 h1:HcUWd006luQPljE73d5sk+/VgYPGUReEVz2y1/qylwY= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 h1:6UKoz5ujsI55KNpsJH3UwCq3T8kKbZwNZBNPuTTje8U= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1/go.mod h1:YvJ2f6MplWDhfxiUC3KpyTy76kYUZA4W3pTv/wdKQ9Y= 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= @@ -309,8 +305,6 @@ github.com/jeremija/gosubmit v0.2.7 h1:At0OhGCFGPXyjPYAsCchoBUhE099pcBXmsb4iZqRO github.com/jeremija/gosubmit v0.2.7/go.mod h1:Ui+HS073lCFREXBbdfrJzMB57OI/bdxTiLtrDHHhFPI= 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/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/ratelimit v1.0.2 h1:sRxmtRiajbvrcLQT7S+JbqU0ntsb9W2yhSdNN8tWfaI= github.com/juju/ratelimit v1.0.2/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= @@ -358,8 +352,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= -github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= @@ -372,8 +366,8 @@ github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= -github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v1.1.7 h1:y2EZDS8sNng4Ksf0GUYNhKbTShZJPJg1FiXJNH/uoCk= github.com/opencontainers/runc v1.1.7/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -423,8 +417,8 @@ github.com/sercand/kuberesolver/v5 v5.1.1 h1:CYH+d67G0sGBj7q5wLK61yzqJJ8gLLC8aep github.com/sercand/kuberesolver/v5 v5.1.1/go.mod h1:Fs1KbKhVRnB2aDWN12NjKCB+RgYMWZJ294T3BtmVCpQ= github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b h1:h+3JX2VoWTFuyQEo87pStk/a99dzIO1mM9KxIyLPGTU= github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc= -github.com/shirou/gopsutil/v3 v3.23.10 h1:/N42opWlYzegYaVkWejXWJpbzKv2JDy3mrgGzKsh9hM= -github.com/shirou/gopsutil/v3 v3.23.10/go.mod h1:JIE26kpucQi+innVlAUnIEOSBhBUkirr5b44yr55+WE= +github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ= +github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -435,10 +429,8 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +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/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= @@ -472,8 +464,8 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/testcontainers/testcontainers-go v0.25.0 h1:erH6cQjsaJrH+rJDU9qIf89KFdhK0Bft0aEZHlYC3Vs= -github.com/testcontainers/testcontainers-go v0.25.0/go.mod h1:4sC9SiJyzD1XFi59q8umTQYWxnkweEc5OjVtTUlJzqQ= +github.com/testcontainers/testcontainers-go v0.27.0 h1:IeIrJN4twonTDuMuBNQdKZ+K97yd7VrmNGu+lDpYcDk= +github.com/testcontainers/testcontainers-go v0.27.0/go.mod h1:+HgYZcd17GshBUZv9b+jKFJ198heWPQq3KQIp2+N+7U= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -498,10 +490,10 @@ 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.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 h1:PzIubN4/sjByhDRHLviCjJuweBXWFZWhghjg7cS28+M= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0/go.mod h1:Ct6zzQEuGK3WpJs2n4dn+wfJYzd/+hNnxMRTWjGn30M= -go.opentelemetry.io/contrib/instrumentation/host v0.46.0 h1:n2JE5k4ZtefmqXseW11OpvmYW0ouawMX2vjWemTGfCA= -go.opentelemetry.io/contrib/instrumentation/host v0.46.0/go.mod h1:wJV0E+WkEumP6ph4Q3F+H6YOy2P/hwmKu4MbO+qj57I= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= +go.opentelemetry.io/contrib/instrumentation/host v0.46.1 h1:jLPv7OPP2CROWQ8PaUx3zONn5S4HjCJnH1syT3fnEEc= +go.opentelemetry.io/contrib/instrumentation/host v0.46.1/go.mod h1:7PhaLiZ6K9zbeZNxOdr+DB8tzxWsrjVa9BcCMGuMPeA= go.opentelemetry.io/contrib/instrumentation/runtime v0.46.0 h1:dRj4IGqk65IHPLsur40gajPeQXxWWjprjeNq6aMJorU= go.opentelemetry.io/contrib/instrumentation/runtime v0.46.0/go.mod h1:LD/bFNptUlSeHOX/6FMaAvjfvralTgFd09/EaZtV8X4= go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= @@ -510,20 +502,20 @@ go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.43.0 h1:2oKqGjXdi5iDIUXFbBbLthG2LMeYlxcdxVmLim1e9qg= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.43.0/go.mod h1:qmFtGlXhoa9qPt5RrZgMp4f5RfRagucrdriI+hb3yWQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 h1:DeFD0VgTZ+Cj6hxravYYZE2W4GlneVH81iAOPjZkzk8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0/go.mod h1:GijYcYmNpX1KazD5JmWGsi4P7dDTTTnfv1UbGn84MnU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 h1:gvmNvqrPYovvyRmCSygkUDyL8lC5Tl845MLEwqpxhEU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0/go.mod h1:vNUq47TGFioo+ffTSnKNdob241vePmtNZnAODKapKd0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.20.0 h1:CsBiKCiQPdSjS+MlRiqeTI9JDDpSuk0Hb6QTRfwer8k= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.20.0/go.mod h1:CMJYNAfooOwSZSAmAeMUV1M+TXld3BiK++z9fqIm2xk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I= go.opentelemetry.io/otel/exporters/zipkin v1.20.0 h1:fD/wt+mqtpl048RxUyUkdXRfFqOjsJYG7K7KUC+GNuc= go.opentelemetry.io/otel/exporters/zipkin v1.20.0/go.mod h1:KktoRB60WLnDCAasFr9X62W+B06RJykJvo0E5gLLt+Q= go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/sdk v1.20.0 h1:5Jf6imeFZlZtKv9Qbo6qt2ZkmWtdWx/wzcCbNUlAWGM= -go.opentelemetry.io/otel/sdk v1.20.0/go.mod h1:rmkSx1cZCm/tn16iWDn1GQbLtsW/LvsdEEFzCSRM6V0= -go.opentelemetry.io/otel/sdk/metric v1.20.0 h1:5eD40l/H2CqdKmbSV7iht2KMK0faAIL2pVYzJOWobGk= -go.opentelemetry.io/otel/sdk/metric v1.20.0/go.mod h1:AGvpC+YF/jblITiafMTYgvRBUiwi9hZf0EYE2E5XlS8= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= +go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= @@ -637,8 +629,8 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= 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= @@ -718,7 +710,6 @@ golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -746,7 +737,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 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-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -870,12 +860,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA= -google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= -google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI= -google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= +google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 h1:I6WNifs6pF9tNdSob2W24JtyxIYjzFB9qDlpUC76q+U= +google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405/go.mod h1:3WDQMjmJk36UQhjQ89emUzb1mdaHcPeeAh4SCBKznB4= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= 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= @@ -892,8 +882,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= 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= @@ -953,6 +943,8 @@ modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +resenje.org/singleflight v0.4.1 h1:ryGHRaOBwhnZLyf34LMDf4AsTSHrs4hdGPdG/I4Hmac= +resenje.org/singleflight v0.4.1/go.mod h1:lAgQK7VfjG6/pgredbQfmV0RvG/uVhKo6vSuZ0vCWfk= 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= diff --git a/integration-test/Dockerfile b/integration-test/Dockerfile index 917db527e..728d70612 100644 --- a/integration-test/Dockerfile +++ b/integration-test/Dockerfile @@ -1,11 +1,11 @@ # Step 1: Modules caching -FROM golang:1.20-alpine3.16 as modules +FROM golang:1.20-alpine3.16@sha256:6469405d7297f82d56195c90a3270b0806ef4bd897aa0628477d9959ab97a577 as modules COPY go.mod go.sum /modules/ WORKDIR /modules RUN go mod download # Step 2: Tests -FROM golang:1.20-alpine3.16 +FROM golang:1.20-alpine3.16@sha256:6469405d7297f82d56195c90a3270b0806ef4bd897aa0628477d9959ab97a577 COPY --from=modules /go/pkg /go/pkg COPY . /app WORKDIR /app diff --git a/internal/config/config.go b/internal/config/config.go index ca1663b8d..d3756667b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -13,6 +13,7 @@ import ( type ( // Config is the main configuration structure containing various sections for different aspects of the application. Config struct { + AccountID string `mapstructure:"account_id"` Server `mapstructure:"server"` // Server configuration for both HTTP and gRPC Log `mapstructure:"logger"` // Logging configuration Profiler `mapstructure:"profiler"` // Profiler configuration @@ -242,6 +243,7 @@ func NewConfigWithFile(dir string) (*Config, error) { // DefaultConfig - Creates default config. func DefaultConfig() *Config { return &Config{ + AccountID: "", Server: Server{ HTTP: HTTP{ Enabled: true, diff --git a/internal/info.go b/internal/info.go index fd6d36a3a..0f7d82c64 100644 --- a/internal/info.go +++ b/internal/info.go @@ -1,11 +1,7 @@ package internal -import ( - "github.com/rs/xid" -) - // Identifier is the unique identifier for the Permify. -var Identifier = xid.New().String() +var Identifier = "" /* ✨ OneLiner: Open-source authorization service inspired by Google Zanzibar @@ -20,7 +16,7 @@ var Identifier = xid.New().String() */ const ( // Version is the last release of the Permify (e.g. v0.1.0) - Version = "v0.6.5" + Version = "v0.6.9" // Banner is the view for terminal. Banner = ` diff --git a/internal/schema/linkedSchema_test.go b/internal/schema/linkedSchema_test.go index 40b7ba14c..c9044ff43 100644 --- a/internal/schema/linkedSchema_test.go +++ b/internal/schema/linkedSchema_test.go @@ -910,5 +910,16 @@ var _ = Describe("linked schema", func() { }, })) }) + + It("Case 18", func() { + Expect(LinkedEntrance{ + Kind: RelationLinkedEntrance, + TargetEntrance: &base.RelationReference{ + Type: "account", + Relation: "admin", + }, + TupleSetRelation: "", + }.LinkedEntranceKind()).Should(Equal(RelationLinkedEntrance)) + }) }) }) diff --git a/internal/storage/decorators/bundleReaderWithCircuitBreaker.go b/internal/storage/decorators/bundleReaderWithCircuitBreaker.go deleted file mode 100644 index dc7ff6a18..000000000 --- a/internal/storage/decorators/bundleReaderWithCircuitBreaker.go +++ /dev/null @@ -1,47 +0,0 @@ -package decorators - -import ( - "context" - "errors" - - "github.com/afex/hystrix-go/hystrix" - - "github.com/Permify/permify/internal/storage" - base "github.com/Permify/permify/pkg/pb/base/v1" -) - -// BundleReaderWithCircuitBreaker - Add circuit breaker behaviour to bundle reader -type BundleReaderWithCircuitBreaker struct { - delegate storage.BundleReader - timeout int -} - -// NewBundleReaderWithCircuitBreaker - Add circuit breaker behaviour to new bundle reader -func NewBundleReaderWithCircuitBreaker(delegate storage.BundleReader, timeout int) *BundleReaderWithCircuitBreaker { - return &BundleReaderWithCircuitBreaker{delegate: delegate, timeout: timeout} -} - -// Read - Reads bundles from the repository -func (r *BundleReaderWithCircuitBreaker) Read(ctx context.Context, tenantID, name string) (bundle *base.DataBundle, err error) { - type circuitBreakerResponse struct { - Bundle *base.DataBundle - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("bundleReader.read", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("bundleReader.read", func() error { - bundle, err := r.delegate.Read(ctx, tenantID, name) - output <- circuitBreakerResponse{Bundle: bundle, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Bundle, out.Error - case <-bErrors: - return nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} diff --git a/internal/storage/decorators/bundleWriterWithCircuitBreaker.go b/internal/storage/decorators/bundleWriterWithCircuitBreaker.go deleted file mode 100644 index 45af1be66..000000000 --- a/internal/storage/decorators/bundleWriterWithCircuitBreaker.go +++ /dev/null @@ -1,71 +0,0 @@ -package decorators - -import ( - "context" - "errors" - - "github.com/afex/hystrix-go/hystrix" - - "github.com/Permify/permify/internal/storage" - base "github.com/Permify/permify/pkg/pb/base/v1" -) - -// BundleWriterWithCircuitBreaker - Add circuit breaker behaviour to bundle writer -type BundleWriterWithCircuitBreaker struct { - delegate storage.BundleWriter - timeout int -} - -// NewBundleWriterWithCircuitBreaker - Add circuit breaker behaviour to new bundle writer -func NewBundleWriterWithCircuitBreaker(delegate storage.BundleWriter, timeout int) *BundleWriterWithCircuitBreaker { - return &BundleWriterWithCircuitBreaker{delegate: delegate, timeout: timeout} -} - -// Write - Write bundles from the repository -func (r *BundleWriterWithCircuitBreaker) Write(ctx context.Context, bundles []storage.Bundle) (names []string, err error) { - type circuitBreakerResponse struct { - Names []string - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("bundleWriter.write", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("bundleWriter.write", func() error { - names, err := r.delegate.Write(ctx, bundles) - output <- circuitBreakerResponse{Names: names, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Names, out.Error - case <-bErrors: - return nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// Delete - Delete bundles from the repository -func (r *BundleWriterWithCircuitBreaker) Delete(ctx context.Context, tenantID, name string) (err error) { - type circuitBreakerResponse struct { - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("bundleWriter.write", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("bundleWriter.write", func() error { - err := r.delegate.Delete(ctx, tenantID, name) - output <- circuitBreakerResponse{Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Error - case <-bErrors: - return errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} diff --git a/internal/storage/decorators/schemaReaderWithCache.go b/internal/storage/decorators/cache/schemaReader.go similarity index 67% rename from internal/storage/decorators/schemaReaderWithCache.go rename to internal/storage/decorators/cache/schemaReader.go index c75fc17a3..bd03c681c 100644 --- a/internal/storage/decorators/schemaReaderWithCache.go +++ b/internal/storage/decorators/cache/schemaReader.go @@ -1,4 +1,4 @@ -package decorators +package cache import ( "context" @@ -11,27 +11,27 @@ import ( base "github.com/Permify/permify/pkg/pb/base/v1" ) -// SchemaReaderWithCache - Add cache behaviour to schema reader -type SchemaReaderWithCache struct { +// SchemaReader - Add cache behaviour to schema reader +type SchemaReader struct { delegate storage.SchemaReader cache cache.Cache } -// NewSchemaReaderWithCache new instance of SchemaReaderWithCache -func NewSchemaReaderWithCache(delegate storage.SchemaReader, cache cache.Cache) *SchemaReaderWithCache { - return &SchemaReaderWithCache{ +// NewSchemaReader new instance of SchemaReader +func NewSchemaReader(delegate storage.SchemaReader, cache cache.Cache) *SchemaReader { + return &SchemaReader{ delegate: delegate, cache: cache, } } // ReadSchema - Read schema from the repository -func (r *SchemaReaderWithCache) ReadSchema(ctx context.Context, tenantID, version string) (schema *base.SchemaDefinition, err error) { +func (r *SchemaReader) ReadSchema(ctx context.Context, tenantID, version string) (schema *base.SchemaDefinition, err error) { return r.delegate.ReadSchema(ctx, tenantID, version) } // ReadEntityDefinition - Read entity definition from the repository -func (r *SchemaReaderWithCache) ReadEntityDefinition(ctx context.Context, tenantID, entityName, version string) (definition *base.EntityDefinition, v string, err error) { +func (r *SchemaReader) ReadEntityDefinition(ctx context.Context, tenantID, entityName, version string) (definition *base.EntityDefinition, v string, err error) { var s interface{} found := false if version != "" { @@ -54,7 +54,7 @@ func (r *SchemaReaderWithCache) ReadEntityDefinition(ctx context.Context, tenant } // ReadRuleDefinition - Read rule definition from the repository -func (r *SchemaReaderWithCache) ReadRuleDefinition(ctx context.Context, tenantID, ruleName, version string) (definition *base.RuleDefinition, v string, err error) { +func (r *SchemaReader) ReadRuleDefinition(ctx context.Context, tenantID, ruleName, version string) (definition *base.RuleDefinition, v string, err error) { var s interface{} found := false if version != "" { @@ -77,6 +77,6 @@ func (r *SchemaReaderWithCache) ReadRuleDefinition(ctx context.Context, tenantID } // HeadVersion - Finds the latest version of the schema. -func (r *SchemaReaderWithCache) HeadVersion(ctx context.Context, tenantID string) (version string, err error) { +func (r *SchemaReader) HeadVersion(ctx context.Context, tenantID string) (version string, err error) { return r.delegate.HeadVersion(ctx, tenantID) } diff --git a/internal/storage/decorators/circuitBreaker/bundleReader.go b/internal/storage/decorators/circuitBreaker/bundleReader.go new file mode 100644 index 000000000..70fe1affc --- /dev/null +++ b/internal/storage/decorators/circuitBreaker/bundleReader.go @@ -0,0 +1,32 @@ +package circuitBreaker + +import ( + "context" + + "github.com/sony/gobreaker" + + "github.com/Permify/permify/internal/storage" + base "github.com/Permify/permify/pkg/pb/base/v1" +) + +// BundleReader - Add circuit breaker behaviour to bundle reader +type BundleReader struct { + delegate storage.BundleReader + cb *gobreaker.CircuitBreaker +} + +// NewBundleReader - Add circuit breaker behaviour to new bundle reader +func NewBundleReader(delegate storage.BundleReader, cb *gobreaker.CircuitBreaker) *BundleReader { + return &BundleReader{delegate: delegate, cb: cb} +} + +// Read - Reads bundles from the repository +func (r *BundleReader) Read(ctx context.Context, tenantID, name string) (bundle *base.DataBundle, err error) { + response, err := r.cb.Execute(func() (interface{}, error) { + return r.delegate.Read(ctx, tenantID, name) + }) + if err != nil { + return nil, err + } + return response.(*base.DataBundle), nil +} diff --git a/internal/storage/decorators/circuitBreaker/dataReader.go b/internal/storage/decorators/circuitBreaker/dataReader.go new file mode 100644 index 000000000..e53594dc1 --- /dev/null +++ b/internal/storage/decorators/circuitBreaker/dataReader.go @@ -0,0 +1,151 @@ +package circuitBreaker + +import ( + "context" + + "github.com/sony/gobreaker" + + "github.com/Permify/permify/internal/storage" + "github.com/Permify/permify/pkg/database" + base "github.com/Permify/permify/pkg/pb/base/v1" + "github.com/Permify/permify/pkg/token" +) + +// DataReader - Add circuit breaker behaviour to data reader +type DataReader struct { + delegate storage.DataReader + cb *gobreaker.CircuitBreaker +} + +// NewDataReader - Add circuit breaker behaviour to new data reader +func NewDataReader(delegate storage.DataReader, cb *gobreaker.CircuitBreaker) *DataReader { + return &DataReader{delegate: delegate, cb: cb} +} + +// QueryRelationships - Reads relation tuples from the repository +func (r *DataReader) QueryRelationships(ctx context.Context, tenantID string, filter *base.TupleFilter, token string) (*database.TupleIterator, error) { + response, err := r.cb.Execute(func() (interface{}, error) { + return r.delegate.QueryRelationships(ctx, tenantID, filter, token) + }) + if err != nil { + return nil, err + } + return response.(*database.TupleIterator), nil +} + +// ReadRelationships - Reads relation tuples from the repository with different options. +func (r *DataReader) ReadRelationships(ctx context.Context, tenantID string, filter *base.TupleFilter, token string, pagination database.Pagination) (collection *database.TupleCollection, ct database.EncodedContinuousToken, err error) { + type circuitBreakerResponse struct { + Collection *database.TupleCollection + ContinuousToken database.EncodedContinuousToken + } + + response, err := r.cb.Execute(func() (interface{}, error) { + var err error + var resp circuitBreakerResponse + resp.Collection, resp.ContinuousToken, err = r.delegate.ReadRelationships(ctx, tenantID, filter, token, pagination) + return resp, err + }) + if err != nil { + return nil, nil, err + } + + resp := response.(circuitBreakerResponse) + return resp.Collection, resp.ContinuousToken, nil +} + +// QuerySingleAttribute - Reads a single attribute from the repository. +func (r *DataReader) QuerySingleAttribute(ctx context.Context, tenantID string, filter *base.AttributeFilter, token string) (*base.Attribute, error) { + response, err := r.cb.Execute(func() (interface{}, error) { + return r.delegate.QuerySingleAttribute(ctx, tenantID, filter, token) + }) + if err != nil { + return nil, err + } + return response.(*base.Attribute), nil +} + +// QueryAttributes - Reads multiple attributes from the repository. +func (r *DataReader) QueryAttributes(ctx context.Context, tenantID string, filter *base.AttributeFilter, token string) (*database.AttributeIterator, error) { + response, err := r.cb.Execute(func() (interface{}, error) { + return r.delegate.QueryAttributes(ctx, tenantID, filter, token) + }) + if err != nil { + return nil, err + } + return response.(*database.AttributeIterator), nil +} + +// ReadAttributes - Reads multiple attributes from the repository with different options. +func (r *DataReader) ReadAttributes(ctx context.Context, tenantID string, filter *base.AttributeFilter, token string, pagination database.Pagination) (collection *database.AttributeCollection, ct database.EncodedContinuousToken, err error) { + type circuitBreakerResponse struct { + Collection *database.AttributeCollection + ContinuousToken database.EncodedContinuousToken + } + + response, err := r.cb.Execute(func() (interface{}, error) { + var err error + var resp circuitBreakerResponse + resp.Collection, resp.ContinuousToken, err = r.delegate.ReadAttributes(ctx, tenantID, filter, token, pagination) + return resp, err + }) + if err != nil { + return nil, nil, err + } + + resp := response.(circuitBreakerResponse) + return resp.Collection, resp.ContinuousToken, nil +} + +// QueryUniqueEntities - Reads unique entities from the repository with different options. +func (r *DataReader) QueryUniqueEntities(ctx context.Context, tenantID, name, token string, pagination database.Pagination) (ids []string, ct database.EncodedContinuousToken, err error) { + type circuitBreakerResponse struct { + IDs []string + ContinuousToken database.EncodedContinuousToken + } + + response, err := r.cb.Execute(func() (interface{}, error) { + var err error + var resp circuitBreakerResponse + resp.IDs, resp.ContinuousToken, err = r.delegate.QueryUniqueEntities(ctx, tenantID, name, token, pagination) + return resp, err + }) + if err != nil { + return nil, nil, err + } + + resp := response.(circuitBreakerResponse) + return resp.IDs, resp.ContinuousToken, nil +} + +// QueryUniqueSubjectReferences - Reads unique subject references from the repository with different options. +func (r *DataReader) QueryUniqueSubjectReferences(ctx context.Context, tenantID string, subjectReference *base.RelationReference, token string, pagination database.Pagination) (ids []string, ct database.EncodedContinuousToken, err error) { + type circuitBreakerResponse struct { + IDs []string + ContinuousToken database.EncodedContinuousToken + } + + response, err := r.cb.Execute(func() (interface{}, error) { + var err error + var resp circuitBreakerResponse + resp.IDs, resp.ContinuousToken, err = r.delegate.QueryUniqueSubjectReferences(ctx, tenantID, subjectReference, token, pagination) + return resp, err + }) + if err != nil { + return nil, nil, err + } + + resp := response.(circuitBreakerResponse) + return resp.IDs, resp.ContinuousToken, nil +} + +// HeadSnapshot - Reads the latest version of the snapshot from the repository. +func (r *DataReader) HeadSnapshot(ctx context.Context, tenantID string) (token.SnapToken, error) { + response, err := r.cb.Execute(func() (interface{}, error) { + return r.delegate.HeadSnapshot(ctx, tenantID) + }) + if err != nil { + return nil, err + } + return response.(token.SnapToken), nil +} diff --git a/internal/storage/decorators/circuitBreaker/schemaReader.go b/internal/storage/decorators/circuitBreaker/schemaReader.go new file mode 100644 index 000000000..4410198c2 --- /dev/null +++ b/internal/storage/decorators/circuitBreaker/schemaReader.go @@ -0,0 +1,85 @@ +package circuitBreaker + +import ( + "context" + + "github.com/sony/gobreaker" + + "github.com/Permify/permify/internal/storage" + base "github.com/Permify/permify/pkg/pb/base/v1" +) + +// SchemaReader - Add circuit breaker behaviour to schema reader +type SchemaReader struct { + delegate storage.SchemaReader + cb *gobreaker.CircuitBreaker +} + +// NewSchemaReader - Add circuit breaker behaviour to new schema reader +func NewSchemaReader(delegate storage.SchemaReader, cb *gobreaker.CircuitBreaker) *SchemaReader { + return &SchemaReader{delegate: delegate, cb: cb} +} + +// ReadSchema - Read schema from repository +func (r *SchemaReader) ReadSchema(ctx context.Context, tenantID, version string) (*base.SchemaDefinition, error) { + response, err := r.cb.Execute(func() (interface{}, error) { + return r.delegate.ReadSchema(ctx, tenantID, version) + }) + if err != nil { + return nil, err + } + return response.(*base.SchemaDefinition), nil +} + +// ReadEntityDefinition - Read entity definition from repository +func (r *SchemaReader) ReadEntityDefinition(ctx context.Context, tenantID, entityName, version string) (*base.EntityDefinition, string, error) { + type circuitBreakerResponse struct { + Definition *base.EntityDefinition + Version string + } + + response, err := r.cb.Execute(func() (interface{}, error) { + var err error + var resp circuitBreakerResponse + resp.Definition, resp.Version, err = r.delegate.ReadEntityDefinition(ctx, tenantID, entityName, version) + return resp, err + }) + if err != nil { + return nil, "", err + } + + resp := response.(circuitBreakerResponse) + return resp.Definition, resp.Version, nil +} + +// ReadRuleDefinition - Read rule definition from repository +func (r *SchemaReader) ReadRuleDefinition(ctx context.Context, tenantID, ruleName, version string) (*base.RuleDefinition, string, error) { + type circuitBreakerResponse struct { + Definition *base.RuleDefinition + Version string + } + + response, err := r.cb.Execute(func() (interface{}, error) { + var err error + var resp circuitBreakerResponse + resp.Definition, resp.Version, err = r.delegate.ReadRuleDefinition(ctx, tenantID, ruleName, version) + return resp, err + }) + if err != nil { + return nil, "", err + } + + resp := response.(circuitBreakerResponse) + return resp.Definition, resp.Version, nil +} + +// HeadVersion - Finds the latest version of the schema. +func (r *SchemaReader) HeadVersion(ctx context.Context, tenantID string) (version string, err error) { + response, err := r.cb.Execute(func() (interface{}, error) { + return r.delegate.HeadVersion(ctx, tenantID) + }) + if err != nil { + return "", err + } + return response.(string), nil +} diff --git a/internal/storage/decorators/circuitBreaker/tenantReader.go b/internal/storage/decorators/circuitBreaker/tenantReader.go new file mode 100644 index 000000000..d8278095d --- /dev/null +++ b/internal/storage/decorators/circuitBreaker/tenantReader.go @@ -0,0 +1,43 @@ +package circuitBreaker + +import ( + "context" + + "github.com/sony/gobreaker" + + "github.com/Permify/permify/internal/storage" + "github.com/Permify/permify/pkg/database" + base "github.com/Permify/permify/pkg/pb/base/v1" +) + +// TenantReader - Add circuit breaker behaviour to tenant reader +type TenantReader struct { + delegate storage.TenantReader + cb *gobreaker.CircuitBreaker +} + +// NewTenantReader - Add circuit breaker behaviour to new tenant reader +func NewTenantReader(delegate storage.TenantReader, cb *gobreaker.CircuitBreaker) *TenantReader { + return &TenantReader{delegate: delegate, cb: cb} +} + +// ListTenants - List tenants from the repository +func (r *TenantReader) ListTenants(ctx context.Context, pagination database.Pagination) (tenants []*base.Tenant, ct database.EncodedContinuousToken, err error) { + type circuitBreakerResponse struct { + Tenants []*base.Tenant + Ct database.EncodedContinuousToken + } + + response, err := r.cb.Execute(func() (interface{}, error) { + var err error + var resp circuitBreakerResponse + resp.Tenants, resp.Ct, err = r.delegate.ListTenants(ctx, pagination) + return resp, err + }) + if err != nil { + return nil, nil, err + } + + resp := response.(circuitBreakerResponse) + return resp.Tenants, resp.Ct, nil +} diff --git a/internal/storage/decorators/dataReaderWithCircuitBreaker.go b/internal/storage/decorators/dataReaderWithCircuitBreaker.go deleted file mode 100644 index 67e1886a7..000000000 --- a/internal/storage/decorators/dataReaderWithCircuitBreaker.go +++ /dev/null @@ -1,228 +0,0 @@ -package decorators - -import ( - "context" - "errors" - - "github.com/afex/hystrix-go/hystrix" - - "github.com/Permify/permify/internal/storage" - "github.com/Permify/permify/pkg/database" - base "github.com/Permify/permify/pkg/pb/base/v1" - "github.com/Permify/permify/pkg/token" -) - -// DataReaderWithCircuitBreaker - Add circuit breaker behaviour to data reader -type DataReaderWithCircuitBreaker struct { - delegate storage.DataReader - timeout int -} - -// NewDataReaderWithCircuitBreaker - Add circuit breaker behaviour to new data reader -func NewDataReaderWithCircuitBreaker(delegate storage.DataReader, timeout int) *DataReaderWithCircuitBreaker { - return &DataReaderWithCircuitBreaker{delegate: delegate, timeout: timeout} -} - -// QueryRelationships - Reads relation tuples from the repository -func (r *DataReaderWithCircuitBreaker) QueryRelationships(ctx context.Context, tenantID string, filter *base.TupleFilter, token string) (*database.TupleIterator, error) { - type circuitBreakerResponse struct { - Iterator *database.TupleIterator - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("dataReader.queryRelationships", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("dataReader.queryRelationships", func() error { - tup, err := r.delegate.QueryRelationships(ctx, tenantID, filter, token) - output <- circuitBreakerResponse{Iterator: tup, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Iterator, out.Error - case <-bErrors: - return nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// ReadRelationships - Reads relation tuples from the repository with different options. -func (r *DataReaderWithCircuitBreaker) ReadRelationships(ctx context.Context, tenantID string, filter *base.TupleFilter, token string, pagination database.Pagination) (collection *database.TupleCollection, ct database.EncodedContinuousToken, err error) { - type circuitBreakerResponse struct { - Collection *database.TupleCollection - ContinuousToken database.EncodedContinuousToken - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("dataReader.readRelationships", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("dataReader.readRelationships", func() error { - tup, ct, err := r.delegate.ReadRelationships(ctx, tenantID, filter, token, pagination) - output <- circuitBreakerResponse{Collection: tup, ContinuousToken: ct, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Collection, out.ContinuousToken, out.Error - case <-bErrors: - return nil, nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// QuerySingleAttribute - Reads a single attribute from the repository. -func (r *DataReaderWithCircuitBreaker) QuerySingleAttribute(ctx context.Context, tenantID string, filter *base.AttributeFilter, token string) (*base.Attribute, error) { - type circuitBreakerResponse struct { - Attribute *base.Attribute - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("dataReader.querySingleAttribute", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("dataReader.querySingleAttribute", func() error { - attr, err := r.delegate.QuerySingleAttribute(ctx, tenantID, filter, token) - output <- circuitBreakerResponse{Attribute: attr, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Attribute, out.Error - case <-bErrors: - return nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// QueryAttributes - Reads multiple attributes from the repository. -func (r *DataReaderWithCircuitBreaker) QueryAttributes(ctx context.Context, tenantID string, filter *base.AttributeFilter, token string) (*database.AttributeIterator, error) { - type circuitBreakerResponse struct { - Iterator *database.AttributeIterator - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("dataReader.queryAttributes", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("dataReader.queryAttributes", func() error { - attr, err := r.delegate.QueryAttributes(ctx, tenantID, filter, token) - output <- circuitBreakerResponse{Iterator: attr, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Iterator, out.Error - case <-bErrors: - return nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// ReadAttributes - Reads multiple attributes from the repository with different options. -func (r *DataReaderWithCircuitBreaker) ReadAttributes(ctx context.Context, tenantID string, filter *base.AttributeFilter, token string, pagination database.Pagination) (collection *database.AttributeCollection, ct database.EncodedContinuousToken, err error) { - type circuitBreakerResponse struct { - Collection *database.AttributeCollection - ContinuousToken database.EncodedContinuousToken - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("dataReader.readAttributes", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("dataReader.readAttributes", func() error { - attr, ct, err := r.delegate.ReadAttributes(ctx, tenantID, filter, token, pagination) - output <- circuitBreakerResponse{Collection: attr, ContinuousToken: ct, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Collection, out.ContinuousToken, out.Error - case <-bErrors: - return nil, nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// QueryUniqueEntities - Reads unique entities from the repository with different options. -func (r *DataReaderWithCircuitBreaker) QueryUniqueEntities(ctx context.Context, tenantID, name, token string, pagination database.Pagination) (ids []string, ct database.EncodedContinuousToken, err error) { - type circuitBreakerResponse struct { - IDs []string - ContinuousToken database.EncodedContinuousToken - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("dataReader.queryUniqueEntities", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("dataReader.queryUniqueEntities", func() error { - ids, ct, err := r.delegate.QueryUniqueEntities(ctx, tenantID, name, token, pagination) - output <- circuitBreakerResponse{IDs: ids, ContinuousToken: ct, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.IDs, out.ContinuousToken, out.Error - case <-bErrors: - return nil, nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// QueryUniqueSubjectReferences - Reads unique subject references from the repository with different options. -func (r *DataReaderWithCircuitBreaker) QueryUniqueSubjectReferences(ctx context.Context, tenantID string, subjectReference *base.RelationReference, token string, pagination database.Pagination) (ids []string, ct database.EncodedContinuousToken, err error) { - type circuitBreakerResponse struct { - IDs []string - ContinuousToken database.EncodedContinuousToken - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("dataReader.queryUniqueSubjectReferences", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("dataReader.queryUniqueSubjectReferences", func() error { - ids, ct, err := r.delegate.QueryUniqueSubjectReferences(ctx, tenantID, subjectReference, token, pagination) - output <- circuitBreakerResponse{IDs: ids, ContinuousToken: ct, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.IDs, out.ContinuousToken, out.Error - case <-bErrors: - return nil, nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// HeadSnapshot - Reads the latest version of the snapshot from the repository. -func (r *DataReaderWithCircuitBreaker) HeadSnapshot(ctx context.Context, tenantID string) (token.SnapToken, error) { - type circuitBreakerResponse struct { - Token token.SnapToken - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("relationshipReader.headSnapshot", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("relationshipReader.headSnapshot", func() error { - tok, err := r.delegate.HeadSnapshot(ctx, tenantID) - output <- circuitBreakerResponse{Token: tok, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Token, out.Error - case <-bErrors: - return nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} diff --git a/internal/storage/decorators/dataWriterWithCircuitBreaker.go b/internal/storage/decorators/dataWriterWithCircuitBreaker.go deleted file mode 100644 index 7e4e4cbe3..000000000 --- a/internal/storage/decorators/dataWriterWithCircuitBreaker.go +++ /dev/null @@ -1,102 +0,0 @@ -package decorators - -import ( - "context" - "errors" - - "github.com/afex/hystrix-go/hystrix" - - "github.com/Permify/permify/internal/storage" - "github.com/Permify/permify/pkg/database" - base "github.com/Permify/permify/pkg/pb/base/v1" - "github.com/Permify/permify/pkg/token" -) - -// DataWriterWithCircuitBreaker - Add circuit breaker behaviour to data writer -type DataWriterWithCircuitBreaker struct { - delegate storage.DataWriter - timeout int -} - -// NewDataWriterWithCircuitBreaker - Add circuit breaker behaviour to new data writer -func NewDataWriterWithCircuitBreaker(delegate storage.DataWriter, timeout int) *DataWriterWithCircuitBreaker { - return &DataWriterWithCircuitBreaker{delegate: delegate, timeout: timeout} -} - -// WriteRelationships - Write relation tuples from the repository -func (r *DataWriterWithCircuitBreaker) Write(ctx context.Context, tenantID string, tupleCollection *database.TupleCollection, attributeCollection *database.AttributeCollection) (token.EncodedSnapToken, error) { - type circuitBreakerResponse struct { - Token token.EncodedSnapToken - Error error - } - - output := make(chan circuitBreakerResponse, 1) - - hystrix.ConfigureCommand("dataWriter.write", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("dataWriter.write", func() error { - t, err := r.delegate.Write(ctx, tenantID, tupleCollection, attributeCollection) - output <- circuitBreakerResponse{Token: t, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Token, out.Error - case <-bErrors: - return nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// Delete - Delete relation tuples and attributes from the repository -func (r *DataWriterWithCircuitBreaker) Delete(ctx context.Context, tenantID string, tupleFilter *base.TupleFilter, attrFilter *base.AttributeFilter) (token.EncodedSnapToken, error) { - type circuitBreakerResponse struct { - Token token.EncodedSnapToken - Error error - } - - output := make(chan circuitBreakerResponse, 1) - - hystrix.ConfigureCommand("dataWriter.deleteRelationships", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("dataWriter.deleteRelationships", func() error { - t, err := r.delegate.Delete(ctx, tenantID, tupleFilter, attrFilter) - output <- circuitBreakerResponse{Token: t, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Token, out.Error - case <-bErrors: - return nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// RunBundle - -func (r *DataWriterWithCircuitBreaker) RunBundle(ctx context.Context, tenantID string, arguments map[string]string, b *base.DataBundle) (token.EncodedSnapToken, error) { - type circuitBreakerResponse struct { - Token token.EncodedSnapToken - Error error - } - - output := make(chan circuitBreakerResponse, 1) - - hystrix.ConfigureCommand("dataWriter.runBundle", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("dataWriter.runBundle", func() error { - t, err := r.delegate.RunBundle(ctx, tenantID, arguments, b) - output <- circuitBreakerResponse{Token: t, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Token, out.Error - case <-bErrors: - return nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} diff --git a/internal/storage/decorators/schemaReaderWithCircuitBreaker.go b/internal/storage/decorators/schemaReaderWithCircuitBreaker.go deleted file mode 100644 index 64da76700..000000000 --- a/internal/storage/decorators/schemaReaderWithCircuitBreaker.go +++ /dev/null @@ -1,128 +0,0 @@ -package decorators - -import ( - "context" - "errors" - - "github.com/afex/hystrix-go/hystrix" - - "github.com/Permify/permify/internal/storage" - base "github.com/Permify/permify/pkg/pb/base/v1" -) - -// SchemaReaderWithCircuitBreaker - Add circuit breaker behaviour to schema reader -type SchemaReaderWithCircuitBreaker struct { - delegate storage.SchemaReader - timeout int -} - -// NewSchemaReaderWithCircuitBreaker - Add circuit breaker behaviour to new schema reader -func NewSchemaReaderWithCircuitBreaker(delegate storage.SchemaReader, timeout int) *SchemaReaderWithCircuitBreaker { - return &SchemaReaderWithCircuitBreaker{delegate: delegate, timeout: timeout} -} - -// ReadSchema - Read schema from repository -func (r *SchemaReaderWithCircuitBreaker) ReadSchema(ctx context.Context, tenantID, version string) (*base.SchemaDefinition, error) { - type circuitBreakerResponse struct { - Schema *base.SchemaDefinition - Error error - } - - output := make(chan circuitBreakerResponse, 1) - - hystrix.ConfigureCommand("schemaReader.readSchema", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("schemaReader.readSchema", func() error { - sch, err := r.delegate.ReadSchema(ctx, tenantID, version) - output <- circuitBreakerResponse{Schema: sch, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Schema, out.Error - case <-bErrors: - return nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// ReadEntityDefinition - Read entity definition from repository -func (r *SchemaReaderWithCircuitBreaker) ReadEntityDefinition(ctx context.Context, tenantID, entityName, version string) (*base.EntityDefinition, string, error) { - type circuitBreakerResponse struct { - Definition *base.EntityDefinition - Version string - Error error - } - - output := make(chan circuitBreakerResponse, 1) - - hystrix.ConfigureCommand("schemaReader.readEntityDefinition", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("schemaReader.readEntityDefinition", func() error { - conf, v, err := r.delegate.ReadEntityDefinition(ctx, tenantID, entityName, version) - output <- circuitBreakerResponse{Definition: conf, Version: v, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Definition, out.Version, out.Error - case <-bErrors: - return nil, "", errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// ReadRuleDefinition - Read rule definition from repository -func (r *SchemaReaderWithCircuitBreaker) ReadRuleDefinition(ctx context.Context, tenantID, ruleName, version string) (*base.RuleDefinition, string, error) { - type circuitBreakerResponse struct { - Definition *base.RuleDefinition - Version string - Error error - } - - output := make(chan circuitBreakerResponse, 1) - - hystrix.ConfigureCommand("schemaReader.readRuleDefinition", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("schemaReader.readRuleDefinition", func() error { - conf, v, err := r.delegate.ReadRuleDefinition(ctx, tenantID, ruleName, version) - output <- circuitBreakerResponse{Definition: conf, Version: v, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Definition, out.Version, out.Error - case <-bErrors: - return nil, "", errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// HeadVersion - Finds the latest version of the schema. -func (r *SchemaReaderWithCircuitBreaker) HeadVersion(ctx context.Context, tenantID string) (version string, err error) { - type circuitBreakerResponse struct { - Version string - Error error - } - - output := make(chan circuitBreakerResponse, 1) - - hystrix.ConfigureCommand("schemaReader.headVersion", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("schemaReader.headVersion", func() error { - v, err := r.delegate.HeadVersion(ctx, tenantID) - output <- circuitBreakerResponse{Version: v, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Version, out.Error - case <-bErrors: - return "", errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} diff --git a/internal/storage/decorators/schemaWriterWithCircuitBreaker.go b/internal/storage/decorators/schemaWriterWithCircuitBreaker.go deleted file mode 100644 index b5a3e4e67..000000000 --- a/internal/storage/decorators/schemaWriterWithCircuitBreaker.go +++ /dev/null @@ -1,47 +0,0 @@ -package decorators - -import ( - "context" - "errors" - - "github.com/afex/hystrix-go/hystrix" - - "github.com/Permify/permify/internal/storage" - base "github.com/Permify/permify/pkg/pb/base/v1" -) - -// SchemaWriterWithCircuitBreaker - Add circuit breaker behaviour to schema writer -type SchemaWriterWithCircuitBreaker struct { - delegate storage.SchemaWriter - timeout int -} - -// NewSchemaWriterWithCircuitBreaker - Add circuit breaker behaviour to new schema writer -func NewSchemaWriterWithCircuitBreaker(delegate storage.SchemaWriter, timeout int) *SchemaWriterWithCircuitBreaker { - return &SchemaWriterWithCircuitBreaker{delegate: delegate, timeout: timeout} -} - -// WriteSchema - Write schema to repository -func (r *SchemaWriterWithCircuitBreaker) WriteSchema(ctx context.Context, definitions []storage.SchemaDefinition) error { - type circuitBreakerResponse struct { - Error error - } - - output := make(chan circuitBreakerResponse, 1) - - hystrix.ConfigureCommand("schemaWriter.writeSchema", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("schemaWriter.writeSchema", func() error { - err := r.delegate.WriteSchema(ctx, definitions) - output <- circuitBreakerResponse{Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Error - case <-bErrors: - return errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} diff --git a/internal/storage/decorators/singleflight/dataReader.go b/internal/storage/decorators/singleflight/dataReader.go new file mode 100644 index 000000000..1ee208d17 --- /dev/null +++ b/internal/storage/decorators/singleflight/dataReader.go @@ -0,0 +1,66 @@ +package singleflight + +import ( + "context" + + "resenje.org/singleflight" + + "github.com/Permify/permify/internal/storage" + "github.com/Permify/permify/pkg/database" + base "github.com/Permify/permify/pkg/pb/base/v1" + "github.com/Permify/permify/pkg/token" +) + +// DataReader - Add singleflight behaviour to data reader +type DataReader struct { + delegate storage.DataReader + group singleflight.Group[string, token.SnapToken] +} + +// NewDataReader - Add singleflight behaviour to new data reader +func NewDataReader(delegate storage.DataReader) *DataReader { + return &DataReader{delegate: delegate} +} + +// QueryRelationships - Reads relation tuples from the repository +func (r *DataReader) QueryRelationships(ctx context.Context, tenantID string, filter *base.TupleFilter, token string) (*database.TupleIterator, error) { + return r.delegate.QueryRelationships(ctx, tenantID, filter, token) +} + +// ReadRelationships - Reads relation tuples from the repository with different options. +func (r *DataReader) ReadRelationships(ctx context.Context, tenantID string, filter *base.TupleFilter, token string, pagination database.Pagination) (collection *database.TupleCollection, ct database.EncodedContinuousToken, err error) { + return r.delegate.ReadRelationships(ctx, tenantID, filter, token, pagination) +} + +// QuerySingleAttribute - Reads a single attribute from the repository. +func (r *DataReader) QuerySingleAttribute(ctx context.Context, tenantID string, filter *base.AttributeFilter, token string) (*base.Attribute, error) { + return r.delegate.QuerySingleAttribute(ctx, tenantID, filter, token) +} + +// QueryAttributes - Reads multiple attributes from the repository. +func (r *DataReader) QueryAttributes(ctx context.Context, tenantID string, filter *base.AttributeFilter, token string) (*database.AttributeIterator, error) { + return r.delegate.QueryAttributes(ctx, tenantID, filter, token) +} + +// ReadAttributes - Reads multiple attributes from the repository with different options. +func (r *DataReader) ReadAttributes(ctx context.Context, tenantID string, filter *base.AttributeFilter, token string, pagination database.Pagination) (collection *database.AttributeCollection, ct database.EncodedContinuousToken, err error) { + return r.delegate.ReadAttributes(ctx, tenantID, filter, token, pagination) +} + +// QueryUniqueEntities - Reads unique entities from the repository with different options. +func (r *DataReader) QueryUniqueEntities(ctx context.Context, tenantID, name, token string, pagination database.Pagination) (ids []string, ct database.EncodedContinuousToken, err error) { + return r.delegate.QueryUniqueEntities(ctx, tenantID, name, token, pagination) +} + +// QueryUniqueSubjectReferences - Reads unique subject references from the repository with different options. +func (r *DataReader) QueryUniqueSubjectReferences(ctx context.Context, tenantID string, subjectReference *base.RelationReference, token string, pagination database.Pagination) (ids []string, ct database.EncodedContinuousToken, err error) { + return r.delegate.QueryUniqueSubjectReferences(ctx, tenantID, subjectReference, token, pagination) +} + +// HeadSnapshot - Reads the latest version of the snapshot from the repository. +func (r *DataReader) HeadSnapshot(ctx context.Context, tenantID string) (token.SnapToken, error) { + rev, _, err := r.group.Do(ctx, "", func(ctx context.Context) (token.SnapToken, error) { + return r.delegate.HeadSnapshot(ctx, tenantID) + }) + return rev, err +} diff --git a/internal/storage/decorators/singleflight/schemaReader.go b/internal/storage/decorators/singleflight/schemaReader.go new file mode 100644 index 000000000..7253f64ea --- /dev/null +++ b/internal/storage/decorators/singleflight/schemaReader.go @@ -0,0 +1,44 @@ +package singleflight + +import ( + "context" + + "resenje.org/singleflight" + + "github.com/Permify/permify/internal/storage" + base "github.com/Permify/permify/pkg/pb/base/v1" +) + +// SchemaReader - Add singleflight behaviour to schema reader +type SchemaReader struct { + delegate storage.SchemaReader + group singleflight.Group[string, string] +} + +// NewSchemaReader - Add singleflight behaviour to new schema reader +func NewSchemaReader(delegate storage.SchemaReader) *SchemaReader { + return &SchemaReader{delegate: delegate} +} + +// ReadSchema - Read schema from repository +func (r *SchemaReader) ReadSchema(ctx context.Context, tenantID, version string) (*base.SchemaDefinition, error) { + return r.delegate.ReadSchema(ctx, tenantID, version) +} + +// ReadEntityDefinition - Read entity definition from repository +func (r *SchemaReader) ReadEntityDefinition(ctx context.Context, tenantID, entityName, version string) (*base.EntityDefinition, string, error) { + return r.delegate.ReadEntityDefinition(ctx, tenantID, entityName, version) +} + +// ReadRuleDefinition - Read rule definition from repository +func (r *SchemaReader) ReadRuleDefinition(ctx context.Context, tenantID, ruleName, version string) (*base.RuleDefinition, string, error) { + return r.delegate.ReadRuleDefinition(ctx, tenantID, ruleName, version) +} + +// HeadVersion - Finds the latest version of the schema. +func (r *SchemaReader) HeadVersion(ctx context.Context, tenantID string) (version string, err error) { + rev, _, err := r.group.Do(ctx, "", func(ctx context.Context) (string, error) { + return r.delegate.HeadVersion(ctx, tenantID) + }) + return rev, err +} diff --git a/internal/storage/decorators/tenantReaderWithCircuitBreaker.go b/internal/storage/decorators/tenantReaderWithCircuitBreaker.go deleted file mode 100644 index ef832062d..000000000 --- a/internal/storage/decorators/tenantReaderWithCircuitBreaker.go +++ /dev/null @@ -1,49 +0,0 @@ -package decorators - -import ( - "context" - - "github.com/afex/hystrix-go/hystrix" - "github.com/pkg/errors" - - "github.com/Permify/permify/internal/storage" - "github.com/Permify/permify/pkg/database" - base "github.com/Permify/permify/pkg/pb/base/v1" -) - -// TenantReaderWithCircuitBreaker - Add circuit breaker behaviour to tenant reader -type TenantReaderWithCircuitBreaker struct { - delegate storage.TenantReader - timeout int -} - -// NewTenantReaderWithCircuitBreaker - Add circuit breaker behaviour to new tenant reader -func NewTenantReaderWithCircuitBreaker(delegate storage.TenantReader, timeout int) *TenantReaderWithCircuitBreaker { - return &TenantReaderWithCircuitBreaker{delegate: delegate, timeout: timeout} -} - -// ListTenants - List tenants from the repository -func (r *TenantReaderWithCircuitBreaker) ListTenants(ctx context.Context, pagination database.Pagination) (tenants []*base.Tenant, ct database.EncodedContinuousToken, err error) { - type circuitBreakerResponse struct { - Tenants []*base.Tenant - Ct database.EncodedContinuousToken - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("tenantReader.listTenants", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("tenantReader.listTenants", func() error { - tenants, ct, err := r.delegate.ListTenants(ctx, pagination) - output <- circuitBreakerResponse{Tenants: tenants, Ct: ct, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Tenants, out.Ct, out.Error - case <-bErrors: - return nil, nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} diff --git a/internal/storage/decorators/tenantWriterWithCircuitBreaker.go b/internal/storage/decorators/tenantWriterWithCircuitBreaker.go deleted file mode 100644 index 9167096f3..000000000 --- a/internal/storage/decorators/tenantWriterWithCircuitBreaker.go +++ /dev/null @@ -1,72 +0,0 @@ -package decorators - -import ( - "context" - "errors" - - "github.com/afex/hystrix-go/hystrix" - - "github.com/Permify/permify/internal/storage" - base "github.com/Permify/permify/pkg/pb/base/v1" -) - -// TenantWriterWithCircuitBreaker - Add circuit breaker behaviour to tenant writer -type TenantWriterWithCircuitBreaker struct { - delegate storage.TenantWriter - timeout int -} - -// NewTenantWriterWithCircuitBreaker - Add circuit breaker behaviour to new bundle reader -func NewTenantWriterWithCircuitBreaker(delegate storage.TenantWriter, timeout int) *TenantWriterWithCircuitBreaker { - return &TenantWriterWithCircuitBreaker{delegate: delegate, timeout: timeout} -} - -// CreateTenant - Create tenant from the repository -func (r *TenantWriterWithCircuitBreaker) CreateTenant(ctx context.Context, id, name string) (result *base.Tenant, err error) { - type circuitBreakerResponse struct { - Tenant *base.Tenant - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("tenantWriter.createTenant", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("tenantWriter.createTenant", func() error { - tenant, err := r.delegate.CreateTenant(ctx, id, name) - output <- circuitBreakerResponse{Tenant: tenant, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Tenant, out.Error - case <-bErrors: - return nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} - -// DeleteTenant - Delete tenant from the repository -func (r *TenantWriterWithCircuitBreaker) DeleteTenant(ctx context.Context, tenantID string) (result *base.Tenant, err error) { - type circuitBreakerResponse struct { - Tenant *base.Tenant - Error error - } - - output := make(chan circuitBreakerResponse, 1) - hystrix.ConfigureCommand("tenantWriter.deleteTenant", hystrix.CommandConfig{Timeout: r.timeout}) - bErrors := hystrix.Go("tenantWriter.deleteTenant", func() error { - tenant, err := r.delegate.DeleteTenant(ctx, tenantID) - output <- circuitBreakerResponse{Tenant: tenant, Error: err} - return nil - }, func(err error) error { - return nil - }) - - select { - case out := <-output: - return out.Tenant, out.Error - case <-bErrors: - return nil, errors.New(base.ErrorCode_ERROR_CODE_CIRCUIT_BREAKER.String()) - } -} diff --git a/internal/storage/memory/bundleReader_test.go b/internal/storage/memory/bundleReader_test.go index d1b252e92..a8ccb52bb 100644 --- a/internal/storage/memory/bundleReader_test.go +++ b/internal/storage/memory/bundleReader_test.go @@ -13,7 +13,7 @@ import ( base "github.com/Permify/permify/pkg/pb/base/v1" ) -var _ = Describe("BundleReader memory", func() { +var _ = Describe("BundleReader", func() { var db *memory.Memory var bundleWriter *BundleWriter var bundleReader *BundleReader diff --git a/internal/storage/memory/dataReader_test.go b/internal/storage/memory/dataReader_test.go new file mode 100644 index 000000000..8c8426e89 --- /dev/null +++ b/internal/storage/memory/dataReader_test.go @@ -0,0 +1,491 @@ +package memory + +import ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/Permify/permify/internal/storage/memory/migrations" + "github.com/Permify/permify/pkg/attribute" + "github.com/Permify/permify/pkg/database" + "github.com/Permify/permify/pkg/database/memory" + base "github.com/Permify/permify/pkg/pb/base/v1" + "github.com/Permify/permify/pkg/tuple" +) + +var _ = Describe("DataReader", func() { + var db *memory.Memory + + var dataWriter *DataWriter + var dataReader *DataReader + + BeforeEach(func() { + database, err := memory.New(migrations.Schema) + Expect(err).ShouldNot(HaveOccurred()) + db = database + + dataWriter = NewDataWriter(db) + dataReader = NewDataReader(db) + }) + + AfterEach(func() { + err := db.Close() + Expect(err).ShouldNot(HaveOccurred()) + }) + + Context("Query Relationships", func() { + It("should write relationships and query relationships correctly", func() { + ctx := context.Background() + + tup1, err := tuple.Tuple("organization:organization-1#admin@user:user-1") + Expect(err).ShouldNot(HaveOccurred()) + + tup2, err := tuple.Tuple("organization:organization-2#admin@user:user-1") + Expect(err).ShouldNot(HaveOccurred()) + + tuples1 := database.NewTupleCollection([]*base.Tuple{ + tup1, + tup2, + }...) + + _, err = dataWriter.Write(ctx, "t1", tuples1, database.NewAttributeCollection()) + Expect(err).ShouldNot(HaveOccurred()) + + tup3, err := tuple.Tuple("organization:organization-1#admin@user:user-2") + Expect(err).ShouldNot(HaveOccurred()) + + tuples2 := database.NewTupleCollection([]*base.Tuple{ + tup3, + }...) + + _, err = dataWriter.Write(ctx, "t1", tuples2, database.NewAttributeCollection()) + Expect(err).ShouldNot(HaveOccurred()) + + it1, err := dataReader.QueryRelationships(ctx, "t1", &base.TupleFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-1"}, + }, + }, "") + Expect(err).ShouldNot(HaveOccurred()) + + Expect(it1.HasNext()).Should(Equal(true)) + Expect(it1.GetNext()).Should(Equal(tup1)) + Expect(it1.HasNext()).Should(Equal(true)) + Expect(it1.GetNext()).Should(Equal(tup3)) + }) + }) + + Context("Read Relationships", func() { + It("should write relationships and read relationships correctly", func() { + ctx := context.Background() + + tup1, err := tuple.Tuple("organization:organization-1#admin@user:user-1") + Expect(err).ShouldNot(HaveOccurred()) + + tup2, err := tuple.Tuple("organization:organization-2#admin@user:user-1") + Expect(err).ShouldNot(HaveOccurred()) + + tup3, err := tuple.Tuple("organization:organization-1#admin@user:user-2") + Expect(err).ShouldNot(HaveOccurred()) + + tup4, err := tuple.Tuple("organization:organization-1#admin@user:user-3") + Expect(err).ShouldNot(HaveOccurred()) + + tup5, err := tuple.Tuple("organization:organization-1#admin@user:user-4") + Expect(err).ShouldNot(HaveOccurred()) + + tup6, err := tuple.Tuple("organization:organization-1#admin@user:user-5") + Expect(err).ShouldNot(HaveOccurred()) + + tuples1 := database.NewTupleCollection([]*base.Tuple{ + tup1, + tup2, + tup3, + tup4, + tup5, + tup6, + }...) + + token1, err := dataWriter.Write(ctx, "t1", tuples1, database.NewAttributeCollection()) + Expect(err).ShouldNot(HaveOccurred()) + + col1, ct1, err := dataReader.ReadRelationships(ctx, "t1", &base.TupleFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-1"}, + }, + }, token1.String(), database.NewPagination(database.Size(2), database.Token(""))) + Expect(err).ShouldNot(HaveOccurred()) + + Expect(len(col1.GetTuples())).Should(Equal(2)) + + col2, ct2, err := dataReader.ReadRelationships(ctx, "t1", &base.TupleFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-1"}, + }, + }, token1.String(), database.NewPagination(database.Size(3), database.Token(ct1.String()))) + Expect(err).ShouldNot(HaveOccurred()) + + Expect(len(col2.GetTuples())).Should(Equal(3)) + Expect(ct2.String()).Should(Equal("")) + + token3, err := dataWriter.Delete(ctx, "t1", &base.TupleFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-1"}, + }, + Relation: "", + Subject: &base.SubjectFilter{ + Type: "user", + Ids: []string{"user-5"}, + }, + }, &base.AttributeFilter{}) + Expect(err).ShouldNot(HaveOccurred()) + + col3, ct3, err := dataReader.ReadRelationships(ctx, "t1", &base.TupleFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-1"}, + }, + }, token3.String(), database.NewPagination(database.Size(4), database.Token(""))) + Expect(err).ShouldNot(HaveOccurred()) + + Expect(len(col3.GetTuples())).Should(Equal(4)) + Expect(ct3.String()).Should(Equal("")) + }) + }) + + Context("Query Single Attribute", func() { + It("should write attributes and query single attributes correctly", func() { + ctx := context.Background() + + attr1, err := attribute.Attribute("organization:organization-1$public|boolean:true") + Expect(err).ShouldNot(HaveOccurred()) + + attr2, err := attribute.Attribute("organization:organization-2$public|boolean:false") + Expect(err).ShouldNot(HaveOccurred()) + + attributes := database.NewAttributeCollection([]*base.Attribute{ + attr1, + attr2, + }...) + + token1, err := dataWriter.Write(ctx, "t1", database.NewTupleCollection(), attributes) + Expect(err).ShouldNot(HaveOccurred()) + + attribute1, err := dataReader.QuerySingleAttribute(ctx, "t1", &base.AttributeFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-1"}, + }, + Attributes: []string{"public"}, + }, token1.String()) + Expect(err).ShouldNot(HaveOccurred()) + + Expect(attr1).Should(Equal(attribute1)) + + token2, err := dataWriter.Delete(ctx, "t1", + &base.TupleFilter{}, + &base.AttributeFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-1"}, + }, + Attributes: []string{"public"}, + }) + Expect(err).ShouldNot(HaveOccurred()) + + attribute2, err := dataReader.QuerySingleAttribute(ctx, "t1", &base.AttributeFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-1"}, + }, + Attributes: []string{"public"}, + }, token2.String()) + Expect(err).ShouldNot(HaveOccurred()) + Expect(attribute2).Should(BeNil()) + }) + }) + + Context("Query Attributes", func() { + It("should write attributes and query attributes correctly", func() { + ctx := context.Background() + + attr1, err := attribute.Attribute("organization:organization-2$public|boolean:true") + Expect(err).ShouldNot(HaveOccurred()) + + attr2, err := attribute.Attribute("organization:organization-1$ip_addresses|string[]:127.0.0.1,127.0.0.2") + Expect(err).ShouldNot(HaveOccurred()) + + attributes1 := database.NewAttributeCollection([]*base.Attribute{ + attr1, + attr2, + }...) + + _, err = dataWriter.Write(ctx, "t1", database.NewTupleCollection(), attributes1) + Expect(err).ShouldNot(HaveOccurred()) + + attr3, err := attribute.Attribute("organization:organization-1$balance|integer:3000") + Expect(err).ShouldNot(HaveOccurred()) + + attributes2 := database.NewAttributeCollection([]*base.Attribute{ + attr3, + }...) + + _, err = dataWriter.Write(ctx, "t1", database.NewTupleCollection(), attributes2) + Expect(err).ShouldNot(HaveOccurred()) + + it1, err := dataReader.QueryAttributes(ctx, "t1", &base.AttributeFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-1"}, + }, + }, "") + Expect(err).ShouldNot(HaveOccurred()) + + Expect(it1.HasNext()).Should(Equal(true)) + Expect(it1.GetNext()).Should(Equal(attr3)) + Expect(it1.HasNext()).Should(Equal(true)) + Expect(it1.GetNext()).Should(Equal(attr2)) + Expect(it1.HasNext()).Should(Equal(false)) + }) + }) + + Context("Read Attributes", func() { + It("should write attributes and read attributes correctly", func() { + ctx := context.Background() + + attr1, err := attribute.Attribute("organization:organization-1$public|boolean:true") + Expect(err).ShouldNot(HaveOccurred()) + + attr2, err := attribute.Attribute("organization:organization-2$ip_addresses|string[]:127.0.0.1,127.0.0.2") + Expect(err).ShouldNot(HaveOccurred()) + + attr3, err := attribute.Attribute("organization:organization-1$ip_addresses|string[]:127.0.0.1,127.0.0.2") + Expect(err).ShouldNot(HaveOccurred()) + + attr4, err := attribute.Attribute("organization:organization-1$balance|integer:3000") + Expect(err).ShouldNot(HaveOccurred()) + + attr5, err := attribute.Attribute("organization:organization-1$private|boolean:false") + Expect(err).ShouldNot(HaveOccurred()) + + attr6, err := attribute.Attribute("organization:organization-1$ppp|boolean[]:true,false") + Expect(err).ShouldNot(HaveOccurred()) + + attributes1 := database.NewAttributeCollection([]*base.Attribute{ + attr1, + attr2, + attr3, + attr4, + attr5, + attr6, + }...) + + token1, err := dataWriter.Write(ctx, "t1", database.NewTupleCollection(), attributes1) + Expect(err).ShouldNot(HaveOccurred()) + + col1, ct1, err := dataReader.ReadAttributes(ctx, "t1", &base.AttributeFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-1"}, + }, + }, token1.String(), database.NewPagination(database.Size(2), database.Token(""))) + Expect(err).ShouldNot(HaveOccurred()) + + Expect(len(col1.GetAttributes())).Should(Equal(2)) + + col2, ct2, err := dataReader.ReadAttributes(ctx, "t1", &base.AttributeFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-1"}, + }, + }, token1.String(), database.NewPagination(database.Size(3), database.Token(ct1.String()))) + Expect(err).ShouldNot(HaveOccurred()) + + Expect(len(col2.GetAttributes())).Should(Equal(3)) + Expect(ct2.String()).Should(Equal("")) + + token3, err := dataWriter.Delete(ctx, "t1", + &base.TupleFilter{}, + &base.AttributeFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-1"}, + }, + Attributes: []string{"ppp"}, + }) + Expect(err).ShouldNot(HaveOccurred()) + + col3, ct3, err := dataReader.ReadAttributes(ctx, "t1", &base.AttributeFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-1"}, + }, + }, token3.String(), database.NewPagination(database.Size(4), database.Token(""))) + Expect(err).ShouldNot(HaveOccurred()) + + Expect(len(col3.GetAttributes())).Should(Equal(4)) + Expect(ct3.String()).Should(Equal("")) + }) + }) + + Context("Query Unique Entities", func() { + It("should write entities and query unique entities correctly", func() { + ctx := context.Background() + + attr1, err := attribute.Attribute("organization:organization-1$public|boolean:true") + Expect(err).ShouldNot(HaveOccurred()) + + attr2, err := attribute.Attribute("organization:organization-2$ip_addresses|string[]:127.0.0.1,127.0.0.2") + Expect(err).ShouldNot(HaveOccurred()) + + attr3, err := attribute.Attribute("organization:organization-3$ip_addresses|string[]:127.0.0.1,127.0.0.5") + Expect(err).ShouldNot(HaveOccurred()) + + attr4, err := attribute.Attribute("organization:organization-16$balance|integer:3000") + Expect(err).ShouldNot(HaveOccurred()) + + attr5, err := attribute.Attribute("organization:organization-28$private|boolean:false") + Expect(err).ShouldNot(HaveOccurred()) + + attr6, err := attribute.Attribute("organization:organization-17$ppp|boolean[]:true,false") + Expect(err).ShouldNot(HaveOccurred()) + + attr7, err := attribute.Attribute("organization:organization-1$ip_addresses|string[]:127.0.0.1,127.0.0.2") + Expect(err).ShouldNot(HaveOccurred()) + + tup1, err := tuple.Tuple("organization:organization-1#admin@user:user-1") + Expect(err).ShouldNot(HaveOccurred()) + + tup2, err := tuple.Tuple("organization:organization-28#admin@user:user-1") + Expect(err).ShouldNot(HaveOccurred()) + + tup3, err := tuple.Tuple("organization:organization-19#admin@user:user-2") + Expect(err).ShouldNot(HaveOccurred()) + + tup4, err := tuple.Tuple("organization:organization-10#admin@user:user-3") + Expect(err).ShouldNot(HaveOccurred()) + + tup5, err := tuple.Tuple("organization:organization-14#admin@user:user-4") + Expect(err).ShouldNot(HaveOccurred()) + + tup6, err := tuple.Tuple("repository:repository-13#admin@user:user-5") + Expect(err).ShouldNot(HaveOccurred()) + + attributes1 := database.NewAttributeCollection([]*base.Attribute{ + attr1, + attr2, + attr3, + attr4, + attr5, + attr6, + attr7, + }...) + + tuples1 := database.NewTupleCollection([]*base.Tuple{ + tup1, + tup2, + tup3, + tup4, + tup5, + tup6, + }...) + + _, err = dataWriter.Write(ctx, "t1", tuples1, attributes1) + Expect(err).ShouldNot(HaveOccurred()) + + ids1, _, err := dataReader.QueryUniqueEntities(ctx, "t1", "organization", "", database.NewPagination()) + Expect(err).ShouldNot(HaveOccurred()) + Expect(len(ids1)).Should(Equal(9)) + + Expect(isSameArray(ids1, []string{"organization-1", "organization-2", "organization-3", "organization-19", "organization-10", "organization-16", "organization-14", "organization-28", "organization-17"})).Should(BeTrue()) + + _, err = dataWriter.Delete(ctx, "t1", + &base.TupleFilter{}, + &base.AttributeFilter{ + Entity: &base.EntityFilter{ + Type: "organization", + Ids: []string{"organization-17"}, + }, + }) + Expect(err).ShouldNot(HaveOccurred()) + + ids4, ct4, err := dataReader.QueryUniqueEntities(ctx, "t1", "organization", "", database.NewPagination()) + Expect(err).ShouldNot(HaveOccurred()) + Expect(len(ids4)).Should(Equal(8)) + Expect(ct4.String()).Should(Equal("")) + + Expect(isSameArray(ids4, []string{"organization-1", "organization-2", "organization-3", "organization-19", "organization-10", "organization-16", "organization-14", "organization-28"})).Should(BeTrue()) + }) + }) + + Context("Query Unique Subject References", func() { + It("should write tuples and query unique subject references correctly", func() { + ctx := context.Background() + + attr1, err := attribute.Attribute("organization:organization-1$public|boolean:true") + Expect(err).ShouldNot(HaveOccurred()) + + attr2, err := attribute.Attribute("organization:organization-2$ip_addresses|string[]:127.0.0.1,127.0.0.2") + Expect(err).ShouldNot(HaveOccurred()) + + tup1, err := tuple.Tuple("organization:organization-1#admin@user:user-1") + Expect(err).ShouldNot(HaveOccurred()) + + tup2, err := tuple.Tuple("organization:organization-3#admin@user:user-1") + Expect(err).ShouldNot(HaveOccurred()) + + tup3, err := tuple.Tuple("organization:organization-19#admin@user:user-2") + Expect(err).ShouldNot(HaveOccurred()) + + tup4, err := tuple.Tuple("organization:organization-10#admin@user:user-3") + Expect(err).ShouldNot(HaveOccurred()) + + tup5, err := tuple.Tuple("organization:organization-14#admin@organization:organization-8#member") + Expect(err).ShouldNot(HaveOccurred()) + + tup6, err := tuple.Tuple("repository:repository-13#admin@user:user-5") + Expect(err).ShouldNot(HaveOccurred()) + + attributes1 := database.NewAttributeCollection([]*base.Attribute{ + attr1, + attr2, + }...) + + tuples1 := database.NewTupleCollection([]*base.Tuple{ + tup1, + tup2, + tup3, + tup4, + tup5, + tup6, + }...) + + token1, err := dataWriter.Write(ctx, "t1", tuples1, attributes1) + Expect(err).ShouldNot(HaveOccurred()) + + refs1, _, err := dataReader.QueryUniqueSubjectReferences(ctx, "t1", &base.RelationReference{ + Type: "user", + Relation: "", + }, token1.String(), database.NewPagination()) + Expect(err).ShouldNot(HaveOccurred()) + Expect(len(refs1)).Should(Equal(4)) + + Expect(isSameArray(refs1, []string{"user-1", "user-2", "user-3", "user-5"})).Should(BeTrue()) + + refs4, ct4, err := dataReader.QueryUniqueSubjectReferences(ctx, "t1", &base.RelationReference{ + Type: "organization", + Relation: "member", + }, token1.String(), database.NewPagination()) + Expect(err).ShouldNot(HaveOccurred()) + Expect(len(refs4)).Should(Equal(1)) + Expect(ct4.String()).Should(Equal("")) + + Expect(isSameArray(refs4, []string{"organization-8"})).Should(BeTrue()) + }) + }) +}) diff --git a/internal/storage/memory/dataWriter.go b/internal/storage/memory/dataWriter.go index 96f803681..7322bd162 100644 --- a/internal/storage/memory/dataWriter.go +++ b/internal/storage/memory/dataWriter.go @@ -11,6 +11,7 @@ import ( "github.com/Permify/permify/internal/storage/memory/constants" "github.com/Permify/permify/internal/storage/memory/snapshot" "github.com/Permify/permify/internal/storage/memory/utils" + "github.com/Permify/permify/internal/validation" "github.com/Permify/permify/pkg/bundle" "github.com/Permify/permify/pkg/database" db "github.com/Permify/permify/pkg/database/memory" @@ -87,42 +88,46 @@ func (w *DataWriter) Delete(_ context.Context, tenantID string, tupleFilter *bas txn := w.database.DB.Txn(true) defer txn.Abort() - tIndex, tArgs := utils.GetRelationTuplesIndexNameAndArgsByFilters(tenantID, tupleFilter) - var tit memdb.ResultIterator - tit, err = txn.Get(constants.RelationTuplesTable, tIndex, tArgs...) - if err != nil { - return nil, errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String()) - } - - tFit := memdb.NewFilterIterator(tit, utils.FilterRelationTuplesQuery(tenantID, tupleFilter)) - for obj := tFit.Next(); obj != nil; obj = tFit.Next() { - t, ok := obj.(storage.RelationTuple) - if !ok { - return nil, errors.New(base.ErrorCode_ERROR_CODE_TYPE_CONVERSATION.String()) - } - err = txn.Delete(constants.RelationTuplesTable, t) + if !validation.IsTupleFilterEmpty(tupleFilter) { + tIndex, tArgs := utils.GetRelationTuplesIndexNameAndArgsByFilters(tenantID, tupleFilter) + var tit memdb.ResultIterator + tit, err = txn.Get(constants.RelationTuplesTable, tIndex, tArgs...) if err != nil { return nil, errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String()) } - } - aIndex, args := utils.GetAttributesIndexNameAndArgsByFilters(tenantID, attributeFilter) - var aIt memdb.ResultIterator - aIt, err = txn.Get(constants.AttributesTable, aIndex, args...) - if err != nil { - return nil, errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String()) + tFit := memdb.NewFilterIterator(tit, utils.FilterRelationTuplesQuery(tenantID, tupleFilter)) + for obj := tFit.Next(); obj != nil; obj = tFit.Next() { + t, ok := obj.(storage.RelationTuple) + if !ok { + return nil, errors.New(base.ErrorCode_ERROR_CODE_TYPE_CONVERSATION.String()) + } + err = txn.Delete(constants.RelationTuplesTable, t) + if err != nil { + return nil, errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String()) + } + } } - fit := memdb.NewFilterIterator(aIt, utils.FilterAttributesQuery(tenantID, attributeFilter)) - for obj := fit.Next(); obj != nil; obj = fit.Next() { - t, ok := obj.(storage.Attribute) - if !ok { - return nil, errors.New(base.ErrorCode_ERROR_CODE_TYPE_CONVERSATION.String()) - } - err = txn.Delete(constants.AttributesTable, t) + if !validation.IsAttributeFilterEmpty(attributeFilter) { + aIndex, args := utils.GetAttributesIndexNameAndArgsByFilters(tenantID, attributeFilter) + var aIt memdb.ResultIterator + aIt, err = txn.Get(constants.AttributesTable, aIndex, args...) if err != nil { return nil, errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String()) } + + fit := memdb.NewFilterIterator(aIt, utils.FilterAttributesQuery(tenantID, attributeFilter)) + for obj := fit.Next(); obj != nil; obj = fit.Next() { + t, ok := obj.(storage.Attribute) + if !ok { + return nil, errors.New(base.ErrorCode_ERROR_CODE_TYPE_CONVERSATION.String()) + } + err = txn.Delete(constants.AttributesTable, t) + if err != nil { + return nil, errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String()) + } + } } txn.Commit() diff --git a/internal/storage/memory/memory_test.go b/internal/storage/memory/memory_test.go index e3755b719..23a50ab83 100644 --- a/internal/storage/memory/memory_test.go +++ b/internal/storage/memory/memory_test.go @@ -1,6 +1,7 @@ package memory import ( + "sort" "testing" . "github.com/onsi/ginkgo/v2" @@ -11,3 +12,26 @@ func TestMemory(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "memory-suite") } + +// isSameArray - check if two arrays are the same +func isSameArray(a, b []string) bool { + if len(a) != len(b) { + return false + } + + sortedA := make([]string, len(a)) + copy(sortedA, a) + sort.Strings(sortedA) + + sortedB := make([]string, len(b)) + copy(sortedB, b) + sort.Strings(sortedB) + + for i := range sortedA { + if sortedA[i] != sortedB[i] { + return false + } + } + + return true +} diff --git a/internal/storage/memory/schemaReader_test.go b/internal/storage/memory/schemaReader_test.go new file mode 100644 index 000000000..f4e815188 --- /dev/null +++ b/internal/storage/memory/schemaReader_test.go @@ -0,0 +1,164 @@ +package memory + +import ( + "context" + "time" + + "github.com/rs/xid" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/Permify/permify/internal/storage" + "github.com/Permify/permify/internal/storage/memory/migrations" + "github.com/Permify/permify/pkg/database/memory" + base "github.com/Permify/permify/pkg/pb/base/v1" +) + +var _ = Describe("SchemaReader", func() { + var db *memory.Memory + + var schemaWriter *SchemaWriter + var schemaReader *SchemaReader + + BeforeEach(func() { + database, err := memory.New(migrations.Schema) + Expect(err).ShouldNot(HaveOccurred()) + db = database + + schemaWriter = NewSchemaWriter(db) + schemaReader = NewSchemaReader(db) + }) + + AfterEach(func() { + err := db.Close() + Expect(err).ShouldNot(HaveOccurred()) + }) + + Context("Head Version", func() { + It("should retrieve the most recent schema version for a tenant", func() { + ctx := context.Background() + + var mostRecentVersion string + + // Insert multiple schema versions for a single tenant + for i := 0; i < 3; i++ { + version := xid.New().String() + schema := []storage.SchemaDefinition{ + {TenantID: "t1", Name: "organization", SerializedDefinition: []byte("entity organization {}"), Version: version}, + {TenantID: "t1", Name: "user", SerializedDefinition: []byte("entity user {}"), Version: version}, + } + err := schemaWriter.WriteSchema(ctx, schema) + Expect(err).ShouldNot(HaveOccurred()) + mostRecentVersion = version // Keep track of the last inserted version + // Sleep to ensure the version is different (if versions are time-based) + time.Sleep(time.Millisecond * 2) + } + + // Attempt to retrieve the head version from SchemaReader + headVersion, err := schemaReader.HeadVersion(ctx, "t1") + Expect(err).ShouldNot(HaveOccurred()) + + // Validate that the retrieved head version matches the most recently inserted version + Expect(headVersion).Should(Equal(mostRecentVersion), "The retrieved head version should be the most recently written one.") + }) + }) + + Context("Read Schema", func() { + It("should write and then read the schema for a tenant", func() { + ctx := context.Background() + + version := xid.New().String() + + schema := []storage.SchemaDefinition{ + {TenantID: "t1", Name: "user", SerializedDefinition: []byte("entity user {}"), Version: version}, + {TenantID: "t1", Name: "organization", SerializedDefinition: []byte("entity organization { relation admin @user}"), Version: version}, + } + + err := schemaWriter.WriteSchema(ctx, schema) + Expect(err).ShouldNot(HaveOccurred()) + + sch, err := schemaReader.ReadSchema(ctx, "t1", version) + Expect(err).ShouldNot(HaveOccurred()) + + Expect(sch.EntityDefinitions["user"]).Should(Equal(&base.EntityDefinition{ + Name: "user", + Relations: map[string]*base.RelationDefinition{}, + Permissions: map[string]*base.PermissionDefinition{}, + Attributes: map[string]*base.AttributeDefinition{}, + References: map[string]base.EntityDefinition_Reference{}, + })) + + Expect(sch.EntityDefinitions["organization"].GetName()).Should(Equal("organization")) + Expect(sch.EntityDefinitions["organization"].GetRelations()["admin"].Name).Should(Equal("admin")) + Expect(sch.EntityDefinitions["organization"].GetRelations()["admin"].GetRelationReferences()[0].GetType()).Should(Equal("user")) + Expect(sch.EntityDefinitions["organization"].GetRelations()["admin"].GetRelationReferences()[0].GetRelation()).Should(Equal("")) + + Expect(sch.EntityDefinitions["organization"].GetPermissions()).Should(Equal(map[string]*base.PermissionDefinition{})) + Expect(sch.EntityDefinitions["organization"].GetAttributes()).Should(Equal(map[string]*base.AttributeDefinition{})) + Expect(sch.EntityDefinitions["organization"].GetReferences()["admin"]).Should(Equal(base.EntityDefinition_REFERENCE_RELATION)) + + Expect(sch.RuleDefinitions).Should(Equal(map[string]*base.RuleDefinition{})) + + Expect(sch.References["user"]).Should(Equal(base.SchemaDefinition_REFERENCE_ENTITY)) + Expect(sch.References["organization"]).Should(Equal(base.SchemaDefinition_REFERENCE_ENTITY)) + }) + }) + + Context("Read Entity Definition", func() { + It("should write and then read the entity definition for a tenant", func() { + ctx := context.Background() + + version := xid.New().String() + + schema := []storage.SchemaDefinition{ + {TenantID: "t1", Name: "user", SerializedDefinition: []byte("entity user {}"), Version: version}, + {TenantID: "t1", Name: "organization", SerializedDefinition: []byte("entity organization { relation admin @user}"), Version: version}, + } + + err := schemaWriter.WriteSchema(ctx, schema) + Expect(err).ShouldNot(HaveOccurred()) + + en, v, err := schemaReader.ReadEntityDefinition(ctx, "t1", "organization", version) + Expect(err).ShouldNot(HaveOccurred()) + + Expect(version).Should(Equal(v)) + + Expect(en.GetName()).Should(Equal("organization")) + + Expect(en.GetRelations()["admin"].GetName()).Should(Equal("admin")) + Expect(en.GetRelations()["admin"].GetRelationReferences()[0].GetType()).Should(Equal("user")) + Expect(en.GetRelations()["admin"].GetRelationReferences()[0].GetRelation()).Should(Equal("")) + + Expect(en.GetPermissions()).Should(Equal(map[string]*base.PermissionDefinition{})) + Expect(en.GetAttributes()).Should(Equal(map[string]*base.AttributeDefinition{})) + Expect(en.GetReferences()["admin"]).Should(Equal(base.EntityDefinition_REFERENCE_RELATION)) + }) + }) + + Context("Read Rule Definition", func() { + It("should write and then read the rule definition for a tenant", func() { + ctx := context.Background() + + version := xid.New().String() + + schema := []storage.SchemaDefinition{ + {TenantID: "t1", Name: "user", SerializedDefinition: []byte("entity user {}"), Version: version}, + {TenantID: "t1", Name: "organization", SerializedDefinition: []byte("entity organization { relation admin @user}"), Version: version}, + {TenantID: "t1", Name: "check_ip_range", SerializedDefinition: []byte("rule check_ip_range(ip_address string, ip_range string[]) {\n ip_address in ip_range\n}"), Version: version}, + } + + err := schemaWriter.WriteSchema(ctx, schema) + Expect(err).ShouldNot(HaveOccurred()) + + ru, v, err := schemaReader.ReadRuleDefinition(ctx, "t1", "check_ip_range", version) + Expect(err).ShouldNot(HaveOccurred()) + Expect(version).Should(Equal(v)) + Expect(ru.Name).Should(Equal("check_ip_range")) + Expect(ru.Arguments).Should(Equal(map[string]base.AttributeType{ + "ip_address": base.AttributeType_ATTRIBUTE_TYPE_STRING, + "ip_range": base.AttributeType_ATTRIBUTE_TYPE_STRING_ARRAY, + })) + }) + }) +}) diff --git a/internal/storage/memory/schemaWriter_test.go b/internal/storage/memory/schemaWriter_test.go new file mode 100644 index 000000000..a446d57d7 --- /dev/null +++ b/internal/storage/memory/schemaWriter_test.go @@ -0,0 +1,89 @@ +package memory + +import ( + "context" + + "github.com/rs/xid" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/Permify/permify/internal/storage" + "github.com/Permify/permify/internal/storage/memory/migrations" + "github.com/Permify/permify/pkg/database/memory" + base "github.com/Permify/permify/pkg/pb/base/v1" +) + +var _ = Describe("SchemaWriter", func() { + var db *memory.Memory + + var schemaWriter *SchemaWriter + var schemaReader *SchemaReader + + BeforeEach(func() { + database, err := memory.New(migrations.Schema) + Expect(err).ShouldNot(HaveOccurred()) + db = database + + schemaWriter = NewSchemaWriter(db) + schemaReader = NewSchemaReader(db) + }) + + AfterEach(func() { + err := db.Close() + Expect(err).ShouldNot(HaveOccurred()) + }) + + Context("Write Schema", func() { + It("should write schema for a tenant", func() { + ctx := context.Background() + + version := xid.New().String() + + schema := []storage.SchemaDefinition{ + {TenantID: "t1", Name: "user", SerializedDefinition: []byte("entity user {}"), Version: version}, + {TenantID: "t1", Name: "organization", SerializedDefinition: []byte("entity organization { relation admin @user}"), Version: version}, + } + + err := schemaWriter.WriteSchema(ctx, schema) + Expect(err).ShouldNot(HaveOccurred()) + + sch, err := schemaReader.ReadSchema(ctx, "t1", version) + Expect(err).ShouldNot(HaveOccurred()) + + Expect(sch.EntityDefinitions["user"]).Should(Equal(&base.EntityDefinition{ + Name: "user", + Relations: map[string]*base.RelationDefinition{}, + Permissions: map[string]*base.PermissionDefinition{}, + Attributes: map[string]*base.AttributeDefinition{}, + References: map[string]base.EntityDefinition_Reference{}, + })) + + Expect(sch.EntityDefinitions["organization"]).Should(Equal(&base.EntityDefinition{ + Name: "organization", + Relations: map[string]*base.RelationDefinition{ + "admin": { + Name: "admin", + RelationReferences: []*base.RelationReference{ + { + Type: "user", + Relation: "", + }, + }, + }, + }, + Permissions: map[string]*base.PermissionDefinition{}, + Attributes: map[string]*base.AttributeDefinition{}, + References: map[string]base.EntityDefinition_Reference{ + "admin": base.EntityDefinition_REFERENCE_RELATION, + }, + }, + )) + + Expect(sch.RuleDefinitions).Should(Equal(map[string]*base.RuleDefinition{})) + + Expect(sch.References["user"]).Should(Equal(base.SchemaDefinition_REFERENCE_ENTITY)) + Expect(sch.References["organization"]).Should(Equal(base.SchemaDefinition_REFERENCE_ENTITY)) + }) + }) +}) diff --git a/internal/storage/memory/tenantReader_test.go b/internal/storage/memory/tenantReader_test.go new file mode 100644 index 000000000..dbd7c0bdf --- /dev/null +++ b/internal/storage/memory/tenantReader_test.go @@ -0,0 +1,66 @@ +package memory + +import ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/Permify/permify/internal/storage/memory/migrations" + "github.com/Permify/permify/pkg/database" + "github.com/Permify/permify/pkg/database/memory" +) + +var _ = Describe("TenantReader", func() { + var db *memory.Memory + + var tenantWriter *TenantWriter + var tenantReader *TenantReader + + BeforeEach(func() { + database, err := memory.New(migrations.Schema) + Expect(err).ShouldNot(HaveOccurred()) + db = database + + tenantWriter = NewTenantWriter(db) + tenantReader = NewTenantReader(db) + }) + + AfterEach(func() { + err := db.Close() + Expect(err).ShouldNot(HaveOccurred()) + }) + + Context("List Tenants", func() { + It("should get tenants", func() { + ctx := context.Background() + + _, err := tenantWriter.CreateTenant(ctx, "test_id_1", "test name 1") + Expect(err).ShouldNot(HaveOccurred()) + + _, err = tenantWriter.CreateTenant(ctx, "test_id_2", "test name 2") + Expect(err).ShouldNot(HaveOccurred()) + + _, err = tenantWriter.CreateTenant(ctx, "test_id_3", "test name 3") + Expect(err).ShouldNot(HaveOccurred()) + + _, err = tenantWriter.CreateTenant(ctx, "test_id_4", "test name 4") + Expect(err).ShouldNot(HaveOccurred()) + + _, err = tenantWriter.CreateTenant(ctx, "test_id_5", "test name 5") + Expect(err).ShouldNot(HaveOccurred()) + + _, err = tenantWriter.CreateTenant(ctx, "test_id_6", "test name 6") + Expect(err).ShouldNot(HaveOccurred()) + + col1, ct1, err := tenantReader.ListTenants(ctx, database.NewPagination(database.Size(3), database.Token(""))) + Expect(err).ShouldNot(HaveOccurred()) + Expect(len(col1)).Should(Equal(3)) + + col2, ct2, err := tenantReader.ListTenants(ctx, database.NewPagination(database.Size(4), database.Token(ct1.String()))) + Expect(err).ShouldNot(HaveOccurred()) + Expect(len(col2)).Should(Equal(3)) + Expect(ct2.String()).Should(Equal("")) + }) + }) +}) diff --git a/internal/storage/memory/tenantWriter_test.go b/internal/storage/memory/tenantWriter_test.go new file mode 100644 index 000000000..e9dfcc2ab --- /dev/null +++ b/internal/storage/memory/tenantWriter_test.go @@ -0,0 +1,60 @@ +package memory + +import ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/Permify/permify/internal/storage/memory/migrations" + "github.com/Permify/permify/pkg/database/memory" +) + +var _ = Describe("TenantWriter", func() { + var db *memory.Memory + + var tenantWriter *TenantWriter + + BeforeEach(func() { + database, err := memory.New(migrations.Schema) + Expect(err).ShouldNot(HaveOccurred()) + db = database + + tenantWriter = NewTenantWriter(db) + }) + + AfterEach(func() { + err := db.Close() + Expect(err).ShouldNot(HaveOccurred()) + }) + + Context("Create Tenant", func() { + It("should create tenant", func() { + ctx := context.Background() + + tenant, err := tenantWriter.CreateTenant(ctx, "test_id_1", "test name 1") + Expect(err).ShouldNot(HaveOccurred()) + + Expect(tenant.Id).Should(Equal("test_id_1")) + Expect(tenant.Name).Should(Equal("test name 1")) + }) + }) + + Context("Delete Tenant", func() { + It("should delete tenant", func() { + ctx := context.Background() + + tenant, err := tenantWriter.CreateTenant(ctx, "test_id_1", "test name 1") + Expect(err).ShouldNot(HaveOccurred()) + + Expect(tenant.Id).Should(Equal("test_id_1")) + Expect(tenant.Name).Should(Equal("test name 1")) + + tenant, err = tenantWriter.DeleteTenant(ctx, "test_id_1") + Expect(err).ShouldNot(HaveOccurred()) + + Expect(tenant.Id).Should(Equal("test_id_1")) + Expect(tenant.Name).Should(Equal("test name 1")) + }) + }) +}) diff --git a/internal/storage/memory/watch_test.go b/internal/storage/memory/watch_test.go new file mode 100644 index 000000000..47f030504 --- /dev/null +++ b/internal/storage/memory/watch_test.go @@ -0,0 +1,45 @@ +package memory + +import ( + "context" + "fmt" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/Permify/permify/internal/storage/memory/migrations" + "github.com/Permify/permify/pkg/database/memory" +) + +var _ = Describe("Watch", func() { + var db *memory.Memory + + var watcher *Watch + + BeforeEach(func() { + database, err := memory.New(migrations.Schema) + Expect(err).ShouldNot(HaveOccurred()) + db = database + + watcher = NewWatcher(db) + }) + + AfterEach(func() { + err := db.Close() + Expect(err).ShouldNot(HaveOccurred()) + }) + + Context("Watch", func() { + It("watch", func() { + _, errs := watcher.Watch(context.Background(), "t1", "") + select { + case err := <-errs: + // Handle and assert the error + Expect(err).ShouldNot(HaveOccurred()) + case <-time.After(time.Second * 10): + fmt.Println("test timed out") + } + }) + }) +}) diff --git a/internal/storage/postgres/dataWriter_test.go b/internal/storage/postgres/dataWriter_test.go index 1d7ac02db..674f25c41 100644 --- a/internal/storage/postgres/dataWriter_test.go +++ b/internal/storage/postgres/dataWriter_test.go @@ -423,66 +423,77 @@ var _ = Describe("DataWriter", func() { }) Context("RunBundle", func() { - It("", func() { + It("should run the bundle successfully and return an encoded snapshot token", func() { ctx := context.Background() - bundles := []*base.DataBundle{ - { - Name: "user_created", - Arguments: []string{ - "organizationID", - "userID", - }, - Operations: []*base.Operation{ - { - RelationshipsWrite: []string{ - "organization:{{.organizationID}}#member@user:{{.userID}}", - "organization:{{.organizationID}}#admin@user:{{.userID}}", - }, - RelationshipsDelete: []string{}, - AttributesWrite: []string{ - "organization:{{.organizationID}}$public|boolean:true", - }, - AttributesDelete: []string{}, + // Create a valid DataBundle + bundle := &base.DataBundle{ + Name: "user_created", + Arguments: []string{ + "organizationID", + "companyID", + "userID", + }, + Operations: []*base.Operation{ + { + RelationshipsWrite: []string{ + "organization:{{.organizationID}}#member@company:{{.companyID}}#admin", + "organization:{{.organizationID}}#member@user:{{.userID}}", + "organization:{{.organizationID}}#admin@user:{{.userID}}", + }, + RelationshipsDelete: []string{ + "organization:{{.organizationID}}#admin@user:{{.userID}}", + }, + AttributesWrite: []string{ + "organization:{{.organizationID}}$public|boolean:true", + "company:{{.companyID}}$public|boolean:true", + }, + AttributesDelete: []string{ + "organization:{{.organizationID}}$balance|double:120.900", }, }, }, } - var sBundles []storage.Bundle - for _, b := range bundles { - sBundles = append(sBundles, storage.Bundle{ - Name: b.Name, - DataBundle: b, + _, err := bundleWriter.Write(ctx, []storage.Bundle{ + { + Name: bundle.Name, + DataBundle: bundle, TenantID: "t1", - }) - } - - _, err := bundleWriter.Write(ctx, sBundles) + }, + }) Expect(err).ShouldNot(HaveOccurred()) - bundle, err := bundleReader.Read(ctx, "t1", "user_created") + dataBundle, err := bundleReader.Read(ctx, "t1", "user_created") Expect(err).ShouldNot(HaveOccurred()) token1, err := dataWriter.RunBundle(ctx, "t1", map[string]string{ - "organizationID": "12", - "userID": "190", - }, bundle) + "organizationID": "1", + "companyID": "4", + "userID": "1", + }, dataBundle) Expect(err).ShouldNot(HaveOccurred()) colT1, _, err := dataReader.ReadRelationships(ctx, "t1", &base.TupleFilter{ Entity: &base.EntityFilter{ Type: "organization", - Ids: []string{"12"}, + Ids: []string{"1"}, + }, + Relation: "", + Subject: &base.SubjectFilter{ + Type: "", + Ids: []string{}, + Relation: "", }, }, token1.String(), database.NewPagination(database.Size(10), database.Token(""))) Expect(len(colT1.GetTuples())).Should(Equal(2)) colA2, _, err := dataReader.ReadAttributes(ctx, "t1", &base.AttributeFilter{ Entity: &base.EntityFilter{ - Type: "organization", - Ids: []string{"12"}, + Type: "company", + Ids: []string{"4"}, }, + Attributes: []string{}, }, token1.String(), database.NewPagination(database.Size(10), database.Token(""))) Expect(len(colA2.GetAttributes())).Should(Equal(1)) }) diff --git a/internal/storage/postgres/migrations/20231230174418_schema_version_index.sql b/internal/storage/postgres/migrations/20231230174418_schema_version_index.sql new file mode 100644 index 000000000..5c4477a0e --- /dev/null +++ b/internal/storage/postgres/migrations/20231230174418_schema_version_index.sql @@ -0,0 +1,10 @@ +-- +goose NO TRANSACTION +-- +goose Up +-- +goose StatementBegin +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_schema_version ON schema_definitions (version); +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +DROP INDEX CONCURRENTLY IF EXISTS idx_schema_version; +-- +goose StatementEnd diff --git a/internal/storage/postgres/postgres_test.go b/internal/storage/postgres/postgres_test.go index 341582fc9..2fec9386b 100644 --- a/internal/storage/postgres/postgres_test.go +++ b/internal/storage/postgres/postgres_test.go @@ -40,9 +40,15 @@ func postgresDB(postgresVersion string) database.Database { Expect(err).ShouldNot(HaveOccurred()) } + // Execute the command in the container + _, _, execErr := postgres.Exec(ctx, []string{"psql", "-U", "postgres", "-c", "ALTER SYSTEM SET track_commit_timestamp = on;"}) + if execErr != nil { + Expect(execErr).ShouldNot(HaveOccurred()) + } + cmd := []string{"sh", "-c", "export PGPASSWORD=postgres" + "; psql -U postgres -d permify -c 'DROP SCHEMA public CASCADE; CREATE SCHEMA public;'"} - _, _, err = postgres.Exec(context.Background(), cmd) + _, _, err = postgres.Exec(ctx, cmd) if err != nil { Expect(err).ShouldNot(HaveOccurred()) } diff --git a/internal/storage/postgres/schemaWriter_test.go b/internal/storage/postgres/schemaWriter_test.go index 60e48b9d3..ecc597059 100644 --- a/internal/storage/postgres/schemaWriter_test.go +++ b/internal/storage/postgres/schemaWriter_test.go @@ -15,7 +15,7 @@ import ( base "github.com/Permify/permify/pkg/pb/base/v1" ) -var _ = Describe("SchemaReader", func() { +var _ = Describe("SchemaWriter", func() { var db database.Database var schemaWriter *SchemaWriter var schemaReader *SchemaReader diff --git a/internal/storage/postgres/snapshot/token_test.go b/internal/storage/postgres/snapshot/token_test.go index 3992a3cda..074bb189e 100644 --- a/internal/storage/postgres/snapshot/token_test.go +++ b/internal/storage/postgres/snapshot/token_test.go @@ -50,6 +50,51 @@ var _ = Describe("token", func() { Expect(tt.target.Encode().String()).ShouldNot(Equal(tt.expected)) } }) + + It("Case 3: Eg Success", func() { + tests := []struct { + token token.SnapToken + target token.SnapToken + }{ + {NewToken(types.XID8{Uint: 4, Status: pgtype.Present}), NewToken(types.XID8{Uint: 4, Status: pgtype.Present})}, + } + + for _, tt := range tests { + Expect(tt.token.Eg(tt.target)).Should(BeTrue()) + } + }) + + It("Case 4: Gt Success", func() { + tests := []struct { + token token.SnapToken + target token.SnapToken + }{ + { + NewToken(types.XID8{Uint: 6, Status: pgtype.Present}), + NewToken(types.XID8{Uint: 4, Status: pgtype.Present}), + }, + } + + for _, tt := range tests { + Expect(tt.token.Gt(tt.target)).Should(BeTrue()) + } + }) + + It("Case 5: Lt Success", func() { + tests := []struct { + token token.SnapToken + target token.SnapToken + }{ + { + NewToken(types.XID8{Uint: 4, Status: pgtype.Present}), + NewToken(types.XID8{Uint: 6, Status: pgtype.Present}), + }, + } + + for _, tt := range tests { + Expect(tt.token.Lt(tt.target)).Should(BeTrue()) + } + }) }) Context("Decode", func() { diff --git a/internal/storage/postgres/tenantReader_test.go b/internal/storage/postgres/tenantReader_test.go index d4de10534..722d87548 100644 --- a/internal/storage/postgres/tenantReader_test.go +++ b/internal/storage/postgres/tenantReader_test.go @@ -11,7 +11,7 @@ import ( PQDatabase "github.com/Permify/permify/pkg/database/postgres" ) -var _ = Describe("TenantWriter", func() { +var _ = Describe("TenantReader", func() { var db database.Database var tenantWriter *TenantWriter var tenantReader *TenantReader diff --git a/internal/storage/postgres/utils/common.go b/internal/storage/postgres/utils/common.go index 99dd138b9..37d5ea351 100644 --- a/internal/storage/postgres/utils/common.go +++ b/internal/storage/postgres/utils/common.go @@ -1,6 +1,7 @@ package utils import ( + "context" "fmt" "log/slog" @@ -124,9 +125,22 @@ func HandleError(span trace.Span, err error, errorCode base.ErrorCode) error { // Set the status of the span span.SetStatus(codes.Error, err.Error()) - // Log the error - slog.Error("Error encountered", slog.Any("error", err), slog.Any("errorCode", errorCode)) + // Check if the error is context-related + if IsContextRelatedError(err) { + // Use debug level logging for context-related errors + slog.Debug("Context-related error encountered", slog.Any("error", err), slog.Any("errorCode", errorCode)) + } else { + // Use error level logging for all other errors + slog.Error("Error encountered", slog.Any("error", err), slog.Any("errorCode", errorCode)) + } // Return a new standardized error with the provided error code return errors.New(errorCode.String()) } + +// IsContextRelatedError checks if the error is due to context cancellation, deadline exceedance, or closed connection +func IsContextRelatedError(err error) bool { + return errors.Is(err, context.Canceled) || + errors.Is(err, context.DeadlineExceeded) || + err.Error() == "conn closed" +} diff --git a/internal/storage/postgres/watch.go b/internal/storage/postgres/watch.go index 2b786e777..c7cea77f5 100644 --- a/internal/storage/postgres/watch.go +++ b/internal/storage/postgres/watch.go @@ -6,9 +6,11 @@ import ( "errors" "fmt" "log/slog" + "strings" "time" - "google.golang.org/protobuf/proto" + "github.com/golang/protobuf/jsonpb" + "google.golang.org/protobuf/types/known/anypb" "github.com/Masterminds/squirrel" @@ -310,17 +312,19 @@ func (w *Watch) getChanges(ctx context.Context, value types.XID8, tenantID strin rt := storage.Attribute{} - var valueBytes []byte + var valueStr string // Scan the result row into a RelationTuple instance. - err = trows.Scan(&rt.EntityType, &rt.EntityID, &rt.Attribute, &valueBytes, &expiredXID) + err = arows.Scan(&rt.EntityType, &rt.EntityID, &rt.Attribute, &valueStr, &expiredXID) if err != nil { slog.Error("Error while scanning row for attributes", slog.Any("error", err)) return nil, err } + // Unmarshal the JSON data from `valueStr` into `rt.Value`. rt.Value = &anypb.Any{} - err = proto.Unmarshal(valueBytes, rt.Value) + unmarshaler := &jsonpb.Unmarshaler{} + err = unmarshaler.Unmarshal(strings.NewReader(valueStr), rt.Value) if err != nil { slog.Error("Failed to unmarshal attribute value", slog.Any("error", err)) return nil, err diff --git a/internal/storage/postgres/watch_test.go b/internal/storage/postgres/watch_test.go new file mode 100644 index 000000000..0a3de530f --- /dev/null +++ b/internal/storage/postgres/watch_test.go @@ -0,0 +1,112 @@ +package postgres + +import ( + "context" + "fmt" + "os" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/Permify/permify/pkg/attribute" + "github.com/Permify/permify/pkg/database" + PQDatabase "github.com/Permify/permify/pkg/database/postgres" + base "github.com/Permify/permify/pkg/pb/base/v1" + "github.com/Permify/permify/pkg/tuple" +) + +var _ = Describe("Watch", func() { + var db database.Database + var dataWriter *DataWriter + var watcher *Watch + + BeforeEach(func() { + version := os.Getenv("POSTGRES_VERSION") + + if version == "" { + version = "14" + } + + db = postgresDB(version) + dataWriter = NewDataWriter(db.(*PQDatabase.Postgres)) + watcher = NewWatcher(db.(*PQDatabase.Postgres)) + }) + + AfterEach(func() { + err := db.Close() + Expect(err).ShouldNot(HaveOccurred()) + }) + + Context("Watch", func() { + It("watch", func() { + ctx := context.Background() + + tup1, err := tuple.Tuple("organization:organization-1#admin@user:user-1") + Expect(err).ShouldNot(HaveOccurred()) + + tuples := database.NewTupleCollection([]*base.Tuple{ + tup1, + }...) + + token1, err := dataWriter.Write(ctx, "t1", tuples, database.NewAttributeCollection()) + Expect(err).ShouldNot(HaveOccurred()) + Expect(token1.String()).ShouldNot(Equal("")) + + changes, errs := watcher.Watch(ctx, "t1", token1.String()) + + time.Sleep(100 * time.Millisecond) + + go func() { + defer GinkgoRecover() + + attr1, err := attribute.Attribute("organization:organization-1$public|boolean:true") + Expect(err).ShouldNot(HaveOccurred()) + + attr2, err := attribute.Attribute("organization:organization-1$ip_addresses|string[]:127.0.0.1,127.0.0.2") + Expect(err).ShouldNot(HaveOccurred()) + + attr3, err := attribute.Attribute("organization:organization-3$balance|double:234.344") + Expect(err).ShouldNot(HaveOccurred()) + + tup1, err := tuple.Tuple("organization:organization-1#admin@user:user-1") + Expect(err).ShouldNot(HaveOccurred()) + + tup2, err := tuple.Tuple("organization:organization-1#admin@user:user-4") + Expect(err).ShouldNot(HaveOccurred()) + + tup3, err := tuple.Tuple("organization:organization-1#admin@user:user-2") + Expect(err).ShouldNot(HaveOccurred()) + + attributes1 := database.NewAttributeCollection([]*base.Attribute{ + attr1, + attr2, + attr3, + }...) + + tuples1 := database.NewTupleCollection([]*base.Tuple{ + tup1, + tup2, + tup3, + }...) + + time.Sleep(time.Second) + token2, err := dataWriter.Write(ctx, "t1", tuples1, attributes1) + Expect(err).ShouldNot(HaveOccurred()) + Expect(token2.String()).ShouldNot(Equal("")) + }() + + select { + case change := <-changes: + // Test the received change + Expect(change.DataChanges).ShouldNot(BeNil()) + // Additional assertions about the structure and content of 'change' + case err := <-errs: + // Handle and assert the error + Expect(err).ShouldNot(HaveOccurred()) + case <-time.After(time.Second * 10): + fmt.Println("test timed out") + } + }) + }) +}) diff --git a/pkg/cmd/flags/serve.go b/pkg/cmd/flags/serve.go index d4dfa1cfd..355582609 100644 --- a/pkg/cmd/flags/serve.go +++ b/pkg/cmd/flags/serve.go @@ -21,6 +21,14 @@ func RegisterServeFlags(cmd *cobra.Command) { panic(err) } + flags.String("account-id", conf.AccountID, "account id") + if err = viper.BindPFlag("account_id", flags.Lookup("account-id")); err != nil { + panic(err) + } + if err = viper.BindEnv("account_id", "PERMIFY_ACCOUNT_ID"); err != nil { + panic(err) + } + // Server flags.Int64("server-rate-limit", conf.Server.RateLimit, "the maximum number of requests the server should handle per second") if err = viper.BindPFlag("server.rate_limit", flags.Lookup("server-rate-limit")); err != nil { @@ -80,6 +88,14 @@ func RegisterServeFlags(cmd *cobra.Command) { panic(err) } + flags.Bool("http-tls-enabled", conf.Server.HTTP.TLSConfig.Enabled, "switch option for HTTP tls server") + if err = viper.BindPFlag("server.http.tls.enabled", flags.Lookup("http-tls-enabled")); err != nil { + panic(err) + } + if err = viper.BindEnv("server.http.tls.enabled", "PERMIFY_HTTP_TLS_ENABLED"); err != nil { + panic(err) + } + flags.String("http-tls-key-path", conf.Server.HTTP.TLSConfig.KeyPath, "HTTP tls key path") if err = viper.BindPFlag("server.http.tls.key", flags.Lookup("http-tls-key-path")); err != nil { panic(err) @@ -196,7 +212,7 @@ func RegisterServeFlags(cmd *cobra.Command) { panic(err) } - flags.String("tracer-exporter", conf.Tracer.Exporter, "export uri for tracing data") + flags.String("tracer-exporter", conf.Tracer.Exporter, "can be; jaeger, signoz, zipkin or otlp. (integrated tracing tools)") if err = viper.BindPFlag("tracer.exporter", flags.Lookup("tracer-exporter")); err != nil { panic(err) } @@ -204,13 +220,14 @@ func RegisterServeFlags(cmd *cobra.Command) { panic(err) } - flags.String("tracer-endpoint", conf.Tracer.Endpoint, "can be; jaeger, signoz, zipkin or otlp. (integrated tracing tools)") + flags.String("tracer-endpoint", conf.Tracer.Endpoint, "export uri for tracing data") if err = viper.BindPFlag("tracer.endpoint", flags.Lookup("tracer-endpoint")); err != nil { panic(err) } if err = viper.BindEnv("tracer.endpoint", "PERMIFY_TRACER_ENDPOINT"); err != nil { panic(err) } + flags.Bool("tracer-insecure", conf.Tracer.Insecure, "use https or http for tracer data, only used for otlp exporter or signoz") if err = viper.BindPFlag("tracer.insecure", flags.Lookup("tracer-insecure")); err != nil { panic(err) @@ -236,7 +253,7 @@ func RegisterServeFlags(cmd *cobra.Command) { panic(err) } - flags.String("meter-exporter", conf.Meter.Exporter, "export uri for metric data") + flags.String("meter-exporter", conf.Meter.Exporter, "can be; otlp. (integrated metric tools)") if err = viper.BindPFlag("meter.exporter", flags.Lookup("meter-exporter")); err != nil { panic(err) } @@ -244,7 +261,7 @@ func RegisterServeFlags(cmd *cobra.Command) { panic(err) } - flags.String("meter-endpoint", conf.Meter.Endpoint, "can be; otlp. (integrated metric tools)") + flags.String("meter-endpoint", conf.Meter.Endpoint, "export uri for metric data") if err = viper.BindPFlag("meter.endpoint", flags.Lookup("meter-endpoint")); err != nil { panic(err) } @@ -301,6 +318,14 @@ func RegisterServeFlags(cmd *cobra.Command) { panic(err) } + flags.Int("service-permission-bulk-limit", conf.Service.Permission.BulkLimit, "bulk operations limit") + if err = viper.BindPFlag("service.permission.bulk_limit", flags.Lookup("service-permission-bulk-limit")); err != nil { + panic(err) + } + if err = viper.BindEnv("service.permission.bulk_limit", "PERMIFY_SERVICE_PERMISSION_BULK_LIMIT"); err != nil { + panic(err) + } + flags.Int("service-permission-concurrency-limit", conf.Service.Permission.ConcurrencyLimit, "concurrency limit") if err = viper.BindPFlag("service.permission.concurrency_limit", flags.Lookup("service-permission-concurrency-limit")); err != nil { panic(err) diff --git a/pkg/cmd/serve.go b/pkg/cmd/serve.go index 944197688..eec157bbb 100644 --- a/pkg/cmd/serve.go +++ b/pkg/cmd/serve.go @@ -7,13 +7,18 @@ import ( "os" "os/signal" "syscall" + "time" + "github.com/sony/gobreaker" "github.com/spf13/viper" "go.opentelemetry.io/otel/sdk/metric" "github.com/Permify/permify/internal/engines/balancer" "github.com/Permify/permify/internal/engines/cache" "github.com/Permify/permify/internal/invoke" + cacheDecorator "github.com/Permify/permify/internal/storage/decorators/cache" + cbDecorator "github.com/Permify/permify/internal/storage/decorators/circuitBreaker" + sfDecorator "github.com/Permify/permify/internal/storage/decorators/singleflight" "github.com/Permify/permify/internal/storage/postgres/gc" "github.com/Permify/permify/pkg/cmd/flags" PQDatabase "github.com/Permify/permify/pkg/database/postgres" @@ -29,7 +34,6 @@ import ( "github.com/Permify/permify/internal/factories" "github.com/Permify/permify/internal/servers" "github.com/Permify/permify/internal/storage" - "github.com/Permify/permify/internal/storage/decorators" pkgcache "github.com/Permify/permify/pkg/cache" "github.com/Permify/permify/pkg/cache/ristretto" "github.com/Permify/permify/pkg/telemetry" @@ -111,6 +115,21 @@ func serve() func(cmd *cobra.Command, args []string) error { slog.Info("🚀 starting permify service...") + internal.Identifier = cfg.AccountID + if internal.Identifier == "" { + message := "Account ID is not set. Please fill in the Account ID for better support. Get your Account ID from https://permify.co/account" + slog.Error(message) + + ticker := time.NewTicker(24 * time.Hour) + defer ticker.Stop() + + go func() { + for range ticker.C { + slog.Error(message) + } + }() + } + // Set up context and signal handling ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() @@ -225,25 +244,34 @@ func serve() func(cmd *cobra.Command, args []string) error { tenantWriter := factories.TenantWriterFactory(db) // Add caching to the schema reader using a decorator - schemaReader = decorators.NewSchemaReaderWithCache(schemaReader, schemaCache) + schemaReader = cacheDecorator.NewSchemaReader(schemaReader, schemaCache) + + dataReader = sfDecorator.NewDataReader(dataReader) + schemaReader = sfDecorator.NewSchemaReader(schemaReader) // Check if circuit breaker should be enabled for services if cfg.Service.CircuitBreaker { - // Add circuit breaker to the relationship reader and writer using decorators - dataWriter = decorators.NewDataWriterWithCircuitBreaker(dataWriter, 1000) - dataReader = decorators.NewDataReaderWithCircuitBreaker(dataReader, 1000) + var cb *gobreaker.CircuitBreaker + var st gobreaker.Settings + st.Name = "storage" + st.ReadyToTrip = func(counts gobreaker.Counts) bool { + failureRatio := float64(counts.TotalFailures) / float64(counts.Requests) + return counts.Requests >= 10 && failureRatio >= 0.6 + } + + cb = gobreaker.NewCircuitBreaker(st) + + // Add circuit breaker to the relationship reader using decorator + dataReader = cbDecorator.NewDataReader(dataReader, cb) - // Add circuit breaker to the bundle reader and writer using decorators - bundleWriter = decorators.NewBundleWriterWithCircuitBreaker(bundleWriter, 1000) - bundleReader = decorators.NewBundleReaderWithCircuitBreaker(bundleReader, 1000) + // Add circuit breaker to the bundle reader using decorators + bundleReader = cbDecorator.NewBundleReader(bundleReader, cb) - // Add circuit breaker to the schema reader and writer using decorators - schemaWriter = decorators.NewSchemaWriterWithCircuitBreaker(schemaWriter, 1000) - schemaReader = decorators.NewSchemaReaderWithCircuitBreaker(schemaReader, 1000) + // Add circuit breaker to the schema reader using decorator + schemaReader = cbDecorator.NewSchemaReader(schemaReader, cb) - // Add circuit breaker to the tenant reader and writer using decorators - tenantWriter = decorators.NewTenantWriterWithCircuitBreaker(tenantWriter, 1000) - tenantReader = decorators.NewTenantReaderWithCircuitBreaker(tenantReader, 1000) + // Add circuit breaker to the tenant reader using decorator + tenantReader = cbDecorator.NewTenantReader(tenantReader, cb) } // Initialize the engines using the key manager, schema reader, and relationship reader diff --git a/pkg/database/iterators_test.go b/pkg/database/iterators_test.go index cfa4217fc..099d33ed3 100644 --- a/pkg/database/iterators_test.go +++ b/pkg/database/iterators_test.go @@ -279,3 +279,164 @@ func TestAttributeIterator(t *testing.T) { t.Error("Expected false for HasNext(), but got true") } } + +func TestUniqueAttributeIterator(t *testing.T) { + isPublic, err := anypb.New(&base.BooleanValue{Data: true}) + assert.NoError(t, err) + + // Create some attributes + attribute1 := &base.Attribute{ + Entity: &base.Entity{ + Type: "entity", + Id: "e1", + }, + Attribute: "public", + Value: isPublic, + } + + attribute2 := &base.Attribute{ + Entity: &base.Entity{ + Type: "entity", + Id: "e2", + }, + Attribute: "public", + Value: isPublic, + } + + attribute3 := &base.Attribute{ + Entity: &base.Entity{ + Type: "entity", + Id: "e3", + }, + Attribute: "public", + Value: isPublic, + } + + attribute4 := &base.Attribute{ + Entity: &base.Entity{ + Type: "entity", + Id: "e4", + }, + Attribute: "public", + Value: isPublic, + } + + attribute5 := &base.Attribute{ + Entity: &base.Entity{ + Type: "entity", + Id: "e5", + }, + Attribute: "public", + Value: isPublic, + } + + attribute6 := &base.Attribute{ + Entity: &base.Entity{ + Type: "entity", + Id: "e6", + }, + Attribute: "public", + Value: isPublic, + } + + // Create a tuple iterators + attributeIterator1 := NewAttributeIterator(attribute1, attribute2, attribute3, attribute6) + attributeIterator2 := NewAttributeIterator(attribute6, attribute1, attribute2, attribute4, attribute5) + + // Create a unique iterator + uniqueIterator := NewUniqueAttributeIterator(attributeIterator1, attributeIterator2) + + // Test HasNext() and GetNext() methods + if !uniqueIterator.HasNext() { + t.Error("Expected true for HasNext(), but got false") + } + i, _ := uniqueIterator.GetNext() + if i != attribute1 { + t.Error("Expected tuple1 for GetNext(), but got something else") + } + if !uniqueIterator.HasNext() { + t.Error("Expected true for HasNext(), but got false") + } + i, _ = uniqueIterator.GetNext() + if i != attribute2 { + t.Error("Expected tuple2 for GetNext(), but got something else") + } + if !uniqueIterator.HasNext() { + t.Error("Expected true for HasNext(), but got false") + } + i, _ = uniqueIterator.GetNext() + if i != attribute3 { + t.Error("Expected tuple3 for GetNext(), but got something else") + } + if !uniqueIterator.HasNext() { + t.Error("Expected false for HasNext(), but got true") + } + i, _ = uniqueIterator.GetNext() + if i != attribute6 { + t.Error("Expected tuple6 for GetNext(), but got something else") + } + if !uniqueIterator.HasNext() { + t.Error("Expected false for HasNext(), but got true") + } + i, _ = uniqueIterator.GetNext() + if i != attribute4 { + t.Error("Expected tuple4 for GetNext(), but got something else") + } + if !uniqueIterator.HasNext() { + t.Error("Expected false for HasNext(), but got true") + } + i, _ = uniqueIterator.GetNext() + if i != attribute5 { + t.Error("Expected tuple5 for GetNext(), but got something else") + } + if uniqueIterator.HasNext() { + t.Error("Expected false for HasNext(), but got true") + } +} + +func TestEntityIterator(t *testing.T) { + // Create some tuples + en1 := &base.Entity{ + Type: "entity", + Id: "e1", + } + + en2 := &base.Entity{ + Type: "entity", + Id: "e2", + } + + en3 := &base.Entity{ + Type: "entity", + Id: "e3", + } + + // Create a entity collection and add the tuples + entityCollection := NewEntityCollection(en1, en2, en3) + + // Create an entity iterator + entityIterator := entityCollection.CreateEntityIterator() + + // Test HasNext() and GetNext() methods + if !entityIterator.HasNext() { + t.Error("Expected true for HasNext(), but got false") + } + if entityIterator.GetNext() != en1 { + t.Error("Expected tuple1 for GetNext(), but got something else") + } + if !entityIterator.HasNext() { + t.Error("Expected true for HasNext(), but got false") + } + if entityIterator.GetNext() != en2 { + t.Error("Expected tuple2 for GetNext(), but got something else") + } + if !entityIterator.HasNext() { + t.Error("Expected true for HasNext(), but got false") + } + if entityIterator.GetNext() != en3 { + t.Error("Expected tuple3 for GetNext(), but got something else") + } + if entityIterator.HasNext() { + t.Error("Expected false for HasNext(), but got true") + } +} diff --git a/pkg/pb/base/v1/openapi.pb.go b/pkg/pb/base/v1/openapi.pb.go index d11ea0bcf..1a7d10e54 100644 --- a/pkg/pb/base/v1/openapi.pb.go +++ b/pkg/pb/base/v1/openapi.pb.go @@ -46,7 +46,7 @@ var file_base_v1_openapi_proto_rawDesc = []byte{ 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x66, 0x79, 0x2f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x66, 0x79, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, - 0x32, 0x06, 0x76, 0x30, 0x2e, 0x36, 0x2e, 0x35, 0x2a, 0x01, 0x02, 0x32, 0x10, 0x61, 0x70, 0x70, + 0x32, 0x06, 0x76, 0x30, 0x2e, 0x36, 0x2e, 0x39, 0x2a, 0x01, 0x02, 0x32, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x5a, 0x23, 0x0a, 0x21, 0x0a, 0x0a, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x41, 0x75, 0x74, 0x68, 0x12, diff --git a/proto/base/v1/openapi.proto b/proto/base/v1/openapi.proto index d00db577c..d9d8fad30 100644 --- a/proto/base/v1/openapi.proto +++ b/proto/base/v1/openapi.proto @@ -9,7 +9,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { info: { title: "Permify API"; description: "Permify is an open source authorization service for creating fine-grained and scalable authorization systems."; - version: "v0.6.5"; + version: "v0.6.9"; contact: { name: "API Support"; url: "https://github.com/Permify/permify/issues"; diff --git a/tools/go.mod b/tools/go.mod index 7e4f51cf0..b45edcd82 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -1,183 +1,3 @@ module github.com/Permify/permify/tools -go 1.19 - -require ( - github.com/golangci/golangci-lint v1.51.1 - github.com/securego/gosec v0.0.0-20200401082031-e946c8c39989 - golang.org/x/vuln v0.0.0-20230213165600-1a019b0c7f30 -) - -require ( - 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect - 4d63.com/gochecknoglobals v0.2.1 // indirect - github.com/Abirdcfly/dupword v0.0.9 // indirect - github.com/Antonboom/errname v0.1.7 // indirect - github.com/Antonboom/nilnil v0.1.1 // indirect - github.com/BurntSushi/toml v1.2.1 // indirect - github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 // indirect - github.com/Masterminds/semver v1.5.0 // indirect - github.com/OpenPeeDeeP/depguard v1.1.1 // indirect - github.com/alexkohler/prealloc v1.0.0 // indirect - github.com/alingse/asasalint v0.0.11 // indirect - github.com/ashanbrown/forbidigo v1.3.0 // indirect - github.com/ashanbrown/makezero v1.1.1 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/bkielbasa/cyclop v1.2.0 // indirect - github.com/blizzy78/varnamelen v0.8.0 // indirect - github.com/bombsimon/wsl/v3 v3.3.0 // indirect - github.com/breml/bidichk v0.2.3 // indirect - github.com/breml/errchkjson v0.3.0 // indirect - github.com/butuzov/ireturn v0.1.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/charithe/durationcheck v0.0.9 // indirect - github.com/chavacava/garif v0.0.0-20221024190013-b3ef35877348 // indirect - github.com/curioswitch/go-reassign v0.2.0 // indirect - github.com/daixiang0/gci v0.9.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/denis-tingaikin/go-header v0.4.3 // indirect - github.com/esimonov/ifshort v1.0.4 // indirect - github.com/ettle/strcase v0.1.1 // indirect - github.com/fatih/color v1.14.1 // indirect - github.com/fatih/structtag v1.2.0 // indirect - github.com/firefart/nonamedreturns v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect - github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/go-critic/go-critic v0.6.5 // indirect - github.com/go-toolsmith/astcast v1.0.0 // indirect - github.com/go-toolsmith/astcopy v1.0.3 // indirect - github.com/go-toolsmith/astequal v1.0.3 // indirect - github.com/go-toolsmith/astfmt v1.0.0 // indirect - github.com/go-toolsmith/astp v1.0.0 // indirect - github.com/go-toolsmith/strparse v1.0.0 // indirect - github.com/go-toolsmith/typep v1.0.2 // indirect - github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect - github.com/gobwas/glob v0.2.3 // indirect - github.com/gofrs/flock v0.8.1 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect - github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect - github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect - github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 // indirect - github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect - github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect - github.com/golangci/misspell v0.4.0 // indirect - github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 // indirect - github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect - github.com/google/go-cmp v0.5.9 // indirect - github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 // indirect - github.com/gostaticanalysis/analysisutil v0.7.1 // indirect - github.com/gostaticanalysis/comment v1.4.2 // indirect - github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect - github.com/gostaticanalysis/nilerr v0.1.1 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hexops/gotextdiff v1.0.3 // indirect - github.com/inconshreveable/mousetrap v1.0.1 // indirect - github.com/jgautheron/goconst v1.5.1 // indirect - github.com/jingyugao/rowserrcheck v1.1.1 // indirect - github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect - github.com/julz/importas v0.1.0 // indirect - github.com/junk1tm/musttag v0.4.4 // indirect - github.com/kisielk/errcheck v1.6.3 // indirect - github.com/kisielk/gotool v1.0.0 // indirect - github.com/kkHAIKE/contextcheck v1.1.3 // indirect - github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.6 // indirect - github.com/kyoh86/exportloopref v0.1.11 // indirect - github.com/ldez/gomoddirectives v0.2.3 // indirect - github.com/ldez/tagliatelle v0.4.0 // indirect - github.com/leonklingele/grouper v1.1.1 // indirect - github.com/lufeee/execinquery v1.2.1 // indirect - github.com/magiconair/properties v1.8.6 // indirect - github.com/maratori/testableexamples v1.0.0 // indirect - github.com/maratori/testpackage v1.1.0 // indirect - github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mbilski/exhaustivestruct v1.2.0 // indirect - github.com/mgechev/revive v1.2.5 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/moricho/tparallel v0.2.1 // indirect - github.com/nakabonne/nestif v0.3.1 // indirect - github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect - github.com/nishanths/exhaustive v0.9.5 // indirect - github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.8.1 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.5 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polyfloyd/go-errorlint v1.0.6 // indirect - github.com/prometheus/client_golang v1.12.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/quasilyte/go-ruleguard v0.3.18 // indirect - github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f // indirect - github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 // indirect - github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect - github.com/ryancurrah/gomodguard v1.3.0 // indirect - github.com/ryanrolds/sqlclosecheck v0.4.0 // indirect - github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect - github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.21.1 // indirect - github.com/securego/gosec/v2 v2.14.0 // indirect - github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect - github.com/sirupsen/logrus v1.9.0 // indirect - github.com/sivchari/containedctx v1.0.2 // indirect - github.com/sivchari/nosnakecase v1.7.0 // indirect - github.com/sivchari/tenv v1.7.1 // indirect - github.com/sonatard/noctx v0.0.1 // indirect - github.com/sourcegraph/go-diff v0.7.0 // indirect - github.com/spf13/afero v1.8.2 // indirect - github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/cobra v1.6.1 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.12.0 // indirect - github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect - github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/stretchr/testify v1.8.1 // indirect - github.com/subosito/gotenv v1.4.1 // indirect - github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect - github.com/tdakkota/asciicheck v0.1.1 // indirect - github.com/tetafro/godot v1.4.11 // indirect - github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e // indirect - github.com/timonwong/loggercheck v0.9.3 // indirect - github.com/tomarrell/wrapcheck/v2 v2.8.0 // indirect - github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect - github.com/ultraware/funlen v0.0.3 // indirect - github.com/ultraware/whitespace v0.0.5 // indirect - github.com/uudashr/gocognit v1.0.6 // indirect - github.com/yagipy/maintidx v1.0.0 // indirect - github.com/yeya24/promlinter v0.2.0 // indirect - gitlab.com/bosi/decorder v0.2.3 // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.17.0 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a // indirect - golang.org/x/mod v0.11.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.9.0 // indirect - golang.org/x/text v0.6.0 // indirect - golang.org/x/tools v0.10.0 // indirect - google.golang.org/protobuf v1.28.0 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/tools v0.4.0 // indirect - mvdan.cc/gofumpt v0.4.0 // indirect - mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect - mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect - mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d // indirect -) +go 1.21 diff --git a/tools/go.sum b/tools/go.sum index aa4f9a6bc..e69de29bb 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -1,1017 +0,0 @@ -4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA= -4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= -4d63.com/gochecknoglobals v0.2.1 h1:1eiorGsgHOFOuoOiJDy2psSrQbRdIHrlge0IJIkUgDc= -4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU= -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.44.3/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 v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -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= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Abirdcfly/dupword v0.0.9 h1:MxprGjKq3yDBICXDgEEsyGirIXfMYXkLNT/agPsE1tk= -github.com/Abirdcfly/dupword v0.0.9/go.mod h1:PzmHVLLZ27MvHSzV7eFmMXSFArWXZPZmfuuziuUrf2g= -github.com/Antonboom/errname v0.1.7 h1:mBBDKvEYwPl4WFFNwec1CZO096G6vzK9vvDQzAwkako= -github.com/Antonboom/errname v0.1.7/go.mod h1:g0ONh16msHIPgJSGsecu1G/dcF2hlYR/0SddnIAGavU= -github.com/Antonboom/nilnil v0.1.1 h1:PHhrh5ANKFWRBh7TdYmyyq2gyT2lotnvFvvFbylF81Q= -github.com/Antonboom/nilnil v0.1.1/go.mod h1:L1jBqoWM7AOeTD+tSquifKSesRHs4ZdaxvZR+xdJEaI= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 h1:+r1rSv4gvYn0wmRjC8X7IAzX8QezqtFV9m0MUHFJgts= -github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/OpenPeeDeeP/depguard v1.1.1 h1:TSUznLjvp/4IUP+OQ0t/4jF4QUyxIcVX8YnghZdunyA= -github.com/OpenPeeDeeP/depguard v1.1.1/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= -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/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= -github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= -github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= -github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= -github.com/ashanbrown/forbidigo v1.3.0 h1:VkYIwb/xxdireGAdJNZoo24O4lmnEWkactplBlWTShc= -github.com/ashanbrown/forbidigo v1.3.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= -github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= -github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= -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/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7A= -github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= -github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= -github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= -github.com/bombsimon/wsl/v3 v3.3.0 h1:Mka/+kRLoQJq7g2rggtgQsjuI/K5Efd87WX96EWFxjM= -github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= -github.com/breml/bidichk v0.2.3 h1:qe6ggxpTfA8E75hdjWPZ581sY3a2lnl0IRxLQFelECI= -github.com/breml/bidichk v0.2.3/go.mod h1:8u2C6DnAy0g2cEq+k/A2+tr9O1s+vHGxWn0LTc70T2A= -github.com/breml/errchkjson v0.3.0 h1:YdDqhfqMT+I1vIxPSas44P+9Z9HzJwCeAzjB8PxP1xw= -github.com/breml/errchkjson v0.3.0/go.mod h1:9Cogkyv9gcT8HREpzi3TiqBxCqDzo8awa92zSDFcofU= -github.com/butuzov/ireturn v0.1.1 h1:QvrO2QF2+/Cx1WA/vETCIYBKtRjc30vesdoPUNo1EbY= -github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -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/charithe/durationcheck v0.0.9 h1:mPP4ucLrf/rKZiIG/a9IPXHGlh8p4CzgpyTy6EEutYk= -github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= -github.com/chavacava/garif v0.0.0-20221024190013-b3ef35877348 h1:cy5GCEZLUCshCGCRRUjxHrDUqkB4l5cuUt3ShEckQEo= -github.com/chavacava/garif v0.0.0-20221024190013-b3ef35877348/go.mod h1:f/miWtG3SSuTxKsNK3o58H1xl+XV6ZIfbC6p7lPPB8U= -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/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= -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-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cristalhq/acmd v0.8.1/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= -github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= -github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= -github.com/daixiang0/gci v0.9.0 h1:t8XZ0vK6l0pwPoOmoGyqW2NwQlvbpAQNVvu/GRBgykM= -github.com/daixiang0/gci v0.9.0/go.mod h1:EpVfrztufwVgQRXjnX4zuNinEpLj5OmMjtu/+MB0V0c= -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/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU= -github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= -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.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= -github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= -github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= -github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= -github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= -github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= -github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= -github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= -github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/go-critic/go-critic v0.6.5 h1:fDaR/5GWURljXwF8Eh31T2GZNz9X4jeboS912mWF8Uo= -github.com/go-critic/go-critic v0.6.5/go.mod h1:ezfP/Lh7MA6dBNn4c6ab5ALv3sKnZVLx37tr00uuaOY= -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-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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= -github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= -github.com/go-toolsmith/astcopy v1.0.2/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= -github.com/go-toolsmith/astcopy v1.0.3 h1:r0bgSRlMOAgO+BdQnVAcpMSMkrQCnV6ZJmIkrJgcJj0= -github.com/go-toolsmith/astcopy v1.0.3/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= -github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= -github.com/go-toolsmith/astequal v1.0.2/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astequal v1.0.3 h1:+LVdyRatFS+XO78SGV4I3TCEA0AC7fKEGma+fH+674o= -github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= -github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= -github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= -github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= -github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5 h1:eD9POs68PHkwrx7hAB78z1cb6PfGq/jyWn3wJywsH1o= -github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5/go.mod h1:3NAwwmD4uY/yggRxoEjk/S00MIV3A+H7rrE3i87eYxM= -github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= -github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= -github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk= -github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= -github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= -github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -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/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/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/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= -github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo= -github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= -github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= -github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= -github.com/golangci/golangci-lint v1.51.1 h1:N5HD/x0ZrhJYsgKWyz7yJxxQ8JKR0Acc+FOP7QtGSAA= -github.com/golangci/golangci-lint v1.51.1/go.mod h1:hnyNNO3fJ2Rjwo6HM+VXvcmLkKDOuBAnR9gVlS1mW1E= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= -github.com/golangci/misspell v0.4.0 h1:KtVB/hTK4bbL/S6bs64rYyk8adjmh1BygbBiaAiX+a0= -github.com/golangci/misspell v0.4.0/go.mod h1:W6O/bwV6lGDxUCChm2ykw9NQdd5bYd1Xkjo88UcWyJc= -github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 h1:DIPQnGy2Gv2FSA4B/hh8Q7xx3B7AIDk3DAMeHclH1vQ= -github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= -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/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU= -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.2/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.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/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/martian/v3 v3.1.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/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= -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/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/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 h1:9alfqbrhuD+9fLZ4iaAVwhlp5PEhmnBt7yvK2Oy5C1U= -github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= -github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= -github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= -github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= -github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= -github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI= -github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= -github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= -github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= -github.com/gostaticanalysis/forcetypeassert v0.1.0 h1:6eUflI3DiGusXGK6X7cCcIgVCpZ2CiZ1Q7jl6ZxNV70= -github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= -github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= -github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= -github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= -github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -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-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -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/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= -github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -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/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= -github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= -github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= -github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= -github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= -github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= -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.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/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/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= -github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= -github.com/junk1tm/musttag v0.4.4 h1:VK4L7v7lvWAhKDDx0cUJgbb0UBNipYinv8pPeHJzH9Q= -github.com/junk1tm/musttag v0.4.4/go.mod h1:XkcL/9O6RmD88JBXb+I15nYRl9W4ExhgQeCBEhfMC8U= -github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8= -github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkHAIKE/contextcheck v1.1.3 h1:l4pNvrb8JSwRd51ojtcOxOeHJzHek+MtOyXbaR0uvmw= -github.com/kkHAIKE/contextcheck v1.1.3/go.mod h1:PG/cwd6c0705/LM0KTr1acO2gORUxkSVWyLJOFW5qoo= -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/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -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.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -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/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= -github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.6 h1:FCKYMF1OF2+RveWlABsdnmsvJrei5aoyZoaGS+Ugg8g= -github.com/kunwardeep/paralleltest v1.0.6/go.mod h1:Y0Y0XISdZM5IKm3TREQMZ6iteqn1YuwCsJO/0kL9Zes= -github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= -github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= -github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= -github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= -github.com/ldez/tagliatelle v0.4.0 h1:sylp7d9kh6AdXN2DpVGHBRb5guTVAgOxqNGhbqc4b1c= -github.com/ldez/tagliatelle v0.4.0/go.mod h1:mNtTfrHy2haaBAw+VT7IBV6VXBThS7TCreYWbBcJ87I= -github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= -github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= -github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= -github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= -github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= -github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= -github.com/maratori/testpackage v1.1.0 h1:GJY4wlzQhuBusMF1oahQCBtUV/AQ/k69IZ68vxaac2Q= -github.com/maratori/testpackage v1.1.0/go.mod h1:PeAhzU8qkCwdGEMTEupsHJNlQu2gZopMC6RjbhmHeDc= -github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= -github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= -github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -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.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= -github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= -github.com/mgechev/revive v1.2.5 h1:UF9AR8pOAuwNmhXj2odp4mxv9Nx2qUIwVz8ZsU+Mbec= -github.com/mgechev/revive v1.2.5/go.mod h1:nFOXent79jMTISAfOAasKfy0Z2Ejq0WX7Qn/KAdYopI= -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/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/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/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/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/moricho/tparallel v0.2.1 h1:95FytivzT6rYzdJLdtfn6m1bfFJylOJK41+lgv/EHf4= -github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= -github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= -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/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= -github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= -github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= -github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= -github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nishanths/exhaustive v0.9.5 h1:TzssWan6orBiLYVqewCG8faud9qlFntJE30ACpzmGME= -github.com/nishanths/exhaustive v0.9.5/go.mod h1:IbwrGdVMizvDcIxPYGVdQn5BqWJaOwpCvg4RGb8r/TA= -github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= -github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.8.1 h1:/y4o/0hV+ruUHj4xXh89xlFjoaitnI4LnkpuYs02q1c= -github.com/nunnatsa/ginkgolinter v0.8.1/go.mod h1:FYYLtszIdmzCH8XMaMPyxPVXZ7VCaIm55bA+gugx+14= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= -github.com/onsi/ginkgo/v2 v2.3.1 h1:8SbseP7qM32WcvE6VaN6vfXxv698izmsJ1UQX9ve7T8= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/onsi/gomega v1.22.1 h1:pY8O4lBfsHKZHM/6nrxkhVPUznOlIu3quZcKP/M20KI= -github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= -github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= -github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= -github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= -github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= -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/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -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/polyfloyd/go-errorlint v1.0.6 h1:ZevdyEGxDoHAMQUVvdTT06hnYuKULe8TQkOmIYx6s1c= -github.com/polyfloyd/go-errorlint v1.0.6/go.mod h1:NcnNncnm8fVV7vfQWiI4HZrzWFzGp24C262IQutNcMs= -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.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 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -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 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -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 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -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.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 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= -github.com/quasilyte/go-ruleguard v0.3.18 h1:sd+abO1PEI9fkYennwzHn9kl3nqP6M5vE7FiOzZ+5CE= -github.com/quasilyte/go-ruleguard v0.3.18/go.mod h1:lOIzcYlgxrQ2sGJ735EHXmf/e9MJ516j16K/Ifcttvs= -github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/dsl v0.3.21/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= -github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f h1:6Gtn2i04RD0gVyYf2/IUMTIs+qYleBt4zxDqkLTcu4U= -github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= -github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY= -github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= -github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= -github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= -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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= -github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= -github.com/ryanrolds/sqlclosecheck v0.4.0 h1:i8SX60Rppc1wRuyQjMciLqIzV3xnoHB7/tXbr6RGYNI= -github.com/ryanrolds/sqlclosecheck v0.4.0/go.mod h1:TBRRjzL31JONc9i4XMinicuo+s+E8yKZ5FN8X3G6CKQ= -github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= -github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= -github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= -github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.21.1 h1:GQGlReyL9Ek8DdJmwtwhHbhwHnuPfsKaprpjnrPcjxc= -github.com/sashamelentyev/usestdlibvars v1.21.1/go.mod h1:MPI52Qq99iO9sFZZcKJ2y/bx6BNjs+/2bw3PCggIbew= -github.com/securego/gosec v0.0.0-20200401082031-e946c8c39989 h1:rq2/kILQnPtq5oL4+IAjgVOjh5e2yj2aaCYi7squEvI= -github.com/securego/gosec v0.0.0-20200401082031-e946c8c39989/go.mod h1:i9l/TNj+yDFh9SZXUTvspXTjbFXgZGP/UvhU1S65A4A= -github.com/securego/gosec/v2 v2.14.0 h1:U1hfs0oBackChXA72plCYVA4cOlQ4gO+209dHiSNZbI= -github.com/securego/gosec/v2 v2.14.0/go.mod h1:Ff03zEi5NwSOfXj9nFpBfhbWTtROCkg9N+9goggrYn4= -github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= -github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -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/sivchari/containedctx v1.0.2 h1:0hLQKpgC53OVF1VT7CeoFHk9YKstur1XOgfYIc1yrHI= -github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= -github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= -github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= -github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak= -github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= -github.com/sonatard/noctx v0.0.1 h1:VC1Qhl6Oxx9vvWo3UDgrGXYCeKCe3Wbw7qAWL6FrmTY= -github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= -github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= -github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= -github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= -github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -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.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= -github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= -github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= -github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= -github.com/stbenjam/no-sprintf-host-port v0.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm07ysF0U6JQXczc= -github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= -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.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -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.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -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.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.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/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= -github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8= -github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= -github.com/tdakkota/asciicheck v0.1.1 h1:PKzG7JUTUmVspQTDqtkX9eSiLGossXTybutHwTXuO0A= -github.com/tdakkota/asciicheck v0.1.1/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= -github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= -github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= -github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= -github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= -github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= -github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e h1:MV6KaVu/hzByHP0UvJ4HcMGE/8a6A4Rggc/0wx2AvJo= -github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= -github.com/timonwong/loggercheck v0.9.3 h1:ecACo9fNiHxX4/Bc02rW2+kaJIAMAes7qJ7JKxt0EZI= -github.com/timonwong/loggercheck v0.9.3/go.mod h1:wUqnk9yAOIKtGA39l1KLE9Iz0QiTocu/YZoOf+OzFdw= -github.com/tomarrell/wrapcheck/v2 v2.8.0 h1:qDzbir0xmoE+aNxGCPrn+rUSxAX+nG6vREgbbXAR81I= -github.com/tomarrell/wrapcheck/v2 v2.8.0/go.mod h1:ao7l5p0aOlUNJKI0qVwB4Yjlqutd0IvAB9Rdwyilxvg= -github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= -github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= -github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iLA= -github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= -github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= -github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= -github.com/uudashr/gocognit v1.0.6 h1:2Cgi6MweCsdB6kpcVQp7EW4U23iBFQWfTXiWlyp842Y= -github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY= -github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= -github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= -github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o= -github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= -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= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -gitlab.com/bosi/decorder v0.2.3 h1:gX4/RgK16ijY8V+BRQHAySfQAb354T7/xQpDB2n10P0= -gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE= -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.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -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-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-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.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-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= -golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a h1:Jw5wfR+h9mnIYH+OtGT2im5wV1YGGDora5vTv/aa5bE= -golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -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/lint v0.0.0-20201208152925-83fdc39ff7b5/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.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.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= -golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -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-20180906233101-161cd47e91fd/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-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-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -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-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -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-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -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-20220722155255-886fb9371eb4/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/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -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-20180909124046-d0be0721c37e/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-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-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/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-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-20200905004654-be1d3432aa8f/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/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-20210423185535-09eb48e85fd7/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-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/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-20220412211240-33da011f77ad/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-20220702020025-31831981b65f/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.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/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -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.4/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/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= -golang.org/x/text v0.6.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/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -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-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/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-20190321232350-e250d351ecad/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-20190910044552-dd2b5c81c578/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-20190916130336-e45ffcd953cc/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-20191108193012-7d206e10da11/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-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-20200117220505-0cba7a3a9ee9/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-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200331202046-9d5940d49312/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -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-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -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-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= -golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= -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.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= -golang.org/x/tools v0.5.1-0.20230117180257-8aba49bb5ea2 h1:v0FhRDmSCNH/0EurAT6T8KRY4aNuUhz6/WwBMxG+gvQ= -golang.org/x/tools v0.5.1-0.20230117180257-8aba49bb5ea2/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= -golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= -golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= -golang.org/x/vuln v0.0.0-20230213165600-1a019b0c7f30 h1:Q4B8LhSjZGto/+P5REBb4N51ec2H4efRqjBIeJ6nv/Y= -golang.org/x/vuln v0.0.0-20230213165600-1a019b0c7f30/go.mod h1:cBP4HMKv0X+x96j8IJWCKk0eqpakBmmHjKGSSC0NaYE= -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= -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/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -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/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-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-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-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -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.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -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.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/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 h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -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.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-20210107192922-496545a6307b/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= -honnef.co/go/tools v0.4.0 h1:lyXVV1c8wUBJRKqI8JgIpT8TW1VDagfYYaxbKa/HoL8= -honnef.co/go/tools v0.4.0/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= -mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM= -mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= -mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d h1:3rvTIIM22r9pvXk+q3swxUQAQOxksVMGK7sml4nG57w= -mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= -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= diff --git a/tools/tools.go b/tools/tools.go index 83de3f993..9fe9a2cf3 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -2,9 +2,3 @@ // +build tools package tools - -import ( - _ "github.com/golangci/golangci-lint/cmd/golangci-lint" - _ "github.com/securego/gosec/cmd/gosec" - _ "golang.org/x/vuln/cmd/govulncheck" -)