From 7bb71b0eab27fbabd467ecd99d42be1814e62f00 Mon Sep 17 00:00:00 2001 From: Tu Nguyen Date: Mon, 30 Oct 2023 15:28:42 +0000 Subject: [PATCH] backport of commit e9006e654873c2e42d911fdca4a0a73698a07661 --- .changelog/19218.txt | 3 - .changelog/{19306.txt => 19274.txt} | 0 .changelog/19311.txt | 3 - ...t-1.17.x.yaml => nightly-test-1.13.x.yaml} | 18 +- .../nightly-test-integrations-1.17.x.yml | 342 ------ .github/workflows/reusable-unit-split.yml | 3 +- .github/workflows/reusable-unit.yml | 3 +- .github/workflows/test-integrations.yml | 1 + .github/workflows/verify-envoy-version.yml | 2 +- agent/consul/fsm/commands_ce.go | 89 +- agent/consul/fsm/decode_ce.go | 145 --- agent/consul/fsm/decode_downgrade.go | 1011 ----------------- agent/consul/fsm/fsm.go | 9 +- agent/consul/options.go | 11 +- agent/consul/server.go | 31 +- agent/consul/server_test.go | 42 +- agent/consul/state/peering.go | 3 - .../testdata/v2-resource-dependencies.md | 45 - agent/consul/type_registry.go | 2 - .../grpc-external/services/resource/delete.go | 7 +- .../services/resource/delete_test.go | 94 +- agent/grpc-external/services/resource/list.go | 9 +- .../services/resource/list_by_owner.go | 9 +- .../services/resource/list_by_owner_test.go | 158 +-- .../services/resource/list_test.go | 101 +- agent/grpc-external/services/resource/read.go | 8 +- .../services/resource/read_test.go | 169 +-- .../grpc-external/services/resource/server.go | 99 +- .../services/resource/server_ce.go | 13 - .../services/resource/server_test.go | 37 +- .../services/resource/testing/testing.go | 21 +- .../services/resource/testing/testing_ce.go | 47 - .../grpc-external/services/resource/watch.go | 9 +- .../services/resource/watch_test.go | 59 +- .../grpc-external/services/resource/write.go | 12 +- .../services/resource/write_status.go | 17 +- .../services/resource/write_status_test.go | 173 +-- .../services/resource/write_test.go | 213 +--- agent/structs/structs.go | 4 - agent/xdsv2/resources_test.go | 21 +- command/resource/delete/delete.go | 4 + command/resource/delete/delete_test.go | 2 +- command/resource/helper.go | 83 +- command/resource/read/read_test.go | 2 +- .../types/computed_traffic_permissions.go | 14 +- .../internal/types/traffic_permissions.go | 64 +- .../auth/internal/types/workload_identity.go | 11 +- .../internal/types/workload_identity_test.go | 10 - internal/catalog/catalogtest/run_test.go | 2 +- .../catalogtest/test_integration_v2beta1.go | 4 +- internal/catalog/internal/types/acl_hooks.go | 19 +- internal/catalog/internal/types/dns_policy.go | 15 +- .../catalog/internal/types/failover_policy.go | 63 +- .../catalog/internal/types/health_checks.go | 15 +- .../catalog/internal/types/health_status.go | 25 +- internal/catalog/internal/types/node.go | 14 +- internal/catalog/internal/types/service.go | 33 +- .../internal/types/service_endpoints.go | 14 +- .../catalog/internal/types/virtual_ips.go | 12 +- internal/catalog/internal/types/workload.go | 49 +- internal/controller/dependencies.go | 100 -- internal/controller/dependencies_test.go | 66 -- .../controller/testdata/dependencies.golden | 5 - .../sidecarproxy/builder/destinations.go | 1 + .../controllers/xds/controller_test.go | 6 +- .../mixed-multi-destination.golden | 2 +- ...ltiple-implicit-destinations-tproxy.golden | 2 +- ...-single-implicit-destination-tproxy.golden | 2 +- ...tion-with-multiple-workloads-tproxy.golden | 2 +- .../mesh/internal/types/computed_routes.go | 13 +- internal/mesh/internal/types/decoded.go | 1 - .../mesh/internal/types/destination_policy.go | 12 +- internal/mesh/internal/types/destinations.go | 30 +- .../types/destinations_configuration.go | 11 +- internal/mesh/internal/types/grpc_route.go | 33 +- internal/mesh/internal/types/http_route.go | 33 +- .../internal/types/proxy_configuration.go | 41 +- .../internal/types/proxy_state_template.go | 14 +- internal/mesh/internal/types/tcp_route.go | 33 +- internal/mesh/internal/types/xroute.go | 32 +- internal/multicluster/exports.go | 22 - .../types/computed_exported_services.go | 37 - .../types/computed_exported_services_test.go | 178 --- .../internal/types/exported_services.go | 59 - .../internal/types/exported_services_test.go | 218 ---- .../multicluster/internal/types/helpers.go | 135 --- .../multicluster/internal/types/helpers_ce.go | 66 -- .../types/namespace_exported_services.go | 33 - .../types/namespace_exported_services_test.go | 184 --- .../types/partition_exported_services.go | 33 - .../types/partition_exported_services_test.go | 185 --- internal/multicluster/internal/types/types.go | 21 - internal/resource/decode.go | 6 +- internal/resource/demo/controller.go | 2 +- internal/resource/demo/demo.go | 2 +- internal/resource/hooks.go | 107 -- internal/resource/hooks_test.go | 243 ---- internal/resource/http/http_test.go | 19 +- internal/resource/registry.go | 25 +- internal/resource/resource.go | 22 - internal/resource/tenancy.go | 26 + .../bridge => resource}/tenancy_bridge_ce.go | 13 +- internal/tenancy/exports.go | 26 +- .../tenancy/internal/bridge/tenancy_bridge.go | 55 - .../internal/controllers/register_ce.go | 14 - internal/tenancy/internal/types/namespace.go | 30 +- .../{types_test.go => namespace_test.go} | 93 +- internal/tenancy/internal/types/types.go | 6 +- .../tenancy/tenancytest/namespace_test.go | 130 --- .../computed_exported_services.pb.binary.go | 38 - .../v2beta1/computed_exported_services.pb.go | 373 ------ .../v2beta1/computed_exported_services.proto | 28 - ...computed_exported_services_deepcopy.gen.go | 69 -- .../computed_exported_services_json.gen.go | 44 - .../v2beta1/exported_services.pb.binary.go | 18 - .../v2beta1/exported_services.pb.go | 193 ---- .../v2beta1/exported_services.proto | 16 - .../exported_services_consumer.pb.binary.go | 18 - .../v2beta1/exported_services_consumer.pb.go | 230 ---- .../v2beta1/exported_services_consumer.proto | 14 - ...exported_services_consumer_deepcopy.gen.go | 27 - .../exported_services_consumer_json.gen.go | 22 - .../v2beta1/exported_services_deepcopy.gen.go | 27 - .../v2beta1/exported_services_json.gen.go | 22 - .../namespace_exported_services.pb.binary.go | 18 - .../v2beta1/namespace_exported_services.pb.go | 185 --- .../v2beta1/namespace_exported_services.proto | 15 - ...amespace_exported_services_deepcopy.gen.go | 27 - .../namespace_exported_services_json.gen.go | 22 - .../partition_exported_services.pb.binary.go | 18 - .../v2beta1/partition_exported_services.pb.go | 185 --- .../v2beta1/partition_exported_services.proto | 15 - ...artition_exported_services_deepcopy.gen.go | 27 - .../partition_exported_services_json.gen.go | 22 - .../v2beta1/resource_types.gen.go | 43 - .../namespace.pb.binary.go | 4 +- .../pbtenancy/v1alpha1/namespace.pb.go | 172 +++ .../{v2beta1 => v1alpha1}/namespace.proto | 2 +- .../namespace_deepcopy.gen.go | 2 +- .../namespace_json.gen.go | 2 +- .../resource_types.gen.go | 4 +- .../pbtenancy/v2beta1/namespace.pb.go | 171 --- .../test/catalog/catalog_test.go | 2 +- testing/deployer/topology/compile.go | 2 +- testing/deployer/topology/images.go | 9 +- version/VERSION | 2 +- .../services/discovery/dns-configuration.mdx | 2 +- 147 files changed, 1155 insertions(+), 6862 deletions(-) delete mode 100644 .changelog/19218.txt rename .changelog/{19306.txt => 19274.txt} (100%) delete mode 100644 .changelog/19311.txt rename .github/workflows/{nightly-test-1.17.x.yaml => nightly-test-1.13.x.yaml} (96%) delete mode 100644 .github/workflows/nightly-test-integrations-1.17.x.yml delete mode 100644 agent/consul/fsm/decode_ce.go delete mode 100644 agent/consul/fsm/decode_downgrade.go delete mode 100644 agent/consul/testdata/v2-resource-dependencies.md delete mode 100644 internal/controller/dependencies.go delete mode 100644 internal/controller/dependencies_test.go delete mode 100644 internal/controller/testdata/dependencies.golden delete mode 100644 internal/multicluster/exports.go delete mode 100644 internal/multicluster/internal/types/computed_exported_services.go delete mode 100644 internal/multicluster/internal/types/computed_exported_services_test.go delete mode 100644 internal/multicluster/internal/types/exported_services.go delete mode 100644 internal/multicluster/internal/types/exported_services_test.go delete mode 100644 internal/multicluster/internal/types/helpers.go delete mode 100644 internal/multicluster/internal/types/helpers_ce.go delete mode 100644 internal/multicluster/internal/types/namespace_exported_services.go delete mode 100644 internal/multicluster/internal/types/namespace_exported_services_test.go delete mode 100644 internal/multicluster/internal/types/partition_exported_services.go delete mode 100644 internal/multicluster/internal/types/partition_exported_services_test.go delete mode 100644 internal/multicluster/internal/types/types.go delete mode 100644 internal/resource/hooks.go delete mode 100644 internal/resource/hooks_test.go delete mode 100644 internal/resource/resource.go rename internal/{tenancy/internal/bridge => resource}/tenancy_bridge_ce.go (52%) delete mode 100644 internal/tenancy/internal/bridge/tenancy_bridge.go delete mode 100644 internal/tenancy/internal/controllers/register_ce.go rename internal/tenancy/internal/types/{types_test.go => namespace_test.go} (54%) delete mode 100644 internal/tenancy/tenancytest/namespace_test.go delete mode 100644 proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.binary.go delete mode 100644 proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.go delete mode 100644 proto-public/pbmulticluster/v2beta1/computed_exported_services.proto delete mode 100644 proto-public/pbmulticluster/v2beta1/computed_exported_services_deepcopy.gen.go delete mode 100644 proto-public/pbmulticluster/v2beta1/computed_exported_services_json.gen.go delete mode 100644 proto-public/pbmulticluster/v2beta1/exported_services.pb.binary.go delete mode 100644 proto-public/pbmulticluster/v2beta1/exported_services.pb.go delete mode 100644 proto-public/pbmulticluster/v2beta1/exported_services.proto delete mode 100644 proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.binary.go delete mode 100644 proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.go delete mode 100644 proto-public/pbmulticluster/v2beta1/exported_services_consumer.proto delete mode 100644 proto-public/pbmulticluster/v2beta1/exported_services_consumer_deepcopy.gen.go delete mode 100644 proto-public/pbmulticluster/v2beta1/exported_services_consumer_json.gen.go delete mode 100644 proto-public/pbmulticluster/v2beta1/exported_services_deepcopy.gen.go delete mode 100644 proto-public/pbmulticluster/v2beta1/exported_services_json.gen.go delete mode 100644 proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.binary.go delete mode 100644 proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.go delete mode 100644 proto-public/pbmulticluster/v2beta1/namespace_exported_services.proto delete mode 100644 proto-public/pbmulticluster/v2beta1/namespace_exported_services_deepcopy.gen.go delete mode 100644 proto-public/pbmulticluster/v2beta1/namespace_exported_services_json.gen.go delete mode 100644 proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.binary.go delete mode 100644 proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.go delete mode 100644 proto-public/pbmulticluster/v2beta1/partition_exported_services.proto delete mode 100644 proto-public/pbmulticluster/v2beta1/partition_exported_services_deepcopy.gen.go delete mode 100644 proto-public/pbmulticluster/v2beta1/partition_exported_services_json.gen.go delete mode 100644 proto-public/pbmulticluster/v2beta1/resource_types.gen.go rename proto-public/pbtenancy/{v2beta1 => v1alpha1}/namespace.pb.binary.go (84%) create mode 100644 proto-public/pbtenancy/v1alpha1/namespace.pb.go rename proto-public/pbtenancy/{v2beta1 => v1alpha1}/namespace.proto (91%) rename proto-public/pbtenancy/{v2beta1 => v1alpha1}/namespace_deepcopy.gen.go (97%) rename proto-public/pbtenancy/{v2beta1 => v1alpha1}/namespace_json.gen.go (96%) rename proto-public/pbtenancy/{v2beta1 => v1alpha1}/resource_types.gen.go (87%) delete mode 100644 proto-public/pbtenancy/v2beta1/namespace.pb.go diff --git a/.changelog/19218.txt b/.changelog/19218.txt deleted file mode 100644 index a3dde32317b47..0000000000000 --- a/.changelog/19218.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -resource: lowercase names enforced for v2 resources only. -``` \ No newline at end of file diff --git a/.changelog/19306.txt b/.changelog/19274.txt similarity index 100% rename from .changelog/19306.txt rename to .changelog/19274.txt diff --git a/.changelog/19311.txt b/.changelog/19311.txt deleted file mode 100644 index e53536f44d32b..0000000000000 --- a/.changelog/19311.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -raft: Fix panic during downgrade from enterprise to oss. -``` \ No newline at end of file diff --git a/.github/workflows/nightly-test-1.17.x.yaml b/.github/workflows/nightly-test-1.13.x.yaml similarity index 96% rename from .github/workflows/nightly-test-1.17.x.yaml rename to .github/workflows/nightly-test-1.13.x.yaml index 9a063001e402c..f314a475dfbd7 100644 --- a/.github/workflows/nightly-test-1.17.x.yaml +++ b/.github/workflows/nightly-test-1.13.x.yaml @@ -1,7 +1,7 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: MPL-2.0 -name: Nightly Frontend Test 1.17.x +name: Nightly Frontend Test 1.13.x on: schedule: - cron: '0 4 * * *' @@ -9,8 +9,8 @@ on: env: EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition - BRANCH: "release/1.17.x" - BRANCH_NAME: "release-1.17.x" # Used for naming artifacts + BRANCH: "release/1.13.x" + BRANCH_NAME: "release-1.13.x" # Used for naming artifacts GOPRIVATE: github.com/hashicorp # Required for enterprise deps jobs: @@ -24,7 +24,7 @@ jobs: # Not necessary to use yarn, but enables caching - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 with: - node-version: 18 + node-version: 14 cache: 'yarn' cache-dependency-path: ./ui/yarn.lock @@ -56,7 +56,7 @@ jobs: # Not necessary to use yarn, but enables caching - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 with: - node-version: 18 + node-version: 14 cache: 'yarn' cache-dependency-path: ./ui/yarn.lock @@ -95,7 +95,7 @@ jobs: # Not necessary to use yarn, but enables caching - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 with: - node-version: 18 + node-version: 14 cache: 'yarn' cache-dependency-path: ./ui/yarn.lock @@ -128,7 +128,7 @@ jobs: # Not necessary to use yarn, but enables caching - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 with: - node-version: 18 + node-version: 14 cache: 'yarn' cache-dependency-path: ./ui/yarn.lock @@ -167,7 +167,7 @@ jobs: # Not necessary to use yarn, but enables caching - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 with: - node-version: 18 + node-version: 14 cache: 'yarn' cache-dependency-path: ./ui/yarn.lock @@ -198,7 +198,7 @@ jobs: # Not necessary to use yarn, but enables caching - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 with: - node-version: 18 + node-version: 14 cache: 'yarn' cache-dependency-path: ./ui/yarn.lock diff --git a/.github/workflows/nightly-test-integrations-1.17.x.yml b/.github/workflows/nightly-test-integrations-1.17.x.yml deleted file mode 100644 index 660a28374b783..0000000000000 --- a/.github/workflows/nightly-test-integrations-1.17.x.yml +++ /dev/null @@ -1,342 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Nightly test-integrations 1.17.x - -on: - schedule: - # Run nightly at 1AM UTC/9PM EST/6PM PST - - cron: '* 1 * * *' - workflow_dispatch: {} - -env: - TEST_RESULTS_DIR: /tmp/test-results - TEST_RESULTS_ARTIFACT_NAME: test-results - CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} - GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} - GOTESTSUM_VERSION: "1.10.1" - CONSUL_BINARY_UPLOAD_NAME: consul-bin - # strip the hashicorp/ off the front of github.repository for consul - CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - BRANCH: "release/1.17.x" - BRANCH_NAME: "release-1.17.x" # Used for naming artifacts - -jobs: - setup: - runs-on: ubuntu-latest - name: Setup - outputs: - compute-small: ${{ steps.runners.outputs.compute-small }} - compute-medium: ${{ steps.runners.outputs.compute-medium }} - compute-large: ${{ steps.runners.outputs.compute-large }} - compute-xl: ${{ steps.runners.outputs.compute-xl }} - enterprise: ${{ steps.runners.outputs.enterprise }} - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - id: runners - run: .github/scripts/get_runner_classes.sh - - dev-build: - needs: [setup] - uses: ./.github/workflows/reusable-dev-build.yml - with: - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - uploaded-binary-name: 'consul-bin' - branch-name: "release/1.17.x" - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - generate-envoy-job-matrices: - needs: [setup] - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - name: Generate Envoy Job Matrices - outputs: - envoy-matrix: ${{ steps.set-matrix.outputs.envoy-matrix }} - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - name: Generate Envoy Job Matrix - id: set-matrix - env: - # this is further going to multiplied in envoy-integration tests by the - # other dimensions in the matrix. Currently TOTAL_RUNNERS would be - # multiplied by 8 based on these values: - # envoy-version: ["1.24.12", "1.25.11", "1.26.6", "1.27.2"] - # xds-target: ["server", "client"] - TOTAL_RUNNERS: 4 - JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' - run: | - NUM_RUNNERS=$TOTAL_RUNNERS - NUM_DIRS=$(find ./test/integration/connect/envoy -mindepth 1 -maxdepth 1 -type d | wc -l) - - if [ "$NUM_DIRS" -lt "$NUM_RUNNERS" ]; then - echo "TOTAL_RUNNERS is larger than the number of tests/packages to split." - NUM_RUNNERS=$((NUM_DIRS-1)) - fi - # fix issue where test splitting calculation generates 1 more split than TOTAL_RUNNERS. - NUM_RUNNERS=$((NUM_RUNNERS-1)) - { - echo -n "envoy-matrix=" - find ./test/integration/connect/envoy -maxdepth 1 -type d -print0 \ - | xargs -0 -n 1 basename \ - | jq --raw-input --argjson runnercount "$NUM_RUNNERS" "$JQ_SLICER" \ - | jq --compact-output 'map(join("|"))' - } >> "$GITHUB_OUTPUT" - - envoy-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - needs: - - setup - - generate-envoy-job-matrices - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - matrix: - envoy-version: ["1.24.12", "1.25.11", "1.26.6", "1.27.2"] - xds-target: ["server", "client"] - test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} - env: - ENVOY_VERSION: ${{ matrix.envoy-version }} - XDS_TARGET: ${{ matrix.xds-target }} - AWS_LAMBDA_REGION: us-west-2 - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - - name: fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: ./bin - - name: restore mode+x - run: chmod +x ./bin/consul - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0 - - - name: Docker build - run: docker build -t consul:local -f ./build-support/docker/Consul-Dev.dockerfile ./bin - - - name: Envoy Integration Tests - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running $(sed 's,|, ,g' <<< "${{ matrix.test-cases }}" |wc -w) subtests" - # shellcheck disable=SC2001 - sed 's,|,\n,g' <<< "${{ matrix.test-cases }}" - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --debug \ - --rerun-fails \ - --rerun-fails-report=/tmp/gotestsum-rerun-fails \ - --jsonfile /tmp/jsonfile/go-test.log \ - --packages=./test/integration/connect/envoy \ - -- -timeout=30m -tags integration -run="TestEnvoy/(${{ matrix.test-cases }})" - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - upgrade-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - needs: - - setup - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - matrix: - consul-version: ["1.15", "1.16", "1.17"] - env: - CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} - ENVOY_VERSION: "1.24.6" - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: go env - - # Get go binary from workspace - - name: fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: . - - name: restore mode+x - run: chmod +x consul - - name: Build consul:local image - run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . - - name: Build consul-envoy:latest-version image - id: buildConsulEnvoyLatestImage - run: | - if ${{ endsWith(github.repository, '-enterprise') }} == 'true' - then - docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }}-ent --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - else - docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }} --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - fi - - name: Build consul-envoy:target-version image - id: buildConsulEnvoyTargetImage - continue-on-error: true - run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - - name: Retry Build consul-envoy:target-version image - if: steps.buildConsulEnvoyTargetImage.outcome == 'failure' - run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - - name: Build sds image - run: docker build -t consul-sds-server ./test/integration/connect/envoy/test-sds-server/ - - name: Configure GH workaround for ipv6 loopback - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - cat /etc/hosts && echo "-----------" - sudo sed -i 's/::1 *localhost ip6-localhost ip6-loopback/::1 ip6-localhost ip6-loopback/g' /etc/hosts - cat /etc/hosts - - name: Upgrade Integration Tests - run: | - mkdir -p "${{ env.TEST_RESULTS_DIR }}" - cd ./test/integration/consul-container/test/upgrade - docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --raw-command \ - --format=short-verbose \ - --debug \ - --rerun-fails=2 \ - --packages="./..." \ - -- \ - go test \ - -p=4 \ - -tags "${{ env.GOTAGS }}" \ - -timeout=30m \ - -json \ - ./... \ - --follow-log=false \ - --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --target-version local \ - --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --latest-version "${{ env.CONSUL_LATEST_VERSION }}" - ls -lrt - env: - # this is needed because of incompatibility between RYUK container and GHA - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - # tput complains if this isn't set to something. - TERM: ansi - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - - test-integrations-success: - needs: - - setup - - dev-build - - generate-envoy-job-matrices - - envoy-integration-test - - upgrade-integration-test - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - if: ${{ always() }} - steps: - - name: evaluate upstream job results - run: | - # exit 1 if failure or cancelled result for any upstream job - if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then - printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" - exit 1 - fi - - name: Notify Slack - if: ${{ failure() }} - id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 - with: - payload: | - { - "message": "One or more nightly integration tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_NIGHTLY_INTEG_TEST_SLACK_WEBHOOK }} diff --git a/.github/workflows/reusable-unit-split.yml b/.github/workflows/reusable-unit-split.yml index 3d959d168beda..29c341998dd65 100644 --- a/.github/workflows/reusable-unit-split.yml +++ b/.github/workflows/reusable-unit-split.yml @@ -130,8 +130,7 @@ jobs: --packages="$PACKAGE_NAMES" \ --junitfile ${{env.TEST_RESULTS}}/gotestsum-report.xml -- \ -tags="${{env.GOTAGS}}" \ - -cover -coverprofile=coverage.txt \ - -timeout=30m + -cover -coverprofile=coverage.txt # NOTE: ENT specific step as we store secrets in Vault. - name: Authenticate to Vault diff --git a/.github/workflows/reusable-unit.yml b/.github/workflows/reusable-unit.yml index 3b50bfa7e3887..42943954475d3 100644 --- a/.github/workflows/reusable-unit.yml +++ b/.github/workflows/reusable-unit.yml @@ -109,8 +109,7 @@ jobs: --junitfile ${{env.TEST_RESULTS}}/gotestsum-report.xml -- \ -tags="${{env.GOTAGS}}" \ ${GO_TEST_FLAGS-} \ - -cover -coverprofile=coverage.txt \ - -timeout=30m + -cover -coverprofile=coverage.txt # NOTE: ENT specific step as we store secrets in Vault. - name: Authenticate to Vault diff --git a/.github/workflows/test-integrations.yml b/.github/workflows/test-integrations.yml index 64da185db6a5e..14c200bfa4b69 100644 --- a/.github/workflows/test-integrations.yml +++ b/.github/workflows/test-integrations.yml @@ -81,6 +81,7 @@ jobs: strategy: matrix: nomad-version: ['v1.6.2', 'v1.5.9', 'v1.4.13'] + steps: - name: Checkout Nomad uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 diff --git a/.github/workflows/verify-envoy-version.yml b/.github/workflows/verify-envoy-version.yml index dafa9db6f22a6..003888eddf6e1 100644 --- a/.github/workflows/verify-envoy-version.yml +++ b/.github/workflows/verify-envoy-version.yml @@ -13,7 +13,7 @@ on: branches: - main - release/** - + env: SKIP_VERIFY_ENVOY_VERSION: ${{ vars.SKIP_VERIFY_ENVOY_VERSION }} diff --git a/agent/consul/fsm/commands_ce.go b/agent/consul/fsm/commands_ce.go index 77bc94de1a9ae..c5e7fd968238b 100644 --- a/agent/consul/fsm/commands_ce.go +++ b/agent/consul/fsm/commands_ce.go @@ -4,7 +4,6 @@ package fsm import ( - "errors" "fmt" "time" @@ -153,11 +152,7 @@ func init() { func (c *FSM) applyRegister(buf []byte, index uint64) interface{} { defer metrics.MeasureSince([]string{"fsm", "register"}, time.Now()) var req structs.RegisterRequest - if err := decodeRegistrationReq(buf, &req); err != nil { - if errors.Is(err, ErrDroppingTenantedReq) { - c.logger.Warn("dropping tenanted register request") - return nil - } + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } @@ -172,11 +167,7 @@ func (c *FSM) applyRegister(buf []byte, index uint64) interface{} { func (c *FSM) applyDeregister(buf []byte, index uint64) interface{} { defer metrics.MeasureSince([]string{"fsm", "deregister"}, time.Now()) var req structs.DeregisterRequest - if err := decodeDeregistrationReq(buf, &req); err != nil { - if errors.Is(err, ErrDroppingTenantedReq) { - c.logger.Warn("dropping tenanted deregister request") - return nil - } + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } @@ -204,11 +195,7 @@ func (c *FSM) applyDeregister(buf []byte, index uint64) interface{} { func (c *FSM) applyKVSOperation(buf []byte, index uint64) interface{} { var req structs.KVSRequest - if err := decodeKVSRequest(buf, &req); err != nil { - if errors.Is(err, ErrDroppingTenantedReq) { - c.logger.Warn("dropping tenanted KV request") - return nil - } + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } defer metrics.MeasureSinceWithLabels([]string{"fsm", "kvs"}, time.Now(), @@ -253,11 +240,7 @@ func (c *FSM) applyKVSOperation(buf []byte, index uint64) interface{} { func (c *FSM) applySessionOperation(buf []byte, index uint64) interface{} { var req structs.SessionRequest - if err := decodeSessionRequest(buf, &req); err != nil { - if errors.Is(err, ErrDroppingTenantedReq) { - c.logger.Warn("dropping tenanted session request") - return nil - } + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } defer metrics.MeasureSinceWithLabels([]string{"fsm", "session"}, time.Now(), @@ -316,11 +299,7 @@ func (c *FSM) applyCoordinateBatchUpdate(buf []byte, index uint64) interface{} { // state store. func (c *FSM) applyPreparedQueryOperation(buf []byte, index uint64) interface{} { var req structs.PreparedQueryRequest - if err := decodePreparedQueryRequest(buf, &req); err != nil { - if errors.Is(err, ErrDroppingTenantedReq) { - c.logger.Warn("dropping tenanted prepared query request") - return nil - } + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } @@ -339,7 +318,7 @@ func (c *FSM) applyPreparedQueryOperation(buf []byte, index uint64) interface{} func (c *FSM) applyTxn(buf []byte, index uint64) interface{} { var req structs.TxnRequest - if err := decodeTxnRequest(buf, &req); err != nil { + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } defer metrics.MeasureSince([]string{"fsm", "txn"}, time.Now()) @@ -506,7 +485,7 @@ func (c *FSM) applyConnectCALeafOperation(buf []byte, index uint64) interface{} func (c *FSM) applyACLTokenSetOperation(buf []byte, index uint64) interface{} { var req structs.ACLTokenBatchSetRequest - if err := decodeACLTokenBatchSetRequest(buf, &req); err != nil { + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } defer metrics.MeasureSinceWithLabels([]string{"fsm", "acl", "token"}, time.Now(), @@ -544,7 +523,7 @@ func (c *FSM) applyACLTokenBootstrap(buf []byte, index uint64) interface{} { func (c *FSM) applyACLPolicySetOperation(buf []byte, index uint64) interface{} { var req structs.ACLPolicyBatchSetRequest - if err := decodeACLPolicyBatchSetRequest(buf, &req); err != nil { + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } defer metrics.MeasureSinceWithLabels([]string{"fsm", "acl", "policy"}, time.Now(), @@ -565,12 +544,10 @@ func (c *FSM) applyACLPolicyDeleteOperation(buf []byte, index uint64) interface{ } func (c *FSM) applyConfigEntryOperation(buf []byte, index uint64) interface{} { - req := structs.ConfigEntryRequest{} - if err := decodeConfigEntryOperationRequest(buf, &req); err != nil { - if errors.Is(err, ErrDroppingTenantedReq) { - c.logger.Warn("dropping tenanted config entry request") - return nil - } + req := structs.ConfigEntryRequest{ + Entry: &structs.ProxyConfigEntry{}, + } + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } @@ -617,7 +594,7 @@ func (c *FSM) applyConfigEntryOperation(buf []byte, index uint64) interface{} { func (c *FSM) applyACLRoleSetOperation(buf []byte, index uint64) interface{} { var req structs.ACLRoleBatchSetRequest - if err := decodeACLRoleBatchSetRequest(buf, &req); err != nil { + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } defer metrics.MeasureSinceWithLabels([]string{"fsm", "acl", "role"}, time.Now(), @@ -639,7 +616,7 @@ func (c *FSM) applyACLRoleDeleteOperation(buf []byte, index uint64) interface{} func (c *FSM) applyACLBindingRuleSetOperation(buf []byte, index uint64) interface{} { var req structs.ACLBindingRuleBatchSetRequest - if err := decodeACLBindingRuleBatchSetRequest(buf, &req); err != nil { + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } defer metrics.MeasureSinceWithLabels([]string{"fsm", "acl", "bindingrule"}, time.Now(), @@ -661,7 +638,7 @@ func (c *FSM) applyACLBindingRuleDeleteOperation(buf []byte, index uint64) inter func (c *FSM) applyACLAuthMethodSetOperation(buf []byte, index uint64) interface{} { var req structs.ACLAuthMethodBatchSetRequest - if err := decodeACLAuthMethodBatchSetRequest(buf, &req); err != nil { + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } defer metrics.MeasureSinceWithLabels([]string{"fsm", "acl", "authmethod"}, time.Now(), @@ -672,11 +649,7 @@ func (c *FSM) applyACLAuthMethodSetOperation(buf []byte, index uint64) interface func (c *FSM) applyACLAuthMethodDeleteOperation(buf []byte, index uint64) interface{} { var req structs.ACLAuthMethodBatchDeleteRequest - if err := decodeACLAuthMethodBatchDeleteRequest(buf, &req); err != nil { - if errors.Is(err, ErrDroppingTenantedReq) { - c.logger.Warn("dropping tenanted acl auth method delete request") - return nil - } + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } defer metrics.MeasureSinceWithLabels([]string{"fsm", "acl", "authmethod"}, time.Now(), @@ -733,11 +706,7 @@ func (c *FSM) applySystemMetadataOperation(buf []byte, index uint64) interface{} func (c *FSM) applyPeeringWrite(buf []byte, index uint64) interface{} { var req pbpeering.PeeringWriteRequest - if err := decodePeeringWriteRequest(buf, &req); err != nil { - if errors.Is(err, ErrDroppingTenantedReq) { - c.logger.Warn("dropping tenanted peering write request") - return nil - } + if err := structs.DecodeProto(buf, &req); err != nil { panic(fmt.Errorf("failed to decode peering write request: %v", err)) } @@ -749,11 +718,7 @@ func (c *FSM) applyPeeringWrite(buf []byte, index uint64) interface{} { func (c *FSM) applyPeeringDelete(buf []byte, index uint64) interface{} { var req pbpeering.PeeringDeleteRequest - if err := decodePeeringDeleteRequest(buf, &req); err != nil { - if errors.Is(err, ErrDroppingTenantedReq) { - c.logger.Warn("dropping tenanted peering delete request") - return nil - } + if err := structs.DecodeProto(buf, &req); err != nil { panic(fmt.Errorf("failed to decode peering delete request: %v", err)) } @@ -793,11 +758,7 @@ func (c *FSM) applyPeeringTerminate(buf []byte, index uint64) interface{} { func (c *FSM) applyPeeringTrustBundleWrite(buf []byte, index uint64) interface{} { var req pbpeering.PeeringTrustBundleWriteRequest - if err := decodePeeringTrustBundleWriteRequest(buf, &req); err != nil { - if errors.Is(err, ErrDroppingTenantedReq) { - c.logger.Warn("dropping tenanted peering trust bundle write request") - return nil - } + if err := structs.DecodeProto(buf, &req); err != nil { panic(fmt.Errorf("failed to decode peering trust bundle write request: %v", err)) } @@ -809,11 +770,7 @@ func (c *FSM) applyPeeringTrustBundleWrite(buf []byte, index uint64) interface{} func (c *FSM) applyPeeringTrustBundleDelete(buf []byte, index uint64) interface{} { var req pbpeering.PeeringTrustBundleDeleteRequest - if err := decodePeeringTrustBundleDeleteRequest(buf, &req); err != nil { - if errors.Is(err, ErrDroppingTenantedReq) { - c.logger.Warn("dropping tenanted peering trust bundle delete request") - return nil - } + if err := structs.DecodeProto(buf, &req); err != nil { panic(fmt.Errorf("failed to decode peering trust bundle delete request: %v", err)) } @@ -833,11 +790,7 @@ func (f *FSM) applyResourceOperation(buf []byte, idx uint64) any { func (c *FSM) applyManualVirtualIPs(buf []byte, index uint64) interface{} { var req state.ServiceVirtualIP - if err := decodeServiceVirtualIPRequest(buf, &req); err != nil { - if errors.Is(err, ErrDroppingTenantedReq) { - c.logger.Warn("dropping tenanted virtual ip request") - return nil - } + if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) } diff --git a/agent/consul/fsm/decode_ce.go b/agent/consul/fsm/decode_ce.go deleted file mode 100644 index 2f4d3da3a26cb..0000000000000 --- a/agent/consul/fsm/decode_ce.go +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package fsm - -import ( - "github.com/hashicorp/consul/agent/consul/state" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/proto/private/pbpeering" -) - -func decodeRegistrationReq(buf []byte, req *structs.RegisterRequest) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - return decodeRegistration(buf, req) -} - -func decodeDeregistrationReq(buf []byte, req *structs.DeregisterRequest) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - return decodeDeregistration(buf, req) -} - -func decodeKVSRequest(buf []byte, req *structs.KVSRequest) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - return decodeKVS(buf, req) -} - -func decodeSessionRequest(buf []byte, req *structs.SessionRequest) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - - return decodeSession(buf, req) -} - -func decodePreparedQueryRequest(buf []byte, req *structs.PreparedQueryRequest) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - return decodePreparedQuery(buf, req) -} - -func decodeTxnRequest(buf []byte, req *structs.TxnRequest) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - return decodeTxn(buf, req) -} - -func decodeACLTokenBatchSetRequest(buf []byte, req *structs.ACLTokenBatchSetRequest) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - return decodeACLTokenBatchSet(buf, req) - -} - -func decodeACLPolicyBatchSetRequest(buf []byte, req *structs.ACLPolicyBatchSetRequest) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - return decodeACLPolicyBatchSet(buf, req) - -} - -func decodeACLRoleBatchSetRequest(buf []byte, req *structs.ACLRoleBatchSetRequest) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - return decodeACLRoleBatchSet(buf, req) -} - -func decodeACLBindingRuleBatchSetRequest(buf []byte, req *structs.ACLBindingRuleBatchSetRequest) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - return decodeACLBindingRuleBatchSet(buf, req) -} - -func decodeACLAuthMethodBatchSetRequest(buf []byte, req *structs.ACLAuthMethodBatchSetRequest) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - return decodeACLAuthMethodBatchSet(buf, req) -} - -func decodeACLAuthMethodBatchDeleteRequest(buf []byte, req *structs.ACLAuthMethodBatchDeleteRequest) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - - return decodeACLAuthMethodBatchDelete(buf, req) -} - -func decodeServiceVirtualIPRequest(buf []byte, req *state.ServiceVirtualIP) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - return decodeServiceVirtualIP(buf, req) -} - -func decodePeeringWriteRequest(buf []byte, req *pbpeering.PeeringWriteRequest) error { - if !structs.CEDowngrade { - return structs.DecodeProto(buf, req) - } - return decodePeeringWrite(buf, req) -} - -func decodePeeringDeleteRequest(buf []byte, req *pbpeering.PeeringDeleteRequest) error { - if !structs.CEDowngrade { - return structs.DecodeProto(buf, req) - } - - return decodePeeringDelete(buf, req) -} - -func decodePeeringTrustBundleWriteRequest(buf []byte, req *pbpeering.PeeringTrustBundleWriteRequest) error { - if !structs.CEDowngrade { - return structs.DecodeProto(buf, req) - } - return decodePeeringTrustBundleWrite(buf, req) -} - -func decodePeeringTrustBundleDeleteRequest(buf []byte, req *pbpeering.PeeringTrustBundleDeleteRequest) error { - if !structs.CEDowngrade { - return structs.DecodeProto(buf, req) - } - return decodePeeringTrustBundleDelete(buf, req) -} - -func decodeConfigEntryOperationRequest(buf []byte, req *structs.ConfigEntryRequest) error { - if !structs.CEDowngrade { - return structs.Decode(buf, req) - } - - return decodeConfigEntryOperation(buf, req) -} diff --git a/agent/consul/fsm/decode_downgrade.go b/agent/consul/fsm/decode_downgrade.go deleted file mode 100644 index 7b8e2fce719f2..0000000000000 --- a/agent/consul/fsm/decode_downgrade.go +++ /dev/null @@ -1,1011 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package fsm - -import ( - "errors" - "fmt" - - "github.com/hashicorp/consul-net-rpc/go-msgpack/codec" - "github.com/hashicorp/consul/agent/consul/state" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/lib" - "github.com/hashicorp/consul/proto/private/pbpeering" -) - -func IsEnterpriseData(namespace, partition string) bool { - if (namespace != "" && namespace != "default") || (partition != "" && partition != "default") { - return true - } - return false -} - -var errIncompatibleTenantedData = errors.New("incompatible tenanted data") -var ErrDroppingTenantedReq = errors.New("dropping tenanted request") - -func decodeRegistration(buf []byte, req *structs.RegisterRequest) error { - type serviceRequest struct { - Namespace string - Partition string - *structs.NodeService - } - type checkRequest struct { - Namespace string - Partition string - *structs.HealthCheck - } - type NewRegReq struct { - - // shadows the Service field from the register request so that we can detect - // tenanted service registrations for untenanted nodes - Service *serviceRequest - - // shadows the Check field from the register request so that we can detect - // tenanted check registrations for untenanted nodes. - Check *checkRequest - - // shadows the Checks field for the same reasons as the singular version. - Checks []*checkRequest - - // Allows parsing the namespace of the whole request/node - Namespace string - - // Allows parsing the partition of the whole request/node - Partition string - *structs.RegisterRequest - } - var newReq NewRegReq - if err := structs.Decode(buf, &newReq); err != nil { - return err - } - - // checks if the node is tenanted - if IsEnterpriseData(newReq.Namespace, newReq.Partition) { - // the whole request can be dropped because the node itself is tenanted - return ErrDroppingTenantedReq - } - - // check if the service is tenanted - if newReq.Service != nil && !IsEnterpriseData(newReq.Service.Namespace, newReq.Service.Partition) { - // copy the shadow service pointer into the real RegisterRequest - newReq.RegisterRequest.Service = newReq.Service.NodeService - } - - // check if the singular check is tenanted - if newReq.Check != nil && !IsEnterpriseData(newReq.Check.Namespace, newReq.Check.Partition) { - newReq.RegisterRequest.Check = newReq.Check.HealthCheck - } - - // check for tenanted checks in the slice - for _, chk := range newReq.Checks { - if !IsEnterpriseData(chk.Namespace, chk.Partition) { - newReq.RegisterRequest.Checks = append(newReq.RegisterRequest.Checks, chk.HealthCheck) - } - } - // copy the data to the output request value - *req = *newReq.RegisterRequest - return nil -} - -func decodeDeregistration(buf []byte, req *structs.DeregisterRequest) error { - type NewDeRegReq struct { - Namespace string - - // Allows parsing the partition of the whole request/node - Partition string - - *structs.DeregisterRequest - - // Allows parsing the namespace of the whole request/node - - } - var newReq NewDeRegReq - if err := structs.Decode(buf, &newReq); err != nil { - return err - } - - // checks if the node is tenanted - if IsEnterpriseData(newReq.Namespace, newReq.Partition) { - // the whole request can be dropped because the node itself is tenanted - return ErrDroppingTenantedReq - } - - // copy the data to the output request value - *req = *newReq.DeregisterRequest - return nil -} - -func decodeKVS(buf []byte, req *structs.KVSRequest) error { - type dirEntryReq struct { - Namespace string - Partition string - *structs.DirEntry - } - type NewDirEntReq struct { - // shadows the DirEnt field from KVSRequest so that we can detect - // tenanted service registrations for untenanted nodes - DirEnt *dirEntryReq - *structs.KVSRequest - } - var newReq NewDirEntReq - if err := structs.Decode(buf, &newReq); err != nil { - return err - } - - if newReq.DirEnt != nil && IsEnterpriseData(newReq.DirEnt.Namespace, newReq.DirEnt.Partition) { - return ErrDroppingTenantedReq - } - - newReq.KVSRequest.DirEnt = *newReq.DirEnt.DirEntry - *req = *newReq.KVSRequest - return nil -} - -func decodeSession(buf []byte, req *structs.SessionRequest) error { - type sessionReq struct { - Namespace string - Partition string - *structs.Session - } - type NewSessionReq struct { - // shadows the Session field from SessionRequest so that we can detect - // tenanted service registrations for untenanted nodes - Session *sessionReq - *structs.SessionRequest - } - var newReq NewSessionReq - if err := structs.Decode(buf, &newReq); err != nil { - return err - } - - if newReq.Session != nil && IsEnterpriseData(newReq.Session.Namespace, newReq.Session.Partition) { - return ErrDroppingTenantedReq - - } - serviceChecks := newReq.Session.ServiceChecks - newReq.Session.ServiceChecks = nil - for _, sessionServiceCheck := range serviceChecks { - if !IsEnterpriseData(sessionServiceCheck.Namespace, "") { - newReq.Session.ServiceChecks = append(newReq.Session.ServiceChecks, sessionServiceCheck) - } - } - - newReq.SessionRequest.Session = *newReq.Session.Session - *req = *newReq.SessionRequest - return nil -} - -func decodePreparedQuery(buf []byte, req *structs.PreparedQueryRequest) error { - type serviceQuery struct { - Namespace string - Partition string - *structs.ServiceQuery - } - type prepQuery struct { - Service *serviceQuery - *structs.PreparedQuery - } - type NewPreparedQueryReq struct { - Query *prepQuery - *structs.PreparedQueryRequest - } - var newReq NewPreparedQueryReq - if err := structs.Decode(buf, &newReq); err != nil { - return err - } - - if newReq.Query != nil && newReq.Query.Service != nil && IsEnterpriseData(newReq.Query.Service.Namespace, newReq.Query.Service.Partition) { - return ErrDroppingTenantedReq - } - - newReq.Query.PreparedQuery.Service = *newReq.Query.Service.ServiceQuery - newReq.PreparedQueryRequest.Query = newReq.Query.PreparedQuery - *req = *newReq.PreparedQueryRequest - return nil -} - -func decodeTxn(buf []byte, req *structs.TxnRequest) error { - type dirEntryReq struct { - Namespace string - Partition string - *structs.DirEntry - } - type txnKVOp struct { - DirEnt *dirEntryReq - *structs.TxnKVOp - } - type nodeService struct { - Namespace string - Partition string - *structs.NodeService - } - type txnServiceOp struct { - Service *nodeService - *structs.TxnServiceOp - } - type healthCheck struct { - Namespace string - Partition string - *structs.HealthCheck - } - type txnCheckOp struct { - Check *healthCheck - *structs.TxnCheckOp - } - type session struct { - Namespace string - Partition string - *structs.Session - } - type txnSessionOp struct { - Session *session - *structs.TxnSessionOp - } - // Only one of the types should be filled out per entry. - type txnOp struct { - KV *txnKVOp - Service *txnServiceOp - Check *txnCheckOp - Session *txnSessionOp - *structs.TxnOp - } - type NewTxnRequest struct { - Ops []*txnOp - *structs.TxnRequest - } - var newReq NewTxnRequest - if err := structs.Decode(buf, &newReq); err != nil { - return err - } - for _, op := range newReq.Ops { - if op.KV != nil && op.KV.DirEnt != nil && !IsEnterpriseData(op.KV.DirEnt.Namespace, op.KV.DirEnt.Partition) { - txnOp := &structs.TxnOp{ - KV: &structs.TxnKVOp{ - Verb: op.KV.Verb, - DirEnt: *op.KV.DirEnt.DirEntry, - }, - } - newReq.TxnRequest.Ops = append(newReq.TxnRequest.Ops, txnOp) - continue - } - - if op.Service != nil && op.Service.Service != nil && !IsEnterpriseData(op.Service.Service.Namespace, op.Service.Service.Partition) { - txnOp := &structs.TxnOp{ - Service: &structs.TxnServiceOp{ - Verb: op.Service.Verb, - Node: op.Service.Node, - Service: *op.Service.Service.NodeService, - }, - } - newReq.TxnRequest.Ops = append(newReq.TxnRequest.Ops, txnOp) - continue - } - - if op.Check != nil && op.Check.Check != nil && !IsEnterpriseData(op.Check.Check.Namespace, op.Check.Check.Partition) { - txnOp := &structs.TxnOp{ - Check: &structs.TxnCheckOp{ - Verb: op.Check.Verb, - Check: *op.Check.Check.HealthCheck, - }, - } - newReq.TxnRequest.Ops = append(newReq.TxnRequest.Ops, txnOp) - continue - } - - if op.Session != nil && op.Session.Session != nil && !IsEnterpriseData(op.Session.Session.Namespace, op.Session.Session.Partition) { - txnOp := &structs.TxnOp{ - Session: &structs.TxnSessionOp{ - Verb: op.Session.Verb, - Session: *op.Session.Session.Session, - }, - } - txnOp.Session.Session.ServiceChecks = nil - for _, sessionServiceCheck := range op.Session.Session.ServiceChecks { - if !IsEnterpriseData(sessionServiceCheck.Namespace, "") { - txnOp.Session.Session.ServiceChecks = append(txnOp.Session.Session.ServiceChecks, sessionServiceCheck) - } - } - newReq.TxnRequest.Ops = append(newReq.TxnRequest.Ops, txnOp) - } - } - - *req = *newReq.TxnRequest - return nil -} - -func decodeACLTokenBatchSet(buf []byte, req *structs.ACLTokenBatchSetRequest) error { - type aclToken struct { - Namespace string - Partition string - *structs.ACLToken - } - type NewACLTokenBatchSetRequest struct { - Tokens []*aclToken - *structs.ACLTokenBatchSetRequest - } - var newReq NewACLTokenBatchSetRequest - if err := structs.Decode(buf, &newReq); err != nil { - return err - } - - for _, token := range newReq.Tokens { - if !IsEnterpriseData(token.Namespace, token.Partition) { - newReq.ACLTokenBatchSetRequest.Tokens = append(newReq.ACLTokenBatchSetRequest.Tokens, token.ACLToken) - } - } - - *req = *newReq.ACLTokenBatchSetRequest - return nil - -} - -func decodeACLPolicyBatchSet(buf []byte, req *structs.ACLPolicyBatchSetRequest) error { - type aclPolicy struct { - Namespace string - Partition string - *structs.ACLPolicy - } - type NewACLPolicyBatchSetRequest struct { - Policies []*aclPolicy - *structs.ACLPolicyBatchSetRequest - } - var newReq NewACLPolicyBatchSetRequest - if err := structs.Decode(buf, &newReq); err != nil { - return err - } - if newReq.ACLPolicyBatchSetRequest == nil { - newReq.ACLPolicyBatchSetRequest = &structs.ACLPolicyBatchSetRequest{} - } - for _, policy := range newReq.Policies { - if !IsEnterpriseData(policy.Namespace, policy.Partition) { - newReq.ACLPolicyBatchSetRequest.Policies = append(newReq.ACLPolicyBatchSetRequest.Policies, policy.ACLPolicy) - } - } - - *req = *newReq.ACLPolicyBatchSetRequest - return nil - -} - -func decodeACLRoleBatchSet(buf []byte, req *structs.ACLRoleBatchSetRequest) error { - type aclRole struct { - Namespace string - Partition string - *structs.ACLRole - } - type NewACLRoleBatchSetRequest struct { - Roles []*aclRole - *structs.ACLRoleBatchSetRequest - } - var newReq NewACLRoleBatchSetRequest - if err := structs.Decode(buf, &newReq); err != nil { - return err - } - - for _, role := range newReq.Roles { - if !IsEnterpriseData(role.Namespace, role.Partition) { - newReq.ACLRoleBatchSetRequest.Roles = append(newReq.ACLRoleBatchSetRequest.Roles, role.ACLRole) - } - } - - *req = *newReq.ACLRoleBatchSetRequest - return nil -} - -func decodeACLBindingRuleBatchSet(buf []byte, req *structs.ACLBindingRuleBatchSetRequest) error { - type aCLBindingRule struct { - Namespace string - Partition string - *structs.ACLBindingRule - } - type NewACLBindingRuleBatchSetRequest struct { - BindingRules []*aCLBindingRule - *structs.ACLBindingRuleBatchSetRequest - } - var newReq NewACLBindingRuleBatchSetRequest - if err := structs.Decode(buf, &newReq); err != nil { - return err - } - if newReq.ACLBindingRuleBatchSetRequest == nil { - newReq.ACLBindingRuleBatchSetRequest = &structs.ACLBindingRuleBatchSetRequest{} - } - for _, rule := range newReq.BindingRules { - if !IsEnterpriseData(rule.Namespace, rule.Partition) { - newReq.ACLBindingRuleBatchSetRequest.BindingRules = append(newReq.ACLBindingRuleBatchSetRequest.BindingRules, rule.ACLBindingRule) - } - } - - *req = *newReq.ACLBindingRuleBatchSetRequest - return nil -} - -func decodeACLAuthMethodBatchSet(buf []byte, req *structs.ACLAuthMethodBatchSetRequest) error { - type aCLAuthMethod struct { - Namespace string - Partition string - *structs.ACLAuthMethod - } - type NewACLAuthMethodBatchSetRequest struct { - AuthMethods []*aCLAuthMethod - *structs.ACLAuthMethodBatchSetRequest - } - var newReq NewACLAuthMethodBatchSetRequest - if err := structs.Decode(buf, &newReq); err != nil { - return err - } - if newReq.ACLAuthMethodBatchSetRequest == nil { - newReq.ACLAuthMethodBatchSetRequest = &structs.ACLAuthMethodBatchSetRequest{} - } - for _, authMethod := range newReq.AuthMethods { - if !IsEnterpriseData(authMethod.Namespace, authMethod.Partition) { - newReq.ACLAuthMethodBatchSetRequest.AuthMethods = append(newReq.ACLAuthMethodBatchSetRequest.AuthMethods, authMethod.ACLAuthMethod) - } - } - - *req = *newReq.ACLAuthMethodBatchSetRequest - return nil -} - -func decodeACLAuthMethodBatchDelete(buf []byte, req *structs.ACLAuthMethodBatchDeleteRequest) error { - type NewACLAuthMethodBatchDeleteRequest struct { - Namespace string - Partition string - *structs.ACLAuthMethodBatchDeleteRequest - } - - var newReq NewACLAuthMethodBatchDeleteRequest - if err := structs.Decode(buf, &newReq); err != nil { - return err - } - - if IsEnterpriseData(newReq.Namespace, newReq.Partition) { - return ErrDroppingTenantedReq - } - - *req = *newReq.ACLAuthMethodBatchDeleteRequest - return nil -} - -func decodeServiceVirtualIP(buf []byte, req *state.ServiceVirtualIP) error { - type serviceName struct { - Namespace string - Partition string - *structs.ServiceName - } - type peeredServiceName struct { - ServiceName *serviceName - *structs.PeeredServiceName - } - type NewServiceVirtualIP struct { - Service *peeredServiceName - *state.ServiceVirtualIP - } - var newReq NewServiceVirtualIP - if err := structs.Decode(buf, &newReq); err != nil { - return err - } - - if newReq.Service != nil && newReq.Service.ServiceName != nil && IsEnterpriseData(newReq.Service.ServiceName.Namespace, newReq.Service.ServiceName.Partition) { - return ErrDroppingTenantedReq - } - newReq.ServiceVirtualIP.Service.ServiceName = *newReq.Service.ServiceName.ServiceName - *req = *newReq.ServiceVirtualIP - return nil -} - -func decodePeeringWrite(buf []byte, req *pbpeering.PeeringWriteRequest) error { - if err := structs.DecodeProto(buf, req); err != nil { - return err - } - - if req.Peering != nil && IsEnterpriseData("", req.Peering.Partition) { - return ErrDroppingTenantedReq - } - - return nil -} - -func decodePeeringDelete(buf []byte, req *pbpeering.PeeringDeleteRequest) error { - if err := structs.DecodeProto(buf, req); err != nil { - return err - } - - if IsEnterpriseData("", req.Partition) { - return ErrDroppingTenantedReq - } - - return nil -} - -func decodePeeringTrustBundleWrite(buf []byte, req *pbpeering.PeeringTrustBundleWriteRequest) error { - if err := structs.DecodeProto(buf, req); err != nil { - return err - } - - if IsEnterpriseData("", req.PeeringTrustBundle.Partition) { - return ErrDroppingTenantedReq - } - - return nil -} - -func decodePeeringTrustBundleDelete(buf []byte, req *pbpeering.PeeringTrustBundleDeleteRequest) error { - if err := structs.DecodeProto(buf, req); err != nil { - return err - } - - if IsEnterpriseData("", req.Partition) { - return ErrDroppingTenantedReq - } - - return nil -} - -func decodeConfigEntryOperation(buf []byte, req *structs.ConfigEntryRequest) error { - - newReq := &ShadowConfigEntryRequest{ - ConfigEntryRequest: req, - } - if err := structs.Decode(buf, newReq); err != nil { - return err - } - shadowConfigEntry := newReq.ConfigEntryRequest.Entry.(ShadowConfigentry) - if err := shadowConfigEntry.CheckEnt(); err != nil { - return err - } - req.Entry = shadowConfigEntry.GetRealConfigEntry() - return nil -} - -type ShadowConfigEntryRequest struct { - *structs.ConfigEntryRequest -} - -func (c *ShadowConfigEntryRequest) UnmarshalBinary(data []byte) error { - // First decode the kind prefix - var kind string - dec := codec.NewDecoderBytes(data, structs.MsgpackHandle) - if err := dec.Decode(&kind); err != nil { - return err - } - - // Then decode the real thing with appropriate kind of ConfigEntry - entry, err := MakeShadowConfigEntry(kind, "") - if err != nil { - return err - } - c.Entry = entry - // Alias juggling to prevent infinite recursive calls back to this decode - // method. - type Alias structs.ConfigEntryRequest - as := struct { - *Alias - }{ - Alias: (*Alias)(c.ConfigEntryRequest), - } - if err := dec.Decode(&as); err != nil { - return err - } - return nil -} -func MakeShadowConfigEntry(kind, name string) (structs.ConfigEntry, error) { - switch kind { - case structs.RateLimitIPConfig: - return nil, ErrDroppingTenantedReq - case structs.ServiceDefaults: - return &ShadowServiceConfigEntry{ServiceConfigEntry: &structs.ServiceConfigEntry{Name: name}}, nil - case structs.ProxyDefaults: - return &ShadowProxyConfigEntry{ProxyConfigEntry: &structs.ProxyConfigEntry{Name: name}}, nil - case structs.ServiceRouter: - return &ShadowServiceRouterConfigEntry{ServiceRouterConfigEntry: &structs.ServiceRouterConfigEntry{Name: name}}, nil - case structs.ServiceSplitter: - return &ShadowServiceSplitterConfigEntry{ServiceSplitterConfigEntry: &structs.ServiceSplitterConfigEntry{Name: name}}, nil - case structs.ServiceResolver: - return &ShadowServiceResolverConfigEntry{ServiceResolverConfigEntry: &structs.ServiceResolverConfigEntry{Name: name}}, nil - case structs.IngressGateway: - return &ShadowIngressGatewayConfigEntry{IngressGatewayConfigEntry: &structs.IngressGatewayConfigEntry{Name: name}}, nil - case structs.TerminatingGateway: - return &ShadowTerminatingGatewayConfigEntry{TerminatingGatewayConfigEntry: &structs.TerminatingGatewayConfigEntry{Name: name}}, nil - case structs.ServiceIntentions: - return &ShadowServiceIntentionsConfigEntry{ServiceIntentionsConfigEntry: &structs.ServiceIntentionsConfigEntry{Name: name}}, nil - case structs.MeshConfig: - return &ShadowMeshConfigEntry{MeshConfigEntry: &structs.MeshConfigEntry{}}, nil - case structs.ExportedServices: - return &ShadowExportedServicesConfigEntry{ExportedServicesConfigEntry: &structs.ExportedServicesConfigEntry{Name: name}}, nil - case structs.SamenessGroup: - return &ShadowSamenessGroupConfigEntry{SamenessGroupConfigEntry: &structs.SamenessGroupConfigEntry{Name: name}}, nil - case structs.APIGateway: - return &ShadowAPIGatewayConfigEntry{APIGatewayConfigEntry: &structs.APIGatewayConfigEntry{Name: name}}, nil - case structs.BoundAPIGateway: - return &ShadowBoundAPIGatewayConfigEntry{BoundAPIGatewayConfigEntry: &structs.BoundAPIGatewayConfigEntry{Name: name}}, nil - case structs.InlineCertificate: - return &ShadowInlineCertificateConfigEntry{InlineCertificateConfigEntry: &structs.InlineCertificateConfigEntry{Name: name}}, nil - case structs.HTTPRoute: - return &ShadowHTTPRouteConfigEntry{HTTPRouteConfigEntry: &structs.HTTPRouteConfigEntry{Name: name}}, nil - case structs.TCPRoute: - return &ShadowTCPRouteConfigEntry{TCPRouteConfigEntry: &structs.TCPRouteConfigEntry{Name: name}}, nil - case structs.JWTProvider: - return &ShadowJWTProviderConfigEntry{JWTProviderConfigEntry: &structs.JWTProviderConfigEntry{Name: name}}, nil - default: - return nil, fmt.Errorf("invalid config entry kind: %s", kind) - } -} - -type ShadowBase struct { - Namespace string - Partition string -} - -func (s ShadowBase) CheckEnt() error { - if IsEnterpriseData(s.Namespace, s.Partition) { - return ErrDroppingTenantedReq - } - return nil -} - -type ShadowConfigentry interface { - CheckEnt() error - GetRealConfigEntry() structs.ConfigEntry -} - -type ShadowProxyConfigEntry struct { - ShadowBase - *structs.ProxyConfigEntry -} - -func (s ShadowProxyConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - return s.ProxyConfigEntry -} - -type ShadowServiceResolverConfigEntry struct { - ShadowBase - *structs.ServiceResolverConfigEntry -} - -func (s ShadowServiceResolverConfigEntry) CheckEnt() error { - if err := s.ShadowBase.CheckEnt(); err != nil { - return err - } - if s.ServiceResolverConfigEntry.Redirect != nil && (IsEnterpriseData(s.ServiceResolverConfigEntry.Redirect.Namespace, s.ServiceResolverConfigEntry.Redirect.Partition) || s.ServiceResolverConfigEntry.Redirect.SamenessGroup != "") { - return errIncompatibleTenantedData - } - for _, failover := range s.ServiceResolverConfigEntry.Failover { - if IsEnterpriseData(failover.Namespace, "") || failover.SamenessGroup != "" { - return errIncompatibleTenantedData - } - for _, target := range failover.Targets { - if IsEnterpriseData(target.Namespace, target.Partition) { - return errIncompatibleTenantedData - } - } - } - return nil -} - -func (s ShadowServiceResolverConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - return s.ServiceResolverConfigEntry -} - -func (e *ShadowProxyConfigEntry) UnmarshalBinary(data []byte) error { - // The goal here is to add a post-decoding operation to - // decoding of a ProxyConfigEntry. The cleanest way I could - // find to do so was to implement the BinaryMarshaller interface - // and use a type alias to do the original round of decoding, - // followed by a MapWalk of the Config to coerce everything - // into JSON compatible types. - type Alias structs.ProxyConfigEntry - as := struct { - *ShadowBase - *Alias - }{ - ShadowBase: &e.ShadowBase, - Alias: (*Alias)(e.ProxyConfigEntry), - } - dec := codec.NewDecoderBytes(data, structs.MsgpackHandle) - if err := dec.Decode(&as); err != nil { - return err - } - config, err := lib.MapWalk(e.Config) - if err != nil { - return err - } - e.Config = config - return nil -} - -type ShadowUpstreamConfig struct { - ShadowBase - *structs.UpstreamConfig -} -type ShadowUpstreamConfiguration struct { - Overrides []*ShadowUpstreamConfig - *structs.UpstreamConfiguration -} -type ShadowServiceConfigEntry struct { - ShadowBase - UpstreamConfig *ShadowUpstreamConfiguration - *structs.ServiceConfigEntry -} - -func (s ShadowServiceConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - if s.UpstreamConfig != nil { - for _, override := range s.UpstreamConfig.Overrides { - if !IsEnterpriseData(override.Namespace, override.Partition) { - if s.ServiceConfigEntry.UpstreamConfig == nil { - s.ServiceConfigEntry.UpstreamConfig = &structs.UpstreamConfiguration{} - } - s.ServiceConfigEntry.UpstreamConfig.Overrides = append(s.ServiceConfigEntry.UpstreamConfig.Overrides, override.UpstreamConfig) - } - } - } - return s.ServiceConfigEntry -} - -type ShadowServiceRouterConfigEntry struct { - ShadowBase - *structs.ServiceRouterConfigEntry -} - -func (s ShadowServiceRouterConfigEntry) CheckEnt() error { - if err := s.ShadowBase.CheckEnt(); err != nil { - return err - } - for _, route := range s.ServiceRouterConfigEntry.Routes { - if IsEnterpriseData(route.Destination.Namespace, route.Destination.Partition) { - return errIncompatibleTenantedData - } - } - return nil -} - -func (s ShadowServiceRouterConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - return s.ServiceRouterConfigEntry -} - -type ShadowServiceSplitterConfigEntry struct { - ShadowBase - *structs.ServiceSplitterConfigEntry -} - -func (s ShadowServiceSplitterConfigEntry) CheckEnt() error { - if err := s.ShadowBase.CheckEnt(); err != nil { - return err - } - for _, split := range s.ServiceSplitterConfigEntry.Splits { - if IsEnterpriseData(split.Namespace, split.Partition) { - return errIncompatibleTenantedData - } - } - return nil -} -func (s ShadowServiceSplitterConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - return s.ServiceSplitterConfigEntry -} - -type ShadowIngressService struct { - ShadowBase - *structs.IngressService -} -type ShadowIngressListener struct { - Services []ShadowIngressService - *structs.IngressListener -} -type ShadowIngressGatewayConfigEntry struct { - ShadowBase - Listeners []ShadowIngressListener - *structs.IngressGatewayConfigEntry -} - -func (s ShadowIngressGatewayConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - for _, listner := range s.Listeners { - for _, svc := range listner.Services { - if !IsEnterpriseData(svc.Namespace, svc.Partition) { - listner.IngressListener.Services = append(listner.IngressListener.Services, *svc.IngressService) - } - } - if len(listner.IngressListener.Services) == 0 { - continue - } - s.IngressGatewayConfigEntry.Listeners = append(s.IngressGatewayConfigEntry.Listeners, *listner.IngressListener) - } - return s.IngressGatewayConfigEntry -} - -type ShadowLinkedService struct { - ShadowBase - *structs.LinkedService -} - -type ShadowTerminatingGatewayConfigEntry struct { - ShadowBase - Services []ShadowLinkedService - *structs.TerminatingGatewayConfigEntry -} - -func (s ShadowTerminatingGatewayConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - for _, svc := range s.Services { - if !IsEnterpriseData(svc.Namespace, svc.Partition) { - s.TerminatingGatewayConfigEntry.Services = append(s.TerminatingGatewayConfigEntry.Services, *svc.LinkedService) - } - } - return s.TerminatingGatewayConfigEntry -} - -type ShadowSourceIntention struct { - ShadowBase - *structs.SourceIntention -} -type ShadowServiceIntentionsConfigEntry struct { - ShadowBase - Sources []*ShadowSourceIntention - *structs.ServiceIntentionsConfigEntry -} - -func (s ShadowServiceIntentionsConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - for _, source := range s.Sources { - if !IsEnterpriseData(source.Namespace, source.Partition) && source.SamenessGroup == "" { - s.ServiceIntentionsConfigEntry.Sources = append(s.ServiceIntentionsConfigEntry.Sources, source.SourceIntention) - } - } - return s.ServiceIntentionsConfigEntry -} - -type ShadowMeshConfigEntry struct { - ShadowBase - *structs.MeshConfigEntry -} - -func (s ShadowMeshConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - return s.MeshConfigEntry -} - -type ShadowExportedServicesConfigEntry struct { - ShadowBase - *structs.ExportedServicesConfigEntry -} - -func (s ShadowExportedServicesConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - services := []structs.ExportedService{} - for _, svc := range s.ExportedServicesConfigEntry.Services { - if !IsEnterpriseData(svc.Namespace, "") { - consumers := []structs.ServiceConsumer{} - for _, consumer := range svc.Consumers { - if !IsEnterpriseData("", consumer.Partition) && consumer.SamenessGroup == "" { - consumers = append(consumers, consumer) - } - } - if len(consumers) == 0 { - continue - } - services = append(services, svc) - } - } - s.ExportedServicesConfigEntry.Services = services - return s.ExportedServicesConfigEntry -} - -type ShadowSamenessGroupConfigEntry struct { - ShadowBase - *structs.SamenessGroupConfigEntry -} - -func (s ShadowSamenessGroupConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - return s.SamenessGroupConfigEntry -} - -type ShadowAPIGatewayConfigEntry struct { - ShadowBase - *structs.APIGatewayConfigEntry -} - -func (s ShadowAPIGatewayConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - return s.APIGatewayConfigEntry -} - -type ShadowBoundAPIGatewayListener struct { - Routes []ShadowResourceReference - Certificates []ShadowResourceReference - *structs.BoundAPIGatewayListener -} -type ShadowBoundAPIGatewayConfigEntry struct { - ShadowBase - Listeners []ShadowBoundAPIGatewayListener - *structs.BoundAPIGatewayConfigEntry -} - -func (s ShadowBoundAPIGatewayConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - for _, listner := range s.Listeners { - for _, route := range listner.Routes { - if !IsEnterpriseData(route.Namespace, route.Partition) { - listner.BoundAPIGatewayListener.Routes = append(listner.BoundAPIGatewayListener.Routes, *route.ResourceReference) - } - } - for _, cf := range listner.Certificates { - if !IsEnterpriseData(cf.Namespace, cf.Partition) { - listner.BoundAPIGatewayListener.Certificates = append(listner.BoundAPIGatewayListener.Certificates, *cf.ResourceReference) - } - } - s.BoundAPIGatewayConfigEntry.Listeners = append(s.BoundAPIGatewayConfigEntry.Listeners, *listner.BoundAPIGatewayListener) - } - return s.BoundAPIGatewayConfigEntry -} - -type ShadowInlineCertificateConfigEntry struct { - ShadowBase - *structs.InlineCertificateConfigEntry -} - -func (s ShadowInlineCertificateConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - return s.InlineCertificateConfigEntry -} - -type ShadowHTTPService struct { - ShadowBase - *structs.HTTPService -} -type ShadowHTTPRouteRule struct { - Services []ShadowHTTPService - *structs.HTTPRouteRule -} -type ShadowResourceReference struct { - ShadowBase - *structs.ResourceReference -} -type ShadowHTTPRouteConfigEntry struct { - ShadowBase - Parents []ShadowResourceReference - Rules []ShadowHTTPRouteRule - *structs.HTTPRouteConfigEntry -} - -func (s ShadowHTTPRouteConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - for _, parent := range s.Parents { - if !IsEnterpriseData(parent.Namespace, parent.Partition) { - s.HTTPRouteConfigEntry.Parents = append(s.HTTPRouteConfigEntry.Parents, *parent.ResourceReference) - } - } - for _, rule := range s.Rules { - for _, svc := range rule.Services { - if !IsEnterpriseData(svc.Namespace, svc.Partition) { - rule.HTTPRouteRule.Services = append(rule.HTTPRouteRule.Services, *svc.HTTPService) - } - } - s.HTTPRouteConfigEntry.Rules = append(s.HTTPRouteConfigEntry.Rules, *rule.HTTPRouteRule) - } - return s.HTTPRouteConfigEntry -} - -type ShadowTCPService struct { - ShadowBase - *structs.TCPService -} -type ShadowTCPRouteConfigEntry struct { - ShadowBase - Parents []ShadowResourceReference - Services []ShadowTCPService - *structs.TCPRouteConfigEntry -} - -func (s ShadowTCPRouteConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - for _, parent := range s.Parents { - if !IsEnterpriseData(parent.Namespace, parent.Partition) { - s.TCPRouteConfigEntry.Parents = append(s.TCPRouteConfigEntry.Parents, *parent.ResourceReference) - } - } - for _, svc := range s.Services { - if !IsEnterpriseData(svc.Namespace, svc.Partition) { - s.TCPRouteConfigEntry.Services = append(s.TCPRouteConfigEntry.Services, *svc.TCPService) - } - } - return s.TCPRouteConfigEntry -} - -type ShadowJWTProviderConfigEntry struct { - ShadowBase - *structs.JWTProviderConfigEntry -} - -func (s ShadowJWTProviderConfigEntry) GetRealConfigEntry() structs.ConfigEntry { - return s.JWTProviderConfigEntry -} diff --git a/agent/consul/fsm/fsm.go b/agent/consul/fsm/fsm.go index 5a350e4dae778..92a3931b5b331 100644 --- a/agent/consul/fsm/fsm.go +++ b/agent/consul/fsm/fsm.go @@ -195,10 +195,6 @@ func (c *FSM) Apply(log *raft.Log) interface{} { c.logger.Warn("ignoring unknown message type, upgrade to newer version", "type", msgType) return nil } - if structs.CEDowngrade && msgType >= 64 { - c.logger.Warn("ignoring enterprise message, for downgrading to oss", "type", msgType) - return nil - } panic(fmt.Errorf("failed to apply request: %#v", buf)) } @@ -267,10 +263,7 @@ func (c *FSM) Restore(old io.ReadCloser) error { return err } default: - if structs.CEDowngrade && msg >= 64 { - c.logger.Warn("ignoring enterprise message , for downgrading to oss", "type", msg) - return nil - } else if msg >= 64 { + if msg >= 64 { return fmt.Errorf("msg type <%d> is a Consul Enterprise log entry. Consul CE cannot restore it", msg) } else { return fmt.Errorf("Unrecognized msg type %d", msg) diff --git a/agent/consul/options.go b/agent/consul/options.go index 88c16bd1a99c5..6dc754b3aef70 100644 --- a/agent/consul/options.go +++ b/agent/consul/options.go @@ -49,7 +49,7 @@ type Deps struct { EnterpriseDeps } -// UseV2Resources returns true if "resource-apis" is present in the Experiments +// useV2Resources returns true if "resource-apis" is present in the Experiments // array of the agent config. func (d Deps) UseV2Resources() bool { if stringslice.Contains(d.Experiments, CatalogResourceExperimentName) { @@ -58,15 +58,6 @@ func (d Deps) UseV2Resources() bool { return false } -// UseV2Tenancy returns true if "v2tenancy" is present in the Experiments -// array of the agent config. -func (d Deps) UseV2Tenancy() bool { - if stringslice.Contains(d.Experiments, V2TenancyExperimentName) { - return true - } - return false -} - type GRPCClientConner interface { ClientConn(datacenter string) (*grpc.ClientConn, error) ClientConnLeader() (*grpc.ClientConn, error) diff --git a/agent/consul/server.go b/agent/consul/server.go index 0dfe48b4bf781..9540cbe1c0fde 100644 --- a/agent/consul/server.go +++ b/agent/consul/server.go @@ -79,7 +79,6 @@ import ( "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/internal/resource/reaper" raftstorage "github.com/hashicorp/consul/internal/storage/raft" - "github.com/hashicorp/consul/internal/tenancy" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/routine" "github.com/hashicorp/consul/lib/stringslice" @@ -468,9 +467,6 @@ type Server struct { registry resource.Registry useV2Resources bool - - // useV2Tenancy is tied to the "v2tenancy" feature flag. - useV2Tenancy bool } func (s *Server) DecrementBlockingQueries() uint64 { @@ -560,7 +556,6 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, routineManager: routine.NewManager(logger.Named(logging.ConsulServer)), registry: flat.Registry, useV2Resources: flat.UseV2Resources(), - useV2Tenancy: flat.UseV2Tenancy(), } incomingRPCLimiter.Register(s) @@ -838,7 +833,7 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, go s.reportingManager.Run(&lib.StopChannelContext{StopCh: s.shutdownCh}) // Setup insecure resource service client. - if err := s.setupInsecureResourceServiceClient(flat.Registry, logger); err != nil { + if err := s.setupInsecureResourceServiceClient(flat.Registry, logger, flat); err != nil { return nil, err } @@ -935,11 +930,6 @@ func isV1CatalogRequest(rpcName string) bool { } func (s *Server) registerControllers(deps Deps, proxyUpdater ProxyUpdater) error { - // When not enabled, the v1 tenancy bridge is used by default. - if s.useV2Tenancy { - tenancy.RegisterControllers(s.controllerManager) - } - if s.useV2Resources { catalog.RegisterControllers(s.controllerManager, catalog.DefaultControllerDependencies()) @@ -986,7 +976,7 @@ func (s *Server) registerControllers(deps Deps, proxyUpdater ProxyUpdater) error demo.RegisterControllers(s.controllerManager) } - return s.controllerManager.ValidateDependencies(s.registry.Types()) + return nil } func newGRPCHandlerFromConfig(deps Deps, config *Config, s *Server) connHandler { @@ -1465,9 +1455,8 @@ func (s *Server) setupExternalGRPC(config *Config, deps Deps, logger hclog.Logge s.peerStreamServer.Register(s.externalGRPCServer) tenancyBridge := NewV1TenancyBridge(s) - if s.useV2Tenancy { - tenancyBridgeV2 := tenancy.NewV2TenancyBridge() - tenancyBridge = tenancyBridgeV2.WithClient(s.insecureResourceServiceClient) + if stringslice.Contains(deps.Experiments, V2TenancyExperimentName) { + tenancyBridge = resource.NewV2TenancyBridge() } s.resourceServiceServer = resourcegrpc.NewServer(resourcegrpc.Config{ @@ -1476,23 +1465,20 @@ func (s *Server) setupExternalGRPC(config *Config, deps Deps, logger hclog.Logge ACLResolver: s.ACLResolver, Logger: logger.Named("grpc-api.resource"), TenancyBridge: tenancyBridge, - UseV2Tenancy: s.useV2Tenancy, }) s.resourceServiceServer.Register(s.externalGRPCServer) reflection.Register(s.externalGRPCServer) } -func (s *Server) setupInsecureResourceServiceClient(typeRegistry resource.Registry, logger hclog.Logger) error { +func (s *Server) setupInsecureResourceServiceClient(typeRegistry resource.Registry, logger hclog.Logger, deps Deps) error { if s.raftStorageBackend == nil { return fmt.Errorf("raft storage backend cannot be nil") } - // Can't use interface type var here since v2 specific "WithClient(...)" is called futher down. tenancyBridge := NewV1TenancyBridge(s) - tenancyBridgeV2 := tenancy.NewV2TenancyBridge() - if s.useV2Tenancy { - tenancyBridge = tenancyBridgeV2 + if stringslice.Contains(deps.Experiments, V2TenancyExperimentName) { + tenancyBridge = resource.NewV2TenancyBridge() } server := resourcegrpc.NewServer(resourcegrpc.Config{ Registry: typeRegistry, @@ -1500,7 +1486,6 @@ func (s *Server) setupInsecureResourceServiceClient(typeRegistry resource.Regist ACLResolver: resolver.DANGER_NO_AUTH{}, Logger: logger.Named("grpc-api.resource"), TenancyBridge: tenancyBridge, - UseV2Tenancy: s.useV2Tenancy, }) conn, err := s.runInProcessGRPCServer(server.Register) @@ -1508,7 +1493,7 @@ func (s *Server) setupInsecureResourceServiceClient(typeRegistry resource.Regist return err } s.insecureResourceServiceClient = pbresource.NewResourceServiceClient(conn) - tenancyBridgeV2.WithClient(s.insecureResourceServiceClient) + return nil } diff --git a/agent/consul/server_test.go b/agent/consul/server_test.go index 95fa102d4a464..0ae028cbf2f2b 100644 --- a/agent/consul/server_test.go +++ b/agent/consul/server_test.go @@ -6,11 +6,9 @@ package consul import ( "context" "crypto/x509" - "flag" "fmt" "net" "os" - "path/filepath" "reflect" "strings" "sync" @@ -38,12 +36,10 @@ import ( external "github.com/hashicorp/consul/agent/grpc-external" grpcmiddleware "github.com/hashicorp/consul/agent/grpc-middleware" hcpclient "github.com/hashicorp/consul/agent/hcp/client" - "github.com/hashicorp/consul/agent/leafcert" "github.com/hashicorp/consul/agent/metadata" "github.com/hashicorp/consul/agent/rpc/middleware" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/token" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/sdk/freeport" "github.com/hashicorp/consul/sdk/testutil" @@ -341,8 +337,7 @@ func newServerWithDeps(t *testing.T, c *Config, deps Deps) (*Server, error) { } } grpcServer := external.NewServer(deps.Logger.Named("grpc.external"), nil, deps.TLSConfigurator, rpcRate.NullRequestLimitsHandler(), keepalive.ServerParameters{}) - proxyUpdater := proxytracker.NewProxyTracker(proxytracker.ProxyTrackerConfig{}) - srv, err := NewServer(c, deps, grpcServer, nil, deps.Logger, proxyUpdater) + srv, err := NewServer(c, deps, grpcServer, nil, deps.Logger, nil) if err != nil { return nil, err } @@ -2106,38 +2101,3 @@ func TestServer_hcpManager(t *testing.T) { hcp1.AssertExpectations(t) } - -// goldenMarkdown reads and optionally writes the expected data to the goldenMarkdown file, -// returning the contents as a string. -func goldenMarkdown(t *testing.T, name, got string) string { - t.Helper() - - golden := filepath.Join("testdata", name+".md") - update := flag.Lookup("update").Value.(flag.Getter).Get().(bool) - if update && got != "" { - err := os.WriteFile(golden, []byte(got), 0644) - require.NoError(t, err) - } - - expected, err := os.ReadFile(golden) - require.NoError(t, err) - - return string(expected) -} - -func TestServer_ControllerDependencies(t *testing.T) { - t.Parallel() - - _, conf := testServerConfig(t) - deps := newDefaultDeps(t, conf) - deps.Experiments = []string{"resource-apis"} - deps.LeafCertManager = &leafcert.Manager{} - - s1, err := newServerWithDeps(t, conf, deps) - require.NoError(t, err) - - waitForLeaderEstablishment(t, s1) - actual := fmt.Sprintf("```mermaid\n%s\n```", s1.controllerManager.CalculateDependencies(s1.registry.Types()).ToMermaid()) - expected := goldenMarkdown(t, "v2-resource-dependencies", actual) - require.Equal(t, expected, actual) -} diff --git a/agent/consul/state/peering.go b/agent/consul/state/peering.go index 05dfa59a37af3..1763777cff838 100644 --- a/agent/consul/state/peering.go +++ b/agent/consul/state/peering.go @@ -202,9 +202,6 @@ func (s *Store) peeringSecretsWriteTxn(tx WriteTxn, req *pbpeering.SecretsWriteR return fmt.Errorf("failed to read peering by id: %w", err) } if peering == nil { - if structs.CEDowngrade { - return nil - } return fmt.Errorf("unknown peering %q for secret", req.PeerID) } diff --git a/agent/consul/testdata/v2-resource-dependencies.md b/agent/consul/testdata/v2-resource-dependencies.md deleted file mode 100644 index 1e34812446a41..0000000000000 --- a/agent/consul/testdata/v2-resource-dependencies.md +++ /dev/null @@ -1,45 +0,0 @@ -```mermaid -flowchart TD - auth/v2beta1/computedtrafficpermissions --> auth/v2beta1/trafficpermissions - auth/v2beta1/computedtrafficpermissions --> auth/v2beta1/workloadidentity - catalog/v2beta1/failoverpolicy --> catalog/v2beta1/service - catalog/v2beta1/healthstatus - catalog/v2beta1/node --> catalog/v2beta1/healthstatus - catalog/v2beta1/service - catalog/v2beta1/serviceendpoints --> catalog/v2beta1/service - catalog/v2beta1/serviceendpoints --> catalog/v2beta1/workload - catalog/v2beta1/workload --> catalog/v2beta1/healthstatus - catalog/v2beta1/workload --> catalog/v2beta1/node - demo/v1/album - demo/v1/artist - demo/v1/concept - demo/v1/executive - demo/v1/recordlabel - demo/v2/album - demo/v2/artist - internal/v1/tombstone - mesh/v2beta1/computedexplicitdestinations --> catalog/v2beta1/service - mesh/v2beta1/computedexplicitdestinations --> catalog/v2beta1/workload - mesh/v2beta1/computedexplicitdestinations --> mesh/v2beta1/computedroutes - mesh/v2beta1/computedexplicitdestinations --> mesh/v2beta1/destinations - mesh/v2beta1/computedproxyconfiguration --> catalog/v2beta1/workload - mesh/v2beta1/computedproxyconfiguration --> mesh/v2beta1/proxyconfiguration - mesh/v2beta1/computedroutes --> catalog/v2beta1/failoverpolicy - mesh/v2beta1/computedroutes --> catalog/v2beta1/service - mesh/v2beta1/computedroutes --> mesh/v2beta1/destinationpolicy - mesh/v2beta1/computedroutes --> mesh/v2beta1/grpcroute - mesh/v2beta1/computedroutes --> mesh/v2beta1/httproute - mesh/v2beta1/computedroutes --> mesh/v2beta1/tcproute - mesh/v2beta1/destinationpolicy - mesh/v2beta1/destinations - mesh/v2beta1/grpcroute - mesh/v2beta1/httproute - mesh/v2beta1/proxyconfiguration - mesh/v2beta1/proxystatetemplate --> auth/v2beta1/computedtrafficpermissions - mesh/v2beta1/proxystatetemplate --> catalog/v2beta1/service - mesh/v2beta1/proxystatetemplate --> catalog/v2beta1/workload - mesh/v2beta1/proxystatetemplate --> mesh/v2beta1/computedexplicitdestinations - mesh/v2beta1/proxystatetemplate --> mesh/v2beta1/computedproxyconfiguration - mesh/v2beta1/proxystatetemplate --> mesh/v2beta1/computedroutes - mesh/v2beta1/tcproute -``` \ No newline at end of file diff --git a/agent/consul/type_registry.go b/agent/consul/type_registry.go index 8bf093c41a112..d93309159d4bb 100644 --- a/agent/consul/type_registry.go +++ b/agent/consul/type_registry.go @@ -7,7 +7,6 @@ import ( "github.com/hashicorp/consul/internal/auth" "github.com/hashicorp/consul/internal/catalog" "github.com/hashicorp/consul/internal/mesh" - "github.com/hashicorp/consul/internal/multicluster" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/internal/tenancy" @@ -28,7 +27,6 @@ func NewTypeRegistry() resource.Registry { catalog.RegisterTypes(registry) auth.RegisterTypes(registry) tenancy.RegisterTypes(registry) - multicluster.RegisterTypes(registry) return registry } diff --git a/agent/grpc-external/services/resource/delete.go b/agent/grpc-external/services/resource/delete.go index f19d4a52492cf..2f30e27f983fb 100644 --- a/agent/grpc-external/services/resource/delete.go +++ b/agent/grpc-external/services/resource/delete.go @@ -7,7 +7,6 @@ import ( "context" "errors" "fmt" - "strings" "time" "github.com/oklog/ulid/v2" @@ -159,10 +158,6 @@ func (s *Server) validateDeleteRequest(req *pbresource.DeleteRequest) (*resource return nil, err } - if err = checkV2Tenancy(s.UseV2Tenancy, req.Id.Type); err != nil { - return nil, err - } - // Check scope if reg.Scope == resource.ScopePartition && req.Id.Tenancy.Namespace != "" { return nil, status.Errorf( @@ -180,5 +175,5 @@ func (s *Server) validateDeleteRequest(req *pbresource.DeleteRequest) (*resource // name by embedding the resources's Uid in the name. func tombstoneName(deleteId *pbresource.ID) string { // deleteId.Name is just included for easier identification - return fmt.Sprintf("tombstone-%v-%v", deleteId.Name, strings.ToLower(deleteId.Uid)) + return fmt.Sprintf("tombstone-%v-%v", deleteId.Name, deleteId.Uid) } diff --git a/agent/grpc-external/services/resource/delete_test.go b/agent/grpc-external/services/resource/delete_test.go index 3bdbb0581d106..5f5d7d7e21920 100644 --- a/agent/grpc-external/services/resource/delete_test.go +++ b/agent/grpc-external/services/resource/delete_test.go @@ -5,7 +5,6 @@ package resource import ( "context" - "strings" "testing" "github.com/stretchr/testify/mock" @@ -23,98 +22,39 @@ import ( func TestDelete_InputValidation(t *testing.T) { server := testServer(t) client := testClient(t, server) - demo.RegisterTypes(server.Registry) - type testCase struct { - modFn func(artistId, recordLabelId *pbresource.ID) *pbresource.ID - errContains string - } + demo.RegisterTypes(server.Registry) - testCases := map[string]testCase{ - "no id": { - modFn: func(_, _ *pbresource.ID) *pbresource.ID { - return nil - }, - errContains: "id is required", - }, - "no type": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Type = nil - return artistId - }, - errContains: "id.type is required", - }, - "no name": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Name = "" - return artistId - }, - errContains: "id.name invalid", - }, - "mixed case name": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Name = "DepecheMode" - return artistId - }, - errContains: "id.name invalid", - }, - "name too long": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Name = strings.Repeat("n", resource.MaxNameLength+1) - return artistId - }, - errContains: "id.name invalid", - }, - "partition mixed case": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy.Partition = "Default" - return artistId - }, - errContains: "id.tenancy.partition invalid", + testCases := map[string]func(artistId, recordLabelId *pbresource.ID) *pbresource.ID{ + "no id": func(artistId, recordLabelId *pbresource.ID) *pbresource.ID { + return nil }, - "partition name too long": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) - return artistId - }, - errContains: "id.tenancy.partition invalid", + "no type": func(artistId, _ *pbresource.ID) *pbresource.ID { + artistId.Type = nil + return artistId }, - "namespace mixed case": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy.Namespace = "Default" - return artistId - }, - errContains: "id.tenancy.namespace invalid", + "no name": func(artistId, _ *pbresource.ID) *pbresource.ID { + artistId.Name = "" + return artistId }, - "namespace name too long": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) - return artistId - }, - errContains: "id.tenancy.namespace invalid", - }, - "partition scoped resource with namespace": { - modFn: func(_, recordLabelId *pbresource.ID) *pbresource.ID { - recordLabelId.Tenancy.Namespace = "ishouldnothaveanamespace" - return recordLabelId - }, - errContains: "cannot have a namespace", + "partition scoped resource with namespace": func(_, recordLabelId *pbresource.ID) *pbresource.ID { + recordLabelId.Tenancy.Namespace = "ishouldnothaveanamespace" + return recordLabelId }, } - for desc, tc := range testCases { + for desc, modFn := range testCases { t.Run(desc, func(t *testing.T) { - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") require.NoError(t, err) artist, err := demo.GenerateV2Artist() require.NoError(t, err) - req := &pbresource.DeleteRequest{Id: tc.modFn(artist.Id, recordLabel.Id), Version: ""} + req := &pbresource.DeleteRequest{Id: modFn(artist.Id, recordLabel.Id), Version: ""} _, err = client.Delete(testContext(t), req) require.Error(t, err) require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) - require.ErrorContains(t, err, tc.errContains) }) } } @@ -189,7 +129,7 @@ func TestDelete_Success(t *testing.T) { server, client, ctx := testDeps(t) demo.RegisterTypes(server.Registry) - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") require.NoError(t, err) writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: recordLabel}) require.NoError(t, err) diff --git a/agent/grpc-external/services/resource/list.go b/agent/grpc-external/services/resource/list.go index 8bdfc4fb3cfe4..c1ecb253448ce 100644 --- a/agent/grpc-external/services/resource/list.go +++ b/agent/grpc-external/services/resource/list.go @@ -100,13 +100,8 @@ func (s *Server) validateListRequest(req *pbresource.ListRequest) (*resource.Reg return nil, err } - if err = checkV2Tenancy(s.UseV2Tenancy, req.Type); err != nil { - return nil, err - } - - if err := validateWildcardTenancy(req.Tenancy, req.NamePrefix); err != nil { - return nil, err - } + // Lowercase + resource.Normalize(req.Tenancy) // Error when partition scoped and namespace not empty. if reg.Scope == resource.ScopePartition && req.Tenancy.Namespace != "" { diff --git a/agent/grpc-external/services/resource/list_by_owner.go b/agent/grpc-external/services/resource/list_by_owner.go index 1f69787901280..2310a5b50eda2 100644 --- a/agent/grpc-external/services/resource/list_by_owner.go +++ b/agent/grpc-external/services/resource/list_by_owner.go @@ -42,8 +42,8 @@ func (s *Server) ListByOwner(ctx context.Context, req *pbresource.ListByOwnerReq return nil, status.Errorf(codes.Internal, "failed list acl: %v", err) } - // Check tenancy exists for the v2 resource. - if err = tenancyExists(reg, s.TenancyBridge, req.Owner.Tenancy, codes.InvalidArgument); err != nil { + // Check v1 tenancy exists for the v2 resource. + if err = v1TenancyExists(reg, s.TenancyBridge, req.Owner.Tenancy, codes.InvalidArgument); err != nil { return nil, err } @@ -105,9 +105,8 @@ func (s *Server) validateListByOwnerRequest(req *pbresource.ListByOwnerRequest) return nil, err } - if err = checkV2Tenancy(s.UseV2Tenancy, req.Owner.Type); err != nil { - return nil, err - } + // Lowercase + resource.Normalize(req.Owner.Tenancy) // Error when partition scoped and namespace not empty. if reg.Scope == resource.ScopePartition && req.Owner.Tenancy.Namespace != "" { diff --git a/agent/grpc-external/services/resource/list_by_owner_test.go b/agent/grpc-external/services/resource/list_by_owner_test.go index 78024e68d0fb2..11c6027c0b642 100644 --- a/agent/grpc-external/services/resource/list_by_owner_test.go +++ b/agent/grpc-external/services/resource/list_by_owner_test.go @@ -6,7 +6,6 @@ package resource import ( "context" "fmt" - "strings" "testing" "github.com/hashicorp/consul/acl" @@ -14,7 +13,6 @@ import ( "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/proto/private/prototest" - "github.com/oklog/ulid/v2" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -28,104 +26,41 @@ func TestListByOwner_InputValidation(t *testing.T) { client := testClient(t, server) demo.RegisterTypes(server.Registry) - type testCase struct { - modFn func(artistId, recordlabelId *pbresource.ID) *pbresource.ID - errContains string - } - testCases := map[string]testCase{ - "no owner": { - modFn: func(artistId, recordLabelId *pbresource.ID) *pbresource.ID { - return nil - }, - errContains: "owner is required", - }, - "no type": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Type = nil - return artistId - }, - errContains: "owner.type is required", - }, - "no name": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Name = "" - return artistId - }, - errContains: "owner.name invalid", - }, - "name mixed case": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Name = "U2" - return artistId - }, - errContains: "owner.name invalid", + testCases := map[string]func(artistId, recordlabelId *pbresource.ID) *pbresource.ID{ + "no owner": func(artistId, recordLabelId *pbresource.ID) *pbresource.ID { + return nil }, - "name too long": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Name = strings.Repeat("n", resource.MaxNameLength+1) - return artistId - }, - errContains: "owner.name invalid", + "no type": func(artistId, _ *pbresource.ID) *pbresource.ID { + artistId.Type = nil + return artistId }, - "partition mixed case": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy.Partition = "Default" - return artistId - }, - errContains: "owner.tenancy.partition invalid", + "no name": func(artistId, _ *pbresource.ID) *pbresource.ID { + artistId.Name = "" + return artistId }, - "partition too long": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) - return artistId - }, - errContains: "owner.tenancy.partition invalid", + "no uid": func(artistId, _ *pbresource.ID) *pbresource.ID { + artistId.Uid = "" + return artistId }, - "namespace mixed case": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy.Namespace = "Default" - return artistId - }, - errContains: "owner.tenancy.namespace invalid", - }, - "namespace too long": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) - return artistId - }, - errContains: "owner.tenancy.namespace invalid", - }, - "no uid": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Uid = "" - return artistId - }, - errContains: "owner uid is required", - }, - "partition scope with non-empty namespace": { - modFn: func(_, recordLabelId *pbresource.ID) *pbresource.ID { - recordLabelId.Uid = ulid.Make().String() - recordLabelId.Tenancy.Namespace = "ishouldnothaveanamespace" - return recordLabelId - }, - errContains: "cannot have a namespace", + "partition scope with non-empty namespace": func(_, recordLabelId *pbresource.ID) *pbresource.ID { + recordLabelId.Tenancy.Namespace = "ishouldnothaveanamespace" + return recordLabelId }, } - for desc, tc := range testCases { + for desc, modFn := range testCases { t.Run(desc, func(t *testing.T) { artist, err := demo.GenerateV2Artist() require.NoError(t, err) - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") require.NoError(t, err) // Each test case picks which resource to use based on the resource type's scope. - req := &pbresource.ListByOwnerRequest{Owner: tc.modFn(artist.Id, recordLabel.Id)} + req := &pbresource.ListByOwnerRequest{Owner: modFn(artist.Id, recordLabel.Id)} _, err = client.ListByOwner(testContext(t), req) require.Error(t, err) require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) - require.ErrorContains(t, err, tc.errContains) }) } } @@ -196,46 +131,33 @@ func TestListByOwner_Many(t *testing.T) { } func TestListByOwner_OwnerTenancyDoesNotExist(t *testing.T) { - type testCase struct { - modFn func(artistId, recordlabelId *pbresource.ID) *pbresource.ID - errContains string - } - tenancyCases := map[string]testCase{ - "partition not found when namespace scoped": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - id := clone(artistId) - id.Uid = "doesnotmatter" - id.Tenancy.Partition = "boguspartition" - return id - }, - errContains: "partition not found", + tenancyCases := map[string]func(artistId, recordlabelId *pbresource.ID) *pbresource.ID{ + "partition not found when namespace scoped": func(artistId, _ *pbresource.ID) *pbresource.ID { + id := clone(artistId) + id.Uid = "doesnotmatter" + id.Tenancy.Partition = "boguspartition" + return id }, - "namespace not found when namespace scoped": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - id := clone(artistId) - id.Uid = "doesnotmatter" - id.Tenancy.Namespace = "bogusnamespace" - return id - }, - errContains: "namespace not found", + "namespace not found when namespace scoped": func(artistId, _ *pbresource.ID) *pbresource.ID { + id := clone(artistId) + id.Uid = "doesnotmatter" + id.Tenancy.Namespace = "bogusnamespace" + return id }, - "partition not found when partition scoped": { - modFn: func(_, recordLabelId *pbresource.ID) *pbresource.ID { - id := clone(recordLabelId) - id.Uid = "doesnotmatter" - id.Tenancy.Partition = "boguspartition" - return id - }, - errContains: "partition not found", + "partition not found when partition scoped": func(_, recordLabelId *pbresource.ID) *pbresource.ID { + id := clone(recordLabelId) + id.Uid = "doesnotmatter" + id.Tenancy.Partition = "boguspartition" + return id }, } - for desc, tc := range tenancyCases { + for desc, modFn := range tenancyCases { t.Run(desc, func(t *testing.T) { server := testServer(t) demo.RegisterTypes(server.Registry) client := testClient(t, server) - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") require.NoError(t, err) recordLabel, err = server.Backend.WriteCAS(testContext(t), recordLabel) require.NoError(t, err) @@ -245,11 +167,11 @@ func TestListByOwner_OwnerTenancyDoesNotExist(t *testing.T) { artist, err = server.Backend.WriteCAS(testContext(t), artist) require.NoError(t, err) - // Verify non-existant tenancy units in owner err with invalid arg. - _, err = client.ListByOwner(testContext(t), &pbresource.ListByOwnerRequest{Owner: tc.modFn(artist.Id, recordLabel.Id)}) + // Verify non-existant tenancy units in owner err with not found. + _, err = client.ListByOwner(testContext(t), &pbresource.ListByOwnerRequest{Owner: modFn(artist.Id, recordLabel.Id)}) require.Error(t, err) require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) - require.ErrorContains(t, err, tc.errContains) + require.Contains(t, err.Error(), "resource not found") }) } } @@ -262,7 +184,7 @@ func TestListByOwner_Tenancy_Defaults_And_Normalization(t *testing.T) { client := testClient(t, server) // Create partition scoped recordLabel. - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") require.NoError(t, err) rsp1, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: recordLabel}) require.NoError(t, err) diff --git a/agent/grpc-external/services/resource/list_test.go b/agent/grpc-external/services/resource/list_test.go index 5af6747f84444..64026b7d34e59 100644 --- a/agent/grpc-external/services/resource/list_test.go +++ b/agent/grpc-external/services/resource/list_test.go @@ -6,8 +6,6 @@ package resource import ( "context" "fmt" - "strconv" - "strings" "testing" "github.com/hashicorp/consul/acl" @@ -28,66 +26,28 @@ import ( func TestList_InputValidation(t *testing.T) { server := testServer(t) client := testClient(t, server) - demo.RegisterTypes(server.Registry) - type testCase struct { - modReqFn func(req *pbresource.ListRequest) - errContains string - } + demo.RegisterTypes(server.Registry) - testCases := map[string]testCase{ - "no type": { - modReqFn: func(req *pbresource.ListRequest) { req.Type = nil }, - errContains: "type is required", - }, - "no tenancy": { - modReqFn: func(req *pbresource.ListRequest) { req.Tenancy = nil }, - errContains: "tenancy is required", - }, - "partition mixed case": { - modReqFn: func(req *pbresource.ListRequest) { req.Tenancy.Partition = "Default" }, - errContains: "tenancy.partition invalid", - }, - "partition too long": { - modReqFn: func(req *pbresource.ListRequest) { - req.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) - }, - errContains: "tenancy.partition invalid", - }, - "namespace mixed case": { - modReqFn: func(req *pbresource.ListRequest) { req.Tenancy.Namespace = "Default" }, - errContains: "tenancy.namespace invalid", - }, - "namespace too long": { - modReqFn: func(req *pbresource.ListRequest) { - req.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) - }, - errContains: "tenancy.namespace invalid", - }, - "name_prefix mixed case": { - modReqFn: func(req *pbresource.ListRequest) { req.NamePrefix = "Violator" }, - errContains: "name_prefix invalid", - }, - "partitioned resource provides non-empty namespace": { - modReqFn: func(req *pbresource.ListRequest) { - req.Type = demo.TypeV1RecordLabel - req.Tenancy.Namespace = "bad" - }, - errContains: "cannot have a namespace", + testCases := map[string]func(*pbresource.ListRequest){ + "no type": func(req *pbresource.ListRequest) { req.Type = nil }, + "no tenancy": func(req *pbresource.ListRequest) { req.Tenancy = nil }, + "partitioned resource provides non-empty namespace": func(req *pbresource.ListRequest) { + req.Type = demo.TypeV1RecordLabel + req.Tenancy.Namespace = "bad" }, } - for desc, tc := range testCases { + for desc, modFn := range testCases { t.Run(desc, func(t *testing.T) { req := &pbresource.ListRequest{ Type: demo.TypeV2Album, Tenancy: resource.DefaultNamespacedTenancy(), } - tc.modReqFn(req) + modFn(req) _, err := client.List(testContext(t), req) require.Error(t, err) require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) - require.ErrorContains(t, err, tc.errContains) }) } } @@ -156,46 +116,6 @@ func TestList_Many(t *testing.T) { } } -func TestList_NamePrefix(t *testing.T) { - for desc, tc := range listTestCases() { - t.Run(desc, func(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) - - expectedResources := []*pbresource.Resource{} - - namePrefixIndex := 0 - // create a name prefix that is always present - namePrefix := fmt.Sprintf("%s-", strconv.Itoa(namePrefixIndex)) - for i := 0; i < 10; i++ { - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - - // Prevent test flakes if the generated names collide. - artist.Id.Name = fmt.Sprintf("%d-%s", i, artist.Id.Name) - - rsp, err := client.Write(tc.ctx, &pbresource.WriteRequest{Resource: artist}) - require.NoError(t, err) - - // only matching name prefix are expected - if i == namePrefixIndex { - expectedResources = append(expectedResources, rsp.Resource) - } - } - - rsp, err := client.List(tc.ctx, &pbresource.ListRequest{ - Type: demo.TypeV2Artist, - Tenancy: resource.DefaultNamespacedTenancy(), - NamePrefix: namePrefix, - }) - - require.NoError(t, err) - prototest.AssertElementsMatch(t, expectedResources, rsp.Resources) - }) - } -} - func TestList_Tenancy_Defaults_And_Normalization(t *testing.T) { // Test units of tenancy get defaulted correctly when empty. ctx := context.Background() @@ -206,7 +126,7 @@ func TestList_Tenancy_Defaults_And_Normalization(t *testing.T) { client := testClient(t, server) // Write partition scoped record label - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LooneyTunes") require.NoError(t, err) recordLabelRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: recordLabel}) require.NoError(t, err) @@ -230,6 +150,7 @@ func TestList_Tenancy_Defaults_And_Normalization(t *testing.T) { prototest.AssertDeepEqual(t, artistRsp.Resource, listRsp.Resources[0]) } }) + } } diff --git a/agent/grpc-external/services/resource/read.go b/agent/grpc-external/services/resource/read.go index 3c413bc13870b..b6cec37254566 100644 --- a/agent/grpc-external/services/resource/read.go +++ b/agent/grpc-external/services/resource/read.go @@ -59,8 +59,8 @@ func (s *Server) Read(ctx context.Context, req *pbresource.ReadRequest) (*pbreso return nil, status.Errorf(codes.Internal, "failed read acl: %v", err) } - // Check tenancy exists for the V2 resource. - if err = tenancyExists(reg, s.TenancyBridge, req.Id.Tenancy, codes.NotFound); err != nil { + // Check V1 tenancy exists for the V2 resource. + if err = v1TenancyExists(reg, s.TenancyBridge, req.Id.Tenancy, codes.NotFound); err != nil { return nil, err } @@ -102,10 +102,6 @@ func (s *Server) validateReadRequest(req *pbresource.ReadRequest) (*resource.Reg return nil, err } - if err = checkV2Tenancy(s.UseV2Tenancy, req.Id.Type); err != nil { - return nil, err - } - // Check scope if reg.Scope == resource.ScopePartition && req.Id.Tenancy.Namespace != "" { return nil, status.Errorf( diff --git a/agent/grpc-external/services/resource/read_test.go b/agent/grpc-external/services/resource/read_test.go index 2afdfeab0e1ea..2601689bc6c4b 100644 --- a/agent/grpc-external/services/resource/read_test.go +++ b/agent/grpc-external/services/resource/read_test.go @@ -6,7 +6,6 @@ package resource import ( "context" "fmt" - "strings" "sync" "testing" @@ -35,114 +34,46 @@ func TestRead_InputValidation(t *testing.T) { tenancy.RegisterTypes(server.Registry) demo.RegisterTypes(server.Registry) - type testCase struct { - modFn func(artistId, recordlabelId, executiveId *pbresource.ID) *pbresource.ID - errContains string - } - - testCases := map[string]testCase{ - "no id": { - modFn: func(_, _, _ *pbresource.ID) *pbresource.ID { - return nil - }, - errContains: "id is required", - }, - "no type": { - modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { - artistId.Type = nil - return artistId - }, - errContains: "id.type is required", - }, - "no name": { - modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { - artistId.Name = "" - return artistId - }, - errContains: "id.name invalid", - }, - "name is mixed case": { - modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { - artistId.Name = "MixedCaseNotAllowed" - return artistId - }, - errContains: "id.name invalid", + testCases := map[string]func(artistId, recordlabelId, executiveId *pbresource.ID) *pbresource.ID{ + "no id": func(_, _, _ *pbresource.ID) *pbresource.ID { return nil }, + "no type": func(artistId, _, _ *pbresource.ID) *pbresource.ID { + artistId.Type = nil + return artistId }, - "name too long": { - modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { - artistId.Name = strings.Repeat("a", resource.MaxNameLength+1) - return artistId - }, - errContains: "id.name invalid", + "no name": func(artistId, _, _ *pbresource.ID) *pbresource.ID { + artistId.Name = "" + return artistId }, - "partition is mixed case": { - modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy.Partition = "Default" - return artistId - }, - errContains: "id.tenancy.partition invalid", + "partition scope with non-empty namespace": func(_, recordLabelId, _ *pbresource.ID) *pbresource.ID { + recordLabelId.Tenancy.Namespace = "ishouldnothaveanamespace" + return recordLabelId }, - "partition too long": { - modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) - return artistId - }, - errContains: "id.tenancy.partition invalid", + "cluster scope with non-empty partition": func(_, _, executiveId *pbresource.ID) *pbresource.ID { + executiveId.Tenancy = &pbresource.Tenancy{Partition: resource.DefaultPartitionName} + return executiveId }, - "namespace is mixed case": { - modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy.Namespace = "Default" - return artistId - }, - errContains: "id.tenancy.namespace invalid", - }, - "namespace too long": { - modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) - return artistId - }, - errContains: "id.tenancy.namespace invalid", - }, - "partition scope with non-empty namespace": { - modFn: func(_, recordLabelId, _ *pbresource.ID) *pbresource.ID { - recordLabelId.Tenancy.Namespace = "ishouldnothaveanamespace" - return recordLabelId - }, - errContains: "cannot have a namespace", - }, - "cluster scope with non-empty partition": { - modFn: func(_, _, executiveId *pbresource.ID) *pbresource.ID { - executiveId.Tenancy = &pbresource.Tenancy{Partition: resource.DefaultPartitionName} - return executiveId - }, - errContains: "cannot have a partition", - }, - "cluster scope with non-empty namespace": { - modFn: func(_, _, executiveId *pbresource.ID) *pbresource.ID { - executiveId.Tenancy = &pbresource.Tenancy{Namespace: resource.DefaultNamespaceName} - return executiveId - }, - errContains: "cannot have a namespace", + "cluster scope with non-empty namespace": func(_, _, executiveId *pbresource.ID) *pbresource.ID { + executiveId.Tenancy = &pbresource.Tenancy{Namespace: resource.DefaultNamespaceName} + return executiveId }, } - for desc, tc := range testCases { + for desc, modFn := range testCases { t.Run(desc, func(t *testing.T) { artist, err := demo.GenerateV2Artist() require.NoError(t, err) - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") require.NoError(t, err) - executive, err := demo.GenerateV1Executive("music-man", "CEO") + executive, err := demo.GenerateV1Executive("MusicMan", "CEO") require.NoError(t, err) // Each test case picks which resource to use based on the resource type's scope. - req := &pbresource.ReadRequest{Id: tc.modFn(artist.Id, recordLabel.Id, executive.Id)} + req := &pbresource.ReadRequest{Id: modFn(artist.Id, recordLabel.Id, executive.Id)} _, err = client.Read(testContext(t), req) require.Error(t, err) require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) - require.ErrorContains(t, err, tc.errContains) }) } } @@ -163,50 +94,34 @@ func TestRead_TypeNotFound(t *testing.T) { func TestRead_ResourceNotFound(t *testing.T) { for desc, tc := range readTestCases() { t.Run(desc, func(t *testing.T) { - type tenancyCase struct { - modFn func(artistId, recordlabelId *pbresource.ID) *pbresource.ID - errContains string - } - tenancyCases := map[string]tenancyCase{ - "resource not found by name": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Name = "bogusname" - return artistId - }, - errContains: "resource not found", + tenancyCases := map[string]func(artistId, recordlabelId *pbresource.ID) *pbresource.ID{ + "resource not found by name": func(artistId, _ *pbresource.ID) *pbresource.ID { + artistId.Name = "bogusname" + return artistId }, - "partition not found when namespace scoped": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - id := clone(artistId) - id.Tenancy.Partition = "boguspartition" - return id - }, - errContains: "partition not found", + "partition not found when namespace scoped": func(artistId, _ *pbresource.ID) *pbresource.ID { + id := clone(artistId) + id.Tenancy.Partition = "boguspartition" + return id }, - "namespace not found when namespace scoped": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - id := clone(artistId) - id.Tenancy.Namespace = "bogusnamespace" - return id - }, - errContains: "namespace not found", + "namespace not found when namespace scoped": func(artistId, _ *pbresource.ID) *pbresource.ID { + id := clone(artistId) + id.Tenancy.Namespace = "bogusnamespace" + return id }, - "partition not found when partition scoped": { - modFn: func(_, recordLabelId *pbresource.ID) *pbresource.ID { - id := clone(recordLabelId) - id.Tenancy.Partition = "boguspartition" - return id - }, - errContains: "partition not found", + "partition not found when partition scoped": func(_, recordLabelId *pbresource.ID) *pbresource.ID { + id := clone(recordLabelId) + id.Tenancy.Partition = "boguspartition" + return id }, } - for tenancyDesc, tenancyCase := range tenancyCases { + for tenancyDesc, modFn := range tenancyCases { t.Run(tenancyDesc, func(t *testing.T) { server := testServer(t) demo.RegisterTypes(server.Registry) client := testClient(t, server) - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") require.NoError(t, err) recordLabel, err = server.Backend.WriteCAS(tc.ctx, recordLabel) require.NoError(t, err) @@ -217,10 +132,10 @@ func TestRead_ResourceNotFound(t *testing.T) { require.NoError(t, err) // Each tenancy test case picks which resource to use based on the resource type's scope. - _, err = client.Read(tc.ctx, &pbresource.ReadRequest{Id: tenancyCase.modFn(artist.Id, recordLabel.Id)}) + _, err = client.Read(tc.ctx, &pbresource.ReadRequest{Id: modFn(artist.Id, recordLabel.Id)}) require.Error(t, err) require.Equal(t, codes.NotFound.String(), status.Code(err).String()) - require.ErrorContains(t, err, tenancyCase.errContains) + require.Contains(t, err.Error(), "resource not found") }) } }) @@ -261,7 +176,7 @@ func TestRead_Success(t *testing.T) { demo.RegisterTypes(server.Registry) client := testClient(t, server) - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") require.NoError(t, err) recordLabel, err = server.Backend.WriteCAS(tc.ctx, recordLabel) require.NoError(t, err) diff --git a/agent/grpc-external/services/resource/server.go b/agent/grpc-external/services/resource/server.go index 88237633edb75..5fc5a01fafd77 100644 --- a/agent/grpc-external/services/resource/server.go +++ b/agent/grpc-external/services/resource/server.go @@ -5,7 +5,6 @@ package resource import ( "context" - "strings" "github.com/hashicorp/go-hclog" "google.golang.org/grpc" @@ -35,11 +34,6 @@ type Config struct { // TenancyBridge temporarily allows us to use V1 implementations of // partitions and namespaces until V2 implementations are available. TenancyBridge TenancyBridge - - // UseV2Tenancy is true if the "v2tenancy" experiement is active, false otherwise. - // Attempts to create v2 tenancy resources (partition or namespace) will fail when the - // flag is false. - UseV2Tenancy bool } //go:generate mockery --name Registry --inpackage @@ -135,12 +129,16 @@ func isGRPCStatusError(err error) bool { } func validateId(id *pbresource.ID, errorPrefix string) error { - if id.Type == nil { - return status.Errorf(codes.InvalidArgument, "%s.type is required", errorPrefix) + var field string + switch { + case id.Type == nil: + field = "type" + case id.Name == "": + field = "name" } - if err := resource.ValidateName(id.Name); err != nil { - return status.Errorf(codes.InvalidArgument, "%s.name invalid: %v", errorPrefix, err) + if field != "" { + return status.Errorf(codes.InvalidArgument, "%s.%s is required", errorPrefix, field) } // Better UX: Allow callers to pass in nil tenancy. Defaulting and inheritance of tenancy @@ -154,98 +152,39 @@ func validateId(id *pbresource.ID, errorPrefix string) error { } } - if id.Tenancy.Partition != "" { - if err := resource.ValidateName(id.Tenancy.Partition); err != nil { - return status.Errorf(codes.InvalidArgument, "%s.tenancy.partition invalid: %v", errorPrefix, err) - } - } - if id.Tenancy.Namespace != "" { - if err := resource.ValidateName(id.Tenancy.Namespace); err != nil { - return status.Errorf(codes.InvalidArgument, "%s.tenancy.namespace invalid: %v", errorPrefix, err) - } - } - // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy - if id.Tenancy.PeerName == "" { - id.Tenancy.PeerName = resource.DefaultPeerName - } - - return nil -} - -func validateRef(ref *pbresource.Reference, errorPrefix string) error { - if ref.Type == nil { - return status.Errorf(codes.InvalidArgument, "%s.type is required", errorPrefix) - } - if err := resource.ValidateName(ref.Name); err != nil { - return status.Errorf(codes.InvalidArgument, "%s.name invalid: %v", errorPrefix, err) - } - if err := resource.ValidateName(ref.Tenancy.Partition); err != nil { - return status.Errorf(codes.InvalidArgument, "%s.tenancy.partition invalid: %v", errorPrefix, err) - } - if err := resource.ValidateName(ref.Tenancy.Namespace); err != nil { - return status.Errorf(codes.InvalidArgument, "%s.tenancy.namespace invalid: %v", errorPrefix, err) - } - return nil -} - -func validateWildcardTenancy(tenancy *pbresource.Tenancy, namePrefix string) error { - // Partition has to be a valid name if not wildcard or empty - if tenancy.Partition != "" && tenancy.Partition != "*" { - if err := resource.ValidateName(tenancy.Partition); err != nil { - return status.Errorf(codes.InvalidArgument, "tenancy.partition invalid: %v", err) - } - } - - // Namespace has to be a valid name if not wildcard or empty - if tenancy.Namespace != "" && tenancy.Namespace != "*" { - if err := resource.ValidateName(tenancy.Namespace); err != nil { - return status.Errorf(codes.InvalidArgument, "tenancy.namespace invalid: %v", err) - } - } - - // Not doing a strict resource name validation here because the prefix can be - // something like "foo-" which is a valid prefix but not valid resource name. - // relax validation to just check for lowercasing - if namePrefix != strings.ToLower(namePrefix) { - return status.Errorf(codes.InvalidArgument, "name_prefix invalid: must be lowercase alphanumeric, got: %v", namePrefix) - } - - // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy - if tenancy.PeerName == "" { - tenancy.PeerName = resource.DefaultPeerName - } + resource.Normalize(id.Tenancy) return nil } -// tenancyExists return an error with the passed in gRPC status code when tenancy partition or namespace do not exist. -func tenancyExists(reg *resource.Registration, tenancyBridge TenancyBridge, tenancy *pbresource.Tenancy, errCode codes.Code) error { +// v1TenancyExists return an error with the passed in gRPC status code when tenancy partition or namespace do not exist. +func v1TenancyExists(reg *resource.Registration, v1Bridge TenancyBridge, tenancy *pbresource.Tenancy, errCode codes.Code) error { if reg.Scope == resource.ScopePartition || reg.Scope == resource.ScopeNamespace { - exists, err := tenancyBridge.PartitionExists(tenancy.Partition) + exists, err := v1Bridge.PartitionExists(tenancy.Partition) switch { case err != nil: return err case !exists: - return status.Errorf(errCode, "partition not found: %v", tenancy.Partition) + return status.Errorf(errCode, "partition resource not found: %v", tenancy.Partition) } } if reg.Scope == resource.ScopeNamespace { - exists, err := tenancyBridge.NamespaceExists(tenancy.Partition, tenancy.Namespace) + exists, err := v1Bridge.NamespaceExists(tenancy.Partition, tenancy.Namespace) switch { case err != nil: return err case !exists: - return status.Errorf(errCode, "namespace not found: %v", tenancy.Namespace) + return status.Errorf(errCode, "namespace resource not found: %v", tenancy.Namespace) } } return nil } -// tenancyMarkedForDeletion returns a gRPC InvalidArgument when either partition or namespace is marked for deletion. -func tenancyMarkedForDeletion(reg *resource.Registration, tenancyBridge TenancyBridge, tenancy *pbresource.Tenancy) error { +// v1TenancyMarkedForDeletion returns a gRPC InvalidArgument when either partition or namespace is marked for deletion. +func v1TenancyMarkedForDeletion(reg *resource.Registration, v1Bridge TenancyBridge, tenancy *pbresource.Tenancy) error { if reg.Scope == resource.ScopePartition || reg.Scope == resource.ScopeNamespace { - marked, err := tenancyBridge.IsPartitionMarkedForDeletion(tenancy.Partition) + marked, err := v1Bridge.IsPartitionMarkedForDeletion(tenancy.Partition) switch { case err != nil: return err @@ -255,7 +194,7 @@ func tenancyMarkedForDeletion(reg *resource.Registration, tenancyBridge TenancyB } if reg.Scope == resource.ScopeNamespace { - marked, err := tenancyBridge.IsNamespaceMarkedForDeletion(tenancy.Partition, tenancy.Namespace) + marked, err := v1Bridge.IsNamespaceMarkedForDeletion(tenancy.Partition, tenancy.Namespace) switch { case err != nil: return err diff --git a/agent/grpc-external/services/resource/server_ce.go b/agent/grpc-external/services/resource/server_ce.go index 2e3f792fe1d10..bc48194574131 100644 --- a/agent/grpc-external/services/resource/server_ce.go +++ b/agent/grpc-external/services/resource/server_ce.go @@ -6,13 +6,9 @@ package resource import ( - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" ) func v2TenancyToV1EntMeta(tenancy *pbresource.Tenancy) *acl.EnterpriseMeta { @@ -28,12 +24,3 @@ func v1EntMetaToV2Tenancy(reg *resource.Registration, entMeta *acl.EnterpriseMet tenancy.Namespace = entMeta.NamespaceOrDefault() } } - -// checkV2Tenancy returns FailedPrecondition error for namespace resource type -// when the "v2tenancy" feature flag is not enabled. -func checkV2Tenancy(useV2Tenancy bool, rtype *pbresource.Type) error { - if resource.EqualType(rtype, pbtenancy.NamespaceType) && !useV2Tenancy { - return status.Errorf(codes.FailedPrecondition, "use of the v2 namespace resource requires the \"v2tenancy\" feature flag") - } - return nil -} diff --git a/agent/grpc-external/services/resource/server_test.go b/agent/grpc-external/services/resource/server_test.go index e0b52263901fe..99add64971218 100644 --- a/agent/grpc-external/services/resource/server_test.go +++ b/agent/grpc-external/services/resource/server_test.go @@ -6,6 +6,7 @@ package resource import ( "context" "fmt" + "strings" "testing" "github.com/stretchr/testify/mock" @@ -75,7 +76,7 @@ func testServer(t *testing.T) *Server { } }) - // Mock the tenancy bridge since we can't use the real thing. + // Mock the V1 tenancy bridge since we can't use the real thing. mockTenancyBridge := &MockTenancyBridge{} mockTenancyBridge.On("PartitionExists", resource.DefaultPartitionName).Return(true, nil) mockTenancyBridge.On("NamespaceExists", resource.DefaultPartitionName, resource.DefaultNamespaceName).Return(true, nil) @@ -157,20 +158,19 @@ func wildcardTenancyCases() map[string]struct { PeerName: "local", }, }, - // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy - "namespaced type with empty peername": { + "namespaced type with empty partition and namespace": { typ: demo.TypeV2Artist, tenancy: &pbresource.Tenancy{ - Partition: resource.DefaultPartitionName, - Namespace: resource.DefaultNamespaceName, - PeerName: "", + Partition: "", + Namespace: "", + PeerName: "local", }, }, - "namespaced type with empty partition and namespace": { + "namespaced type with uppercase partition and namespace": { typ: demo.TypeV2Artist, tenancy: &pbresource.Tenancy{ - Partition: "", - Namespace: "", + Partition: "DEFAULT", + Namespace: "DEFAULT", PeerName: "local", }, }, @@ -198,6 +198,14 @@ func wildcardTenancyCases() map[string]struct { PeerName: "local", }, }, + "partitioned type with uppercase partition": { + typ: demo.TypeV1RecordLabel, + tenancy: &pbresource.Tenancy{ + Partition: "DEFAULT", + Namespace: "", + PeerName: "local", + }, + }, "partitioned type with wildcard partition": { typ: demo.TypeV1RecordLabel, tenancy: &pbresource.Tenancy{ @@ -216,6 +224,12 @@ func tenancyCases() map[string]func(artistId, recordlabelId *pbresource.ID) *pbr "namespaced resource provides nonempty partition and namespace": func(artistId, recordLabelId *pbresource.ID) *pbresource.ID { return artistId }, + "namespaced resource provides uppercase partition and namespace": func(artistId, _ *pbresource.ID) *pbresource.ID { + id := clone(artistId) + id.Tenancy.Partition = strings.ToUpper(artistId.Tenancy.Partition) + id.Tenancy.Namespace = strings.ToUpper(artistId.Tenancy.Namespace) + return id + }, "namespaced resource inherits tokens partition when empty": func(artistId, _ *pbresource.ID) *pbresource.ID { id := clone(artistId) id.Tenancy.Partition = "" @@ -240,6 +254,11 @@ func tenancyCases() map[string]func(artistId, recordlabelId *pbresource.ID) *pbr "partitioned resource provides nonempty partition": func(_, recordLabelId *pbresource.ID) *pbresource.ID { return recordLabelId }, + "partitioned resource provides uppercase partition": func(_, recordLabelId *pbresource.ID) *pbresource.ID { + id := clone(recordLabelId) + id.Tenancy.Partition = strings.ToUpper(recordLabelId.Tenancy.Partition) + return id + }, "partitioned resource inherits tokens partition when empty": func(_, recordLabelId *pbresource.ID) *pbresource.ID { id := clone(recordLabelId) id.Tenancy.Partition = "" diff --git a/agent/grpc-external/services/resource/testing/testing.go b/agent/grpc-external/services/resource/testing/testing.go index c9f03bea1a259..2375ae95b8894 100644 --- a/agent/grpc-external/services/resource/testing/testing.go +++ b/agent/grpc-external/services/resource/testing/testing.go @@ -7,12 +7,13 @@ import ( "context" "testing" - "github.com/hashicorp/go-uuid" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl/resolver" svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" @@ -21,7 +22,6 @@ import ( "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/storage/inmem" - "github.com/hashicorp/consul/internal/tenancy" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/sdk/testutil" ) @@ -94,17 +94,10 @@ func RunResourceServiceWithConfig(t *testing.T, config svc.Config, registerFns . mockTenancyBridge.On("PartitionExists", resource.DefaultPartitionName).Return(true, nil) mockTenancyBridge.On("PartitionExists", "foo").Return(true, nil) mockTenancyBridge.On("NamespaceExists", resource.DefaultPartitionName, resource.DefaultNamespaceName).Return(true, nil) - mockTenancyBridge.On("PartitionExists", "foo").Return(true, nil) mockTenancyBridge.On("IsPartitionMarkedForDeletion", resource.DefaultPartitionName).Return(false, nil) mockTenancyBridge.On("IsPartitionMarkedForDeletion", "foo").Return(false, nil) mockTenancyBridge.On("IsNamespaceMarkedForDeletion", resource.DefaultPartitionName, resource.DefaultNamespaceName).Return(false, nil) config.TenancyBridge = mockTenancyBridge - } else { - switch config.TenancyBridge.(type) { - case *tenancy.V2TenancyBridge: - err = initTenancy(ctx, backend) - require.NoError(t, err) - } } if config.ACLResolver == nil { @@ -147,14 +140,6 @@ func RunResourceServiceWithConfig(t *testing.T, config svc.Config, registerFns . ) require.NoError(t, err) t.Cleanup(func() { _ = conn.Close() }) - client := pbresource.NewResourceServiceClient(conn) - if config.TenancyBridge != nil { - switch config.TenancyBridge.(type) { - case *tenancy.V2TenancyBridge: - config.TenancyBridge.(*tenancy.V2TenancyBridge).WithClient(client) - } - - } - return client + return pbresource.NewResourceServiceClient(conn) } diff --git a/agent/grpc-external/services/resource/testing/testing_ce.go b/agent/grpc-external/services/resource/testing/testing_ce.go index da20be3533d44..023fa5189cccc 100644 --- a/agent/grpc-external/services/resource/testing/testing_ce.go +++ b/agent/grpc-external/services/resource/testing/testing_ce.go @@ -6,19 +6,7 @@ package testing import ( - "context" - "errors" - "time" - - "github.com/oklog/ulid/v2" - "google.golang.org/protobuf/types/known/anypb" - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/storage" - "github.com/hashicorp/consul/internal/storage/inmem" - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" ) func FillEntMeta(entMeta *acl.EnterpriseMeta) { @@ -28,38 +16,3 @@ func FillEntMeta(entMeta *acl.EnterpriseMeta) { func FillAuthorizerContext(authzContext *acl.AuthorizerContext) { // nothing to to in CE. } - -// initTenancy create the base tenancy objects (default/default) -func initTenancy(ctx context.Context, b *inmem.Backend) error { - //TODO(dhiaayachi): This is now called for testing purpose but at some point we need to add something similar - // when bootstrapping a server, probably in the tenancy controllers. - nsData, err := anypb.New(&pbtenancy.Namespace{Description: "default namespace in default partition"}) - if err != nil { - return err - } - nsID := &pbresource.ID{ - Type: pbtenancy.NamespaceType, - Name: resource.DefaultNamespaceName, - Tenancy: resource.DefaultPartitionedTenancy(), - Uid: ulid.Make().String(), - } - read, err := b.Read(ctx, storage.StrongConsistency, nsID) - if err != nil && !errors.Is(err, storage.ErrNotFound) { - return err - } - if read == nil && errors.Is(err, storage.ErrNotFound) { - _, err = b.WriteCAS(ctx, &pbresource.Resource{ - Id: nsID, - Generation: ulid.Make().String(), - Data: nsData, - Metadata: map[string]string{ - "generated_at": time.Now().Format(time.RFC3339), - }, - }) - if err != nil { - return err - } - } - return nil - -} diff --git a/agent/grpc-external/services/resource/watch.go b/agent/grpc-external/services/resource/watch.go index a984194ca2062..f20d3f00f875a 100644 --- a/agent/grpc-external/services/resource/watch.go +++ b/agent/grpc-external/services/resource/watch.go @@ -110,13 +110,8 @@ func (s *Server) validateWatchListRequest(req *pbresource.WatchListRequest) (*re return nil, err } - if err = checkV2Tenancy(s.UseV2Tenancy, req.Type); err != nil { - return nil, err - } - - if err := validateWildcardTenancy(req.Tenancy, req.NamePrefix); err != nil { - return nil, err - } + // Lowercase + resource.Normalize(req.Tenancy) // Error when partition scoped and namespace not empty. if reg.Scope == resource.ScopePartition && req.Tenancy.Namespace != "" { diff --git a/agent/grpc-external/services/resource/watch_test.go b/agent/grpc-external/services/resource/watch_test.go index 5e5590d3f9fdc..051264441bbc8 100644 --- a/agent/grpc-external/services/resource/watch_test.go +++ b/agent/grpc-external/services/resource/watch_test.go @@ -7,7 +7,6 @@ import ( "context" "errors" "io" - "strings" "testing" "time" @@ -28,61 +27,24 @@ import ( func TestWatchList_InputValidation(t *testing.T) { server := testServer(t) client := testClient(t, server) - demo.RegisterTypes(server.Registry) - type testCase struct { - modFn func(*pbresource.WatchListRequest) - errContains string - } + demo.RegisterTypes(server.Registry) - testCases := map[string]testCase{ - "no type": { - modFn: func(req *pbresource.WatchListRequest) { req.Type = nil }, - errContains: "type is required", - }, - "no tenancy": { - modFn: func(req *pbresource.WatchListRequest) { req.Tenancy = nil }, - errContains: "tenancy is required", - }, - "partition mixed case": { - modFn: func(req *pbresource.WatchListRequest) { req.Tenancy.Partition = "Default" }, - errContains: "tenancy.partition invalid", - }, - "partition too long": { - modFn: func(req *pbresource.WatchListRequest) { - req.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) - }, - errContains: "tenancy.partition invalid", - }, - "namespace mixed case": { - modFn: func(req *pbresource.WatchListRequest) { req.Tenancy.Namespace = "Default" }, - errContains: "tenancy.namespace invalid", - }, - "namespace too long": { - modFn: func(req *pbresource.WatchListRequest) { - req.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) - }, - errContains: "tenancy.namespace invalid", - }, - "name_prefix mixed case": { - modFn: func(req *pbresource.WatchListRequest) { req.NamePrefix = "Smashing" }, - errContains: "name_prefix invalid", - }, - "partitioned type provides non-empty namespace": { - modFn: func(req *pbresource.WatchListRequest) { - req.Type = demo.TypeV1RecordLabel - req.Tenancy.Namespace = "bad" - }, - errContains: "cannot have a namespace", + testCases := map[string]func(*pbresource.WatchListRequest){ + "no type": func(req *pbresource.WatchListRequest) { req.Type = nil }, + "no tenancy": func(req *pbresource.WatchListRequest) { req.Tenancy = nil }, + "partitioned type provides non-empty namespace": func(req *pbresource.WatchListRequest) { + req.Type = demo.TypeV1RecordLabel + req.Tenancy.Namespace = "bad" }, } - for desc, tc := range testCases { + for desc, modFn := range testCases { t.Run(desc, func(t *testing.T) { req := &pbresource.WatchListRequest{ Type: demo.TypeV2Album, Tenancy: resource.DefaultNamespacedTenancy(), } - tc.modFn(req) + modFn(req) stream, err := client.WatchList(testContext(t), req) require.NoError(t, err) @@ -90,7 +52,6 @@ func TestWatchList_InputValidation(t *testing.T) { _, err = stream.Recv() require.Error(t, err) require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) - require.ErrorContains(t, err, tc.errContains) }) } } @@ -175,7 +136,7 @@ func TestWatchList_Tenancy_Defaults_And_Normalization(t *testing.T) { rspCh := handleResourceStream(t, stream) // Testcase will pick one of recordLabel or artist based on scope of type. - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LooneyTunes") require.NoError(t, err) artist, err := demo.GenerateV2Artist() require.NoError(t, err) diff --git a/agent/grpc-external/services/resource/write.go b/agent/grpc-external/services/resource/write.go index 7b1bd8a73d8f5..7110122313fa3 100644 --- a/agent/grpc-external/services/resource/write.go +++ b/agent/grpc-external/services/resource/write.go @@ -78,13 +78,13 @@ func (s *Server) Write(ctx context.Context, req *pbresource.WriteRequest) (*pbre return nil, status.Errorf(codes.Internal, "failed write acl: %v", err) } - // Check tenancy exists for the V2 resource - if err = tenancyExists(reg, s.TenancyBridge, req.Resource.Id.Tenancy, codes.InvalidArgument); err != nil { + // Check V1 tenancy exists for the V2 resource + if err = v1TenancyExists(reg, s.TenancyBridge, req.Resource.Id.Tenancy, codes.InvalidArgument); err != nil { return nil, err } - // Check tenancy not marked for deletion. - if err = tenancyMarkedForDeletion(reg, s.TenancyBridge, req.Resource.Id.Tenancy); err != nil { + // Check V1 tenancy not marked for deletion. + if err = v1TenancyMarkedForDeletion(reg, s.TenancyBridge, req.Resource.Id.Tenancy); err != nil { return nil, err } @@ -294,10 +294,6 @@ func (s *Server) validateWriteRequest(req *pbresource.WriteRequest) (*resource.R return nil, err } - if err = checkV2Tenancy(s.UseV2Tenancy, req.Resource.Id.Type); err != nil { - return nil, err - } - // Check scope if reg.Scope == resource.ScopePartition && req.Resource.Id.Tenancy.Namespace != "" { return nil, status.Errorf( diff --git a/agent/grpc-external/services/resource/write_status.go b/agent/grpc-external/services/resource/write_status.go index 7009a7fd72bb2..0d3b68bb08766 100644 --- a/agent/grpc-external/services/resource/write_status.go +++ b/agent/grpc-external/services/resource/write_status.go @@ -34,9 +34,9 @@ func (s *Server) WriteStatus(ctx context.Context, req *pbresource.WriteStatusReq // Apply defaults when tenancy units empty. v1EntMetaToV2Tenancy(reg, entMeta, req.Id.Tenancy) - // Check tenancy exists for the V2 resource. Ignore "marked for deletion" since status updates + // Check V1 tenancy exists for the V2 resource. Ignore "marked for deletion" since status updates // should still work regardless. - if err = tenancyExists(reg, s.TenancyBridge, req.Id.Tenancy, codes.InvalidArgument); err != nil { + if err = v1TenancyExists(reg, s.TenancyBridge, req.Id.Tenancy, codes.InvalidArgument); err != nil { return nil, err } @@ -178,17 +178,8 @@ func (s *Server) validateWriteStatusRequest(req *pbresource.WriteStatusRequest) } } - if err := validateId(req.Id, "id"); err != nil { - return nil, err - } - - for i, condition := range req.Status.Conditions { - if condition.Resource != nil { - if err := validateRef(condition.Resource, fmt.Sprintf("status.conditions[%d].resource", i)); err != nil { - return nil, err - } - } - } + // Lowercase + resource.Normalize(req.Id.Tenancy) // Check type exists. reg, err := s.resolveType(req.Id.Type) diff --git a/agent/grpc-external/services/resource/write_status_test.go b/agent/grpc-external/services/resource/write_status_test.go index 1ddf738632365..5b71983475d94 100644 --- a/agent/grpc-external/services/resource/write_status_test.go +++ b/agent/grpc-external/services/resource/write_status_test.go @@ -74,155 +74,64 @@ func TestWriteStatus_InputValidation(t *testing.T) { demo.RegisterTypes(server.Registry) testCases := map[string]struct { - typ *pbresource.Type - modFn func(req *pbresource.WriteStatusRequest) - errContains string + typ *pbresource.Type + modFn func(req *pbresource.WriteStatusRequest) }{ "no id": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id = nil }, - errContains: "id is required", + typ: demo.TypeV2Artist, + modFn: func(req *pbresource.WriteStatusRequest) { req.Id = nil }, }, "no type": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Type = nil }, - errContains: "id.type is required", + typ: demo.TypeV2Artist, + modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Type = nil }, }, "no name": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Name = "" }, - errContains: "id.name is required", + typ: demo.TypeV2Artist, + modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Name = "" }, }, "no uid": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Uid = "" }, - errContains: "id.uid is required", - }, - "name mixed case": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Name = "U2" }, - errContains: "id.name invalid", - }, - "name too long": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { - req.Id.Name = strings.Repeat("a", resource.MaxNameLength+1) - }, - errContains: "id.name invalid", - }, - "partition mixed case": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Partition = "Default" }, - errContains: "id.tenancy.partition invalid", - }, - "partition too long": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { - req.Id.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) - }, - errContains: "id.tenancy.partition invalid", - }, - "namespace mixed case": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Namespace = "Default" }, - errContains: "id.tenancy.namespace invalid", - }, - "namespace too long": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { - req.Id.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) - }, - errContains: "id.tenancy.namespace invalid", + typ: demo.TypeV2Artist, + modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Uid = "" }, }, "no key": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Key = "" }, - errContains: "key is required", + typ: demo.TypeV2Artist, + modFn: func(req *pbresource.WriteStatusRequest) { req.Key = "" }, }, "no status": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Status = nil }, - errContains: "status is required", + typ: demo.TypeV2Artist, + modFn: func(req *pbresource.WriteStatusRequest) { req.Status = nil }, }, "no observed generation": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Status.ObservedGeneration = "" }, - errContains: "status.observed_generation is required", + typ: demo.TypeV2Artist, + modFn: func(req *pbresource.WriteStatusRequest) { req.Status.ObservedGeneration = "" }, }, "bad observed generation": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Status.ObservedGeneration = "bogus" }, - errContains: "status.observed_generation is not valid", + typ: demo.TypeV2Artist, + modFn: func(req *pbresource.WriteStatusRequest) { req.Status.ObservedGeneration = "bogus" }, }, "no condition type": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Status.Conditions[0].Type = "" }, - errContains: "status.conditions[0].type is required", + typ: demo.TypeV2Artist, + modFn: func(req *pbresource.WriteStatusRequest) { req.Status.Conditions[0].Type = "" }, }, "no reference type": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Status.Conditions[0].Resource.Type = nil }, - errContains: "status.conditions[0].resource.type is required", + typ: demo.TypeV2Artist, + modFn: func(req *pbresource.WriteStatusRequest) { req.Status.Conditions[0].Resource.Type = nil }, }, "no reference tenancy": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Status.Conditions[0].Resource.Tenancy = nil }, - errContains: "status.conditions[0].resource.tenancy is required", + typ: demo.TypeV2Artist, + modFn: func(req *pbresource.WriteStatusRequest) { req.Status.Conditions[0].Resource.Tenancy = nil }, }, "no reference name": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Status.Conditions[0].Resource.Name = "" }, - errContains: "status.conditions[0].resource.name is required", - }, - "reference name mixed case": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Status.Conditions[0].Resource.Name = "U2" }, - errContains: "status.conditions[0].resource.name invalid", - }, - "reference name too long": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { - req.Status.Conditions[0].Resource.Name = strings.Repeat("r", resource.MaxNameLength+1) - }, - errContains: "status.conditions[0].resource.name invalid", - }, - "reference partition mixed case": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { - req.Status.Conditions[0].Resource.Tenancy.Partition = "Default" - }, - errContains: "status.conditions[0].resource.tenancy.partition invalid", - }, - "reference partition too long": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { - req.Status.Conditions[0].Resource.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) - }, - errContains: "status.conditions[0].resource.tenancy.partition invalid", - }, - "reference namespace mixed case": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { - req.Status.Conditions[0].Resource.Tenancy.Namespace = "Default" - }, - errContains: "status.conditions[0].resource.tenancy.namespace invalid", - }, - "reference namespace too long": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { - req.Status.Conditions[0].Resource.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) - }, - errContains: "status.conditions[0].resource.tenancy.namespace invalid", + typ: demo.TypeV2Artist, + modFn: func(req *pbresource.WriteStatusRequest) { req.Status.Conditions[0].Resource.Name = "" }, }, "updated at provided": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Status.UpdatedAt = timestamppb.Now() }, - errContains: "status.updated_at is automatically set and cannot be provided", + typ: demo.TypeV2Artist, + modFn: func(req *pbresource.WriteStatusRequest) { req.Status.UpdatedAt = timestamppb.Now() }, }, "partition scoped type provides namespace in tenancy": { - typ: demo.TypeV1RecordLabel, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Namespace = "bad" }, - errContains: "cannot have a namespace", + typ: demo.TypeV1RecordLabel, + modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Namespace = "bad" }, }, } for desc, tc := range testCases { @@ -233,7 +142,7 @@ func TestWriteStatus_InputValidation(t *testing.T) { case resource.EqualType(demo.TypeV2Artist, tc.typ): res, err = demo.GenerateV2Artist() case resource.EqualType(demo.TypeV1RecordLabel, tc.typ): - res, err = demo.GenerateV1RecordLabel("looney-tunes") + res, err = demo.GenerateV1RecordLabel("Looney Tunes") default: t.Fatal("unsupported type", tc.typ) } @@ -248,7 +157,6 @@ func TestWriteStatus_InputValidation(t *testing.T) { _, err = client.WriteStatus(testContext(t), req) require.Error(t, err) require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) - require.ErrorContains(t, err, tc.errContains) }) } } @@ -302,6 +210,13 @@ func TestWriteStatus_Tenancy_Defaults(t *testing.T) { scope: resource.ScopeNamespace, modFn: func(req *pbresource.WriteStatusRequest) {}, }, + "namespaced resource provides uppercase partition and namespace": { + scope: resource.ScopeNamespace, + modFn: func(req *pbresource.WriteStatusRequest) { + req.Id.Tenancy.Partition = strings.ToUpper(req.Id.Tenancy.Partition) + req.Id.Tenancy.Namespace = strings.ToUpper(req.Id.Tenancy.Namespace) + }, + }, "namespaced resource inherits tokens partition when empty": { scope: resource.ScopeNamespace, modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Partition = "" }, @@ -325,6 +240,12 @@ func TestWriteStatus_Tenancy_Defaults(t *testing.T) { scope: resource.ScopePartition, modFn: func(req *pbresource.WriteStatusRequest) {}, }, + "partitioned resource provides uppercase partition": { + scope: resource.ScopePartition, + modFn: func(req *pbresource.WriteStatusRequest) { + req.Id.Tenancy.Partition = strings.ToUpper(req.Id.Tenancy.Partition) + }, + }, "partitioned resource inherits tokens partition when empty": { scope: resource.ScopePartition, modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Partition = "" }, @@ -342,7 +263,7 @@ func TestWriteStatus_Tenancy_Defaults(t *testing.T) { case resource.ScopeNamespace: res, err = demo.GenerateV2Artist() case resource.ScopePartition: - res, err = demo.GenerateV1RecordLabel("looney-tunes") + res, err = demo.GenerateV1RecordLabel("Looney Tunes") } require.NoError(t, err) @@ -359,7 +280,7 @@ func TestWriteStatus_Tenancy_Defaults(t *testing.T) { require.NoError(t, err) res = rsp.Resource - // Re-read resource and verify status successfully written (not nil) + // Re-read resoruce and verify status successfully written (not nil) _, err = client.Read(testContext(t), &pbresource.ReadRequest{Id: res.Id}) require.NoError(t, err) res = rsp.Resource @@ -406,7 +327,7 @@ func TestWriteStatus_Tenancy_NotFound(t *testing.T) { case resource.ScopeNamespace: res, err = demo.GenerateV2Artist() case resource.ScopePartition: - res, err = demo.GenerateV1RecordLabel("looney-tunes") + res, err = demo.GenerateV1RecordLabel("Looney Tunes") } require.NoError(t, err) diff --git a/agent/grpc-external/services/resource/write_test.go b/agent/grpc-external/services/resource/write_test.go index 9f7704b52b97c..3828ff9753f2d 100644 --- a/agent/grpc-external/services/resource/write_test.go +++ b/agent/grpc-external/services/resource/write_test.go @@ -29,123 +29,54 @@ import ( func TestWrite_InputValidation(t *testing.T) { server := testServer(t) client := testClient(t, server) - demo.RegisterTypes(server.Registry) - type testCase struct { - modFn func(artist, recordLabel *pbresource.Resource) *pbresource.Resource - errContains string - } + demo.RegisterTypes(server.Registry) - testCases := map[string]testCase{ - "no resource": { - modFn: func(_, _ *pbresource.Resource) *pbresource.Resource { - return nil - }, - errContains: "resource is required", - }, - "no id": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id = nil - return artist - }, - errContains: "resource.id is required", - }, - "no type": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Type = nil - return artist - }, - errContains: "resource.id.type is required", - }, - "no name": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Name = "" - return artist - }, - errContains: "resource.id.name invalid", - }, - "name is mixed case": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Name = "MixedCaseNotAllowed" - return artist - }, - errContains: "resource.id.name invalid", + testCases := map[string]func(artist, recordLabel *pbresource.Resource) *pbresource.Resource{ + "no resource": func(artist, recordLabel *pbresource.Resource) *pbresource.Resource { return nil }, + "no id": func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id = nil + return artist }, - "name too long": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Name = strings.Repeat("a", resource.MaxNameLength+1) - return artist - }, - errContains: "resource.id.name invalid", - }, - "wrong data type": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - var err error - artist.Data, err = anypb.New(&pbdemov2.Album{}) - require.NoError(t, err) - return artist - }, - errContains: "resource.data is of wrong type", - }, - "partition is mixed case": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Partition = "Default" - return artist - }, - errContains: "resource.id.tenancy.partition invalid", - }, - "partition too long": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) - return artist - }, - errContains: "resource.id.tenancy.partition invalid", + "no type": func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Type = nil + return artist }, - "namespace is mixed case": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Namespace = "Default" - return artist - }, - errContains: "resource.id.tenancy.namespace invalid", + "no name": func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Name = "" + return artist }, - "namespace too long": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) - return artist - }, - errContains: "resource.id.tenancy.namespace invalid", + "wrong data type": func(artist, _ *pbresource.Resource) *pbresource.Resource { + var err error + artist.Data, err = anypb.New(&pbdemov2.Album{}) + require.NoError(t, err) + return artist }, - "fail validation hook": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - buffer := &pbdemov2.Artist{} - require.NoError(t, artist.Data.UnmarshalTo(buffer)) - buffer.Name = "" // name cannot be empty - require.NoError(t, artist.Data.MarshalFrom(buffer)) - return artist - }, - errContains: "artist.name required", + "fail validation hook": func(artist, _ *pbresource.Resource) *pbresource.Resource { + buffer := &pbdemov2.Artist{} + require.NoError(t, artist.Data.UnmarshalTo(buffer)) + buffer.Name = "" // name cannot be empty + require.NoError(t, artist.Data.MarshalFrom(buffer)) + return artist }, - "partition scope with non-empty namespace": { - modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { - recordLabel.Id.Tenancy.Namespace = "bogus" - return recordLabel - }, - errContains: "cannot have a namespace", + "partition scope with non-empty namespace": func(_, recordLabel *pbresource.Resource) *pbresource.Resource { + recordLabel.Id.Tenancy.Namespace = "bogus" + return recordLabel }, + // TODO(spatel): add cluster scope tests when we have an actual cluster scoped resource (e.g. partition) } - for desc, tc := range testCases { + for desc, modFn := range testCases { t.Run(desc, func(t *testing.T) { artist, err := demo.GenerateV2Artist() require.NoError(t, err) - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") require.NoError(t, err) - req := &pbresource.WriteRequest{Resource: tc.modFn(artist, recordLabel)} + req := &pbresource.WriteRequest{Resource: modFn(artist, recordLabel)} _, err = client.Write(testContext(t), req) require.Error(t, err) require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) - require.ErrorContains(t, err, tc.errContains) }) } } @@ -153,6 +84,7 @@ func TestWrite_InputValidation(t *testing.T) { func TestWrite_OwnerValidation(t *testing.T) { server := testServer(t) client := testClient(t, server) + demo.RegisterTypes(server.Registry) type testCase struct { @@ -162,49 +94,15 @@ func TestWrite_OwnerValidation(t *testing.T) { testCases := map[string]testCase{ "no owner type": { modReqFn: func(req *pbresource.WriteRequest) { req.Resource.Owner.Type = nil }, - errorContains: "resource.owner.type is required", + errorContains: "resource.owner.type", }, "no owner tenancy": { modReqFn: func(req *pbresource.WriteRequest) { req.Resource.Owner.Tenancy = nil }, - errorContains: "resource.owner does not exist", + errorContains: "resource.owner", }, "no owner name": { modReqFn: func(req *pbresource.WriteRequest) { req.Resource.Owner.Name = "" }, - errorContains: "resource.owner.name invalid", - }, - "mixed case owner name": { - modReqFn: func(req *pbresource.WriteRequest) { req.Resource.Owner.Name = strings.ToUpper(req.Resource.Owner.Name) }, - errorContains: "resource.owner.name invalid", - }, - "owner name too long": { - modReqFn: func(req *pbresource.WriteRequest) { - req.Resource.Owner.Name = strings.Repeat("a", resource.MaxNameLength+1) - }, - errorContains: "resource.owner.name invalid", - }, - "owner partition is mixed case": { - modReqFn: func(req *pbresource.WriteRequest) { - req.Resource.Owner.Tenancy.Partition = "Default" - }, - errorContains: "resource.owner.tenancy.partition invalid", - }, - "owner partition too long": { - modReqFn: func(req *pbresource.WriteRequest) { - req.Resource.Owner.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) - }, - errorContains: "resource.owner.tenancy.partition invalid", - }, - "owner namespace is mixed case": { - modReqFn: func(req *pbresource.WriteRequest) { - req.Resource.Owner.Tenancy.Namespace = "Default" - }, - errorContains: "resource.owner.tenancy.namespace invalid", - }, - "owner namespace too long": { - modReqFn: func(req *pbresource.WriteRequest) { - req.Resource.Owner.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) - }, - errorContains: "resource.owner.tenancy.namespace invalid", + errorContains: "resource.owner.name", }, } for desc, tc := range testCases { @@ -317,6 +215,14 @@ func TestWrite_Create_Success(t *testing.T) { }, expectedTenancy: resource.DefaultNamespacedTenancy(), }, + "namespaced resource provides uppercase partition and namespace": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Tenancy.Partition = strings.ToUpper(artist.Id.Tenancy.Partition) + artist.Id.Tenancy.Namespace = strings.ToUpper(artist.Id.Tenancy.Namespace) + return artist + }, + expectedTenancy: resource.DefaultNamespacedTenancy(), + }, "namespaced resource inherits tokens partition when empty": { modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { artist.Id.Tenancy.Partition = "" @@ -360,6 +266,13 @@ func TestWrite_Create_Success(t *testing.T) { }, expectedTenancy: resource.DefaultPartitionedTenancy(), }, + "partitioned resource provides uppercase partition": { + modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { + recordLabel.Id.Tenancy.Partition = strings.ToUpper(recordLabel.Id.Tenancy.Partition) + return recordLabel + }, + expectedTenancy: resource.DefaultPartitionedTenancy(), + }, "partitioned resource inherits tokens partition when empty": { modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { recordLabel.Id.Tenancy.Partition = "" @@ -390,7 +303,7 @@ func TestWrite_Create_Success(t *testing.T) { client := testClient(t, server) demo.RegisterTypes(server.Registry) - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") require.NoError(t, err) artist, err := demo.GenerateV2Artist() @@ -418,7 +331,7 @@ func TestWrite_Create_Tenancy_NotFound(t *testing.T) { return artist }, errCode: codes.InvalidArgument, - errContains: "partition not found", + errContains: "partition", }, "namespaced resource provides nonexistant namespace": { modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { @@ -426,7 +339,7 @@ func TestWrite_Create_Tenancy_NotFound(t *testing.T) { return artist }, errCode: codes.InvalidArgument, - errContains: "namespace not found", + errContains: "namespace", }, "partitioned resource provides nonexistant partition": { modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { @@ -434,7 +347,7 @@ func TestWrite_Create_Tenancy_NotFound(t *testing.T) { return recordLabel }, errCode: codes.InvalidArgument, - errContains: "partition not found", + errContains: "partition", }, } for desc, tc := range testCases { @@ -443,7 +356,7 @@ func TestWrite_Create_Tenancy_NotFound(t *testing.T) { client := testClient(t, server) demo.RegisterTypes(server.Registry) - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") require.NoError(t, err) artist, err := demo.GenerateV2Artist() @@ -465,22 +378,22 @@ func TestWrite_Tenancy_MarkedForDeletion(t *testing.T) { }{ "namespaced resources partition marked for deletion": { modFn: func(artist, _ *pbresource.Resource, mockTenancyBridge *MockTenancyBridge) *pbresource.Resource { - mockTenancyBridge.On("IsPartitionMarkedForDeletion", "ap1").Return(true, nil) + mockTenancyBridge.On("IsPartitionMarkedForDeletion", "part1").Return(true, nil) return artist }, errContains: "partition marked for deletion", }, "namespaced resources namespace marked for deletion": { modFn: func(artist, _ *pbresource.Resource, mockTenancyBridge *MockTenancyBridge) *pbresource.Resource { - mockTenancyBridge.On("IsPartitionMarkedForDeletion", "ap1").Return(false, nil) - mockTenancyBridge.On("IsNamespaceMarkedForDeletion", "ap1", "ns1").Return(true, nil) + mockTenancyBridge.On("IsPartitionMarkedForDeletion", "part1").Return(false, nil) + mockTenancyBridge.On("IsNamespaceMarkedForDeletion", "part1", "ns1").Return(true, nil) return artist }, errContains: "namespace marked for deletion", }, "partitioned resources partition marked for deletion": { modFn: func(_, recordLabel *pbresource.Resource, mockTenancyBridge *MockTenancyBridge) *pbresource.Resource { - mockTenancyBridge.On("IsPartitionMarkedForDeletion", "ap1").Return(true, nil) + mockTenancyBridge.On("IsPartitionMarkedForDeletion", "part1").Return(true, nil) return recordLabel }, errContains: "partition marked for deletion", @@ -491,18 +404,18 @@ func TestWrite_Tenancy_MarkedForDeletion(t *testing.T) { server := testServer(t) client := testClient(t, server) demo.RegisterTypes(server.Registry) - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") require.NoError(t, err) - recordLabel.Id.Tenancy.Partition = "ap1" + recordLabel.Id.Tenancy.Partition = "part1" artist, err := demo.GenerateV2Artist() require.NoError(t, err) - artist.Id.Tenancy.Partition = "ap1" + artist.Id.Tenancy.Partition = "part1" artist.Id.Tenancy.Namespace = "ns1" mockTenancyBridge := &MockTenancyBridge{} - mockTenancyBridge.On("PartitionExists", "ap1").Return(true, nil) - mockTenancyBridge.On("NamespaceExists", "ap1", "ns1").Return(true, nil) + mockTenancyBridge.On("PartitionExists", "part1").Return(true, nil) + mockTenancyBridge.On("NamespaceExists", "part1", "ns1").Return(true, nil) server.TenancyBridge = mockTenancyBridge _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: tc.modFn(artist, recordLabel, mockTenancyBridge)}) diff --git a/agent/structs/structs.go b/agent/structs/structs.go index 9b2685946cbeb..5a6fd95118920 100644 --- a/agent/structs/structs.go +++ b/agent/structs/structs.go @@ -10,7 +10,6 @@ import ( "encoding/json" "fmt" "math/rand" - "os" "reflect" "regexp" "sort" @@ -228,9 +227,6 @@ const ( var allowedConsulMetaKeysForMeshGateway = map[string]struct{}{MetaWANFederationKey: {}} -// CEDowngrade indicates if we are in downgrading from ent to ce -var CEDowngrade = os.Getenv("CONSUL_ENTERPRISE_DOWNGRADE_TO_CE") == "true" - var ( NodeMaintCheckID = NewCheckID(NodeMaint, nil) ) diff --git a/agent/xdsv2/resources_test.go b/agent/xdsv2/resources_test.go index 433295f9c8970..c1afbda705be8 100644 --- a/agent/xdsv2/resources_test.go +++ b/agent/xdsv2/resources_test.go @@ -54,16 +54,17 @@ func TestAllResourcesFromIR_XDSGoldenFileInputs(t *testing.T) { "destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy", //sources - please add in alphabetical order - "source/l4-multiple-workload-addresses-with-specific-ports", - "source/l4-multiple-workload-addresses-without-ports", - "source/l4-single-workload-address-without-ports", - "source/l7-expose-paths", - "source/local-and-inbound-connections", - "source/multiport-l4-multiple-workload-addresses-with-specific-ports", - "source/multiport-l4-multiple-workload-addresses-without-ports", - "source/multiport-l4-workload-with-only-mesh-port", - "source/multiport-l7-multiple-workload-addresses-with-specific-ports", - "source/multiport-l7-multiple-workload-addresses-without-ports", + //"source/l4-multiple-workload-addresses-with-specific-ports", + //"source/l4-multiple-workload-addresses-without-ports", + //"source/l4-single-workload-address-without-ports", + //"source/l7-expose-paths", + //"source/local-and-inbound-connections", + //"source/multiport-l4-multiple-workload-addresses-with-specific-ports", + //"source/multiport-l4-multiple-workload-addresses-without-ports", + //"source/multiport-l4-workload-with-only-mesh-port", + //"source/multiport-l7-multiple-workload-addresses-with-specific-ports", + //"source/multiport-l7-multiple-workload-addresses-without-ports", + //"source/multiport-l7-multiple-workload-addresses-without-ports", } for _, name := range cases { diff --git a/command/resource/delete/delete.go b/command/resource/delete/delete.go index 06421d6d1e2d7..2679951da8b16 100644 --- a/command/resource/delete/delete.go +++ b/command/resource/delete/delete.go @@ -84,6 +84,10 @@ func (c *cmd) Run(args []string) int { return 1 } } else { + if len(args) < 2 { + c.UI.Error("Incorrect argument format: Must specify two arguments: resource type and resource name") + return 1 + } var err error gvk, resourceName, err = resource.GetTypeAndResourceName(args) if err != nil { diff --git a/command/resource/delete/delete_test.go b/command/resource/delete/delete_test.go index 7454455c941e6..f888bb3c8fd52 100644 --- a/command/resource/delete/delete_test.go +++ b/command/resource/delete/delete_test.go @@ -67,7 +67,7 @@ func TestResourceDeleteInvalidArgs(t *testing.T) { "invalid resource type format": { args: []string{"a.", "name", "-namespace", "default"}, expectedCode: 1, - expectedErr: errors.New("Must provide resource type argument with either in group.verion.kind format or its shorthand name"), + expectedErr: errors.New("Incorrect argument format: Must include resource type argument in group.verion.kind format"), }, } diff --git a/command/resource/helper.go b/command/resource/helper.go index 221a018599a77..417144ac78969 100644 --- a/command/resource/helper.go +++ b/command/resource/helper.go @@ -96,7 +96,21 @@ func parseJson(js string) (*pbresource.Resource, error) { } func ParseResourceFromFile(filePath string) (*pbresource.Resource, error) { - return ParseResourceInput(filePath, nil) + data, err := helpers.LoadDataSourceNoRaw(filePath, nil) + if err != nil { + return nil, fmt.Errorf("Failed to load data: %v", err) + } + var parsedResource *pbresource.Resource + if isHCL([]byte(data)) { + parsedResource, err = resourcehcl.Unmarshal([]byte(data), consul.NewTypeRegistry()) + } else { + parsedResource, err = parseJson(data) + } + if err != nil { + return nil, fmt.Errorf("Failed to decode resource from input file: %v", err) + } + + return parsedResource, nil } // this is an inlined variant of hcl.lexMode() @@ -151,17 +165,23 @@ func ParseInputParams(inputArgs []string, flags *flag.FlagSet) error { } func GetTypeAndResourceName(args []string) (gvk *GVK, resourceName string, e error) { - if len(args) < 2 { - return nil, "", fmt.Errorf("Must specify two arguments: resource type and resource name") - } // it has to be resource name after the type if strings.HasPrefix(args[1], "-") { return nil, "", fmt.Errorf("Must provide resource name right after type") } - resourceName = args[1] - gvk, e = inferGVKFromResourceType(args[0]) + s := strings.Split(args[0], ".") + if len(s) != 3 { + return nil, "", fmt.Errorf("Must include resource type argument in group.verion.kind format") + } + + gvk = &GVK{ + Group: s[0], + Version: s[1], + Kind: s[2], + } + resourceName = args[1] return } @@ -262,54 +282,3 @@ func (resource *Resource) List(gvk *GVK, q *client.QueryOptions) (*ListResponse, return out, nil } - -func inferGVKFromResourceType(resourceType string) (*GVK, error) { - s := strings.Split(resourceType, ".") - switch length := len(s); { - // only kind is provided - case length == 1: - kindToGVKMap := BuildKindToGVKMap() - kind := strings.ToLower(s[0]) - switch len(kindToGVKMap[kind]) { - // no g.v.k is found - case 0: - return nil, fmt.Errorf("The shorthand name does not map to any existing resource type, please check `consul api-resources`") - // only one is found - case 1: - // infer gvk from resource kind - gvkSplit := strings.Split(kindToGVKMap[kind][0], ".") - return &GVK{ - Group: gvkSplit[0], - Version: gvkSplit[1], - Kind: gvkSplit[2], - }, nil - // it alerts error if any conflict is found - default: - return nil, fmt.Errorf("The shorthand name has conflicts %v, please use the full name", kindToGVKMap[s[0]]) - } - case length == 3: - return &GVK{ - Group: s[0], - Version: s[1], - Kind: s[2], - }, nil - default: - return nil, fmt.Errorf("Must provide resource type argument with either in group.verion.kind format or its shorthand name") - } -} - -func BuildKindToGVKMap() map[string][]string { - // this use the local copy of registration to build map - typeRegistry := consul.NewTypeRegistry() - kindToGVKMap := map[string][]string{} - for _, r := range typeRegistry.Types() { - gvkString := fmt.Sprintf("%s.%s.%s", r.Type.Group, r.Type.GroupVersion, r.Type.Kind) - kindKey := strings.ToLower(r.Type.Kind) - if len(kindToGVKMap[kindKey]) == 0 { - kindToGVKMap[kindKey] = []string{gvkString} - } else { - kindToGVKMap[kindKey] = append(kindToGVKMap[kindKey], gvkString) - } - } - return kindToGVKMap -} diff --git a/command/resource/read/read_test.go b/command/resource/read/read_test.go index a293a9faf5e20..766f86b02cc19 100644 --- a/command/resource/read/read_test.go +++ b/command/resource/read/read_test.go @@ -67,7 +67,7 @@ func TestResourceReadInvalidArgs(t *testing.T) { "invalid resource type format": { args: []string{"a.", "name", "-namespace", "default"}, expectedCode: 1, - expectedErr: errors.New("Incorrect argument format: Must provide resource type argument with either in group.verion.kind format or its shorthand name"), + expectedErr: errors.New("Incorrect argument format: Must include resource type argument in group.verion.kind format"), }, } diff --git a/internal/auth/internal/types/computed_traffic_permissions.go b/internal/auth/internal/types/computed_traffic_permissions.go index 800d2a8fb66f4..0a32e13d29267 100644 --- a/internal/auth/internal/types/computed_traffic_permissions.go +++ b/internal/auth/internal/types/computed_traffic_permissions.go @@ -12,8 +12,6 @@ import ( "github.com/hashicorp/consul/proto-public/pbresource" ) -type DecodedComputedTrafficPermissions = resource.DecodedResource[*pbauth.ComputedTrafficPermissions] - func RegisterComputedTrafficPermission(r resource.Registry) { r.Register(resource.Registration{ Type: pbauth.ComputedTrafficPermissionsType, @@ -28,12 +26,16 @@ func RegisterComputedTrafficPermission(r resource.Registry) { }) } -var ValidateComputedTrafficPermissions = resource.DecodeAndValidate(validateComputedTrafficPermissions) +func ValidateComputedTrafficPermissions(res *pbresource.Resource) error { + var ctp pbauth.ComputedTrafficPermissions + + if err := res.Data.UnmarshalTo(&ctp); err != nil { + return resource.NewErrDataParse(&ctp, err) + } -func validateComputedTrafficPermissions(res *DecodedComputedTrafficPermissions) error { var merr error - for i, permission := range res.Data.AllowPermissions { + for i, permission := range ctp.AllowPermissions { wrapErr := func(err error) error { return resource.ErrInvalidListElement{ Name: "allow_permissions", @@ -46,7 +48,7 @@ func validateComputedTrafficPermissions(res *DecodedComputedTrafficPermissions) } } - for i, permission := range res.Data.DenyPermissions { + for i, permission := range ctp.DenyPermissions { wrapErr := func(err error) error { return resource.ErrInvalidListElement{ Name: "deny_permissions", diff --git a/internal/auth/internal/types/traffic_permissions.go b/internal/auth/internal/types/traffic_permissions.go index bf22fdb0b5fab..78d53c70c6288 100644 --- a/internal/auth/internal/types/traffic_permissions.go +++ b/internal/auth/internal/types/traffic_permissions.go @@ -12,15 +12,13 @@ import ( "github.com/hashicorp/consul/proto-public/pbresource" ) -type DecodedTrafficPermissions = resource.DecodedResource[*pbauth.TrafficPermissions] - func RegisterTrafficPermissions(r resource.Registry) { r.Register(resource.Registration{ Type: pbauth.TrafficPermissionsType, Proto: &pbauth.TrafficPermissions{}, ACLs: &resource.ACLHooks{ - Read: resource.DecodeAndAuthorizeRead(aclReadHookTrafficPermissions), - Write: resource.DecodeAndAuthorizeWrite(aclWriteHookTrafficPermissions), + Read: aclReadHookTrafficPermissions, + Write: aclWriteHookTrafficPermissions, List: resource.NoOpACLListHook, }, Validate: ValidateTrafficPermissions, @@ -29,12 +27,16 @@ func RegisterTrafficPermissions(r resource.Registry) { }) } -var MutateTrafficPermissions = resource.DecodeAndMutate(mutateTrafficPermissions) +func MutateTrafficPermissions(res *pbresource.Resource) error { + var tp pbauth.TrafficPermissions + + if err := res.Data.UnmarshalTo(&tp); err != nil { + return resource.NewErrDataParse(&tp, err) + } -func mutateTrafficPermissions(res *DecodedTrafficPermissions) (bool, error) { var changed bool - for _, p := range res.Data.Permissions { + for _, p := range tp.Permissions { for _, s := range p.Sources { if updated := normalizedTenancyForSource(s, res.Id.Tenancy); updated { changed = true @@ -42,7 +44,11 @@ func mutateTrafficPermissions(res *DecodedTrafficPermissions) (bool, error) { } } - return changed, nil + if !changed { + return nil + } + + return res.Data.MarshalFrom(&tp) } func normalizedTenancyForSource(src *pbauth.Source, parentTenancy *pbresource.Tenancy) bool { @@ -104,13 +110,17 @@ func firstNonEmptyString(a, b, c string) (string, bool) { return c, true } -var ValidateTrafficPermissions = resource.DecodeAndValidate(validateTrafficPermissions) +func ValidateTrafficPermissions(res *pbresource.Resource) error { + var tp pbauth.TrafficPermissions + + if err := res.Data.UnmarshalTo(&tp); err != nil { + return resource.NewErrDataParse(&tp, err) + } -func validateTrafficPermissions(res *DecodedTrafficPermissions) error { var merr error // enumcover:pbauth.Action - switch res.Data.Action { + switch tp.Action { case pbauth.Action_ACTION_ALLOW: case pbauth.Action_ACTION_DENY: case pbauth.Action_ACTION_UNSPECIFIED: @@ -122,14 +132,14 @@ func validateTrafficPermissions(res *DecodedTrafficPermissions) error { }) } - if res.Data.Destination == nil || (len(res.Data.Destination.IdentityName) == 0) { + if tp.Destination == nil || (len(tp.Destination.IdentityName) == 0) { merr = multierror.Append(merr, resource.ErrInvalidField{ Name: "data.destination", Wrapped: resource.ErrEmpty, }) } // Validate permissions - for i, permission := range res.Data.Permissions { + for i, permission := range tp.Permissions { wrapErr := func(err error) error { return resource.ErrInvalidListElement{ Name: "permissions", @@ -261,10 +271,30 @@ func isLocalPeer(p string) bool { return p == "local" || p == "" } -func aclReadHookTrafficPermissions(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *DecodedTrafficPermissions) error { - return authorizer.ToAllowAuthorizer().TrafficPermissionsReadAllowed(res.Data.Destination.IdentityName, authzContext) +func aclReadHookTrafficPermissions(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, _ *pbresource.ID, res *pbresource.Resource) error { + if res == nil { + return resource.ErrNeedResource + } + return authorizeDestination(res, func(dest string) error { + return authorizer.ToAllowAuthorizer().TrafficPermissionsReadAllowed(dest, authzContext) + }) } -func aclWriteHookTrafficPermissions(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *DecodedTrafficPermissions) error { - return authorizer.ToAllowAuthorizer().TrafficPermissionsWriteAllowed(res.Data.Destination.IdentityName, authzContext) +func aclWriteHookTrafficPermissions(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { + return authorizeDestination(res, func(dest string) error { + return authorizer.ToAllowAuthorizer().TrafficPermissionsWriteAllowed(dest, authzContext) + }) +} + +func authorizeDestination(res *pbresource.Resource, intentionAllowed func(string) error) error { + tp, err := resource.Decode[*pbauth.TrafficPermissions](res) + if err != nil { + return err + } + // Check intention:x permissions for identity + err = intentionAllowed(tp.Data.Destination.IdentityName) + if err != nil { + return err + } + return nil } diff --git a/internal/auth/internal/types/workload_identity.go b/internal/auth/internal/types/workload_identity.go index a15fd5bf5b2dd..17334e66099ef 100644 --- a/internal/auth/internal/types/workload_identity.go +++ b/internal/auth/internal/types/workload_identity.go @@ -10,8 +10,6 @@ import ( "github.com/hashicorp/consul/proto-public/pbresource" ) -type DecodedWorkloadIdentity = resource.DecodedResource[*pbauth.WorkloadIdentity] - func RegisterWorkloadIdentity(r resource.Registry) { r.Register(resource.Registration{ Type: pbauth.WorkloadIdentityType, @@ -22,17 +20,10 @@ func RegisterWorkloadIdentity(r resource.Registry) { Write: aclWriteHookWorkloadIdentity, List: resource.NoOpACLListHook, }, - Validate: ValidateWorkloadIdentity, + Validate: nil, }) } -var ValidateWorkloadIdentity = resource.DecodeAndValidate(validateWorkloadIdentity) - -func validateWorkloadIdentity(res *DecodedWorkloadIdentity) error { - // currently the WorkloadIdentity type has no fields. - return nil -} - func aclReadHookWorkloadIdentity( authorizer acl.Authorizer, authzCtx *acl.AuthorizerContext, diff --git a/internal/auth/internal/types/workload_identity_test.go b/internal/auth/internal/types/workload_identity_test.go index 19ed4cbeea87e..8dfb22bc74a2e 100644 --- a/internal/auth/internal/types/workload_identity_test.go +++ b/internal/auth/internal/types/workload_identity_test.go @@ -144,13 +144,3 @@ func TestWorkloadIdentityACLs(t *testing.T) { }) } } - -func TestWorkloadIdentity_ParseError(t *testing.T) { - rsc := resourcetest.Resource(pbauth.WorkloadIdentityType, "example"). - WithData(t, &pbauth.TrafficPermissions{}). - Build() - - err := ValidateWorkloadIdentity(rsc) - var parseErr resource.ErrDataParse - require.ErrorAs(t, err, &parseErr) -} diff --git a/internal/catalog/catalogtest/run_test.go b/internal/catalog/catalogtest/run_test.go index 5a6e1e62e3548..2c12785bbb0be 100644 --- a/internal/catalog/catalogtest/run_test.go +++ b/internal/catalog/catalogtest/run_test.go @@ -38,7 +38,7 @@ func runInMemResourceServiceAndControllers(t *testing.T, deps controllers.Depend func TestControllers_Integration(t *testing.T) { client := runInMemResourceServiceAndControllers(t, catalog.DefaultControllerDependencies()) - RunCatalogV2Beta1IntegrationTest(t, client) + RunCatalogV1Alpha1IntegrationTest(t, client) } func TestControllers_Lifecycle(t *testing.T) { diff --git a/internal/catalog/catalogtest/test_integration_v2beta1.go b/internal/catalog/catalogtest/test_integration_v2beta1.go index 79ffea7e79539..9f83ab3655912 100644 --- a/internal/catalog/catalogtest/test_integration_v2beta1.go +++ b/internal/catalog/catalogtest/test_integration_v2beta1.go @@ -26,7 +26,7 @@ var ( testData embed.FS ) -// RunCatalogV2Beta1IntegrationTest will push up a bunch of catalog related data and then +// RunCatalogV1Alpha1IntegrationTest will push up a bunch of catalog related data and then // verify that all the expected reconciliations happened correctly. This test is // intended to exercise a large swathe of behavior of the overall catalog package. // Besides just controller reconciliation behavior, the intent is also to verify @@ -38,7 +38,7 @@ var ( // is another RunCatalogIntegrationTestLifeCycle function that can be used for those // purposes. The two are distinct so that the data being published and the assertions // made against the system can be reused in upgrade tests. -func RunCatalogV2Beta1IntegrationTest(t *testing.T, client pbresource.ResourceServiceClient) { +func RunCatalogV1Alpha1IntegrationTest(t *testing.T, client pbresource.ResourceServiceClient) { t.Helper() PublishCatalogV2Beta1IntegrationTestData(t, client) diff --git a/internal/catalog/internal/types/acl_hooks.go b/internal/catalog/internal/types/acl_hooks.go index d9ddcb8e93cc1..8250767f72549 100644 --- a/internal/catalog/internal/types/acl_hooks.go +++ b/internal/catalog/internal/types/acl_hooks.go @@ -13,22 +13,31 @@ func aclReadHookResourceWithWorkloadSelector(authorizer acl.Authorizer, authzCon return authorizer.ToAllowAuthorizer().ServiceReadAllowed(id.GetName(), authzContext) } -func aclWriteHookResourceWithWorkloadSelector[T WorkloadSelecting](authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, r *resource.DecodedResource[T]) error { +func aclWriteHookResourceWithWorkloadSelector[T WorkloadSelecting](authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { + if res == nil { + return resource.ErrNeedResource + } + + decodedService, err := resource.Decode[T](res) + if err != nil { + return resource.ErrNeedResource + } + // First check service:write on the name. - err := authorizer.ToAllowAuthorizer().ServiceWriteAllowed(r.GetId().GetName(), authzContext) + err = authorizer.ToAllowAuthorizer().ServiceWriteAllowed(res.GetId().GetName(), authzContext) if err != nil { return err } // Then also check whether we're allowed to select a service. - for _, name := range r.Data.GetWorkloads().GetNames() { + for _, name := range decodedService.GetData().GetWorkloads().GetNames() { err = authorizer.ToAllowAuthorizer().ServiceReadAllowed(name, authzContext) if err != nil { return err } } - for _, prefix := range r.Data.GetWorkloads().GetPrefixes() { + for _, prefix := range decodedService.GetData().GetWorkloads().GetPrefixes() { err = authorizer.ToAllowAuthorizer().ServiceReadPrefixAllowed(prefix, authzContext) if err != nil { return err @@ -41,7 +50,7 @@ func aclWriteHookResourceWithWorkloadSelector[T WorkloadSelecting](authorizer ac func ACLHooksForWorkloadSelectingType[T WorkloadSelecting]() *resource.ACLHooks { return &resource.ACLHooks{ Read: aclReadHookResourceWithWorkloadSelector, - Write: resource.DecodeAndAuthorizeWrite(aclWriteHookResourceWithWorkloadSelector[T]), + Write: aclWriteHookResourceWithWorkloadSelector[T], List: resource.NoOpACLListHook, } } diff --git a/internal/catalog/internal/types/dns_policy.go b/internal/catalog/internal/types/dns_policy.go index 91dd2615455ca..8e9dd864a9573 100644 --- a/internal/catalog/internal/types/dns_policy.go +++ b/internal/catalog/internal/types/dns_policy.go @@ -10,10 +10,9 @@ import ( "github.com/hashicorp/consul/internal/resource" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" + "github.com/hashicorp/consul/proto-public/pbresource" ) -type DecodedDNSPolicy = resource.DecodedResource[*pbcatalog.DNSPolicy] - func RegisterDNSPolicy(r resource.Registry) { r.Register(resource.Registration{ Type: pbcatalog.DNSPolicyType, @@ -24,13 +23,17 @@ func RegisterDNSPolicy(r resource.Registry) { }) } -var ValidateDNSPolicy = resource.DecodeAndValidate(validateDNSPolicy) +func ValidateDNSPolicy(res *pbresource.Resource) error { + var policy pbcatalog.DNSPolicy + + if err := res.Data.UnmarshalTo(&policy); err != nil { + return resource.NewErrDataParse(&policy, err) + } -func validateDNSPolicy(res *DecodedDNSPolicy) error { var err error // Ensure that this resource isn't useless and is attempting to // select at least one workload. - if selErr := ValidateSelector(res.Data.Workloads, false); selErr != nil { + if selErr := ValidateSelector(policy.Workloads, false); selErr != nil { err = multierror.Append(err, resource.ErrInvalidField{ Name: "workloads", Wrapped: selErr, @@ -38,7 +41,7 @@ func validateDNSPolicy(res *DecodedDNSPolicy) error { } // Validate the weights - if weightErr := validateDNSPolicyWeights(res.Data.Weights); weightErr != nil { + if weightErr := validateDNSPolicyWeights(policy.Weights); weightErr != nil { err = multierror.Append(err, resource.ErrInvalidField{ Name: "weights", Wrapped: weightErr, diff --git a/internal/catalog/internal/types/failover_policy.go b/internal/catalog/internal/types/failover_policy.go index 012150fc046dc..047bb9a95b050 100644 --- a/internal/catalog/internal/types/failover_policy.go +++ b/internal/catalog/internal/types/failover_policy.go @@ -15,8 +15,6 @@ import ( "github.com/hashicorp/consul/proto-public/pbresource" ) -type DecodedFailoverPolicy = resource.DecodedResource[*pbcatalog.FailoverPolicy] - func RegisterFailoverPolicy(r resource.Registry) { r.Register(resource.Registration{ Type: pbcatalog.FailoverPolicyType, @@ -26,32 +24,36 @@ func RegisterFailoverPolicy(r resource.Registry) { Validate: ValidateFailoverPolicy, ACLs: &resource.ACLHooks{ Read: aclReadHookFailoverPolicy, - Write: resource.DecodeAndAuthorizeWrite(aclWriteHookFailoverPolicy), + Write: aclWriteHookFailoverPolicy, List: resource.NoOpACLListHook, }, }) } -var MutateFailoverPolicy = resource.DecodeAndMutate(mutateFailoverPolicy) +func MutateFailoverPolicy(res *pbresource.Resource) error { + var failover pbcatalog.FailoverPolicy + + if err := res.Data.UnmarshalTo(&failover); err != nil { + return resource.NewErrDataParse(&failover, err) + } -func mutateFailoverPolicy(res *DecodedFailoverPolicy) (bool, error) { changed := false // Handle eliding empty configs. - if res.Data.Config != nil && res.Data.Config.IsEmpty() { - res.Data.Config = nil + if failover.Config != nil && failover.Config.IsEmpty() { + failover.Config = nil changed = true } - if res.Data.Config != nil { - if mutateFailoverConfig(res.Id.Tenancy, res.Data.Config) { + if failover.Config != nil { + if mutateFailoverConfig(res.Id.Tenancy, failover.Config) { changed = true } } - for port, pc := range res.Data.PortConfigs { + for port, pc := range failover.PortConfigs { if pc.IsEmpty() { - delete(res.Data.PortConfigs, port) + delete(failover.PortConfigs, port) changed = true } else { if mutateFailoverConfig(res.Id.Tenancy, pc) { @@ -59,12 +61,16 @@ func mutateFailoverPolicy(res *DecodedFailoverPolicy) (bool, error) { } } } - if len(res.Data.PortConfigs) == 0 { - res.Data.PortConfigs = nil + if len(failover.PortConfigs) == 0 { + failover.PortConfigs = nil changed = true } - return changed, nil + if !changed { + return nil + } + + return res.Data.MarshalFrom(&failover) } func mutateFailoverConfig(policyTenancy *pbresource.Tenancy, config *pbcatalog.FailoverConfig) (changed bool) { @@ -103,31 +109,35 @@ func isLocalPeer(p string) bool { return p == "local" || p == "" } -var ValidateFailoverPolicy = resource.DecodeAndValidate(validateFailoverPolicy) +func ValidateFailoverPolicy(res *pbresource.Resource) error { + var failover pbcatalog.FailoverPolicy + + if err := res.Data.UnmarshalTo(&failover); err != nil { + return resource.NewErrDataParse(&failover, err) + } -func validateFailoverPolicy(res *DecodedFailoverPolicy) error { var merr error - if res.Data.Config == nil && len(res.Data.PortConfigs) == 0 { + if failover.Config == nil && len(failover.PortConfigs) == 0 { merr = multierror.Append(merr, resource.ErrInvalidField{ Name: "config", Wrapped: fmt.Errorf("at least one of config or port_configs must be set"), }) } - if res.Data.Config != nil { + if failover.Config != nil { wrapConfigErr := func(err error) error { return resource.ErrInvalidField{ Name: "config", Wrapped: err, } } - if cfgErr := validateFailoverConfig(res.Data.Config, false, wrapConfigErr); cfgErr != nil { + if cfgErr := validateFailoverConfig(failover.Config, false, wrapConfigErr); cfgErr != nil { merr = multierror.Append(merr, cfgErr) } } - for portName, pc := range res.Data.PortConfigs { + for portName, pc := range failover.PortConfigs { wrapConfigErr := func(err error) error { return resource.ErrInvalidMapValue{ Map: "port_configs", @@ -323,7 +333,7 @@ func aclReadHookFailoverPolicy(authorizer acl.Authorizer, authzContext *acl.Auth return authorizer.ToAllowAuthorizer().ServiceReadAllowed(serviceName, authzContext) } -func aclWriteHookFailoverPolicy(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *DecodedFailoverPolicy) error { +func aclWriteHookFailoverPolicy(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { // FailoverPolicy is name-aligned with Service serviceName := res.Id.Name @@ -332,10 +342,15 @@ func aclWriteHookFailoverPolicy(authorizer acl.Authorizer, authzContext *acl.Aut return err } + dec, err := resource.Decode[*pbcatalog.FailoverPolicy](res) + if err != nil { + return err + } + // Ensure you have service:read on any destination that may be affected by // traffic FROM this config change. - if res.Data.Config != nil { - for _, dest := range res.Data.Config.Destinations { + if dec.Data.Config != nil { + for _, dest := range dec.Data.Config.Destinations { destAuthzContext := resource.AuthorizerContext(dest.Ref.GetTenancy()) destServiceName := dest.Ref.GetName() if err := authorizer.ToAllowAuthorizer().ServiceReadAllowed(destServiceName, destAuthzContext); err != nil { @@ -343,7 +358,7 @@ func aclWriteHookFailoverPolicy(authorizer acl.Authorizer, authzContext *acl.Aut } } } - for _, pc := range res.Data.PortConfigs { + for _, pc := range dec.Data.PortConfigs { for _, dest := range pc.Destinations { destAuthzContext := resource.AuthorizerContext(dest.Ref.GetTenancy()) destServiceName := dest.Ref.GetName() diff --git a/internal/catalog/internal/types/health_checks.go b/internal/catalog/internal/types/health_checks.go index 3d819e12885aa..1333e2368d882 100644 --- a/internal/catalog/internal/types/health_checks.go +++ b/internal/catalog/internal/types/health_checks.go @@ -8,10 +8,9 @@ import ( "github.com/hashicorp/consul/internal/resource" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" + "github.com/hashicorp/consul/proto-public/pbresource" ) -type DecodedHealthChecks = resource.DecodedResource[*pbcatalog.HealthChecks] - func RegisterHealthChecks(r resource.Registry) { r.Register(resource.Registration{ Type: pbcatalog.HealthChecksType, @@ -22,13 +21,17 @@ func RegisterHealthChecks(r resource.Registry) { }) } -var ValidateHealthChecks = resource.DecodeAndValidate(validateHealthChecks) +func ValidateHealthChecks(res *pbresource.Resource) error { + var checks pbcatalog.HealthChecks + + if err := res.Data.UnmarshalTo(&checks); err != nil { + return resource.NewErrDataParse(&checks, err) + } -func validateHealthChecks(res *DecodedHealthChecks) error { var err error // Validate the workload selector - if selErr := ValidateSelector(res.Data.Workloads, false); selErr != nil { + if selErr := ValidateSelector(checks.Workloads, false); selErr != nil { err = multierror.Append(err, resource.ErrInvalidField{ Name: "workloads", Wrapped: selErr, @@ -36,7 +39,7 @@ func validateHealthChecks(res *DecodedHealthChecks) error { } // Validate each check - for idx, check := range res.Data.HealthChecks { + for idx, check := range checks.HealthChecks { if checkErr := validateCheck(check); checkErr != nil { err = multierror.Append(err, resource.ErrInvalidListElement{ Name: "checks", diff --git a/internal/catalog/internal/types/health_status.go b/internal/catalog/internal/types/health_status.go index c5ea7e106fa3b..fe92e858b025e 100644 --- a/internal/catalog/internal/types/health_status.go +++ b/internal/catalog/internal/types/health_status.go @@ -12,8 +12,6 @@ import ( "github.com/hashicorp/consul/proto-public/pbresource" ) -type DecodedHealthStatus = resource.DecodedResource[*pbcatalog.HealthStatus] - func RegisterHealthStatus(r resource.Registry) { r.Register(resource.Registration{ Type: pbcatalog.HealthStatusType, @@ -21,29 +19,33 @@ func RegisterHealthStatus(r resource.Registry) { Scope: resource.ScopeNamespace, Validate: ValidateHealthStatus, ACLs: &resource.ACLHooks{ - Read: resource.AuthorizeReadWithResource(aclReadHookHealthStatus), + Read: aclReadHookHealthStatus, Write: aclWriteHookHealthStatus, List: resource.NoOpACLListHook, }, }) } -var ValidateHealthStatus = resource.DecodeAndValidate(validateHealthStatus) +func ValidateHealthStatus(res *pbresource.Resource) error { + var hs pbcatalog.HealthStatus + + if err := res.Data.UnmarshalTo(&hs); err != nil { + return resource.NewErrDataParse(&hs, err) + } -func validateHealthStatus(res *DecodedHealthStatus) error { var err error // Should we allow empty types? I think for now it will be safest to require // the type field is set and we can relax this restriction in the future // if we deem it desirable. - if res.Data.Type == "" { + if hs.Type == "" { err = multierror.Append(err, resource.ErrInvalidField{ Name: "type", Wrapped: resource.ErrMissing, }) } - switch res.Data.Status { + switch hs.Status { case pbcatalog.Health_HEALTH_PASSING, pbcatalog.Health_HEALTH_WARNING, pbcatalog.Health_HEALTH_CRITICAL, @@ -59,7 +61,7 @@ func validateHealthStatus(res *DecodedHealthStatus) error { // owner is currently the resource that this HealthStatus applies to. If we // change this to be a parent reference within the HealthStatus.Data then // we could allow for other owners. - if res.Resource.Owner == nil { + if res.Owner == nil { err = multierror.Append(err, resource.ErrInvalidField{ Name: "owner", Wrapped: resource.ErrMissing, @@ -71,13 +73,15 @@ func validateHealthStatus(res *DecodedHealthStatus) error { return err } -func aclReadHookHealthStatus(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { +func aclReadHookHealthStatus(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, _ *pbresource.ID, res *pbresource.Resource) error { + if res == nil { + return resource.ErrNeedResource + } // For a health status of a workload we need to check service:read perms. if res.GetOwner() != nil && resource.EqualType(res.GetOwner().GetType(), pbcatalog.WorkloadType) { return authorizer.ToAllowAuthorizer().ServiceReadAllowed(res.GetOwner().GetName(), authzContext) } - // For a health status of a node we need to check node:read perms. if res.GetOwner() != nil && resource.EqualType(res.GetOwner().GetType(), pbcatalog.NodeType) { return authorizer.ToAllowAuthorizer().NodeReadAllowed(res.GetOwner().GetName(), authzContext) } @@ -91,7 +95,6 @@ func aclWriteHookHealthStatus(authorizer acl.Authorizer, authzContext *acl.Autho return authorizer.ToAllowAuthorizer().ServiceWriteAllowed(res.GetOwner().GetName(), authzContext) } - // For a health status of a node we need to check node:write perms. if res.GetOwner() != nil && resource.EqualType(res.GetOwner().GetType(), pbcatalog.NodeType) { return authorizer.ToAllowAuthorizer().NodeWriteAllowed(res.GetOwner().GetName(), authzContext) } diff --git a/internal/catalog/internal/types/node.go b/internal/catalog/internal/types/node.go index 1ee68f22ca82e..42ac833c6e7d8 100644 --- a/internal/catalog/internal/types/node.go +++ b/internal/catalog/internal/types/node.go @@ -12,8 +12,6 @@ import ( "github.com/hashicorp/consul/proto-public/pbresource" ) -type DecodedNode = resource.DecodedResource[*pbcatalog.Node] - func RegisterNode(r resource.Registry) { r.Register(resource.Registration{ Type: pbcatalog.NodeType, @@ -33,12 +31,16 @@ func RegisterNode(r resource.Registry) { }) } -var ValidateNode = resource.DecodeAndValidate(validateNode) +func ValidateNode(res *pbresource.Resource) error { + var node pbcatalog.Node + + if err := res.Data.UnmarshalTo(&node); err != nil { + return resource.NewErrDataParse(&node, err) + } -func validateNode(res *DecodedNode) error { var err error // Validate that the node has at least 1 address - if len(res.Data.Addresses) < 1 { + if len(node.Addresses) < 1 { err = multierror.Append(err, resource.ErrInvalidField{ Name: "addresses", Wrapped: resource.ErrEmpty, @@ -46,7 +48,7 @@ func validateNode(res *DecodedNode) error { } // Validate each node address - for idx, addr := range res.Data.Addresses { + for idx, addr := range node.Addresses { if addrErr := validateNodeAddress(addr); addrErr != nil { err = multierror.Append(err, resource.ErrInvalidListElement{ Name: "addresses", diff --git a/internal/catalog/internal/types/service.go b/internal/catalog/internal/types/service.go index bb56fe10a5710..a91f3a7c51801 100644 --- a/internal/catalog/internal/types/service.go +++ b/internal/catalog/internal/types/service.go @@ -10,10 +10,9 @@ import ( "github.com/hashicorp/consul/internal/resource" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" + "github.com/hashicorp/consul/proto-public/pbresource" ) -type DecodedService = resource.DecodedResource[*pbcatalog.Service] - func RegisterService(r resource.Registry) { r.Register(resource.Registration{ Type: pbcatalog.ServiceType, @@ -25,25 +24,37 @@ func RegisterService(r resource.Registry) { }) } -var MutateService = resource.DecodeAndMutate(mutateService) +func MutateService(res *pbresource.Resource) error { + var service pbcatalog.Service + + if err := res.Data.UnmarshalTo(&service); err != nil { + return err + } -func mutateService(res *DecodedService) (bool, error) { changed := false // Default service port protocols. - for _, port := range res.Data.Ports { + for _, port := range service.Ports { if port.Protocol == pbcatalog.Protocol_PROTOCOL_UNSPECIFIED { port.Protocol = pbcatalog.Protocol_PROTOCOL_TCP changed = true } } - return changed, nil + if !changed { + return nil + } + + return res.Data.MarshalFrom(&service) } -var ValidateService = resource.DecodeAndValidate(validateService) +func ValidateService(res *pbresource.Resource) error { + var service pbcatalog.Service + + if err := res.Data.UnmarshalTo(&service); err != nil { + return resource.NewErrDataParse(&service, err) + } -func validateService(res *DecodedService) error { var err error // Validate the workload selector. We are allowing selectors with no @@ -51,7 +62,7 @@ func validateService(res *DecodedService) error { // ServiceEndpoints objects for this service such as when desiring to // configure endpoint information for external services that are not // registered as workloads - if selErr := ValidateSelector(res.Data.Workloads, true); selErr != nil { + if selErr := ValidateSelector(service.Workloads, true); selErr != nil { err = multierror.Append(err, resource.ErrInvalidField{ Name: "workloads", Wrapped: selErr, @@ -61,7 +72,7 @@ func validateService(res *DecodedService) error { usedVirtualPorts := make(map[uint32]int) // Validate each port - for idx, port := range res.Data.Ports { + for idx, port := range service.Ports { if usedIdx, found := usedVirtualPorts[port.VirtualPort]; found { err = multierror.Append(err, resource.ErrInvalidListElement{ Name: "ports", @@ -119,7 +130,7 @@ func validateService(res *DecodedService) error { } // Validate that the Virtual IPs are all IP addresses - for idx, vip := range res.Data.VirtualIps { + for idx, vip := range service.VirtualIps { if vipErr := validateIPAddress(vip); vipErr != nil { err = multierror.Append(err, resource.ErrInvalidListElement{ Name: "virtual_ips", diff --git a/internal/catalog/internal/types/service_endpoints.go b/internal/catalog/internal/types/service_endpoints.go index b78a1bc705fa5..1991c455ad901 100644 --- a/internal/catalog/internal/types/service_endpoints.go +++ b/internal/catalog/internal/types/service_endpoints.go @@ -14,8 +14,6 @@ import ( "github.com/hashicorp/consul/proto-public/pbresource" ) -type DecodedServiceEndpoints = resource.DecodedResource[*pbcatalog.ServiceEndpoints] - func RegisterServiceEndpoints(r resource.Registry) { r.Register(resource.Registration{ Type: pbcatalog.ServiceEndpointsType, @@ -47,9 +45,13 @@ func MutateServiceEndpoints(res *pbresource.Resource) error { return nil } -var ValidateServiceEndpoints = resource.DecodeAndValidate[*pbcatalog.ServiceEndpoints](validateServiceEndpoints) +func ValidateServiceEndpoints(res *pbresource.Resource) error { + var svcEndpoints pbcatalog.ServiceEndpoints + + if err := res.Data.UnmarshalTo(&svcEndpoints); err != nil { + return resource.NewErrDataParse(&svcEndpoints, err) + } -func validateServiceEndpoints(res *DecodedServiceEndpoints) error { var err error if !resource.EqualType(res.Owner.Type, pbcatalog.ServiceType) { err = multierror.Append(err, resource.ErrOwnerTypeInvalid{ @@ -76,8 +78,8 @@ func validateServiceEndpoints(res *DecodedServiceEndpoints) error { }) } - for idx, endpoint := range res.Data.Endpoints { - if endpointErr := validateEndpoint(endpoint, res.Resource); endpointErr != nil { + for idx, endpoint := range svcEndpoints.Endpoints { + if endpointErr := validateEndpoint(endpoint, res); endpointErr != nil { err = multierror.Append(err, resource.ErrInvalidListElement{ Name: "endpoints", Index: idx, diff --git a/internal/catalog/internal/types/virtual_ips.go b/internal/catalog/internal/types/virtual_ips.go index be692f63ed65a..9c7a065474059 100644 --- a/internal/catalog/internal/types/virtual_ips.go +++ b/internal/catalog/internal/types/virtual_ips.go @@ -12,8 +12,6 @@ import ( "github.com/hashicorp/consul/proto-public/pbresource" ) -type DecodedVirtualIPs = resource.DecodedResource[*pbcatalog.VirtualIPs] - func RegisterVirtualIPs(r resource.Registry) { r.Register(resource.Registration{ Type: pbcatalog.VirtualIPsType, @@ -32,11 +30,15 @@ func RegisterVirtualIPs(r resource.Registry) { }) } -var ValidateVirtualIPs = resource.DecodeAndValidate(validateVirtualIPs) +func ValidateVirtualIPs(res *pbresource.Resource) error { + var vips pbcatalog.VirtualIPs + + if err := res.Data.UnmarshalTo(&vips); err != nil { + return resource.NewErrDataParse(&vips, err) + } -func validateVirtualIPs(res *DecodedVirtualIPs) error { var err error - for idx, ip := range res.Data.Ips { + for idx, ip := range vips.Ips { if vipErr := validateIPAddress(ip.Address); vipErr != nil { err = multierror.Append(err, resource.ErrInvalidListElement{ Name: "ips", diff --git a/internal/catalog/internal/types/workload.go b/internal/catalog/internal/types/workload.go index 8535a6250491d..c09513a4a5b3d 100644 --- a/internal/catalog/internal/types/workload.go +++ b/internal/catalog/internal/types/workload.go @@ -15,8 +15,6 @@ import ( "github.com/hashicorp/consul/proto-public/pbresource" ) -type DecodedWorkload = resource.DecodedResource[*pbcatalog.Workload] - func RegisterWorkload(r resource.Registry) { r.Register(resource.Registration{ Type: pbcatalog.WorkloadType, @@ -25,19 +23,23 @@ func RegisterWorkload(r resource.Registry) { Validate: ValidateWorkload, ACLs: &resource.ACLHooks{ Read: aclReadHookWorkload, - Write: resource.DecodeAndAuthorizeWrite(aclWriteHookWorkload), + Write: aclWriteHookWorkload, List: resource.NoOpACLListHook, }, }) } -var ValidateWorkload = resource.DecodeAndValidate(validateWorkload) +func ValidateWorkload(res *pbresource.Resource) error { + var workload pbcatalog.Workload + + if err := res.Data.UnmarshalTo(&workload); err != nil { + return resource.NewErrDataParse(&workload, err) + } -func validateWorkload(res *DecodedWorkload) error { var err error // Validate that the workload has at least one port - if len(res.Data.Ports) < 1 { + if len(workload.Ports) < 1 { err = multierror.Append(err, resource.ErrInvalidField{ Name: "ports", Wrapped: resource.ErrEmpty, @@ -47,7 +49,7 @@ func validateWorkload(res *DecodedWorkload) error { var meshPorts []string // Validate the Workload Ports - for portName, port := range res.Data.Ports { + for portName, port := range workload.Ports { if portNameErr := ValidatePortName(portName); portNameErr != nil { err = multierror.Append(err, resource.ErrInvalidMapKey{ Map: "ports", @@ -98,12 +100,12 @@ func validateWorkload(res *DecodedWorkload) error { // If the workload is mesh enabled then a valid identity must be provided. // If not mesh enabled but a non-empty identity is provided then we still // validate that its valid. - if len(meshPorts) > 0 && res.Data.Identity == "" { + if len(meshPorts) > 0 && workload.Identity == "" { err = multierror.Append(err, resource.ErrInvalidField{ Name: "identity", Wrapped: resource.ErrMissing, }) - } else if res.Data.Identity != "" && !isValidDNSLabel(res.Data.Identity) { + } else if workload.Identity != "" && !isValidDNSLabel(workload.Identity) { err = multierror.Append(err, resource.ErrInvalidField{ Name: "identity", Wrapped: errNotDNSLabel, @@ -111,7 +113,7 @@ func validateWorkload(res *DecodedWorkload) error { } // Validate workload locality - if res.Data.Locality != nil && res.Data.Locality.Region == "" && res.Data.Locality.Zone != "" { + if workload.Locality != nil && workload.Locality.Region == "" && workload.Locality.Zone != "" { err = multierror.Append(err, resource.ErrInvalidField{ Name: "locality", Wrapped: errLocalityZoneNoRegion, @@ -120,8 +122,8 @@ func validateWorkload(res *DecodedWorkload) error { // Node associations are optional but if present the name should // be a valid DNS label. - if res.Data.NodeName != "" { - if !isValidDNSLabel(res.Data.NodeName) { + if workload.NodeName != "" { + if !isValidDNSLabel(workload.NodeName) { err = multierror.Append(err, resource.ErrInvalidField{ Name: "node_name", Wrapped: errNotDNSLabel, @@ -129,7 +131,7 @@ func validateWorkload(res *DecodedWorkload) error { } } - if len(res.Data.Addresses) < 1 { + if len(workload.Addresses) < 1 { err = multierror.Append(err, resource.ErrInvalidField{ Name: "addresses", Wrapped: resource.ErrEmpty, @@ -137,8 +139,8 @@ func validateWorkload(res *DecodedWorkload) error { } // Validate Workload Addresses - for idx, addr := range res.Data.Addresses { - if addrErr := validateWorkloadAddress(addr, res.Data.Ports); addrErr != nil { + for idx, addr := range workload.Addresses { + if addrErr := validateWorkloadAddress(addr, workload.Ports); addrErr != nil { err = multierror.Append(err, resource.ErrInvalidListElement{ Name: "addresses", Index: idx, @@ -154,21 +156,26 @@ func aclReadHookWorkload(authorizer acl.Authorizer, authzContext *acl.Authorizer return authorizer.ToAllowAuthorizer().ServiceReadAllowed(id.GetName(), authzContext) } -func aclWriteHookWorkload(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *DecodedWorkload) error { +func aclWriteHookWorkload(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { + decodedWorkload, err := resource.Decode[*pbcatalog.Workload](res) + if err != nil { + return resource.ErrNeedResource + } + // First check service:write on the workload name. - err := authorizer.ToAllowAuthorizer().ServiceWriteAllowed(res.GetId().GetName(), authzContext) + err = authorizer.ToAllowAuthorizer().ServiceWriteAllowed(res.GetId().GetName(), authzContext) if err != nil { return err } // Check node:read permissions if node is specified. - if res.Data.GetNodeName() != "" { - return authorizer.ToAllowAuthorizer().NodeReadAllowed(res.Data.GetNodeName(), authzContext) + if decodedWorkload.GetData().GetNodeName() != "" { + return authorizer.ToAllowAuthorizer().NodeReadAllowed(decodedWorkload.GetData().GetNodeName(), authzContext) } // Check identity:read permissions if identity is specified. - if res.Data.GetIdentity() != "" { - return authorizer.ToAllowAuthorizer().IdentityReadAllowed(res.Data.GetIdentity(), authzContext) + if decodedWorkload.GetData().GetIdentity() != "" { + return authorizer.ToAllowAuthorizer().IdentityReadAllowed(decodedWorkload.GetData().GetIdentity(), authzContext) } return nil diff --git a/internal/controller/dependencies.go b/internal/controller/dependencies.go deleted file mode 100644 index 6a91d91ff7b72..0000000000000 --- a/internal/controller/dependencies.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package controller - -import ( - "fmt" - "sort" - "strings" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func (m *Manager) ValidateDependencies(registrations []resource.Registration) error { - deps := m.CalculateDependencies(registrations) - - return deps.validate() -} - -type Dependencies map[string][]string - -func (deps Dependencies) validate() error { - var merr error - seen := make(map[string]map[string]struct{}) - - mkErr := func(src, dst string) error { - vals := []string{src, dst} - sort.Strings(vals) - return fmt.Errorf("circular dependency between %q and %q", vals[0], vals[1]) - } - - for src, dsts := range deps { - seenDsts := seen[src] - if len(seenDsts) == 0 { - seen[src] = make(map[string]struct{}) - } - - for _, dst := range dsts { - if _, ok := seenDsts[dst]; ok { - merr = multierror.Append(merr, mkErr(src, dst)) - } - - if inverseDsts := seen[dst]; len(inverseDsts) > 0 { - if _, ok := inverseDsts[src]; ok { - merr = multierror.Append(merr, mkErr(src, dst)) - } - } - seen[src][dst] = struct{}{} - } - } - - return merr -} - -func (m *Manager) CalculateDependencies(registrations []resource.Registration) Dependencies { - typeToString := func(t *pbresource.Type) string { - return strings.ToLower(fmt.Sprintf("%s/%s/%s", t.Group, t.GroupVersion, t.Kind)) - } - - out := make(map[string][]string) - for _, r := range registrations { - out[typeToString(r.Type)] = nil - } - - for _, c := range m.controllers { - watches := make([]string, 0, len(c.watches)) - for _, w := range c.watches { - watches = append(watches, typeToString(w.watchedType)) - } - - out[typeToString(c.managedType)] = watches - } - - return out -} - -func (deps Dependencies) ToMermaid() string { - depStrings := make([]string, 0, len(deps)) - - for src, dsts := range deps { - if len(dsts) == 0 { - depStrings = append(depStrings, fmt.Sprintf(" %s", src)) - continue - } - - for _, dst := range dsts { - depStrings = append(depStrings, fmt.Sprintf(" %s --> %s", src, dst)) - } - } - - sort.Slice(depStrings, func(a, b int) bool { - return depStrings[a] < depStrings[b] - }) - out := "flowchart TD\n" + strings.Join(depStrings, "\n") - - return out -} diff --git a/internal/controller/dependencies_test.go b/internal/controller/dependencies_test.go deleted file mode 100644 index 18db58a2853ae..0000000000000 --- a/internal/controller/dependencies_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package controller - -import ( - "testing" - - "github.com/hashicorp/consul/internal/testing/golden" - "github.com/stretchr/testify/require" -) - -func TestDependenciesGolden(t *testing.T) { - deps := Dependencies{ - "t1": []string{"t2", "t3"}, - "t2": []string{"t4"}, - "t4": []string{"t1"}, - } - mermaid := deps.ToMermaid() - expected := golden.Get(t, mermaid, "dependencies.golden") - require.Equal(t, expected, mermaid) -} - -func TestValidateDependencies(t *testing.T) { - type testCase struct { - dependencies Dependencies - expectErr string - } - - run := func(t *testing.T, tc testCase) { - err := tc.dependencies.validate() - if len(tc.expectErr) > 0 { - require.Contains(t, err.Error(), tc.expectErr) - } else { - require.NoError(t, err) - } - - } - - cases := map[string]testCase{ - "empty": { - dependencies: nil, - }, - "no circular dependencies": { - dependencies: Dependencies{ - "t1": []string{"t2", "t3"}, - "t2": []string{"t3"}, - "t3": []string{"t4"}, - "t4": nil, - }, - }, - "with circular dependency": { - dependencies: Dependencies{ - "t1": []string{"t2", "t3"}, - "t2": []string{"t1"}, - }, - expectErr: `circular dependency between "t1" and "t2"`, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/controller/testdata/dependencies.golden b/internal/controller/testdata/dependencies.golden deleted file mode 100644 index f0ff372a1634f..0000000000000 --- a/internal/controller/testdata/dependencies.golden +++ /dev/null @@ -1,5 +0,0 @@ -flowchart TD - t1 --> t2 - t1 --> t3 - t2 --> t4 - t4 --> t1 \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/destinations.go b/internal/mesh/internal/controllers/sidecarproxy/builder/destinations.go index f2c4901c89b6d..aea4360b83108 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/destinations.go +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/destinations.go @@ -290,6 +290,7 @@ func (b *Builder) buildDestination( clusterName := fmt.Sprintf("%s.%s", portName, sni) egName := "" + if details.FailoverConfig != nil { egName = fmt.Sprintf("%s%d~%s", xdscommon.FailoverClusterNamePrefix, 0, clusterName) } diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go index 270d0f0fdfa92..e1dd0ebb61719 100644 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ b/internal/mesh/internal/controllers/xds/controller_test.go @@ -241,10 +241,7 @@ func (suite *xdsControllerTestSuite) TestReconcile_ReadEndpointError() { require.Error(suite.T(), err) // Assert on the status reflecting endpoint couldn't be read. - suite.client.RequireStatusCondition(suite.T(), fooProxyStateTemplate.Id, ControllerName, status.ConditionRejectedErrorReadingEndpoints( - status.KeyFromID(badID), - "rpc error: code = InvalidArgument desc = id.name invalid: a resource name must consist of lower case alphanumeric characters or '-', must start and end with an alphanumeric character and be less than 64 characters, got: \"\"", - )) + suite.client.RequireStatusCondition(suite.T(), fooProxyStateTemplate.Id, ControllerName, status.ConditionRejectedErrorReadingEndpoints(status.KeyFromID(badID), "rpc error: code = InvalidArgument desc = id.name is required")) } // This test is a happy path creation test to make sure pbproxystate.Endpoints are created in the computed @@ -1042,7 +1039,6 @@ func (suite *xdsControllerTestSuite) TestReconcile_SidecarProxyGoldenFileInputs( "source/multiport-l4-workload-with-only-mesh-port", "source/multiport-l7-multiple-workload-addresses-with-specific-ports", "source/multiport-l7-multiple-workload-addresses-without-ports", - "source/multiport-l7-multiple-workload-addresses-without-ports", } for _, name := range cases { diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden b/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden index 2638cf3f806e0..16b1841296ed8 100644 --- a/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden +++ b/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden @@ -377,4 +377,4 @@ "trustDomain": "some-trust-domain" } } -} \ No newline at end of file +} diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden index 0d418fc680598..7ac1ec80710b5 100644 --- a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden +++ b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden @@ -463,4 +463,4 @@ "trustDomain": "some-trust-domain" } } -} \ No newline at end of file +} diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden index c465d0ad84b78..8f5e73c92ee52 100644 --- a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden +++ b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden @@ -259,4 +259,4 @@ "trustDomain": "some-trust-domain" } } -} \ No newline at end of file +} diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden index c465d0ad84b78..8f5e73c92ee52 100644 --- a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden +++ b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden @@ -259,4 +259,4 @@ "trustDomain": "some-trust-domain" } } -} \ No newline at end of file +} diff --git a/internal/mesh/internal/types/computed_routes.go b/internal/mesh/internal/types/computed_routes.go index b572c01fc3764..1f66cc97ac211 100644 --- a/internal/mesh/internal/types/computed_routes.go +++ b/internal/mesh/internal/types/computed_routes.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/consul/internal/resource" pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" + "github.com/hashicorp/consul/proto-public/pbresource" ) const ( @@ -29,12 +30,16 @@ func RegisterComputedRoutes(r resource.Registry) { }) } -var ValidateComputedRoutes = resource.DecodeAndValidate(validateComputedRoutes) +func ValidateComputedRoutes(res *pbresource.Resource) error { + var config pbmesh.ComputedRoutes + + if err := res.Data.UnmarshalTo(&config); err != nil { + return resource.NewErrDataParse(&config, err) + } -func validateComputedRoutes(res *DecodedComputedRoutes) error { var merr error - if len(res.Data.PortedConfigs) == 0 { + if len(config.PortedConfigs) == 0 { merr = multierror.Append(merr, resource.ErrInvalidField{ Name: "ported_configs", Wrapped: resource.ErrEmpty, @@ -43,7 +48,7 @@ func validateComputedRoutes(res *DecodedComputedRoutes) error { // TODO(rb): do more elaborate validation - for port, pmc := range res.Data.PortedConfigs { + for port, pmc := range config.PortedConfigs { wrapErr := func(err error) error { return resource.ErrInvalidMapValue{ Map: "ported_configs", diff --git a/internal/mesh/internal/types/decoded.go b/internal/mesh/internal/types/decoded.go index be4836c066ff7..ee1244fdcb1bc 100644 --- a/internal/mesh/internal/types/decoded.go +++ b/internal/mesh/internal/types/decoded.go @@ -15,7 +15,6 @@ type ( DecodedGRPCRoute = resource.DecodedResource[*pbmesh.GRPCRoute] DecodedTCPRoute = resource.DecodedResource[*pbmesh.TCPRoute] DecodedDestinationPolicy = resource.DecodedResource[*pbmesh.DestinationPolicy] - DecodedDestinationsConfiguration = resource.DecodedResource[*pbmesh.DestinationsConfiguration] DecodedComputedRoutes = resource.DecodedResource[*pbmesh.ComputedRoutes] DecodedComputedTrafficPermissions = resource.DecodedResource[*pbauth.ComputedTrafficPermissions] DecodedFailoverPolicy = resource.DecodedResource[*pbcatalog.FailoverPolicy] diff --git a/internal/mesh/internal/types/destination_policy.go b/internal/mesh/internal/types/destination_policy.go index 4fe3062367cf5..68b37345baf3e 100644 --- a/internal/mesh/internal/types/destination_policy.go +++ b/internal/mesh/internal/types/destination_policy.go @@ -29,19 +29,23 @@ func RegisterDestinationPolicy(r resource.Registry) { }) } -var ValidateDestinationPolicy = resource.DecodeAndValidate(validateDestinationPolicy) +func ValidateDestinationPolicy(res *pbresource.Resource) error { + var policy pbmesh.DestinationPolicy + + if err := res.Data.UnmarshalTo(&policy); err != nil { + return resource.NewErrDataParse(&policy, err) + } -func validateDestinationPolicy(res *DecodedDestinationPolicy) error { var merr error - if len(res.Data.PortConfigs) == 0 { + if len(policy.PortConfigs) == 0 { merr = multierror.Append(merr, resource.ErrInvalidField{ Name: "port_configs", Wrapped: resource.ErrEmpty, }) } - for port, pc := range res.Data.PortConfigs { + for port, pc := range policy.PortConfigs { wrapErr := func(err error) error { return resource.ErrInvalidMapValue{ Map: "port_configs", diff --git a/internal/mesh/internal/types/destinations.go b/internal/mesh/internal/types/destinations.go index 7de3011e3ef0a..34287e627ab71 100644 --- a/internal/mesh/internal/types/destinations.go +++ b/internal/mesh/internal/types/destinations.go @@ -26,12 +26,16 @@ func RegisterDestinations(r resource.Registry) { }) } -var MutateDestinations = resource.DecodeAndMutate(mutateDestinations) +func MutateDestinations(res *pbresource.Resource) error { + var destinations pbmesh.Destinations + + if err := res.Data.UnmarshalTo(&destinations); err != nil { + return resource.NewErrDataParse(&destinations, err) + } -func mutateDestinations(res *DecodedDestinations) (bool, error) { changed := false - for _, dest := range res.Data.Destinations { + for _, dest := range destinations.Destinations { if dest.DestinationRef == nil { continue // skip; let the validation hook error out instead } @@ -52,33 +56,41 @@ func mutateDestinations(res *DecodedDestinations) (bool, error) { } } - return changed, nil + if !changed { + return nil + } + + return res.Data.MarshalFrom(&destinations) } func isLocalPeer(p string) bool { return p == "local" || p == "" } -var ValidateDestinations = resource.DecodeAndValidate(validateDestinations) +func ValidateDestinations(res *pbresource.Resource) error { + var destinations pbmesh.Destinations + + if err := res.Data.UnmarshalTo(&destinations); err != nil { + return resource.NewErrDataParse(&destinations, err) + } -func validateDestinations(res *DecodedDestinations) error { var merr error - if selErr := catalog.ValidateSelector(res.Data.Workloads, false); selErr != nil { + if selErr := catalog.ValidateSelector(destinations.Workloads, false); selErr != nil { merr = multierror.Append(merr, resource.ErrInvalidField{ Name: "workloads", Wrapped: selErr, }) } - if res.Data.GetPqDestinations() != nil { + if destinations.GetPqDestinations() != nil { merr = multierror.Append(merr, resource.ErrInvalidField{ Name: "pq_destinations", Wrapped: resource.ErrUnsupported, }) } - for i, dest := range res.Data.Destinations { + for i, dest := range destinations.Destinations { wrapDestErr := func(err error) error { return resource.ErrInvalidListElement{ Name: "destinations", diff --git a/internal/mesh/internal/types/destinations_configuration.go b/internal/mesh/internal/types/destinations_configuration.go index 7d46d93ed9993..fedbe40df48c1 100644 --- a/internal/mesh/internal/types/destinations_configuration.go +++ b/internal/mesh/internal/types/destinations_configuration.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/consul/internal/resource" pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" + "github.com/hashicorp/consul/proto-public/pbresource" ) func RegisterDestinationsConfiguration(r resource.Registry) { @@ -22,13 +23,17 @@ func RegisterDestinationsConfiguration(r resource.Registry) { }) } -var ValidateDestinationsConfiguration = resource.DecodeAndValidate(validateDestinationsConfiguration) +func ValidateDestinationsConfiguration(res *pbresource.Resource) error { + var cfg pbmesh.DestinationsConfiguration + + if err := res.Data.UnmarshalTo(&cfg); err != nil { + return resource.NewErrDataParse(&cfg, err) + } -func validateDestinationsConfiguration(res *DecodedDestinationsConfiguration) error { var merr error // Validate the workload selector - if selErr := catalog.ValidateSelector(res.Data.Workloads, false); selErr != nil { + if selErr := catalog.ValidateSelector(cfg.Workloads, false); selErr != nil { merr = multierror.Append(merr, resource.ErrInvalidField{ Name: "workloads", Wrapped: selErr, diff --git a/internal/mesh/internal/types/grpc_route.go b/internal/mesh/internal/types/grpc_route.go index b861abccdc050..630e416e611c4 100644 --- a/internal/mesh/internal/types/grpc_route.go +++ b/internal/mesh/internal/types/grpc_route.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/consul/internal/resource" pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" + "github.com/hashicorp/consul/proto-public/pbresource" ) func RegisterGRPCRoute(r resource.Registry) { @@ -24,16 +25,20 @@ func RegisterGRPCRoute(r resource.Registry) { }) } -var MutateGRPCRoute = resource.DecodeAndMutate(mutateGRPCRoute) +func MutateGRPCRoute(res *pbresource.Resource) error { + var route pbmesh.GRPCRoute + + if err := res.Data.UnmarshalTo(&route); err != nil { + return resource.NewErrDataParse(&route, err) + } -func mutateGRPCRoute(res *DecodedGRPCRoute) (bool, error) { changed := false - if mutateParentRefs(res.Id.Tenancy, res.Data.ParentRefs) { + if mutateParentRefs(res.Id.Tenancy, route.ParentRefs) { changed = true } - for _, rule := range res.Data.Rules { + for _, rule := range route.Rules { for _, backend := range rule.BackendRefs { if backend.BackendRef == nil || backend.BackendRef.Ref == nil { continue @@ -44,25 +49,33 @@ func mutateGRPCRoute(res *DecodedGRPCRoute) (bool, error) { } } - return changed, nil + if !changed { + return nil + } + + return res.Data.MarshalFrom(&route) } -var ValidateGRPCRoute = resource.DecodeAndValidate(validateGRPCRoute) +func ValidateGRPCRoute(res *pbresource.Resource) error { + var route pbmesh.GRPCRoute + + if err := res.Data.UnmarshalTo(&route); err != nil { + return resource.NewErrDataParse(&route, err) + } -func validateGRPCRoute(res *DecodedGRPCRoute) error { var merr error - if err := validateParentRefs(res.Id, res.Data.ParentRefs); err != nil { + if err := validateParentRefs(res.Id, route.ParentRefs); err != nil { merr = multierror.Append(merr, err) } - if len(res.Data.Hostnames) > 0 { + if len(route.Hostnames) > 0 { merr = multierror.Append(merr, resource.ErrInvalidField{ Name: "hostnames", Wrapped: errors.New("should not populate hostnames"), }) } - for i, rule := range res.Data.Rules { + for i, rule := range route.Rules { wrapRuleErr := func(err error) error { return resource.ErrInvalidListElement{ Name: "rules", diff --git a/internal/mesh/internal/types/http_route.go b/internal/mesh/internal/types/http_route.go index d32f55dc6cc82..0ac2dcbf5c8b0 100644 --- a/internal/mesh/internal/types/http_route.go +++ b/internal/mesh/internal/types/http_route.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/consul/internal/resource" pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" + "github.com/hashicorp/consul/proto-public/pbresource" ) func RegisterHTTPRoute(r resource.Registry) { @@ -26,16 +27,20 @@ func RegisterHTTPRoute(r resource.Registry) { }) } -var MutateHTTPRoute = resource.DecodeAndMutate(mutateHTTPRoute) +func MutateHTTPRoute(res *pbresource.Resource) error { + var route pbmesh.HTTPRoute + + if err := res.Data.UnmarshalTo(&route); err != nil { + return resource.NewErrDataParse(&route, err) + } -func mutateHTTPRoute(res *DecodedHTTPRoute) (bool, error) { changed := false - if mutateParentRefs(res.Id.Tenancy, res.Data.ParentRefs) { + if mutateParentRefs(res.Id.Tenancy, route.ParentRefs) { changed = true } - for _, rule := range res.Data.Rules { + for _, rule := range route.Rules { for _, match := range rule.Matches { if match.Method != "" { norm := strings.ToUpper(match.Method) @@ -55,25 +60,33 @@ func mutateHTTPRoute(res *DecodedHTTPRoute) (bool, error) { } } - return changed, nil + if !changed { + return nil + } + + return res.Data.MarshalFrom(&route) } -var ValidateHTTPRoute = resource.DecodeAndValidate(validateHTTPRoute) +func ValidateHTTPRoute(res *pbresource.Resource) error { + var route pbmesh.HTTPRoute + + if err := res.Data.UnmarshalTo(&route); err != nil { + return resource.NewErrDataParse(&route, err) + } -func validateHTTPRoute(res *DecodedHTTPRoute) error { var merr error - if err := validateParentRefs(res.Id, res.Data.ParentRefs); err != nil { + if err := validateParentRefs(res.Id, route.ParentRefs); err != nil { merr = multierror.Append(merr, err) } - if len(res.Data.Hostnames) > 0 { + if len(route.Hostnames) > 0 { merr = multierror.Append(merr, resource.ErrInvalidField{ Name: "hostnames", Wrapped: errors.New("should not populate hostnames"), }) } - for i, rule := range res.Data.Rules { + for i, rule := range route.Rules { wrapRuleErr := func(err error) error { return resource.ErrInvalidListElement{ Name: "rules", diff --git a/internal/mesh/internal/types/proxy_configuration.go b/internal/mesh/internal/types/proxy_configuration.go index 9a4388a40f01d..081324d721675 100644 --- a/internal/mesh/internal/types/proxy_configuration.go +++ b/internal/mesh/internal/types/proxy_configuration.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/consul/internal/resource" pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" + "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/sdk/iptables" ) @@ -26,40 +27,52 @@ func RegisterProxyConfiguration(r resource.Registry) { }) } -var MutateProxyConfiguration = resource.DecodeAndMutate(mutateProxyConfiguration) +func MutateProxyConfiguration(res *pbresource.Resource) error { + var proxyCfg pbmesh.ProxyConfiguration + err := res.Data.UnmarshalTo(&proxyCfg) + if err != nil { + return resource.NewErrDataParse(&proxyCfg, err) + } -func mutateProxyConfiguration(res *DecodedProxyConfiguration) (bool, error) { changed := false // Default the tproxy outbound port. - if res.Data.IsTransparentProxy() { - if res.Data.GetDynamicConfig().GetTransparentProxy() == nil { - res.Data.DynamicConfig.TransparentProxy = &pbmesh.TransparentProxy{ + if proxyCfg.IsTransparentProxy() { + if proxyCfg.GetDynamicConfig().GetTransparentProxy() == nil { + proxyCfg.DynamicConfig.TransparentProxy = &pbmesh.TransparentProxy{ OutboundListenerPort: iptables.DefaultTProxyOutboundPort, } changed = true - } else if res.Data.GetDynamicConfig().GetTransparentProxy().OutboundListenerPort == 0 { - res.Data.DynamicConfig.TransparentProxy.OutboundListenerPort = iptables.DefaultTProxyOutboundPort + } else if proxyCfg.GetDynamicConfig().GetTransparentProxy().OutboundListenerPort == 0 { + proxyCfg.DynamicConfig.TransparentProxy.OutboundListenerPort = iptables.DefaultTProxyOutboundPort changed = true } } - return changed, nil + if !changed { + return nil + } + + return res.Data.MarshalFrom(&proxyCfg) } -var ValidateProxyConfiguration = resource.DecodeAndValidate(validateProxyConfiguration) +func ValidateProxyConfiguration(res *pbresource.Resource) error { + decodedProxyCfg, decodeErr := resource.Decode[*pbmesh.ProxyConfiguration](res) + if decodeErr != nil { + return resource.NewErrDataParse(decodedProxyCfg.GetData(), decodeErr) + } + proxyCfg := decodedProxyCfg.GetData() -func validateProxyConfiguration(res *DecodedProxyConfiguration) error { var err error - if selErr := catalog.ValidateSelector(res.Data.Workloads, false); selErr != nil { + if selErr := catalog.ValidateSelector(proxyCfg.Workloads, false); selErr != nil { err = multierror.Append(err, resource.ErrInvalidField{ Name: "workloads", Wrapped: selErr, }) } - if res.Data.GetDynamicConfig() == nil && res.Data.GetBootstrapConfig() == nil { + if proxyCfg.GetDynamicConfig() == nil && proxyCfg.GetBootstrapConfig() == nil { err = multierror.Append(err, resource.ErrInvalidFields{ Names: []string{"dynamic_config", "bootstrap_config"}, Wrapped: errMissingProxyConfigData, @@ -67,14 +80,14 @@ func validateProxyConfiguration(res *DecodedProxyConfiguration) error { } // nolint:staticcheck - if res.Data.GetOpaqueConfig() != nil { + if proxyCfg.GetOpaqueConfig() != nil { err = multierror.Append(err, resource.ErrInvalidField{ Name: "opaque_config", Wrapped: resource.ErrUnsupported, }) } - if dynamicCfgErr := validateDynamicProxyConfiguration(res.Data.GetDynamicConfig()); dynamicCfgErr != nil { + if dynamicCfgErr := validateDynamicProxyConfiguration(proxyCfg.GetDynamicConfig()); dynamicCfgErr != nil { err = multierror.Append(err, resource.ErrInvalidField{ Name: "dynamic_config", Wrapped: dynamicCfgErr, diff --git a/internal/mesh/internal/types/proxy_state_template.go b/internal/mesh/internal/types/proxy_state_template.go index 43d2148217e03..7db3dbaf55fd9 100644 --- a/internal/mesh/internal/types/proxy_state_template.go +++ b/internal/mesh/internal/types/proxy_state_template.go @@ -50,21 +50,25 @@ func RegisterProxyStateTemplate(r resource.Registry) { }) } -var ValidateProxyStateTemplate = resource.DecodeAndValidate(validateProxyStateTemplate) - -func validateProxyStateTemplate(res *DecodedProxyStateTemplate) error { +func ValidateProxyStateTemplate(res *pbresource.Resource) error { // TODO(v2): validate a lot more of this + var pst pbmesh.ProxyStateTemplate + + if err := res.Data.UnmarshalTo(&pst); err != nil { + return resource.NewErrDataParse(&pst, err) + } + var merr error - if res.Data.ProxyState != nil { + if pst.ProxyState != nil { wrapProxyStateErr := func(err error) error { return resource.ErrInvalidField{ Name: "proxy_state", Wrapped: err, } } - for name, cluster := range res.Data.ProxyState.Clusters { + for name, cluster := range pst.ProxyState.Clusters { if name == "" { merr = multierror.Append(merr, wrapProxyStateErr(resource.ErrInvalidMapKey{ Map: "clusters", diff --git a/internal/mesh/internal/types/tcp_route.go b/internal/mesh/internal/types/tcp_route.go index 02dd5aaa10fdd..c7470b14d55ae 100644 --- a/internal/mesh/internal/types/tcp_route.go +++ b/internal/mesh/internal/types/tcp_route.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/consul/internal/resource" pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" + "github.com/hashicorp/consul/proto-public/pbresource" ) func RegisterTCPRoute(r resource.Registry) { @@ -23,16 +24,20 @@ func RegisterTCPRoute(r resource.Registry) { }) } -var MutateTCPRoute = resource.DecodeAndMutate(mutateTCPRoute) +func MutateTCPRoute(res *pbresource.Resource) error { + var route pbmesh.TCPRoute + + if err := res.Data.UnmarshalTo(&route); err != nil { + return resource.NewErrDataParse(&route, err) + } -func mutateTCPRoute(res *DecodedTCPRoute) (bool, error) { changed := false - if mutateParentRefs(res.Id.Tenancy, res.Data.ParentRefs) { + if mutateParentRefs(res.Id.Tenancy, route.ParentRefs) { changed = true } - for _, rule := range res.Data.Rules { + for _, rule := range route.Rules { for _, backend := range rule.BackendRefs { if backend.BackendRef == nil || backend.BackendRef.Ref == nil { continue @@ -43,26 +48,34 @@ func mutateTCPRoute(res *DecodedTCPRoute) (bool, error) { } } - return changed, nil + if !changed { + return nil + } + + return res.Data.MarshalFrom(&route) } -var ValidateTCPRoute = resource.DecodeAndValidate(validateTCPRoute) +func ValidateTCPRoute(res *pbresource.Resource) error { + var route pbmesh.TCPRoute + + if err := res.Data.UnmarshalTo(&route); err != nil { + return resource.NewErrDataParse(&route, err) + } -func validateTCPRoute(res *DecodedTCPRoute) error { var merr error - if err := validateParentRefs(res.Id, res.Data.ParentRefs); err != nil { + if err := validateParentRefs(res.Id, route.ParentRefs); err != nil { merr = multierror.Append(merr, err) } - if len(res.Data.Rules) > 1 { + if len(route.Rules) > 1 { merr = multierror.Append(merr, resource.ErrInvalidField{ Name: "rules", Wrapped: fmt.Errorf("must only specify a single rule for now"), }) } - for i, rule := range res.Data.Rules { + for i, rule := range route.Rules { wrapRuleErr := func(err error) error { return resource.ErrInvalidListElement{ Name: "rules", diff --git a/internal/mesh/internal/types/xroute.go b/internal/mesh/internal/types/xroute.go index 92e2136cd1356..619c9cb682435 100644 --- a/internal/mesh/internal/types/xroute.go +++ b/internal/mesh/internal/types/xroute.go @@ -288,17 +288,28 @@ func isValidRetryCondition(retryOn string) bool { func xRouteACLHooks[R XRouteData]() *resource.ACLHooks { hooks := &resource.ACLHooks{ - Read: resource.DecodeAndAuthorizeRead(aclReadHookXRoute[R]), - Write: resource.DecodeAndAuthorizeWrite(aclWriteHookXRoute[R]), + Read: aclReadHookXRoute[R], + Write: aclWriteHookXRoute[R], List: resource.NoOpACLListHook, } return hooks } -func aclReadHookXRoute[R XRouteData](authorizer acl.Authorizer, _ *acl.AuthorizerContext, res *resource.DecodedResource[R]) error { +func aclReadHookXRoute[R XRouteData](authorizer acl.Authorizer, _ *acl.AuthorizerContext, _ *pbresource.ID, res *pbresource.Resource) error { + if res == nil { + return resource.ErrNeedResource + } + + dec, err := resource.Decode[R](res) + if err != nil { + return err + } + + route := dec.Data + // Need service:read on ALL of the services this is controlling traffic for. - for _, parentRef := range res.Data.GetParentRefs() { + for _, parentRef := range route.GetParentRefs() { parentAuthzContext := resource.AuthorizerContext(parentRef.Ref.GetTenancy()) parentServiceName := parentRef.Ref.GetName() @@ -310,9 +321,16 @@ func aclReadHookXRoute[R XRouteData](authorizer acl.Authorizer, _ *acl.Authorize return nil } -func aclWriteHookXRoute[R XRouteData](authorizer acl.Authorizer, _ *acl.AuthorizerContext, res *resource.DecodedResource[R]) error { +func aclWriteHookXRoute[R XRouteData](authorizer acl.Authorizer, _ *acl.AuthorizerContext, res *pbresource.Resource) error { + dec, err := resource.Decode[R](res) + if err != nil { + return err + } + + route := dec.Data + // Need service:write on ALL of the services this is controlling traffic for. - for _, parentRef := range res.Data.GetParentRefs() { + for _, parentRef := range route.GetParentRefs() { parentAuthzContext := resource.AuthorizerContext(parentRef.Ref.GetTenancy()) parentServiceName := parentRef.Ref.GetName() @@ -322,7 +340,7 @@ func aclWriteHookXRoute[R XRouteData](authorizer acl.Authorizer, _ *acl.Authoriz } // Need service:read on ALL of the services this directs traffic at. - for _, backendRef := range res.Data.GetUnderlyingBackendRefs() { + for _, backendRef := range route.GetUnderlyingBackendRefs() { backendAuthzContext := resource.AuthorizerContext(backendRef.Ref.GetTenancy()) backendServiceName := backendRef.Ref.GetName() diff --git a/internal/multicluster/exports.go b/internal/multicluster/exports.go deleted file mode 100644 index fcf5873d81ceb..0000000000000 --- a/internal/multicluster/exports.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package multicluster - -import ( - "github.com/hashicorp/consul/internal/multicluster/internal/types" - "github.com/hashicorp/consul/internal/resource" -) - -var ( - // API Group Information - APIGroup = types.GroupName - VersionV2Beta1 = types.VersionV2Beta1 - CurrentVersion = types.CurrentVersion -) - -// RegisterTypes adds all resource types within the "multicluster" API group -// to the given type registry -func RegisterTypes(r resource.Registry) { - types.Register(r) -} diff --git a/internal/multicluster/internal/types/computed_exported_services.go b/internal/multicluster/internal/types/computed_exported_services.go deleted file mode 100644 index 70c900c9b86cd..0000000000000 --- a/internal/multicluster/internal/types/computed_exported_services.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - ComputedExportedServicesName = "global" -) - -func RegisterComputedExportedServices(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmulticluster.ComputedExportedServicesType, - Proto: &pbmulticluster.ComputedExportedServices{}, - Scope: resource.ScopePartition, - Validate: ValidateComputedExportedServices, - ACLs: &resource.ACLHooks{ - Read: aclReadHookComputedExportedServices, - Write: aclWriteHookComputedExportedServices, - List: resource.NoOpACLListHook, - }, - }) -} - -func aclReadHookComputedExportedServices(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, _ *pbresource.ID, res *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().MeshReadAllowed(authzContext) -} - -func aclWriteHookComputedExportedServices(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, _ *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().MeshWriteAllowed(authzContext) -} diff --git a/internal/multicluster/internal/types/computed_exported_services_test.go b/internal/multicluster/internal/types/computed_exported_services_test.go deleted file mode 100644 index 79462c7088c32..0000000000000 --- a/internal/multicluster/internal/types/computed_exported_services_test.go +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/stretchr/testify/require" - "testing" -) - -func computedExportedServicesWithPartition(partitionName string) *pbmulticluster.ComputedExportedServices { - consumers := []*pbmulticluster.ComputedExportedService{ - { - Consumers: []*pbmulticluster.ComputedExportedServicesConsumer{ - { - ConsumerTenancy: &pbmulticluster.ComputedExportedServicesConsumer_Partition{ - Partition: partitionName, - }, - }, - }, - }, - } - return &pbmulticluster.ComputedExportedServices{ - Consumers: consumers, - } -} - -func computedExportedServicesWithPeer(peerName string) *pbmulticluster.ComputedExportedServices { - consumers := []*pbmulticluster.ComputedExportedService{ - { - Consumers: []*pbmulticluster.ComputedExportedServicesConsumer{ - { - ConsumerTenancy: &pbmulticluster.ComputedExportedServicesConsumer_Peer{ - Peer: peerName, - }, - }, - }, - }, - } - return &pbmulticluster.ComputedExportedServices{ - Consumers: consumers, - } -} - -func TestComputedExportedServicesValidations_InvalidName(t *testing.T) { - res := resourcetest.Resource(pbmulticluster.ComputedExportedServicesType, "computed-exported-services"). - WithData(t, computedExportedServicesWithPeer("peer")). - Build() - - err := ValidateComputedExportedServices(res) - require.Error(t, err) - expectedError := errors.New("invalid \"name\" field: name can only be \"global\"") - require.ErrorAs(t, err, &expectedError) -} - -func TestComputedExportedServicesACLs(t *testing.T) { - // Wire up a registry to generically invoke hooks - registry := resource.NewRegistry() - Register(registry) - - type testcase struct { - rules string - readOK string - writeOK string - listOK string - } - - const ( - DENY = resourcetest.DENY - ALLOW = resourcetest.ALLOW - DEFAULT = resourcetest.DEFAULT - ) - - exportedServiceData := &pbmulticluster.ComputedExportedServices{} - res := resourcetest.Resource(pbmulticluster.ComputedExportedServicesType, "global"). - WithData(t, exportedServiceData). - Build() - resourcetest.ValidateAndNormalize(t, registry, res) - - cases := map[string]testcase{ - "no rules": { - rules: ``, - readOK: DENY, - writeOK: DENY, - listOK: DEFAULT, - }, - "mesh read policy": { - rules: `mesh = "read"`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "mesh write policy": { - rules: `mesh = "write"`, - readOK: ALLOW, - writeOK: ALLOW, - listOK: DEFAULT, - }, - } - - for _, tc := range cases { - aclTestCase := resourcetest.ACLTestCase{ - Rules: tc.rules, - Res: res, - ReadOK: tc.readOK, - WriteOK: tc.writeOK, - ListOK: tc.listOK, - } - resourcetest.RunACLTestCase(t, aclTestCase, registry) - } -} - -func TestComputedExportedServicesValidations(t *testing.T) { - type testcase struct { - Resource *pbresource.Resource - expectErrorCE []string - expectErrorENT []string - } - - isEnterprise := structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty() == "default" - - run := func(t *testing.T, tc testcase) { - expectError := tc.expectErrorCE - if isEnterprise { - expectError = tc.expectErrorENT - } - err := ValidateComputedExportedServices(tc.Resource) - if len(expectError) == 0 { - require.NoError(t, err) - } else { - require.Error(t, err) - for _, er := range expectError { - require.ErrorContains(t, err, er) - } - } - } - - cases := map[string]testcase{ - "computed exported services with peer": { - Resource: resourcetest.Resource(pbmulticluster.ComputedExportedServicesType, ComputedExportedServicesName). - WithData(t, computedExportedServicesWithPeer("peer")). - Build(), - }, - "computed exported services with partition": { - Resource: resourcetest.Resource(pbmulticluster.ComputedExportedServicesType, ComputedExportedServicesName). - WithData(t, computedExportedServicesWithPartition("partition")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "partition": can only be set in Enterprise`}, - }, - "computed exported services with peer empty": { - Resource: resourcetest.Resource(pbmulticluster.ComputedExportedServicesType, ComputedExportedServicesName). - WithData(t, computedExportedServicesWithPeer("")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "peer": can not be empty`}, - expectErrorENT: []string{`invalid element at index 0 of list "peer": can not be empty`}, - }, - "computed exported services with partition empty": { - Resource: resourcetest.Resource(pbmulticluster.ComputedExportedServicesType, ComputedExportedServicesName). - WithData(t, computedExportedServicesWithPartition("")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "partition": can not be empty`, - `invalid element at index 0 of list "partition": can only be set in Enterprise`}, - expectErrorENT: []string{`invalid element at index 0 of list "partition": can not be empty`}, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/multicluster/internal/types/exported_services.go b/internal/multicluster/internal/types/exported_services.go deleted file mode 100644 index 87cebb244ab4e..0000000000000 --- a/internal/multicluster/internal/types/exported_services.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func RegisterExportedServices(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmulticluster.ExportedServicesType, - Proto: &pbmulticluster.ExportedServices{}, - Scope: resource.ScopeNamespace, - Validate: ValidateExportedServices, - ACLs: &resource.ACLHooks{ - Read: aclReadHookExportedServices, - Write: aclWriteHookExportedServices, - List: resource.NoOpACLListHook, - }, - }) -} - -func aclReadHookExportedServices(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, _ *pbresource.ID, res *pbresource.Resource) error { - if res == nil { - return resource.ErrNeedResource - } - - var exportedService pbmulticluster.ExportedServices - - if err := res.Data.UnmarshalTo(&exportedService); err != nil { - return resource.NewErrDataParse(&exportedService, err) - } - - for _, serviceName := range exportedService.Services { - if err := authorizer.ToAllowAuthorizer().ServiceReadAllowed(serviceName, authzContext); err != nil { - return err - } - } - return nil -} - -func aclWriteHookExportedServices(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { - var exportedService pbmulticluster.ExportedServices - - if err := res.Data.UnmarshalTo(&exportedService); err != nil { - return resource.NewErrDataParse(&exportedService, err) - } - - for _, serviceName := range exportedService.Services { - if err := authorizer.ToAllowAuthorizer().ServiceWriteAllowed(serviceName, authzContext); err != nil { - return err - } - } - return nil -} diff --git a/internal/multicluster/internal/types/exported_services_test.go b/internal/multicluster/internal/types/exported_services_test.go deleted file mode 100644 index ea80b16e43df4..0000000000000 --- a/internal/multicluster/internal/types/exported_services_test.go +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/stretchr/testify/require" - "testing" -) - -func inValidExportedServices() *pbmulticluster.ExportedServices { - return &pbmulticluster.ExportedServices{} -} - -func exportedServicesWithPeer(peerName string) *pbmulticluster.ExportedServices { - consumers := []*pbmulticluster.ExportedServicesConsumer{ - { - ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_Peer{ - Peer: peerName, - }, - }, - } - return &pbmulticluster.ExportedServices{ - Services: []string{"api", "frontend", "backend"}, - Consumers: consumers, - } -} - -func exportedServicesWithPartition(partitionName string) *pbmulticluster.ExportedServices { - consumers := []*pbmulticluster.ExportedServicesConsumer{ - { - ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_Partition{ - Partition: partitionName, - }, - }, - } - return &pbmulticluster.ExportedServices{ - Services: []string{"api", "frontend", "backend"}, - Consumers: consumers, - } -} - -func exportedServicesWithSamenessGroup(samenessGroupName string) *pbmulticluster.ExportedServices { - consumers := []*pbmulticluster.ExportedServicesConsumer{ - { - ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_SamenessGroup{ - SamenessGroup: samenessGroupName, - }, - }, - } - return &pbmulticluster.ExportedServices{ - Services: []string{"api", "frontend", "backend"}, - Consumers: consumers, - } -} - -func TestExportedServicesValidation_NoServices(t *testing.T) { - res := resourcetest.Resource(pbmulticluster.ExportedServicesType, "exportedservices1"). - WithData(t, inValidExportedServices()). - Build() - - err := ValidateExportedServices(res) - require.Error(t, err) - expectedError := errors.New("invalid \"services\" field: at least one service must be set") - require.ErrorAs(t, err, &expectedError) -} - -func TestExportedServicesACLs(t *testing.T) { - // Wire up a registry to generically invoke hooks - registry := resource.NewRegistry() - Register(registry) - - type testcase struct { - rules string - readOK string - writeOK string - listOK string - } - - const ( - DENY = resourcetest.DENY - ALLOW = resourcetest.ALLOW - DEFAULT = resourcetest.DEFAULT - ) - - exportedServiceData := &pbmulticluster.ExportedServices{ - Services: []string{"api", "backend"}, - } - res := resourcetest.Resource(pbmulticluster.ExportedServicesType, "exps"). - WithData(t, exportedServiceData). - Build() - resourcetest.ValidateAndNormalize(t, registry, res) - - cases := map[string]testcase{ - "no rules": { - rules: ``, - readOK: DENY, - writeOK: DENY, - listOK: DEFAULT, - }, - "all services has read policy": { - rules: `service "api" { policy = "read" } service "backend" {policy = "read"}`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "all services has write policy": { - rules: `service "api" { policy = "write" } service "backend" {policy = "write"}`, - readOK: ALLOW, - writeOK: ALLOW, - listOK: DEFAULT, - }, - "only one services has read policy": { - rules: `service "api" { policy = "read" }`, - readOK: DENY, - writeOK: DENY, - listOK: DEFAULT, - }, - "only one services has write policy": { - rules: `service "api" { policy = "write" }`, - readOK: DENY, - writeOK: DENY, - listOK: DEFAULT, - }, - } - - for _, tc := range cases { - aclTestCase := resourcetest.ACLTestCase{ - Rules: tc.rules, - Res: res, - ReadOK: tc.readOK, - WriteOK: tc.writeOK, - ListOK: tc.listOK, - } - resourcetest.RunACLTestCase(t, aclTestCase, registry) - } -} - -func TestExportedServicesValidation(t *testing.T) { - type testcase struct { - Resource *pbresource.Resource - expectErrorCE []string - expectErrorENT []string - } - - isEnterprise := structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty() == "default" - - run := func(t *testing.T, tc testcase) { - expectError := tc.expectErrorCE - if isEnterprise { - expectError = tc.expectErrorENT - } - err := ValidateExportedServices(tc.Resource) - if len(expectError) == 0 { - require.NoError(t, err) - } else { - require.Error(t, err) - for _, er := range expectError { - require.ErrorContains(t, err, er) - } - } - } - - cases := map[string]testcase{ - "exported services with peer": { - Resource: resourcetest.Resource(pbmulticluster.ExportedServicesType, "exported-services"). - WithData(t, exportedServicesWithPeer("peer")). - Build(), - }, - "exported services with partition": { - Resource: resourcetest.Resource(pbmulticluster.ExportedServicesType, "exported-services"). - WithData(t, exportedServicesWithPartition("partition")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "partition": can only be set in Enterprise`}, - }, - "exported services with sameness_group": { - Resource: resourcetest.Resource(pbmulticluster.ExportedServicesType, "exported-services"). - WithData(t, exportedServicesWithSamenessGroup("sameness_group")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "sameness_group": can only be set in Enterprise`}, - }, - "exported services with peer empty": { - Resource: resourcetest.Resource(pbmulticluster.ExportedServicesType, "exported-services"). - WithData(t, exportedServicesWithPeer("")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "peer": can not be empty or local`}, - expectErrorENT: []string{`invalid element at index 0 of list "peer": can not be empty or local`}, - }, - "exported services with partition empty": { - Resource: resourcetest.Resource(pbmulticluster.ExportedServicesType, "exported-services"). - WithData(t, exportedServicesWithPartition("")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "partition": can not be empty`, - `invalid element at index 0 of list "partition": can only be set in Enterprise`}, - expectErrorENT: []string{`invalid element at index 0 of list "partition": can not be empty`}, - }, - "exported services with sameness_group empty": { - Resource: resourcetest.Resource(pbmulticluster.ExportedServicesType, "exported-services"). - WithData(t, exportedServicesWithSamenessGroup("")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "sameness_group": can not be empty`, - `invalid element at index 0 of list "sameness_group": can only be set in Enterprise`}, - expectErrorENT: []string{`invalid element at index 0 of list "sameness_group": can not be empty`}, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/multicluster/internal/types/helpers.go b/internal/multicluster/internal/types/helpers.go deleted file mode 100644 index 5dac17f1e7a97..0000000000000 --- a/internal/multicluster/internal/types/helpers.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "fmt" - "github.com/hashicorp/consul/internal/resource" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/go-multierror" -) - -func validateExportedServiceConsumerCommon(consumer *pbmulticluster.ExportedServicesConsumer, indx int) error { - switch consumer.GetConsumerTenancy().(type) { - case *pbmulticluster.ExportedServicesConsumer_Peer: - { - if consumer.GetPeer() == "" || consumer.GetPeer() == "local" { - return resource.ErrInvalidListElement{ - Name: "peer", - Index: indx, - Wrapped: fmt.Errorf("can not be empty or local"), - } - } - } - case *pbmulticluster.ExportedServicesConsumer_Partition: - { - if consumer.GetPartition() == "" { - return resource.ErrInvalidListElement{ - Name: "partition", - Index: indx, - Wrapped: fmt.Errorf("can not be empty"), - } - } - } - case *pbmulticluster.ExportedServicesConsumer_SamenessGroup: - { - if consumer.GetSamenessGroup() == "" { - return resource.ErrInvalidListElement{ - Name: "sameness_group", - Index: indx, - Wrapped: fmt.Errorf("can not be empty"), - } - } - } - } - return nil -} - -func validateExportedServicesConsumersEnterprise(consumers []*pbmulticluster.ExportedServicesConsumer) error { - var merr error - - for indx, consumer := range consumers { - vmerr := validateExportedServiceConsumerCommon(consumer, indx) - if vmerr != nil { - merr = multierror.Append(merr, vmerr) - } - vmerr = validateExportedServicesConsumer(consumer, indx) - if vmerr != nil { - merr = multierror.Append(merr, vmerr) - } - } - - return merr -} - -func ValidateExportedServices(res *pbresource.Resource) error { - var exportedService pbmulticluster.ExportedServices - - if err := res.Data.UnmarshalTo(&exportedService); err != nil { - return resource.NewErrDataParse(&exportedService, err) - } - - var merr error - - if len(exportedService.Services) == 0 { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "services", - Wrapped: fmt.Errorf("at least one service must be set"), - }) - } - - vmerr := validateExportedServicesConsumersEnterprise(exportedService.Consumers) - - if vmerr != nil { - merr = multierror.Append(merr, vmerr) - } - - return merr -} - -func ValidateNamespaceExportedServices(res *pbresource.Resource) error { - var exportedService pbmulticluster.NamespaceExportedServices - - if err := res.Data.UnmarshalTo(&exportedService); err != nil { - return resource.NewErrDataParse(&exportedService, err) - } - - return validateExportedServicesConsumersEnterprise(exportedService.Consumers) -} - -func ValidatePartitionExportedServices(res *pbresource.Resource) error { - var exportedService pbmulticluster.PartitionExportedServices - - if err := res.Data.UnmarshalTo(&exportedService); err != nil { - return resource.NewErrDataParse(&exportedService, err) - } - - return validateExportedServicesConsumersEnterprise(exportedService.Consumers) -} - -func ValidateComputedExportedServices(res *pbresource.Resource) error { - var computedExportedServices pbmulticluster.ComputedExportedServices - - if err := res.Data.UnmarshalTo(&computedExportedServices); err != nil { - return resource.NewErrDataParse(&computedExportedServices, err) - } - - var merr error - - if res.Id.Name != ComputedExportedServicesName { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "name", - Wrapped: fmt.Errorf("name can only be \"global\""), - }) - } - - vmerr := ValidateComputedExportedServicesEnterprise(&computedExportedServices) - - if vmerr != nil { - merr = multierror.Append(merr, vmerr) - } - - return merr -} diff --git a/internal/multicluster/internal/types/helpers_ce.go b/internal/multicluster/internal/types/helpers_ce.go deleted file mode 100644 index b997b8671ad05..0000000000000 --- a/internal/multicluster/internal/types/helpers_ce.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent - -package types - -import ( - "fmt" - "github.com/hashicorp/consul/internal/resource" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" - "github.com/hashicorp/go-multierror" -) - -func validateExportedServicesConsumer(consumer *pbmulticluster.ExportedServicesConsumer, indx int) error { - switch consumer.GetConsumerTenancy().(type) { - case *pbmulticluster.ExportedServicesConsumer_Partition: - return resource.ErrInvalidListElement{ - Name: "partition", - Index: indx, - Wrapped: fmt.Errorf("can only be set in Enterprise"), - } - case *pbmulticluster.ExportedServicesConsumer_SamenessGroup: - return resource.ErrInvalidListElement{ - Name: "sameness_group", - Index: indx, - Wrapped: fmt.Errorf("can only be set in Enterprise"), - } - } - return nil -} - -func ValidateComputedExportedServicesEnterprise(computedExportedServices *pbmulticluster.ComputedExportedServices) error { - - var merr error - - for indx, consumer := range computedExportedServices.GetConsumers() { - for _, computedExportedServiceConsumer := range consumer.GetConsumers() { - switch computedExportedServiceConsumer.GetConsumerTenancy().(type) { - case *pbmulticluster.ComputedExportedServicesConsumer_Partition: - merr = multierror.Append(merr, resource.ErrInvalidListElement{ - Name: "partition", - Index: indx, - Wrapped: fmt.Errorf("can only be set in Enterprise"), - }) - if computedExportedServiceConsumer.GetPartition() == "" { - merr = multierror.Append(merr, resource.ErrInvalidListElement{ - Name: "partition", - Index: indx, - Wrapped: fmt.Errorf("can not be empty"), - }) - } - case *pbmulticluster.ComputedExportedServicesConsumer_Peer: - if computedExportedServiceConsumer.GetPeer() == "" { - merr = multierror.Append(merr, resource.ErrInvalidListElement{ - Name: "peer", - Index: indx, - Wrapped: fmt.Errorf("can not be empty"), - }) - } - } - } - } - - return merr -} diff --git a/internal/multicluster/internal/types/namespace_exported_services.go b/internal/multicluster/internal/types/namespace_exported_services.go deleted file mode 100644 index 857ea868b8e96..0000000000000 --- a/internal/multicluster/internal/types/namespace_exported_services.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func RegisterNamespaceExportedServices(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmulticluster.NamespaceExportedServicesType, - Proto: &pbmulticluster.NamespaceExportedServices{}, - Scope: resource.ScopeNamespace, - Validate: ValidateNamespaceExportedServices, - ACLs: &resource.ACLHooks{ - Read: aclReadHookNamespaceExportedServices, - Write: aclWriteHookNamespaceExportedServices, - List: resource.NoOpACLListHook, - }, - }) -} - -func aclReadHookNamespaceExportedServices(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID, res *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().MeshReadAllowed(authzContext) -} - -func aclWriteHookNamespaceExportedServices(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().MeshWriteAllowed(authzContext) -} diff --git a/internal/multicluster/internal/types/namespace_exported_services_test.go b/internal/multicluster/internal/types/namespace_exported_services_test.go deleted file mode 100644 index ab88a03767fce..0000000000000 --- a/internal/multicluster/internal/types/namespace_exported_services_test.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/stretchr/testify/require" - "testing" -) - -func validNamespaceExportedServicesWithPeer(peerName string) *pbmulticluster.NamespaceExportedServices { - consumers := []*pbmulticluster.ExportedServicesConsumer{ - { - ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_Peer{ - Peer: peerName, - }, - }, - } - return &pbmulticluster.NamespaceExportedServices{ - Consumers: consumers, - } -} - -func validNamespaceExportedServicesWithPartition(partitionName string) *pbmulticluster.NamespaceExportedServices { - consumers := []*pbmulticluster.ExportedServicesConsumer{ - { - ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_Partition{ - Partition: partitionName, - }, - }, - } - return &pbmulticluster.NamespaceExportedServices{ - Consumers: consumers, - } -} - -func validNamespaceExportedServicesWithSamenessGroup(samenessGroupName string) *pbmulticluster.NamespaceExportedServices { - consumers := []*pbmulticluster.ExportedServicesConsumer{ - { - ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_SamenessGroup{ - SamenessGroup: samenessGroupName, - }, - }, - } - return &pbmulticluster.NamespaceExportedServices{ - Consumers: consumers, - } -} -func TestNamespaceExportedServicesACLs(t *testing.T) { - // Wire up a registry to generically invoke hooks - registry := resource.NewRegistry() - Register(registry) - - type testcase struct { - rules string - readOK string - writeOK string - listOK string - } - - const ( - DENY = resourcetest.DENY - ALLOW = resourcetest.ALLOW - DEFAULT = resourcetest.DEFAULT - ) - - cases := map[string]testcase{ - "no rules": { - rules: ``, - readOK: DENY, - writeOK: DENY, - listOK: DEFAULT, - }, - "mesh read policy": { - rules: `mesh = "read"`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "mesh write policy": { - rules: `mesh = "write"`, - readOK: ALLOW, - writeOK: ALLOW, - listOK: DEFAULT, - }, - } - - exportedServiceData := &pbmulticluster.NamespaceExportedServices{} - res := resourcetest.Resource(pbmulticluster.NamespaceExportedServicesType, "namespace-exported-services"). - WithData(t, exportedServiceData). - Build() - resourcetest.ValidateAndNormalize(t, registry, res) - - for _, tc := range cases { - aclTestCase := resourcetest.ACLTestCase{ - Rules: tc.rules, - Res: res, - ReadOK: tc.readOK, - WriteOK: tc.writeOK, - ListOK: tc.listOK, - } - resourcetest.RunACLTestCase(t, aclTestCase, registry) - } -} - -func TestNamespaceExportedServicesValidations(t *testing.T) { - type testcase struct { - Resource *pbresource.Resource - expectErrorCE []string - expectErrorENT []string - } - - isEnterprise := structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty() == "default" - - run := func(t *testing.T, tc testcase) { - expectError := tc.expectErrorCE - if isEnterprise { - expectError = tc.expectErrorENT - } - err := ValidateNamespaceExportedServices(tc.Resource) - if len(expectError) == 0 { - require.NoError(t, err) - } else { - require.Error(t, err) - for _, er := range expectError { - require.ErrorContains(t, err, er) - } - } - } - - cases := map[string]testcase{ - "namespace exported services with peer": { - Resource: resourcetest.Resource(pbmulticluster.NamespaceExportedServicesType, "namespace-exported-services"). - WithData(t, validNamespaceExportedServicesWithPeer("peer")). - Build(), - }, - "namespace exported services with partition": { - Resource: resourcetest.Resource(pbmulticluster.NamespaceExportedServicesType, "namespace-exported-services"). - WithData(t, validNamespaceExportedServicesWithPartition("partition")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "partition": can only be set in Enterprise`}, - }, - "namespace exported services with sameness_group": { - Resource: resourcetest.Resource(pbmulticluster.NamespaceExportedServicesType, "namespace-exported-services"). - WithData(t, validNamespaceExportedServicesWithSamenessGroup("sameness_group")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "sameness_group": can only be set in Enterprise`}, - }, - "namespace exported services with peer empty": { - Resource: resourcetest.Resource(pbmulticluster.NamespaceExportedServicesType, "namespace-exported-services"). - WithData(t, validNamespaceExportedServicesWithPeer("")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "peer": can not be empty or local`}, - expectErrorENT: []string{`invalid element at index 0 of list "peer": can not be empty or local`}, - }, - "namespace exported services with partition empty": { - Resource: resourcetest.Resource(pbmulticluster.NamespaceExportedServicesType, "namespace-exported-services"). - WithData(t, validNamespaceExportedServicesWithPartition("")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "partition": can not be empty`, - `invalid element at index 0 of list "partition": can only be set in Enterprise`}, - expectErrorENT: []string{`invalid element at index 0 of list "partition": can not be empty`}, - }, - "namespace exported services with sameness_group empty": { - Resource: resourcetest.Resource(pbmulticluster.NamespaceExportedServicesType, "namespace-exported-services"). - WithData(t, validNamespaceExportedServicesWithSamenessGroup("")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "sameness_group": can not be empty`, - `invalid element at index 0 of list "sameness_group": can only be set in Enterprise`}, - expectErrorENT: []string{`invalid element at index 0 of list "sameness_group": can not be empty`}, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/multicluster/internal/types/partition_exported_services.go b/internal/multicluster/internal/types/partition_exported_services.go deleted file mode 100644 index 110eb5d6efa13..0000000000000 --- a/internal/multicluster/internal/types/partition_exported_services.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func RegisterPartitionExportedServices(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmulticluster.PartitionExportedServicesType, - Proto: &pbmulticluster.PartitionExportedServices{}, - Scope: resource.ScopePartition, - Validate: ValidatePartitionExportedServices, - ACLs: &resource.ACLHooks{ - Read: aclReadHookPartitionExportedServices, - Write: aclWriteHookPartitionExportedServices, - List: resource.NoOpACLListHook, - }, - }) -} - -func aclReadHookPartitionExportedServices(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID, res *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().MeshReadAllowed(authzContext) -} - -func aclWriteHookPartitionExportedServices(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().MeshWriteAllowed(authzContext) -} diff --git a/internal/multicluster/internal/types/partition_exported_services_test.go b/internal/multicluster/internal/types/partition_exported_services_test.go deleted file mode 100644 index fdd90ef11d12f..0000000000000 --- a/internal/multicluster/internal/types/partition_exported_services_test.go +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/stretchr/testify/require" - "testing" -) - -func validPartitionExportedServicesWithPeer(peerName string) *pbmulticluster.PartitionExportedServices { - consumers := []*pbmulticluster.ExportedServicesConsumer{ - { - ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_Peer{ - Peer: peerName, - }, - }, - } - return &pbmulticluster.PartitionExportedServices{ - Consumers: consumers, - } -} - -func validPartitionExportedServicesWithPartition(partitionName string) *pbmulticluster.PartitionExportedServices { - consumers := []*pbmulticluster.ExportedServicesConsumer{ - { - ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_Partition{ - Partition: partitionName, - }, - }, - } - return &pbmulticluster.PartitionExportedServices{ - Consumers: consumers, - } -} - -func validPartitionExportedServicesWithSamenessGroup(samenessGroupName string) *pbmulticluster.PartitionExportedServices { - consumers := []*pbmulticluster.ExportedServicesConsumer{ - { - ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_SamenessGroup{ - SamenessGroup: samenessGroupName, - }, - }, - } - return &pbmulticluster.PartitionExportedServices{ - Consumers: consumers, - } -} - -func TestPartitionExportedServicesACLs(t *testing.T) { - // Wire up a registry to generically invoke hooks - registry := resource.NewRegistry() - Register(registry) - - type testcase struct { - rules string - readOK string - writeOK string - listOK string - } - - const ( - DENY = resourcetest.DENY - ALLOW = resourcetest.ALLOW - DEFAULT = resourcetest.DEFAULT - ) - - cases := map[string]testcase{ - "no rules": { - rules: ``, - readOK: DENY, - writeOK: DENY, - listOK: DEFAULT, - }, - "mesh read policy": { - rules: `mesh = "read"`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "mesh write policy": { - rules: `mesh = "write"`, - readOK: ALLOW, - writeOK: ALLOW, - listOK: DEFAULT, - }, - } - - exportedServiceData := &pbmulticluster.PartitionExportedServices{} - res := resourcetest.Resource(pbmulticluster.PartitionExportedServicesType, "partition-exported-services"). - WithData(t, exportedServiceData). - Build() - resourcetest.ValidateAndNormalize(t, registry, res) - - for _, tc := range cases { - aclTestCase := resourcetest.ACLTestCase{ - Rules: tc.rules, - Res: res, - ReadOK: tc.readOK, - WriteOK: tc.writeOK, - ListOK: tc.listOK, - } - resourcetest.RunACLTestCase(t, aclTestCase, registry) - } -} - -func TestPartitionExportedServicesValidations(t *testing.T) { - type testcase struct { - Resource *pbresource.Resource - expectErrorCE []string - expectErrorENT []string - } - - isEnterprise := structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty() == "default" - - run := func(t *testing.T, tc testcase) { - expectError := tc.expectErrorCE - if isEnterprise { - expectError = tc.expectErrorENT - } - err := ValidatePartitionExportedServices(tc.Resource) - if len(expectError) == 0 { - require.NoError(t, err) - } else { - require.Error(t, err) - for _, er := range expectError { - require.ErrorContains(t, err, er) - } - } - } - - cases := map[string]testcase{ - "partition exported services with peer": { - Resource: resourcetest.Resource(pbmulticluster.PartitionExportedServicesType, "partition-exported-services"). - WithData(t, validPartitionExportedServicesWithPeer("peer")). - Build(), - }, - "partition exported services with partition": { - Resource: resourcetest.Resource(pbmulticluster.PartitionExportedServicesType, "partition-exported-services"). - WithData(t, validPartitionExportedServicesWithPartition("partition")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "partition": can only be set in Enterprise`}, - }, - "partition exported services with sameness_group": { - Resource: resourcetest.Resource(pbmulticluster.PartitionExportedServicesType, "partition-exported-services"). - WithData(t, validPartitionExportedServicesWithSamenessGroup("sameness_group")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "sameness_group": can only be set in Enterprise`}, - }, - "partition exported services with peer empty": { - Resource: resourcetest.Resource(pbmulticluster.PartitionExportedServicesType, "partition-exported-services"). - WithData(t, validPartitionExportedServicesWithPeer("")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "peer": can not be empty or local`}, - expectErrorENT: []string{`invalid element at index 0 of list "peer": can not be empty or local`}, - }, - "partition exported services with partition empty": { - Resource: resourcetest.Resource(pbmulticluster.PartitionExportedServicesType, "partition-exported-services"). - WithData(t, validPartitionExportedServicesWithPartition("")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "partition": can not be empty`, - `invalid element at index 0 of list "partition": can only be set in Enterprise`}, - expectErrorENT: []string{`invalid element at index 0 of list "partition": can not be empty`}, - }, - "partition exported services with sameness_group empty": { - Resource: resourcetest.Resource(pbmulticluster.PartitionExportedServicesType, "partition-exported-services"). - WithData(t, validPartitionExportedServicesWithSamenessGroup("")). - Build(), - expectErrorCE: []string{`invalid element at index 0 of list "sameness_group": can not be empty`, - `invalid element at index 0 of list "sameness_group": can only be set in Enterprise`}, - expectErrorENT: []string{`invalid element at index 0 of list "sameness_group": can not be empty`}, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/multicluster/internal/types/types.go b/internal/multicluster/internal/types/types.go deleted file mode 100644 index 9ee6691e19ec8..0000000000000 --- a/internal/multicluster/internal/types/types.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/internal/resource" -) - -const ( - GroupName = "multicluster" - VersionV2Beta1 = "v2beta1" - CurrentVersion = VersionV2Beta1 -) - -func Register(r resource.Registry) { - RegisterExportedServices(r) - RegisterNamespaceExportedServices(r) - RegisterPartitionExportedServices(r) - RegisterComputedExportedServices(r) -} diff --git a/internal/resource/decode.go b/internal/resource/decode.go index d96cb79a9a7ca..ba9abd87d60d9 100644 --- a/internal/resource/decode.go +++ b/internal/resource/decode.go @@ -16,10 +16,8 @@ import ( // DecodedResource is a generic holder to contain an original Resource and its // decoded contents. type DecodedResource[T proto.Message] struct { - // Embedding here allows us to shadow the Resource.Data Any field to fake out - // using a single struct with inlined data. - *pbresource.Resource - Data T + Resource *pbresource.Resource + Data T } func (d *DecodedResource[T]) GetResource() *pbresource.Resource { diff --git a/internal/resource/demo/controller.go b/internal/resource/demo/controller.go index a8757fcae2624..7f1bba902ea51 100644 --- a/internal/resource/demo/controller.go +++ b/internal/resource/demo/controller.go @@ -71,7 +71,7 @@ func (r *artistReconciler) Reconcile(ctx context.Context, rt controller.Runtime, actualAlbums, err := rt.Client.List(ctx, &pbresource.ListRequest{ Type: TypeV2Album, Tenancy: res.Id.Tenancy, - NamePrefix: fmt.Sprintf("%s-", res.Id.Name), + NamePrefix: fmt.Sprintf("%s/", res.Id.Name), }) if err != nil { return err diff --git a/internal/resource/demo/demo.go b/internal/resource/demo/demo.go index 12fced6718e61..8e978c9fb49ab 100644 --- a/internal/resource/demo/demo.go +++ b/internal/resource/demo/demo.go @@ -354,7 +354,7 @@ func generateV2Album(artistID *pbresource.ID, rand *rand.Rand) (*pbresource.Reso Id: &pbresource.ID{ Type: TypeV2Album, Tenancy: clone(artistID.Tenancy), - Name: fmt.Sprintf("%s-%s-%s", artistID.Name, strings.ToLower(adjective), strings.ToLower(noun)), + Name: fmt.Sprintf("%s/%s-%s", artistID.Name, strings.ToLower(adjective), strings.ToLower(noun)), }, Owner: artistID, Data: data, diff --git a/internal/resource/hooks.go b/internal/resource/hooks.go deleted file mode 100644 index 2b9d72b88925f..0000000000000 --- a/internal/resource/hooks.go +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resource - -import ( - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/proto-public/pbresource" - "google.golang.org/protobuf/proto" -) - -// DecodedValidationHook is the function signature needed for usage with the DecodeAndValidate function -type DecodedValidationHook[T proto.Message] func(*DecodedResource[T]) error - -// DecodeAndValidate will generate a validation hook function that decodes the specified type and -// passes it off to another validation hook. This is mainly a convenience to avoid many other -// validation hooks needing to attempt decoding the data and erroring in a consistent manner. -func DecodeAndValidate[T proto.Message](fn DecodedValidationHook[T]) ValidationHook { - return func(res *pbresource.Resource) error { - decoded, err := Decode[T](res) - if err != nil { - return err - } - - return fn(decoded) - } -} - -// DecodedMutationHook is the function signature needed for usage with the DecodeAndMutate function -// The boolean return value indicates whether the Data field within the DecodedResource was modified. -// When true, the DecodeAndMutate hook function will automatically re-encode the Any data and store -// it on the internal Resource's Data field. -type DecodedMutationHook[T proto.Message] func(*DecodedResource[T]) (bool, error) - -// DecodeAndMutate will generate a MutationHook that decodes the specified type and passes it -// off to another mutation hook. This is mainly a convenience to avoid other mutation hooks -// needing to decode and potentially reencode the Any data. When the inner mutation hook returns -// no error and that the Data was modified (true for the boolean return value), the generated -// hook will reencode the Any data back into the Resource wrapper -func DecodeAndMutate[T proto.Message](fn DecodedMutationHook[T]) MutationHook { - return func(res *pbresource.Resource) error { - decoded, err := Decode[T](res) - if err != nil { - return err - } - - modified, err := fn(decoded) - if err != nil { - return err - } - - if modified { - return decoded.Resource.Data.MarshalFrom(decoded.Data) - } - return nil - } -} - -// DecodedAuthorizationHook is the function signature needed for usage with the DecodeAndAuthorizeWrite -// and DecodeAndAuthorizeRead functions. -type DecodedAuthorizationHook[T proto.Message] func(acl.Authorizer, *acl.AuthorizerContext, *DecodedResource[T]) error - -// DecodeAndAuthorizeWrite will generate an ACLAuthorizeWriteHook that decodes the specified type and passes -// it off to another authorization hook. This is mainly a convenience to avoid many other write authorization -// hooks needing to attempt decoding the data and erroring in a consistent manner. -func DecodeAndAuthorizeWrite[T proto.Message](fn DecodedAuthorizationHook[T]) ACLAuthorizeWriteHook { - return func(authz acl.Authorizer, ctx *acl.AuthorizerContext, res *pbresource.Resource) error { - decoded, err := Decode[T](res) - if err != nil { - return err - } - - return fn(authz, ctx, decoded) - } -} - -// DecodeAndAuthorizeRead will generate an ACLAuthorizeReadHook that decodes the specified type and passes -// it off to another authorization hook. This is mainly a convenience to avoid many other read authorization -// hooks needing to attempt decoding the data and erroring in a consistent manner. -func DecodeAndAuthorizeRead[T proto.Message](fn DecodedAuthorizationHook[T]) ACLAuthorizeReadHook { - return func(authz acl.Authorizer, ctx *acl.AuthorizerContext, _ *pbresource.ID, res *pbresource.Resource) error { - if res == nil { - return ErrNeedResource - } - - decoded, err := Decode[T](res) - if err != nil { - return err - } - - return fn(authz, ctx, decoded) - } -} - -type ReadAuthorizationWithResourceHook func(acl.Authorizer, *acl.AuthorizerContext, *pbresource.Resource) error - -// AuthorizeReadWithResource is a small wrapper to ensure that the authorization function is -// invoked with the full resource being read instead of just an id. -func AuthorizeReadWithResource(fn ReadAuthorizationWithResourceHook) ACLAuthorizeReadHook { - return func(authz acl.Authorizer, ctx *acl.AuthorizerContext, id *pbresource.ID, res *pbresource.Resource) error { - if res == nil { - return ErrNeedResource - } - - return fn(authz, ctx, res) - } -} diff --git a/internal/resource/hooks_test.go b/internal/resource/hooks_test.go deleted file mode 100644 index d9fa4d4272b74..0000000000000 --- a/internal/resource/hooks_test.go +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resource_test - -import ( - "fmt" - "testing" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/demo" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - "github.com/hashicorp/consul/proto-public/pbresource" - pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v2" - "github.com/stretchr/testify/require" -) - -func TestDecodeAndValidate(t *testing.T) { - res := rtest.Resource(demo.TypeV2Artist, "babypants"). - WithData(t, &pbdemo.Artist{Name: "caspar babypants"}). - Build() - - t.Run("ok", func(t *testing.T) { - err := resource.DecodeAndValidate[*pbdemo.Artist](func(dec *resource.DecodedResource[*pbdemo.Artist]) error { - require.NotNil(t, dec.Resource) - require.NotNil(t, dec.Data) - - return nil - })(res) - - require.NoError(t, err) - }) - - t.Run("inner-validation-error", func(t *testing.T) { - fakeErr := fmt.Errorf("fake") - - err := resource.DecodeAndValidate[*pbdemo.Artist](func(dec *resource.DecodedResource[*pbdemo.Artist]) error { - return fakeErr - })(res) - - require.Error(t, err) - require.Equal(t, fakeErr, err) - }) - - t.Run("decode-error", func(t *testing.T) { - err := resource.DecodeAndValidate[*pbdemo.Album](func(dec *resource.DecodedResource[*pbdemo.Album]) error { - require.Fail(t, "callback should not be called when decoding fails") - return nil - })(res) - - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) - }) -} - -func TestDecodeAndMutate(t *testing.T) { - res := rtest.Resource(demo.TypeV2Artist, "babypants"). - WithData(t, &pbdemo.Artist{Name: "caspar babypants"}). - Build() - - t.Run("no-writeback", func(t *testing.T) { - original := res.Data.Value - - err := resource.DecodeAndMutate[*pbdemo.Artist](func(dec *resource.DecodedResource[*pbdemo.Artist]) (bool, error) { - require.NotNil(t, dec.Resource) - require.NotNil(t, dec.Data) - - // we are going to change the data but not tell the outer hook about it - dec.Data.Name = "changed" - - return false, nil - })(res) - - require.NoError(t, err) - // Ensure that the outer hook didn't overwrite the resources data because we told it not to - require.Equal(t, original, res.Data.Value) - }) - - t.Run("writeback", func(t *testing.T) { - original := res.Data.Value - - err := resource.DecodeAndMutate[*pbdemo.Artist](func(dec *resource.DecodedResource[*pbdemo.Artist]) (bool, error) { - require.NotNil(t, dec.Resource) - require.NotNil(t, dec.Data) - - dec.Data.Name = "changed" - - return true, nil - })(res) - - require.NoError(t, err) - // Ensure that the outer hook reencoded the Any data because we told it to. - require.NotEqual(t, original, res.Data.Value) - }) - - t.Run("inner-mutation-error", func(t *testing.T) { - fakeErr := fmt.Errorf("fake") - - err := resource.DecodeAndMutate[*pbdemo.Artist](func(dec *resource.DecodedResource[*pbdemo.Artist]) (bool, error) { - return false, fakeErr - })(res) - - require.Error(t, err) - require.Equal(t, fakeErr, err) - }) - - t.Run("decode-error", func(t *testing.T) { - err := resource.DecodeAndMutate[*pbdemo.Album](func(dec *resource.DecodedResource[*pbdemo.Album]) (bool, error) { - require.Fail(t, "callback should not be called when decoding fails") - return false, nil - })(res) - - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) - }) -} - -func TestDecodeAndAuthorizeWrite(t *testing.T) { - res := rtest.Resource(demo.TypeV2Artist, "babypants"). - WithData(t, &pbdemo.Artist{Name: "caspar babypants"}). - Build() - - t.Run("allowed", func(t *testing.T) { - err := resource.DecodeAndAuthorizeWrite[*pbdemo.Artist](func(a acl.Authorizer, c *acl.AuthorizerContext, dec *resource.DecodedResource[*pbdemo.Artist]) error { - require.NotNil(t, a) - require.NotNil(t, c) - require.NotNil(t, dec.Resource) - require.NotNil(t, dec.Data) - - // access allowed - return nil - })(acl.DenyAll(), &acl.AuthorizerContext{}, res) - - require.NoError(t, err) - }) - - t.Run("denied", func(t *testing.T) { - err := resource.DecodeAndAuthorizeWrite[*pbdemo.Artist](func(a acl.Authorizer, c *acl.AuthorizerContext, dec *resource.DecodedResource[*pbdemo.Artist]) error { - return acl.PermissionDenied("fake") - })(acl.DenyAll(), nil, res) - - require.Error(t, err) - require.True(t, acl.IsErrPermissionDenied(err)) - }) - - t.Run("decode-error", func(t *testing.T) { - err := resource.DecodeAndAuthorizeWrite[*pbdemo.Album](func(a acl.Authorizer, c *acl.AuthorizerContext, dec *resource.DecodedResource[*pbdemo.Album]) error { - require.Fail(t, "callback should not be called when decoding fails") - return nil - })(acl.DenyAll(), &acl.AuthorizerContext{}, res) - - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) - }) -} - -func TestDecodeAndAuthorizeRead(t *testing.T) { - res := rtest.Resource(demo.TypeV2Artist, "babypants"). - WithData(t, &pbdemo.Artist{Name: "caspar babypants"}). - Build() - - t.Run("allowed", func(t *testing.T) { - err := resource.DecodeAndAuthorizeRead[*pbdemo.Artist](func(a acl.Authorizer, c *acl.AuthorizerContext, dec *resource.DecodedResource[*pbdemo.Artist]) error { - require.NotNil(t, a) - require.NotNil(t, c) - require.NotNil(t, dec.Resource) - require.NotNil(t, dec.Data) - - // access allowed - return nil - })(acl.DenyAll(), &acl.AuthorizerContext{}, nil, res) - - require.NoError(t, err) - }) - - t.Run("denied", func(t *testing.T) { - err := resource.DecodeAndAuthorizeRead[*pbdemo.Artist](func(a acl.Authorizer, c *acl.AuthorizerContext, dec *resource.DecodedResource[*pbdemo.Artist]) error { - return acl.PermissionDenied("fake") - })(acl.DenyAll(), nil, nil, res) - - require.Error(t, err) - require.True(t, acl.IsErrPermissionDenied(err)) - }) - - t.Run("decode-error", func(t *testing.T) { - err := resource.DecodeAndAuthorizeRead[*pbdemo.Album](func(a acl.Authorizer, c *acl.AuthorizerContext, dec *resource.DecodedResource[*pbdemo.Album]) error { - require.Fail(t, "callback should not be called when decoding fails") - return nil - })(acl.DenyAll(), &acl.AuthorizerContext{}, nil, res) - - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) - }) - - t.Run("err-need-resource", func(t *testing.T) { - err := resource.DecodeAndAuthorizeRead[*pbdemo.Artist](func(a acl.Authorizer, c *acl.AuthorizerContext, dec *resource.DecodedResource[*pbdemo.Artist]) error { - require.Fail(t, "callback should not be called when no resource was provided to be decoded") - return nil - })(acl.DenyAll(), &acl.AuthorizerContext{}, nil, nil) - - require.Error(t, err) - require.ErrorIs(t, err, resource.ErrNeedResource) - }) -} - -func TestAuthorizeReadWithResource(t *testing.T) { - res := rtest.Resource(demo.TypeV2Artist, "babypants"). - WithData(t, &pbdemo.Artist{Name: "caspar babypants"}). - Build() - - t.Run("allowed", func(t *testing.T) { - err := resource.AuthorizeReadWithResource(func(a acl.Authorizer, c *acl.AuthorizerContext, res *pbresource.Resource) error { - require.NotNil(t, a) - require.NotNil(t, c) - require.NotNil(t, res) - - // access allowed - return nil - })(acl.DenyAll(), &acl.AuthorizerContext{}, nil, res) - - require.NoError(t, err) - }) - - t.Run("denied", func(t *testing.T) { - err := resource.AuthorizeReadWithResource(func(a acl.Authorizer, c *acl.AuthorizerContext, res *pbresource.Resource) error { - return acl.PermissionDenied("fake") - })(acl.DenyAll(), nil, nil, res) - - require.Error(t, err) - require.True(t, acl.IsErrPermissionDenied(err)) - }) - - t.Run("err-need-resource", func(t *testing.T) { - err := resource.AuthorizeReadWithResource(func(a acl.Authorizer, c *acl.AuthorizerContext, res *pbresource.Resource) error { - require.Fail(t, "callback should not be called when no resource was provided to be decoded") - return nil - })(acl.DenyAll(), &acl.AuthorizerContext{}, nil, nil) - - require.Error(t, err) - require.ErrorIs(t, err, resource.ErrNeedResource) - }) -} diff --git a/internal/resource/http/http_test.go b/internal/resource/http/http_test.go index aeb85f0b8332a..50f50fbe39488 100644 --- a/internal/resource/http/http_test.go +++ b/internal/resource/http/http_test.go @@ -42,7 +42,7 @@ func TestResourceHandler_InputValidation(t *testing.T) { request *http.Request response *httptest.ResponseRecorder expectedResponseCode int - responseBodyContains string + expectedErrorMessage string } client := svctest.RunResourceService(t, demo.RegisterTypes) resourceHandler := resourceHandler{ @@ -72,7 +72,7 @@ func TestResourceHandler_InputValidation(t *testing.T) { `)), response: httptest.NewRecorder(), expectedResponseCode: http.StatusBadRequest, - responseBodyContains: "resource.id.name invalid", + expectedErrorMessage: "rpc error: code = InvalidArgument desc = resource.id.name is required", }, { description: "wrong schema", @@ -89,21 +89,21 @@ func TestResourceHandler_InputValidation(t *testing.T) { `)), response: httptest.NewRecorder(), expectedResponseCode: http.StatusBadRequest, - responseBodyContains: "Request body didn't follow the resource schema", + expectedErrorMessage: "Request body didn't follow the resource schema", }, { description: "invalid request body", request: httptest.NewRequest("PUT", "/keith-urban?partition=default&peer_name=local&namespace=default", strings.NewReader("bad-input")), response: httptest.NewRecorder(), expectedResponseCode: http.StatusBadRequest, - responseBodyContains: "Request body format is invalid", + expectedErrorMessage: "Request body format is invalid", }, { description: "no id", request: httptest.NewRequest("DELETE", "/?partition=default&peer_name=local&namespace=default", strings.NewReader("")), response: httptest.NewRecorder(), expectedResponseCode: http.StatusBadRequest, - responseBodyContains: "id.name invalid", + expectedErrorMessage: "rpc error: code = InvalidArgument desc = id.name is required", }, } @@ -119,7 +119,7 @@ func TestResourceHandler_InputValidation(t *testing.T) { require.NoError(t, err) require.Equal(t, tc.expectedResponseCode, tc.response.Result().StatusCode) - require.Contains(t, string(b), tc.responseBodyContains) + require.Equal(t, tc.expectedErrorMessage, string(b)) }) } } @@ -157,7 +157,7 @@ func TestResourceWriteHandler(t *testing.T) { require.Equal(t, http.StatusForbidden, rsp.Result().StatusCode) }) - var readRsp *pbresource.ReadResponse + t.Run("should write to the resource backend", func(t *testing.T) { rsp := httptest.NewRecorder() req := httptest.NewRequest("PUT", "/demo/v2/artist/keith-urban?partition=default&peer_name=local&namespace=default", strings.NewReader(` @@ -183,8 +183,7 @@ func TestResourceWriteHandler(t *testing.T) { require.Equal(t, "Keith Urban", result["data"].(map[string]any)["name"]) require.Equal(t, "keith-urban", result["id"].(map[string]any)["name"]) - var err error - readRsp, err = client.Read(testutil.TestContext(t), &pbresource.ReadRequest{ + readRsp, err := client.Read(testutil.TestContext(t), &pbresource.ReadRequest{ Id: &pbresource.ID{ Type: demo.TypeV2Artist, Tenancy: resource.DefaultNamespacedTenancy(), @@ -201,7 +200,7 @@ func TestResourceWriteHandler(t *testing.T) { t.Run("should update the record with version parameter", func(t *testing.T) { rsp := httptest.NewRecorder() - req := httptest.NewRequest("PUT", fmt.Sprintf("/demo/v2/artist/keith-urban?partition=default&peer_name=local&namespace=default&version=%s", readRsp.Resource.Version), strings.NewReader(` + req := httptest.NewRequest("PUT", "/demo/v2/artist/keith-urban?partition=default&peer_name=local&namespace=default&version=1", strings.NewReader(` { "metadata": { "foo": "bar" diff --git a/internal/resource/registry.go b/internal/resource/registry.go index 7897ffb1b4bce..20c1f4dc41a85 100644 --- a/internal/resource/registry.go +++ b/internal/resource/registry.go @@ -42,17 +42,6 @@ type Registry interface { Types() []Registration } -// ValidationHook is the function signature for a validation hook. These hooks can inspect -// the data as they see fit but are expected to not mutate the data in any way. If Go -// supported it, we would pass something akin to a const pointer into the callback to have -// the compiler enforce this immutability. -type ValidationHook func(*pbresource.Resource) error - -// MutationHook is the function signature for a validation hook. These hooks can inspect -// and mutate the resource. If modifying the resources Data, the hook needs to ensure that -// the data gets reencoded and stored back to the Data field. -type MutationHook func(*pbresource.Resource) error - type Registration struct { // Type is the GVK of the resource type. Type *pbresource.Type @@ -67,13 +56,13 @@ type Registration struct { // Validate is called to structurally validate the resource (e.g. // check for required fields). Validate can assume that Mutate // has been called. - Validate ValidationHook + Validate func(*pbresource.Resource) error // Mutate is called to fill out any autogenerated fields (e.g. UUIDs) or // apply defaults before validation. Mutate can assume that // Resource.ID is populated and has non-empty tenancy fields. This does // not mean those tenancy fields actually exist. - Mutate MutationHook + Mutate func(*pbresource.Resource) error // Scope describes the tenancy scope of a resource. Scope Scope @@ -81,10 +70,6 @@ type Registration struct { var ErrNeedResource = errors.New("authorization check requires the entire resource") -type ACLAuthorizeReadHook func(acl.Authorizer, *acl.AuthorizerContext, *pbresource.ID, *pbresource.Resource) error -type ACLAuthorizeWriteHook func(acl.Authorizer, *acl.AuthorizerContext, *pbresource.Resource) error -type ACLAuthorizeListHook func(acl.Authorizer, *acl.AuthorizerContext) error - type ACLHooks struct { // Read is used to authorize Read RPCs and to filter results in List // RPCs. @@ -94,17 +79,17 @@ type ACLHooks struct { // check will be deferred until the data is fetched from the storage layer. // // If it is omitted, `operator:read` permission is assumed. - Read ACLAuthorizeReadHook + Read func(acl.Authorizer, *acl.AuthorizerContext, *pbresource.ID, *pbresource.Resource) error // Write is used to authorize Write and Delete RPCs. // // If it is omitted, `operator:write` permission is assumed. - Write ACLAuthorizeWriteHook + Write func(acl.Authorizer, *acl.AuthorizerContext, *pbresource.Resource) error // List is used to authorize List RPCs. // // If it is omitted, we only filter the results using Read. - List ACLAuthorizeListHook + List func(acl.Authorizer, *acl.AuthorizerContext) error } // Resource type registry diff --git a/internal/resource/resource.go b/internal/resource/resource.go deleted file mode 100644 index b5100f002955f..0000000000000 --- a/internal/resource/resource.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resource - -import ( - "fmt" - "strings" - - "github.com/hashicorp/consul/agent/dns" -) - -const MaxNameLength = 63 - -// ValidateName returns an error a name is not a valid resource name. -// The error will contain reference to what constitutes a valid resource name. -func ValidateName(name string) error { - if !dns.IsValidLabel(name) || strings.ToLower(name) != name || len(name) > MaxNameLength { - return fmt.Errorf("a resource name must consist of lower case alphanumeric characters or '-', must start and end with an alphanumeric character and be less than %d characters, got: %q", MaxNameLength+1, name) - } - return nil -} diff --git a/internal/resource/tenancy.go b/internal/resource/tenancy.go index 597253aa8dc13..126e12413f6a8 100644 --- a/internal/resource/tenancy.go +++ b/internal/resource/tenancy.go @@ -5,6 +5,7 @@ package resource import ( "fmt" + "strings" "google.golang.org/protobuf/proto" @@ -24,6 +25,15 @@ const ( DefaultPeerName = "local" ) +// V2TenancyBridge is used by the resource service to access V2 implementations of +// partitions and namespaces. +type V2TenancyBridge struct { +} + +func NewV2TenancyBridge() TenancyBridge { + return &V2TenancyBridge{} +} + // Scope describes the tenancy scope of a resource. type Scope int @@ -52,6 +62,20 @@ func (s Scope) String() string { panic(fmt.Sprintf("string mapping missing for scope %v", int(s))) } +// Normalize lowercases the partition and namespace. +func Normalize(tenancy *pbresource.Tenancy) { + if tenancy == nil { + return + } + tenancy.Partition = strings.ToLower(tenancy.Partition) + tenancy.Namespace = strings.ToLower(tenancy.Namespace) + + // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy + if tenancy.PeerName == "" { + tenancy.PeerName = DefaultPeerName + } +} + // DefaultClusteredTenancy returns the default tenancy for a cluster scoped resource. func DefaultClusteredTenancy() *pbresource.Tenancy { return &pbresource.Tenancy{ @@ -132,6 +156,7 @@ func defaultTenancy(itemTenancy, parentTenancy, scopeTenancy *pbresource.Tenancy if itemTenancy.PeerName == "" { itemTenancy.PeerName = DefaultPeerName } + Normalize(itemTenancy) if parentTenancy != nil { // Recursively normalize this tenancy as well. @@ -142,6 +167,7 @@ func defaultTenancy(itemTenancy, parentTenancy, scopeTenancy *pbresource.Tenancy if parentTenancy == nil { parentTenancy = scopeTenancy } + Normalize(parentTenancy) if !equalOrEmpty(itemTenancy.PeerName, DefaultPeerName) { panic("peering is not supported yet for resource tenancies") diff --git a/internal/tenancy/internal/bridge/tenancy_bridge_ce.go b/internal/resource/tenancy_bridge_ce.go similarity index 52% rename from internal/tenancy/internal/bridge/tenancy_bridge_ce.go rename to internal/resource/tenancy_bridge_ce.go index dcf4df663cc73..9f88c22361998 100644 --- a/internal/tenancy/internal/bridge/tenancy_bridge_ce.go +++ b/internal/resource/tenancy_bridge_ce.go @@ -3,7 +3,7 @@ //go:build !consulent -package bridge +package resource func (b *V2TenancyBridge) PartitionExists(partition string) (bool, error) { if partition == "default" { @@ -15,3 +15,14 @@ func (b *V2TenancyBridge) PartitionExists(partition string) (bool, error) { func (b *V2TenancyBridge) IsPartitionMarkedForDeletion(partition string) (bool, error) { return false, nil } + +func (b *V2TenancyBridge) NamespaceExists(partition, namespace string) (bool, error) { + if partition == "default" && namespace == "default" { + return true, nil + } + return false, nil +} + +func (b *V2TenancyBridge) IsNamespaceMarkedForDeletion(partition, namespace string) (bool, error) { + return false, nil +} diff --git a/internal/tenancy/exports.go b/internal/tenancy/exports.go index 806e85b7b076f..aadd7efb59beb 100644 --- a/internal/tenancy/exports.go +++ b/internal/tenancy/exports.go @@ -4,15 +4,21 @@ package tenancy import ( - "github.com/hashicorp/consul/internal/controller" "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/tenancy/internal/bridge" - "github.com/hashicorp/consul/internal/tenancy/internal/controllers" "github.com/hashicorp/consul/internal/tenancy/internal/types" ) -type ( - V2TenancyBridge = bridge.V2TenancyBridge +var ( + // API Group Information + + APIGroup = types.GroupName + VersionV1Alpha1 = types.VersionV1Alpha1 + CurrentVersion = types.CurrentVersion + + // Resource Kind Names. + + NamespaceKind = types.NamespaceKind + NamespaceV1Alpha1Type = types.NamespaceV1Alpha1Type ) // RegisterTypes adds all resource types within the "tenancy" API group @@ -20,13 +26,3 @@ type ( func RegisterTypes(r resource.Registry) { types.Register(r) } - -// RegisterControllers registers controllers for the tenancy types with -// the given controller manager. -func RegisterControllers(mgr *controller.Manager) { - controllers.Register(mgr) -} - -func NewV2TenancyBridge() *V2TenancyBridge { - return bridge.NewV2TenancyBridge() -} diff --git a/internal/tenancy/internal/bridge/tenancy_bridge.go b/internal/tenancy/internal/bridge/tenancy_bridge.go deleted file mode 100644 index db6a4dd53a176..0000000000000 --- a/internal/tenancy/internal/bridge/tenancy_bridge.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package bridge - -import ( - "context" - - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" -) - -// V2TenancyBridge is used by the resource service to access V2 implementations of -// partitions and namespaces. -type V2TenancyBridge struct { - client pbresource.ResourceServiceClient -} - -// WithClient inject a ResourceServiceClient in the V2TenancyBridge. -// This is needed to break a circular dependency between -// the ResourceServiceServer, ResourceServiceClient and the TenancyBridge -func (b *V2TenancyBridge) WithClient(client pbresource.ResourceServiceClient) *V2TenancyBridge { - b.client = client - return b -} - -func NewV2TenancyBridge() *V2TenancyBridge { - return &V2TenancyBridge{} -} - -func (b *V2TenancyBridge) NamespaceExists(partition, namespace string) (bool, error) { - read, err := b.client.Read(context.Background(), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Name: namespace, - Tenancy: &pbresource.Tenancy{ - Partition: partition, - }, - Type: pbtenancy.NamespaceType, - }, - }) - return read != nil && read.Resource != nil, err -} - -func (b *V2TenancyBridge) IsNamespaceMarkedForDeletion(partition, namespace string) (bool, error) { - read, err := b.client.Read(context.Background(), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Name: namespace, - Tenancy: &pbresource.Tenancy{ - Partition: partition, - }, - Type: pbtenancy.NamespaceType, - }, - }) - return read.Resource != nil, err -} diff --git a/internal/tenancy/internal/controllers/register_ce.go b/internal/tenancy/internal/controllers/register_ce.go deleted file mode 100644 index 324f1bcfc0345..0000000000000 --- a/internal/tenancy/internal/controllers/register_ce.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent - -package controllers - -import ( - "github.com/hashicorp/consul/internal/controller" -) - -func Register(mgr *controller.Manager) { - //mgr.Register(namespace.NamespaceController()) -} diff --git a/internal/tenancy/internal/types/namespace.go b/internal/tenancy/internal/types/namespace.go index c45b405e8b325..4bc95d1505f7d 100644 --- a/internal/tenancy/internal/types/namespace.go +++ b/internal/tenancy/internal/types/namespace.go @@ -5,26 +5,44 @@ package types import ( "fmt" - "strings" - "github.com/hashicorp/consul/agent/dns" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" + tenancyv1alpha1 "github.com/hashicorp/consul/proto-public/pbtenancy/v1alpha1" + "strings" +) + +const ( + NamespaceKind = "Namespace" +) + +var ( + NamespaceV1Alpha1Type = &pbresource.Type{ + Group: GroupName, + GroupVersion: VersionV1Alpha1, + Kind: NamespaceKind, + } + NamespaceType = NamespaceV1Alpha1Type ) func RegisterNamespace(r resource.Registry) { r.Register(resource.Registration{ - Type: pbtenancy.NamespaceType, - Proto: &pbtenancy.Namespace{}, + Type: NamespaceV1Alpha1Type, + Proto: &tenancyv1alpha1.Namespace{}, Scope: resource.ScopePartition, Validate: ValidateNamespace, + Mutate: MutateNamespace, // ACLs: TODO }) } +func MutateNamespace(res *pbresource.Resource) error { + res.Id.Name = strings.ToLower(res.Id.Name) + return nil +} + func ValidateNamespace(res *pbresource.Resource) error { - var ns pbtenancy.Namespace + var ns tenancyv1alpha1.Namespace if err := res.Data.UnmarshalTo(&ns); err != nil { return resource.NewErrDataParse(&ns, err) diff --git a/internal/tenancy/internal/types/types_test.go b/internal/tenancy/internal/types/namespace_test.go similarity index 54% rename from internal/tenancy/internal/types/types_test.go rename to internal/tenancy/internal/types/namespace_test.go index df22b71f13a27..b64f86d5212bc 100644 --- a/internal/tenancy/internal/types/types_test.go +++ b/internal/tenancy/internal/types/namespace_test.go @@ -4,6 +4,14 @@ package types import ( + "context" + "errors" + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" + pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" + "github.com/hashicorp/consul/proto/private/prototest" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "testing" "github.com/stretchr/testify/require" @@ -11,15 +19,14 @@ import ( "google.golang.org/protobuf/types/known/anypb" "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" + pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v1alpha1" ) func createNamespaceResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource { res := &pbresource.Resource{ Id: &pbresource.ID{ - Type: pbtenancy.NamespaceType, + Type: NamespaceV1Alpha1Type, Tenancy: resource.DefaultPartitionedTenancy(), Name: "ns1234", }, @@ -86,6 +93,28 @@ func TestValidateNamespace_ParseError(t *testing.T) { require.ErrorAs(t, err, &resource.ErrDataParse{}) } +func TestMutateNamespace(t *testing.T) { + tests := []struct { + name string + namespaceName string + expectedName string + err error + }{ + {"lower", "lower", "lower", nil}, + {"mixed", "MiXeD", "mixed", nil}, + {"upper", "UPPER", "upper", nil}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := &pbresource.Resource{Id: &pbresource.ID{Name: tt.namespaceName}} + if err := MutateNamespace(res); !errors.Is(err, tt.err) { + t.Errorf("MutateNamespace() error = %v", err) + } + require.Equal(t, res.Id.Name, tt.expectedName) + }) + } +} + func TestValidateNamespace(t *testing.T) { tests := []struct { name string @@ -114,6 +143,64 @@ func TestValidateNamespace(t *testing.T) { } } +func TestRead_Success(t *testing.T) { + client := svctest.RunResourceService(t, Register) + client = rtest.NewClient(client) + + res := rtest.Resource(NamespaceType, "ns1"). + WithData(t, validNamespace()). + Write(t, client) + + readRsp, err := client.Read(context.Background(), &pbresource.ReadRequest{Id: res.Id}) + require.NoError(t, err) + prototest.AssertDeepEqual(t, res.Id, readRsp.Resource.Id) +} + +func TestRead_NotFound(t *testing.T) { + client := svctest.RunResourceService(t, Register) + client = rtest.NewClient(client) + + res := rtest.Resource(NamespaceType, "ns1"). + WithData(t, validNamespace()).Build() + + _, err := client.Read(context.Background(), &pbresource.ReadRequest{Id: res.Id}) + require.Error(t, err) + require.Equal(t, codes.NotFound.String(), status.Code(err).String()) +} + +func TestDelete_Success(t *testing.T) { + client := svctest.RunResourceService(t, Register) + client = rtest.NewClient(client) + + res := rtest.Resource(NamespaceType, "ns1"). + WithData(t, validNamespace()).Write(t, client) + + readRsp, err := client.Read(context.Background(), &pbresource.ReadRequest{Id: res.Id}) + require.NoError(t, err) + prototest.AssertDeepEqual(t, res.Id, readRsp.Resource.Id) + + _, err = client.Delete(context.Background(), &pbresource.DeleteRequest{Id: res.Id}) + require.NoError(t, err) + + _, err = client.Read(context.Background(), &pbresource.ReadRequest{Id: res.Id}) + require.Error(t, err) + require.Equal(t, codes.NotFound.String(), status.Code(err).String()) + +} + +func TestRead_MixedCases_Success(t *testing.T) { + client := svctest.RunResourceService(t, Register) + client = rtest.NewClient(client) + + res := rtest.Resource(NamespaceType, "nS1"). + WithData(t, validNamespace()).Write(t, client) + + readRsp, err := client.Read(context.Background(), &pbresource.ReadRequest{Id: res.Id}) + require.NoError(t, err) + prototest.AssertDeepEqual(t, res.Id, readRsp.Resource.Id) + +} + func validNamespace() *pbtenancy.Namespace { return &pbtenancy.Namespace{ Description: "ns namespace", diff --git a/internal/tenancy/internal/types/types.go b/internal/tenancy/internal/types/types.go index 5955ade8a5d7b..be0a615153fd0 100644 --- a/internal/tenancy/internal/types/types.go +++ b/internal/tenancy/internal/types/types.go @@ -4,7 +4,7 @@ package types const ( - GroupName = "tenancy" - VersionV2Beta1 = "v2beta1" - CurrentVersion = VersionV2Beta1 + GroupName = "tenancy" + VersionV1Alpha1 = "v1alpha1" + CurrentVersion = VersionV1Alpha1 ) diff --git a/internal/tenancy/tenancytest/namespace_test.go b/internal/tenancy/tenancytest/namespace_test.go deleted file mode 100644 index e2461c254cd20..0000000000000 --- a/internal/tenancy/tenancytest/namespace_test.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tenancytest - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - "github.com/hashicorp/consul/internal/tenancy" - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestWriteNamespace_Success(t *testing.T) { - v2TenancyBridge := tenancy.NewV2TenancyBridge() - config := svc.Config{TenancyBridge: v2TenancyBridge, UseV2Tenancy: true} - client := svctest.RunResourceServiceWithConfig(t, config, tenancy.RegisterTypes) - cl := rtest.NewClient(client) - - res := rtest.Resource(pbtenancy.NamespaceType, "ns1"). - WithTenancy(resource.DefaultPartitionedTenancy()). - WithData(t, validNamespace()). - Build() - - writeRsp, err := cl.Write(context.Background(), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - prototest.AssertDeepEqual(t, res.Id.Type, writeRsp.Resource.Id.Type) - prototest.AssertDeepEqual(t, res.Id.Tenancy, writeRsp.Resource.Id.Tenancy) - prototest.AssertDeepEqual(t, res.Id.Name, writeRsp.Resource.Id.Name) - prototest.AssertDeepEqual(t, res.Data, writeRsp.Resource.Data) -} - -func TestReadNamespace_Success(t *testing.T) { - v2TenancyBridge := tenancy.NewV2TenancyBridge() - config := svc.Config{TenancyBridge: v2TenancyBridge, UseV2Tenancy: true} - client := svctest.RunResourceServiceWithConfig(t, config, tenancy.RegisterTypes) - cl := rtest.NewClient(client) - - res := rtest.Resource(pbtenancy.NamespaceType, "ns1"). - WithData(t, validNamespace()). - Write(t, cl) - - cases := []struct { - name string - resource *pbresource.Resource - errMsg string - }{ - { - name: "read namespace", - resource: rtest.Resource(pbtenancy.NamespaceType, "ns1"). - WithData(t, validNamespace()). - Build(), - }, - } - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - readRsp, err := cl.Read(context.Background(), &pbresource.ReadRequest{Id: tc.resource.Id}) - require.NoError(t, err) - prototest.AssertDeepEqual(t, res.Id, readRsp.Resource.Id) - prototest.AssertDeepEqual(t, res.Data, readRsp.Resource.Data) - }) - } -} - -func TestDeleteNamespace_Success(t *testing.T) { - v2TenancyBridge := tenancy.NewV2TenancyBridge() - config := svc.Config{TenancyBridge: v2TenancyBridge, UseV2Tenancy: true} - client := svctest.RunResourceServiceWithConfig(t, config, tenancy.RegisterTypes) - cl := rtest.NewClient(client) - - res := rtest.Resource(pbtenancy.NamespaceType, "ns1"). - WithData(t, validNamespace()).Write(t, cl) - - readRsp, err := cl.Read(context.Background(), &pbresource.ReadRequest{Id: res.Id}) - require.NoError(t, err) - prototest.AssertDeepEqual(t, res.Id, readRsp.Resource.Id) - - _, err = cl.Delete(context.Background(), &pbresource.DeleteRequest{Id: res.Id}) - require.NoError(t, err) - - _, err = cl.Read(context.Background(), &pbresource.ReadRequest{Id: res.Id}) - require.Error(t, err) - require.Equal(t, codes.NotFound.String(), status.Code(err).String()) - -} - -func TestListNamespace_Success(t *testing.T) { - v2TenancyBridge := tenancy.NewV2TenancyBridge() - config := svc.Config{TenancyBridge: v2TenancyBridge, UseV2Tenancy: true} - client := svctest.RunResourceServiceWithConfig(t, config, tenancy.RegisterTypes) - cl := rtest.NewClient(client) - - res := rtest.Resource(pbtenancy.NamespaceType, "ns1"). - WithData(t, validNamespace()).Write(t, cl) - - require.NotNil(t, res) - res = rtest.Resource(pbtenancy.NamespaceType, "ns2"). - WithData(t, validNamespace()).Write(t, cl) - - require.NotNil(t, res) - - listRsp, err := cl.List(context.Background(), &pbresource.ListRequest{Type: pbtenancy.NamespaceType, Tenancy: resource.DefaultPartitionedTenancy()}) - require.NoError(t, err) - require.Len(t, listRsp.Resources, 3) - names := []string{ - listRsp.Resources[0].Id.Name, - listRsp.Resources[1].Id.Name, - listRsp.Resources[2].Id.Name, - } - require.Contains(t, names, "default") - require.Contains(t, names, "ns1") - require.Contains(t, names, "ns2") -} - -func validNamespace() *pbtenancy.Namespace { - return &pbtenancy.Namespace{ - Description: "ns namespace", - } -} diff --git a/proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.binary.go b/proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.binary.go deleted file mode 100644 index f5b389089f42d..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.binary.go +++ /dev/null @@ -1,38 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmulticluster/v2beta1/computed_exported_services.proto - -package multiclusterv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedExportedServices) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedExportedServices) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedExportedService) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedExportedService) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedExportedServicesConsumer) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedExportedServicesConsumer) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.go b/proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.go deleted file mode 100644 index 11ebe79f9dc6f..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.go +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmulticluster/v2beta1/computed_exported_services.proto - -package multiclusterv2beta1 - -import ( - pbresource "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ComputedExportedServices struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Consumers []*ComputedExportedService `protobuf:"bytes,1,rep,name=consumers,proto3" json:"consumers,omitempty"` -} - -func (x *ComputedExportedServices) Reset() { - *x = ComputedExportedServices{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedExportedServices) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedExportedServices) ProtoMessage() {} - -func (x *ComputedExportedServices) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedExportedServices.ProtoReflect.Descriptor instead. -func (*ComputedExportedServices) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescGZIP(), []int{0} -} - -func (x *ComputedExportedServices) GetConsumers() []*ComputedExportedService { - if x != nil { - return x.Consumers - } - return nil -} - -type ComputedExportedService struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TargetRef *pbresource.Reference `protobuf:"bytes,1,opt,name=target_ref,json=targetRef,proto3" json:"target_ref,omitempty"` - Consumers []*ComputedExportedServicesConsumer `protobuf:"bytes,2,rep,name=consumers,proto3" json:"consumers,omitempty"` -} - -func (x *ComputedExportedService) Reset() { - *x = ComputedExportedService{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedExportedService) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedExportedService) ProtoMessage() {} - -func (x *ComputedExportedService) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedExportedService.ProtoReflect.Descriptor instead. -func (*ComputedExportedService) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescGZIP(), []int{1} -} - -func (x *ComputedExportedService) GetTargetRef() *pbresource.Reference { - if x != nil { - return x.TargetRef - } - return nil -} - -func (x *ComputedExportedService) GetConsumers() []*ComputedExportedServicesConsumer { - if x != nil { - return x.Consumers - } - return nil -} - -type ComputedExportedServicesConsumer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // no sameness group - // - // Types that are assignable to ConsumerTenancy: - // - // *ComputedExportedServicesConsumer_Peer - // *ComputedExportedServicesConsumer_Partition - ConsumerTenancy isComputedExportedServicesConsumer_ConsumerTenancy `protobuf_oneof:"consumer_tenancy"` -} - -func (x *ComputedExportedServicesConsumer) Reset() { - *x = ComputedExportedServicesConsumer{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedExportedServicesConsumer) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedExportedServicesConsumer) ProtoMessage() {} - -func (x *ComputedExportedServicesConsumer) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedExportedServicesConsumer.ProtoReflect.Descriptor instead. -func (*ComputedExportedServicesConsumer) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescGZIP(), []int{2} -} - -func (m *ComputedExportedServicesConsumer) GetConsumerTenancy() isComputedExportedServicesConsumer_ConsumerTenancy { - if m != nil { - return m.ConsumerTenancy - } - return nil -} - -func (x *ComputedExportedServicesConsumer) GetPeer() string { - if x, ok := x.GetConsumerTenancy().(*ComputedExportedServicesConsumer_Peer); ok { - return x.Peer - } - return "" -} - -func (x *ComputedExportedServicesConsumer) GetPartition() string { - if x, ok := x.GetConsumerTenancy().(*ComputedExportedServicesConsumer_Partition); ok { - return x.Partition - } - return "" -} - -type isComputedExportedServicesConsumer_ConsumerTenancy interface { - isComputedExportedServicesConsumer_ConsumerTenancy() -} - -type ComputedExportedServicesConsumer_Peer struct { - Peer string `protobuf:"bytes,3,opt,name=peer,proto3,oneof"` -} - -type ComputedExportedServicesConsumer_Partition struct { - Partition string `protobuf:"bytes,4,opt,name=partition,proto3,oneof"` -} - -func (*ComputedExportedServicesConsumer_Peer) isComputedExportedServicesConsumer_ConsumerTenancy() {} - -func (*ComputedExportedServicesConsumer_Partition) isComputedExportedServicesConsumer_ConsumerTenancy() { -} - -var File_pbmulticluster_v2beta1_computed_exported_services_proto protoreflect.FileDescriptor - -var file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDesc = []byte{ - 0x0a, 0x37, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, - 0x64, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x25, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, - 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x80, 0x01, 0x0a, 0x18, 0x43, 0x6f, - 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x5c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, - 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6d, 0x65, 0x72, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x02, 0x22, 0xc5, 0x01, 0x0a, - 0x17, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x52, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x66, 0x12, 0x65, 0x0a, - 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x47, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, - 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6d, 0x65, 0x72, 0x73, 0x22, 0x6c, 0x0a, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, - 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x12, 0x1e, - 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x12, - 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x74, 0x65, 0x6e, 0x61, 0x6e, - 0x63, 0x79, 0x42, 0xd6, 0x02, 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x42, 0x1d, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x53, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x75, - 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x3b, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x25, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x31, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x28, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, -} - -var ( - file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescOnce sync.Once - file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescData = file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDesc -) - -func file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescGZIP() []byte { - file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescOnce.Do(func() { - file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescData) - }) - return file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescData -} - -var file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_pbmulticluster_v2beta1_computed_exported_services_proto_goTypes = []interface{}{ - (*ComputedExportedServices)(nil), // 0: hashicorp.consul.multicluster.v2beta1.ComputedExportedServices - (*ComputedExportedService)(nil), // 1: hashicorp.consul.multicluster.v2beta1.ComputedExportedService - (*ComputedExportedServicesConsumer)(nil), // 2: hashicorp.consul.multicluster.v2beta1.ComputedExportedServicesConsumer - (*pbresource.Reference)(nil), // 3: hashicorp.consul.resource.Reference -} -var file_pbmulticluster_v2beta1_computed_exported_services_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.multicluster.v2beta1.ComputedExportedServices.consumers:type_name -> hashicorp.consul.multicluster.v2beta1.ComputedExportedService - 3, // 1: hashicorp.consul.multicluster.v2beta1.ComputedExportedService.target_ref:type_name -> hashicorp.consul.resource.Reference - 2, // 2: hashicorp.consul.multicluster.v2beta1.ComputedExportedService.consumers:type_name -> hashicorp.consul.multicluster.v2beta1.ComputedExportedServicesConsumer - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_pbmulticluster_v2beta1_computed_exported_services_proto_init() } -func file_pbmulticluster_v2beta1_computed_exported_services_proto_init() { - if File_pbmulticluster_v2beta1_computed_exported_services_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedExportedServices); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedExportedService); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedExportedServicesConsumer); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[2].OneofWrappers = []interface{}{ - (*ComputedExportedServicesConsumer_Peer)(nil), - (*ComputedExportedServicesConsumer_Partition)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmulticluster_v2beta1_computed_exported_services_proto_goTypes, - DependencyIndexes: file_pbmulticluster_v2beta1_computed_exported_services_proto_depIdxs, - MessageInfos: file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes, - }.Build() - File_pbmulticluster_v2beta1_computed_exported_services_proto = out.File - file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDesc = nil - file_pbmulticluster_v2beta1_computed_exported_services_proto_goTypes = nil - file_pbmulticluster_v2beta1_computed_exported_services_proto_depIdxs = nil -} diff --git a/proto-public/pbmulticluster/v2beta1/computed_exported_services.proto b/proto-public/pbmulticluster/v2beta1/computed_exported_services.proto deleted file mode 100644 index b8a619558451c..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/computed_exported_services.proto +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -syntax = "proto3"; - -package hashicorp.consul.multicluster.v2beta1; - -import "pbresource/annotations.proto"; -import "pbresource/resource.proto"; - -message ComputedExportedServices { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_PARTITION}; - - repeated ComputedExportedService consumers = 1; -} - -message ComputedExportedService { - hashicorp.consul.resource.Reference target_ref = 1; - repeated ComputedExportedServicesConsumer consumers = 2; -} - -message ComputedExportedServicesConsumer { - // no sameness group - oneof consumer_tenancy { - string peer = 3; - string partition = 4; - } -} diff --git a/proto-public/pbmulticluster/v2beta1/computed_exported_services_deepcopy.gen.go b/proto-public/pbmulticluster/v2beta1/computed_exported_services_deepcopy.gen.go deleted file mode 100644 index b50f35a20bd92..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/computed_exported_services_deepcopy.gen.go +++ /dev/null @@ -1,69 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package multiclusterv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using ComputedExportedServices within kubernetes types, where deepcopy-gen is used. -func (in *ComputedExportedServices) DeepCopyInto(out *ComputedExportedServices) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedExportedServices. Required by controller-gen. -func (in *ComputedExportedServices) DeepCopy() *ComputedExportedServices { - if in == nil { - return nil - } - out := new(ComputedExportedServices) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedExportedServices. Required by controller-gen. -func (in *ComputedExportedServices) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedExportedService within kubernetes types, where deepcopy-gen is used. -func (in *ComputedExportedService) DeepCopyInto(out *ComputedExportedService) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedExportedService. Required by controller-gen. -func (in *ComputedExportedService) DeepCopy() *ComputedExportedService { - if in == nil { - return nil - } - out := new(ComputedExportedService) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedExportedService. Required by controller-gen. -func (in *ComputedExportedService) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedExportedServicesConsumer within kubernetes types, where deepcopy-gen is used. -func (in *ComputedExportedServicesConsumer) DeepCopyInto(out *ComputedExportedServicesConsumer) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedExportedServicesConsumer. Required by controller-gen. -func (in *ComputedExportedServicesConsumer) DeepCopy() *ComputedExportedServicesConsumer { - if in == nil { - return nil - } - out := new(ComputedExportedServicesConsumer) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedExportedServicesConsumer. Required by controller-gen. -func (in *ComputedExportedServicesConsumer) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmulticluster/v2beta1/computed_exported_services_json.gen.go b/proto-public/pbmulticluster/v2beta1/computed_exported_services_json.gen.go deleted file mode 100644 index 709a7e6ef6b20..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/computed_exported_services_json.gen.go +++ /dev/null @@ -1,44 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package multiclusterv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for ComputedExportedServices -func (this *ComputedExportedServices) MarshalJSON() ([]byte, error) { - str, err := ComputedExportedServicesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedExportedServices -func (this *ComputedExportedServices) UnmarshalJSON(b []byte) error { - return ComputedExportedServicesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedExportedService -func (this *ComputedExportedService) MarshalJSON() ([]byte, error) { - str, err := ComputedExportedServicesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedExportedService -func (this *ComputedExportedService) UnmarshalJSON(b []byte) error { - return ComputedExportedServicesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedExportedServicesConsumer -func (this *ComputedExportedServicesConsumer) MarshalJSON() ([]byte, error) { - str, err := ComputedExportedServicesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedExportedServicesConsumer -func (this *ComputedExportedServicesConsumer) UnmarshalJSON(b []byte) error { - return ComputedExportedServicesUnmarshaler.Unmarshal(b, this) -} - -var ( - ComputedExportedServicesMarshaler = &protojson.MarshalOptions{} - ComputedExportedServicesUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmulticluster/v2beta1/exported_services.pb.binary.go b/proto-public/pbmulticluster/v2beta1/exported_services.pb.binary.go deleted file mode 100644 index 1530294804123..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmulticluster/v2beta1/exported_services.proto - -package multiclusterv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ExportedServices) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ExportedServices) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services.pb.go b/proto-public/pbmulticluster/v2beta1/exported_services.pb.go deleted file mode 100644 index 7e776c3a94c16..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services.pb.go +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmulticluster/v2beta1/exported_services.proto - -package multiclusterv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ExportedServices struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Services []string `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` - Consumers []*ExportedServicesConsumer `protobuf:"bytes,2,rep,name=consumers,proto3" json:"consumers,omitempty"` -} - -func (x *ExportedServices) Reset() { - *x = ExportedServices{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_exported_services_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ExportedServices) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExportedServices) ProtoMessage() {} - -func (x *ExportedServices) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_exported_services_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExportedServices.ProtoReflect.Descriptor instead. -func (*ExportedServices) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_exported_services_proto_rawDescGZIP(), []int{0} -} - -func (x *ExportedServices) GetServices() []string { - if x != nil { - return x.Services - } - return nil -} - -func (x *ExportedServices) GetConsumers() []*ExportedServicesConsumer { - if x != nil { - return x.Consumers - } - return nil -} - -var File_pbmulticluster_v2beta1_exported_services_proto protoreflect.FileDescriptor - -var file_pbmulticluster_v2beta1_exported_services_proto_rawDesc = []byte{ - 0x0a, 0x2e, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x25, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x37, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, - 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x95, - 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, - 0x5d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, - 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6d, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x3a, 0x06, - 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x42, 0xce, 0x02, 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x42, 0x15, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x53, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x28, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x3a, 0x3a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x3a, - 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmulticluster_v2beta1_exported_services_proto_rawDescOnce sync.Once - file_pbmulticluster_v2beta1_exported_services_proto_rawDescData = file_pbmulticluster_v2beta1_exported_services_proto_rawDesc -) - -func file_pbmulticluster_v2beta1_exported_services_proto_rawDescGZIP() []byte { - file_pbmulticluster_v2beta1_exported_services_proto_rawDescOnce.Do(func() { - file_pbmulticluster_v2beta1_exported_services_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2beta1_exported_services_proto_rawDescData) - }) - return file_pbmulticluster_v2beta1_exported_services_proto_rawDescData -} - -var file_pbmulticluster_v2beta1_exported_services_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmulticluster_v2beta1_exported_services_proto_goTypes = []interface{}{ - (*ExportedServices)(nil), // 0: hashicorp.consul.multicluster.v2beta1.ExportedServices - (*ExportedServicesConsumer)(nil), // 1: hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer -} -var file_pbmulticluster_v2beta1_exported_services_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.multicluster.v2beta1.ExportedServices.consumers:type_name -> hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_pbmulticluster_v2beta1_exported_services_proto_init() } -func file_pbmulticluster_v2beta1_exported_services_proto_init() { - if File_pbmulticluster_v2beta1_exported_services_proto != nil { - return - } - file_pbmulticluster_v2beta1_exported_services_consumer_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmulticluster_v2beta1_exported_services_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExportedServices); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmulticluster_v2beta1_exported_services_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmulticluster_v2beta1_exported_services_proto_goTypes, - DependencyIndexes: file_pbmulticluster_v2beta1_exported_services_proto_depIdxs, - MessageInfos: file_pbmulticluster_v2beta1_exported_services_proto_msgTypes, - }.Build() - File_pbmulticluster_v2beta1_exported_services_proto = out.File - file_pbmulticluster_v2beta1_exported_services_proto_rawDesc = nil - file_pbmulticluster_v2beta1_exported_services_proto_goTypes = nil - file_pbmulticluster_v2beta1_exported_services_proto_depIdxs = nil -} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services.proto b/proto-public/pbmulticluster/v2beta1/exported_services.proto deleted file mode 100644 index 76cd98ad7a46f..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services.proto +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -syntax = "proto3"; - -package hashicorp.consul.multicluster.v2beta1; - -import "pbmulticluster/v2beta1/exported_services_consumer.proto"; -import "pbresource/annotations.proto"; - -message ExportedServices { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - repeated string services = 1; - repeated ExportedServicesConsumer consumers = 2; -} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.binary.go b/proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.binary.go deleted file mode 100644 index 5f8eecd75158b..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmulticluster/v2beta1/exported_services_consumer.proto - -package multiclusterv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ExportedServicesConsumer) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ExportedServicesConsumer) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.go b/proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.go deleted file mode 100644 index a254b81af0a63..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.go +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmulticluster/v2beta1/exported_services_consumer.proto - -package multiclusterv2beta1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ExportedServicesConsumer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to ConsumerTenancy: - // - // *ExportedServicesConsumer_Peer - // *ExportedServicesConsumer_Partition - // *ExportedServicesConsumer_SamenessGroup - ConsumerTenancy isExportedServicesConsumer_ConsumerTenancy `protobuf_oneof:"consumer_tenancy"` -} - -func (x *ExportedServicesConsumer) Reset() { - *x = ExportedServicesConsumer{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_exported_services_consumer_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ExportedServicesConsumer) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExportedServicesConsumer) ProtoMessage() {} - -func (x *ExportedServicesConsumer) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_exported_services_consumer_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExportedServicesConsumer.ProtoReflect.Descriptor instead. -func (*ExportedServicesConsumer) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescGZIP(), []int{0} -} - -func (m *ExportedServicesConsumer) GetConsumerTenancy() isExportedServicesConsumer_ConsumerTenancy { - if m != nil { - return m.ConsumerTenancy - } - return nil -} - -func (x *ExportedServicesConsumer) GetPeer() string { - if x, ok := x.GetConsumerTenancy().(*ExportedServicesConsumer_Peer); ok { - return x.Peer - } - return "" -} - -func (x *ExportedServicesConsumer) GetPartition() string { - if x, ok := x.GetConsumerTenancy().(*ExportedServicesConsumer_Partition); ok { - return x.Partition - } - return "" -} - -func (x *ExportedServicesConsumer) GetSamenessGroup() string { - if x, ok := x.GetConsumerTenancy().(*ExportedServicesConsumer_SamenessGroup); ok { - return x.SamenessGroup - } - return "" -} - -type isExportedServicesConsumer_ConsumerTenancy interface { - isExportedServicesConsumer_ConsumerTenancy() -} - -type ExportedServicesConsumer_Peer struct { - Peer string `protobuf:"bytes,1,opt,name=peer,proto3,oneof"` -} - -type ExportedServicesConsumer_Partition struct { - Partition string `protobuf:"bytes,2,opt,name=partition,proto3,oneof"` -} - -type ExportedServicesConsumer_SamenessGroup struct { - SamenessGroup string `protobuf:"bytes,3,opt,name=sameness_group,json=samenessGroup,proto3,oneof"` -} - -func (*ExportedServicesConsumer_Peer) isExportedServicesConsumer_ConsumerTenancy() {} - -func (*ExportedServicesConsumer_Partition) isExportedServicesConsumer_ConsumerTenancy() {} - -func (*ExportedServicesConsumer_SamenessGroup) isExportedServicesConsumer_ConsumerTenancy() {} - -var File_pbmulticluster_v2beta1_exported_services_consumer_proto protoreflect.FileDescriptor - -var file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDesc = []byte{ - 0x0a, 0x37, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6d, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x25, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x22, 0x8d, 0x01, 0x0a, 0x18, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x12, 0x14, 0x0a, - 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x70, - 0x65, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0e, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x5f, - 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0d, 0x73, - 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x12, 0x0a, 0x10, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, - 0x42, 0xd6, 0x02, 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x1d, - 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x53, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x3b, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x75, - 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, - 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x28, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} - -var ( - file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescOnce sync.Once - file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescData = file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDesc -) - -func file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescGZIP() []byte { - file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescOnce.Do(func() { - file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescData) - }) - return file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescData -} - -var file_pbmulticluster_v2beta1_exported_services_consumer_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmulticluster_v2beta1_exported_services_consumer_proto_goTypes = []interface{}{ - (*ExportedServicesConsumer)(nil), // 0: hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer -} -var file_pbmulticluster_v2beta1_exported_services_consumer_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pbmulticluster_v2beta1_exported_services_consumer_proto_init() } -func file_pbmulticluster_v2beta1_exported_services_consumer_proto_init() { - if File_pbmulticluster_v2beta1_exported_services_consumer_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmulticluster_v2beta1_exported_services_consumer_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExportedServicesConsumer); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmulticluster_v2beta1_exported_services_consumer_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*ExportedServicesConsumer_Peer)(nil), - (*ExportedServicesConsumer_Partition)(nil), - (*ExportedServicesConsumer_SamenessGroup)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmulticluster_v2beta1_exported_services_consumer_proto_goTypes, - DependencyIndexes: file_pbmulticluster_v2beta1_exported_services_consumer_proto_depIdxs, - MessageInfos: file_pbmulticluster_v2beta1_exported_services_consumer_proto_msgTypes, - }.Build() - File_pbmulticluster_v2beta1_exported_services_consumer_proto = out.File - file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDesc = nil - file_pbmulticluster_v2beta1_exported_services_consumer_proto_goTypes = nil - file_pbmulticluster_v2beta1_exported_services_consumer_proto_depIdxs = nil -} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_consumer.proto b/proto-public/pbmulticluster/v2beta1/exported_services_consumer.proto deleted file mode 100644 index 1a110099dcf59..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services_consumer.proto +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -syntax = "proto3"; - -package hashicorp.consul.multicluster.v2beta1; - -message ExportedServicesConsumer { - oneof consumer_tenancy { - string peer = 1; - string partition = 2; - string sameness_group = 3; - } -} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_consumer_deepcopy.gen.go b/proto-public/pbmulticluster/v2beta1/exported_services_consumer_deepcopy.gen.go deleted file mode 100644 index 847fe0ec3e31d..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services_consumer_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package multiclusterv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using ExportedServicesConsumer within kubernetes types, where deepcopy-gen is used. -func (in *ExportedServicesConsumer) DeepCopyInto(out *ExportedServicesConsumer) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExportedServicesConsumer. Required by controller-gen. -func (in *ExportedServicesConsumer) DeepCopy() *ExportedServicesConsumer { - if in == nil { - return nil - } - out := new(ExportedServicesConsumer) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ExportedServicesConsumer. Required by controller-gen. -func (in *ExportedServicesConsumer) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_consumer_json.gen.go b/proto-public/pbmulticluster/v2beta1/exported_services_consumer_json.gen.go deleted file mode 100644 index 3f43f69932a19..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services_consumer_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package multiclusterv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for ExportedServicesConsumer -func (this *ExportedServicesConsumer) MarshalJSON() ([]byte, error) { - str, err := ExportedServicesConsumerMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ExportedServicesConsumer -func (this *ExportedServicesConsumer) UnmarshalJSON(b []byte) error { - return ExportedServicesConsumerUnmarshaler.Unmarshal(b, this) -} - -var ( - ExportedServicesConsumerMarshaler = &protojson.MarshalOptions{} - ExportedServicesConsumerUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_deepcopy.gen.go b/proto-public/pbmulticluster/v2beta1/exported_services_deepcopy.gen.go deleted file mode 100644 index f5897233ef8b6..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package multiclusterv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using ExportedServices within kubernetes types, where deepcopy-gen is used. -func (in *ExportedServices) DeepCopyInto(out *ExportedServices) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExportedServices. Required by controller-gen. -func (in *ExportedServices) DeepCopy() *ExportedServices { - if in == nil { - return nil - } - out := new(ExportedServices) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ExportedServices. Required by controller-gen. -func (in *ExportedServices) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_json.gen.go b/proto-public/pbmulticluster/v2beta1/exported_services_json.gen.go deleted file mode 100644 index 40a7cdc38b9b4..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package multiclusterv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for ExportedServices -func (this *ExportedServices) MarshalJSON() ([]byte, error) { - str, err := ExportedServicesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ExportedServices -func (this *ExportedServices) UnmarshalJSON(b []byte) error { - return ExportedServicesUnmarshaler.Unmarshal(b, this) -} - -var ( - ExportedServicesMarshaler = &protojson.MarshalOptions{} - ExportedServicesUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.binary.go b/proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.binary.go deleted file mode 100644 index eb000381077b7..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmulticluster/v2beta1/namespace_exported_services.proto - -package multiclusterv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *NamespaceExportedServices) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *NamespaceExportedServices) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.go b/proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.go deleted file mode 100644 index 5936f86fda119..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.go +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmulticluster/v2beta1/namespace_exported_services.proto - -package multiclusterv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type NamespaceExportedServices struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Consumers []*ExportedServicesConsumer `protobuf:"bytes,1,rep,name=consumers,proto3" json:"consumers,omitempty"` -} - -func (x *NamespaceExportedServices) Reset() { - *x = NamespaceExportedServices{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_namespace_exported_services_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NamespaceExportedServices) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NamespaceExportedServices) ProtoMessage() {} - -func (x *NamespaceExportedServices) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_namespace_exported_services_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NamespaceExportedServices.ProtoReflect.Descriptor instead. -func (*NamespaceExportedServices) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescGZIP(), []int{0} -} - -func (x *NamespaceExportedServices) GetConsumers() []*ExportedServicesConsumer { - if x != nil { - return x.Consumers - } - return nil -} - -var File_pbmulticluster_v2beta1_namespace_exported_services_proto protoreflect.FileDescriptor - -var file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDesc = []byte{ - 0x0a, 0x38, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x25, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x1a, 0x37, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x82, 0x01, 0x0a, 0x19, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x5d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, - 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x72, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x42, 0xd7, 0x02, - 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x1e, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x53, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x28, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x3a, 0x3a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x3a, - 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescOnce sync.Once - file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescData = file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDesc -) - -func file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescGZIP() []byte { - file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescOnce.Do(func() { - file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescData) - }) - return file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescData -} - -var file_pbmulticluster_v2beta1_namespace_exported_services_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmulticluster_v2beta1_namespace_exported_services_proto_goTypes = []interface{}{ - (*NamespaceExportedServices)(nil), // 0: hashicorp.consul.multicluster.v2beta1.NamespaceExportedServices - (*ExportedServicesConsumer)(nil), // 1: hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer -} -var file_pbmulticluster_v2beta1_namespace_exported_services_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.multicluster.v2beta1.NamespaceExportedServices.consumers:type_name -> hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_pbmulticluster_v2beta1_namespace_exported_services_proto_init() } -func file_pbmulticluster_v2beta1_namespace_exported_services_proto_init() { - if File_pbmulticluster_v2beta1_namespace_exported_services_proto != nil { - return - } - file_pbmulticluster_v2beta1_exported_services_consumer_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmulticluster_v2beta1_namespace_exported_services_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NamespaceExportedServices); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmulticluster_v2beta1_namespace_exported_services_proto_goTypes, - DependencyIndexes: file_pbmulticluster_v2beta1_namespace_exported_services_proto_depIdxs, - MessageInfos: file_pbmulticluster_v2beta1_namespace_exported_services_proto_msgTypes, - }.Build() - File_pbmulticluster_v2beta1_namespace_exported_services_proto = out.File - file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDesc = nil - file_pbmulticluster_v2beta1_namespace_exported_services_proto_goTypes = nil - file_pbmulticluster_v2beta1_namespace_exported_services_proto_depIdxs = nil -} diff --git a/proto-public/pbmulticluster/v2beta1/namespace_exported_services.proto b/proto-public/pbmulticluster/v2beta1/namespace_exported_services.proto deleted file mode 100644 index 074d44d36063e..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/namespace_exported_services.proto +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -syntax = "proto3"; - -package hashicorp.consul.multicluster.v2beta1; - -import "pbmulticluster/v2beta1/exported_services_consumer.proto"; -import "pbresource/annotations.proto"; - -message NamespaceExportedServices { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - repeated ExportedServicesConsumer consumers = 1; -} diff --git a/proto-public/pbmulticluster/v2beta1/namespace_exported_services_deepcopy.gen.go b/proto-public/pbmulticluster/v2beta1/namespace_exported_services_deepcopy.gen.go deleted file mode 100644 index 9d061a755bdae..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/namespace_exported_services_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package multiclusterv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using NamespaceExportedServices within kubernetes types, where deepcopy-gen is used. -func (in *NamespaceExportedServices) DeepCopyInto(out *NamespaceExportedServices) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceExportedServices. Required by controller-gen. -func (in *NamespaceExportedServices) DeepCopy() *NamespaceExportedServices { - if in == nil { - return nil - } - out := new(NamespaceExportedServices) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceExportedServices. Required by controller-gen. -func (in *NamespaceExportedServices) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmulticluster/v2beta1/namespace_exported_services_json.gen.go b/proto-public/pbmulticluster/v2beta1/namespace_exported_services_json.gen.go deleted file mode 100644 index 5d4ee1e42c7a9..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/namespace_exported_services_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package multiclusterv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for NamespaceExportedServices -func (this *NamespaceExportedServices) MarshalJSON() ([]byte, error) { - str, err := NamespaceExportedServicesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for NamespaceExportedServices -func (this *NamespaceExportedServices) UnmarshalJSON(b []byte) error { - return NamespaceExportedServicesUnmarshaler.Unmarshal(b, this) -} - -var ( - NamespaceExportedServicesMarshaler = &protojson.MarshalOptions{} - NamespaceExportedServicesUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.binary.go b/proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.binary.go deleted file mode 100644 index 5518b8a004053..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmulticluster/v2beta1/partition_exported_services.proto - -package multiclusterv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *PartitionExportedServices) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *PartitionExportedServices) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.go b/proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.go deleted file mode 100644 index 116e4784e6fe7..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.go +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmulticluster/v2beta1/partition_exported_services.proto - -package multiclusterv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type PartitionExportedServices struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Consumers []*ExportedServicesConsumer `protobuf:"bytes,1,rep,name=consumers,proto3" json:"consumers,omitempty"` -} - -func (x *PartitionExportedServices) Reset() { - *x = PartitionExportedServices{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_partition_exported_services_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PartitionExportedServices) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PartitionExportedServices) ProtoMessage() {} - -func (x *PartitionExportedServices) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_partition_exported_services_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PartitionExportedServices.ProtoReflect.Descriptor instead. -func (*PartitionExportedServices) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescGZIP(), []int{0} -} - -func (x *PartitionExportedServices) GetConsumers() []*ExportedServicesConsumer { - if x != nil { - return x.Consumers - } - return nil -} - -var File_pbmulticluster_v2beta1_partition_exported_services_proto protoreflect.FileDescriptor - -var file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDesc = []byte{ - 0x0a, 0x38, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x25, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x1a, 0x37, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x82, 0x01, 0x0a, 0x19, 0x50, 0x61, 0x72, - 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x5d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, - 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x72, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x02, 0x42, 0xd7, 0x02, - 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x1e, 0x50, 0x61, 0x72, - 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x53, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x28, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x3a, 0x3a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x3a, - 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescOnce sync.Once - file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescData = file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDesc -) - -func file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescGZIP() []byte { - file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescOnce.Do(func() { - file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescData) - }) - return file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescData -} - -var file_pbmulticluster_v2beta1_partition_exported_services_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmulticluster_v2beta1_partition_exported_services_proto_goTypes = []interface{}{ - (*PartitionExportedServices)(nil), // 0: hashicorp.consul.multicluster.v2beta1.PartitionExportedServices - (*ExportedServicesConsumer)(nil), // 1: hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer -} -var file_pbmulticluster_v2beta1_partition_exported_services_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.multicluster.v2beta1.PartitionExportedServices.consumers:type_name -> hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_pbmulticluster_v2beta1_partition_exported_services_proto_init() } -func file_pbmulticluster_v2beta1_partition_exported_services_proto_init() { - if File_pbmulticluster_v2beta1_partition_exported_services_proto != nil { - return - } - file_pbmulticluster_v2beta1_exported_services_consumer_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmulticluster_v2beta1_partition_exported_services_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PartitionExportedServices); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmulticluster_v2beta1_partition_exported_services_proto_goTypes, - DependencyIndexes: file_pbmulticluster_v2beta1_partition_exported_services_proto_depIdxs, - MessageInfos: file_pbmulticluster_v2beta1_partition_exported_services_proto_msgTypes, - }.Build() - File_pbmulticluster_v2beta1_partition_exported_services_proto = out.File - file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDesc = nil - file_pbmulticluster_v2beta1_partition_exported_services_proto_goTypes = nil - file_pbmulticluster_v2beta1_partition_exported_services_proto_depIdxs = nil -} diff --git a/proto-public/pbmulticluster/v2beta1/partition_exported_services.proto b/proto-public/pbmulticluster/v2beta1/partition_exported_services.proto deleted file mode 100644 index b3cf249a0c90f..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/partition_exported_services.proto +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -syntax = "proto3"; - -package hashicorp.consul.multicluster.v2beta1; - -import "pbmulticluster/v2beta1/exported_services_consumer.proto"; -import "pbresource/annotations.proto"; - -message PartitionExportedServices { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_PARTITION}; - - repeated ExportedServicesConsumer consumers = 1; -} diff --git a/proto-public/pbmulticluster/v2beta1/partition_exported_services_deepcopy.gen.go b/proto-public/pbmulticluster/v2beta1/partition_exported_services_deepcopy.gen.go deleted file mode 100644 index 9f048e16d2008..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/partition_exported_services_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package multiclusterv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using PartitionExportedServices within kubernetes types, where deepcopy-gen is used. -func (in *PartitionExportedServices) DeepCopyInto(out *PartitionExportedServices) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PartitionExportedServices. Required by controller-gen. -func (in *PartitionExportedServices) DeepCopy() *PartitionExportedServices { - if in == nil { - return nil - } - out := new(PartitionExportedServices) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new PartitionExportedServices. Required by controller-gen. -func (in *PartitionExportedServices) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmulticluster/v2beta1/partition_exported_services_json.gen.go b/proto-public/pbmulticluster/v2beta1/partition_exported_services_json.gen.go deleted file mode 100644 index e9dfafd702740..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/partition_exported_services_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package multiclusterv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for PartitionExportedServices -func (this *PartitionExportedServices) MarshalJSON() ([]byte, error) { - str, err := PartitionExportedServicesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for PartitionExportedServices -func (this *PartitionExportedServices) UnmarshalJSON(b []byte) error { - return PartitionExportedServicesUnmarshaler.Unmarshal(b, this) -} - -var ( - PartitionExportedServicesMarshaler = &protojson.MarshalOptions{} - PartitionExportedServicesUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmulticluster/v2beta1/resource_types.gen.go b/proto-public/pbmulticluster/v2beta1/resource_types.gen.go deleted file mode 100644 index 910811b98f931..0000000000000 --- a/proto-public/pbmulticluster/v2beta1/resource_types.gen.go +++ /dev/null @@ -1,43 +0,0 @@ -// Code generated by protoc-gen-resource-types. DO NOT EDIT. - -package multiclusterv2beta1 - -import ( - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - GroupName = "multicluster" - Version = "v2beta1" - - ComputedExportedServicesKind = "ComputedExportedServices" - ExportedServicesKind = "ExportedServices" - NamespaceExportedServicesKind = "NamespaceExportedServices" - PartitionExportedServicesKind = "PartitionExportedServices" -) - -var ( - ComputedExportedServicesType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: ComputedExportedServicesKind, - } - - ExportedServicesType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: ExportedServicesKind, - } - - NamespaceExportedServicesType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: NamespaceExportedServicesKind, - } - - PartitionExportedServicesType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: PartitionExportedServicesKind, - } -) diff --git a/proto-public/pbtenancy/v2beta1/namespace.pb.binary.go b/proto-public/pbtenancy/v1alpha1/namespace.pb.binary.go similarity index 84% rename from proto-public/pbtenancy/v2beta1/namespace.pb.binary.go rename to proto-public/pbtenancy/v1alpha1/namespace.pb.binary.go index 1884a0943b0da..f6097062d32dc 100644 --- a/proto-public/pbtenancy/v2beta1/namespace.pb.binary.go +++ b/proto-public/pbtenancy/v1alpha1/namespace.pb.binary.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbtenancy/v2beta1/namespace.proto +// source: pbtenancy/v1alpha1/namespace.proto -package tenancyv2beta1 +package tenancyv1alpha1 import ( "google.golang.org/protobuf/proto" diff --git a/proto-public/pbtenancy/v1alpha1/namespace.pb.go b/proto-public/pbtenancy/v1alpha1/namespace.pb.go new file mode 100644 index 0000000000000..e7fec0b5d0086 --- /dev/null +++ b/proto-public/pbtenancy/v1alpha1/namespace.pb.go @@ -0,0 +1,172 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc (unknown) +// source: pbtenancy/v1alpha1/namespace.proto + +package tenancyv1alpha1 + +import ( + _ "github.com/hashicorp/consul/proto-public/pbresource" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The name of the Namespace is in the outer Resource.ID.Name. +// It must be unique within a partition and must be a +// DNS hostname. There are also other reserved names that may not be used. +type Namespace struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Description is where the user puts any information they want + // about the namespace. It is not used internally. + Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` +} + +func (x *Namespace) Reset() { + *x = Namespace{} + if protoimpl.UnsafeEnabled { + mi := &file_pbtenancy_v1alpha1_namespace_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Namespace) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Namespace) ProtoMessage() {} + +func (x *Namespace) ProtoReflect() protoreflect.Message { + mi := &file_pbtenancy_v1alpha1_namespace_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Namespace.ProtoReflect.Descriptor instead. +func (*Namespace) Descriptor() ([]byte, []int) { + return file_pbtenancy_v1alpha1_namespace_proto_rawDescGZIP(), []int{0} +} + +func (x *Namespace) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +var File_pbtenancy_v1alpha1_namespace_proto protoreflect.FileDescriptor + +var file_pbtenancy_v1alpha1_namespace_proto_rawDesc = []byte{ + 0x0a, 0x22, 0x70, 0x62, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x2f, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x35, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x02, 0x42, 0xab, 0x02, 0x0a, + 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x2f, 0x70, 0x62, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x2f, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x54, 0xaa, 0x02, 0x21, 0x48, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x54, + 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, + 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x5c, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x5c, 0x56, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x24, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, + 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, + 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_pbtenancy_v1alpha1_namespace_proto_rawDescOnce sync.Once + file_pbtenancy_v1alpha1_namespace_proto_rawDescData = file_pbtenancy_v1alpha1_namespace_proto_rawDesc +) + +func file_pbtenancy_v1alpha1_namespace_proto_rawDescGZIP() []byte { + file_pbtenancy_v1alpha1_namespace_proto_rawDescOnce.Do(func() { + file_pbtenancy_v1alpha1_namespace_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbtenancy_v1alpha1_namespace_proto_rawDescData) + }) + return file_pbtenancy_v1alpha1_namespace_proto_rawDescData +} + +var file_pbtenancy_v1alpha1_namespace_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_pbtenancy_v1alpha1_namespace_proto_goTypes = []interface{}{ + (*Namespace)(nil), // 0: hashicorp.consul.tenancy.v1alpha1.Namespace +} +var file_pbtenancy_v1alpha1_namespace_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_pbtenancy_v1alpha1_namespace_proto_init() } +func file_pbtenancy_v1alpha1_namespace_proto_init() { + if File_pbtenancy_v1alpha1_namespace_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pbtenancy_v1alpha1_namespace_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Namespace); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pbtenancy_v1alpha1_namespace_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pbtenancy_v1alpha1_namespace_proto_goTypes, + DependencyIndexes: file_pbtenancy_v1alpha1_namespace_proto_depIdxs, + MessageInfos: file_pbtenancy_v1alpha1_namespace_proto_msgTypes, + }.Build() + File_pbtenancy_v1alpha1_namespace_proto = out.File + file_pbtenancy_v1alpha1_namespace_proto_rawDesc = nil + file_pbtenancy_v1alpha1_namespace_proto_goTypes = nil + file_pbtenancy_v1alpha1_namespace_proto_depIdxs = nil +} diff --git a/proto-public/pbtenancy/v2beta1/namespace.proto b/proto-public/pbtenancy/v1alpha1/namespace.proto similarity index 91% rename from proto-public/pbtenancy/v2beta1/namespace.proto rename to proto-public/pbtenancy/v1alpha1/namespace.proto index 6d4a739f6e21f..e90b10c1e573c 100644 --- a/proto-public/pbtenancy/v2beta1/namespace.proto +++ b/proto-public/pbtenancy/v1alpha1/namespace.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package hashicorp.consul.tenancy.v2beta1; +package hashicorp.consul.tenancy.v1alpha1; import "pbresource/annotations.proto"; diff --git a/proto-public/pbtenancy/v2beta1/namespace_deepcopy.gen.go b/proto-public/pbtenancy/v1alpha1/namespace_deepcopy.gen.go similarity index 97% rename from proto-public/pbtenancy/v2beta1/namespace_deepcopy.gen.go rename to proto-public/pbtenancy/v1alpha1/namespace_deepcopy.gen.go index 2384004c869f3..97af531ab3330 100644 --- a/proto-public/pbtenancy/v2beta1/namespace_deepcopy.gen.go +++ b/proto-public/pbtenancy/v1alpha1/namespace_deepcopy.gen.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package tenancyv2beta1 +package tenancyv1alpha1 import ( proto "google.golang.org/protobuf/proto" diff --git a/proto-public/pbtenancy/v2beta1/namespace_json.gen.go b/proto-public/pbtenancy/v1alpha1/namespace_json.gen.go similarity index 96% rename from proto-public/pbtenancy/v2beta1/namespace_json.gen.go rename to proto-public/pbtenancy/v1alpha1/namespace_json.gen.go index 4ad7901c16c3c..9df4de9df7199 100644 --- a/proto-public/pbtenancy/v2beta1/namespace_json.gen.go +++ b/proto-public/pbtenancy/v1alpha1/namespace_json.gen.go @@ -1,5 +1,5 @@ // Code generated by protoc-json-shim. DO NOT EDIT. -package tenancyv2beta1 +package tenancyv1alpha1 import ( protojson "google.golang.org/protobuf/encoding/protojson" diff --git a/proto-public/pbtenancy/v2beta1/resource_types.gen.go b/proto-public/pbtenancy/v1alpha1/resource_types.gen.go similarity index 87% rename from proto-public/pbtenancy/v2beta1/resource_types.gen.go rename to proto-public/pbtenancy/v1alpha1/resource_types.gen.go index b0c3040408234..f1b6f70cf1038 100644 --- a/proto-public/pbtenancy/v2beta1/resource_types.gen.go +++ b/proto-public/pbtenancy/v1alpha1/resource_types.gen.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-resource-types. DO NOT EDIT. -package tenancyv2beta1 +package tenancyv1alpha1 import ( "github.com/hashicorp/consul/proto-public/pbresource" @@ -8,7 +8,7 @@ import ( const ( GroupName = "tenancy" - Version = "v2beta1" + Version = "v1alpha1" NamespaceKind = "Namespace" ) diff --git a/proto-public/pbtenancy/v2beta1/namespace.pb.go b/proto-public/pbtenancy/v2beta1/namespace.pb.go deleted file mode 100644 index 2118814a68a7f..0000000000000 --- a/proto-public/pbtenancy/v2beta1/namespace.pb.go +++ /dev/null @@ -1,171 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbtenancy/v2beta1/namespace.proto - -package tenancyv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// The name of the Namespace is in the outer Resource.ID.Name. -// It must be unique within a partition and must be a -// DNS hostname. There are also other reserved names that may not be used. -type Namespace struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Description is where the user puts any information they want - // about the namespace. It is not used internally. - Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` -} - -func (x *Namespace) Reset() { - *x = Namespace{} - if protoimpl.UnsafeEnabled { - mi := &file_pbtenancy_v2beta1_namespace_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Namespace) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Namespace) ProtoMessage() {} - -func (x *Namespace) ProtoReflect() protoreflect.Message { - mi := &file_pbtenancy_v2beta1_namespace_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Namespace.ProtoReflect.Descriptor instead. -func (*Namespace) Descriptor() ([]byte, []int) { - return file_pbtenancy_v2beta1_namespace_proto_rawDescGZIP(), []int{0} -} - -func (x *Namespace) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -var File_pbtenancy_v2beta1_namespace_proto protoreflect.FileDescriptor - -var file_pbtenancy_v2beta1_namespace_proto_rawDesc = []byte{ - 0x0a, 0x21, 0x70, 0x62, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x20, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x35, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x02, 0x42, 0xa4, 0x02, 0x0a, 0x24, 0x63, - 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x42, 0x0e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, - 0x70, 0x62, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x3b, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xa2, 0x02, 0x03, 0x48, 0x43, 0x54, 0xaa, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, - 0x79, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x54, 0x65, 0x6e, - 0x61, 0x6e, 0x63, 0x79, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x2c, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, - 0x3a, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbtenancy_v2beta1_namespace_proto_rawDescOnce sync.Once - file_pbtenancy_v2beta1_namespace_proto_rawDescData = file_pbtenancy_v2beta1_namespace_proto_rawDesc -) - -func file_pbtenancy_v2beta1_namespace_proto_rawDescGZIP() []byte { - file_pbtenancy_v2beta1_namespace_proto_rawDescOnce.Do(func() { - file_pbtenancy_v2beta1_namespace_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbtenancy_v2beta1_namespace_proto_rawDescData) - }) - return file_pbtenancy_v2beta1_namespace_proto_rawDescData -} - -var file_pbtenancy_v2beta1_namespace_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbtenancy_v2beta1_namespace_proto_goTypes = []interface{}{ - (*Namespace)(nil), // 0: hashicorp.consul.tenancy.v2beta1.Namespace -} -var file_pbtenancy_v2beta1_namespace_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pbtenancy_v2beta1_namespace_proto_init() } -func file_pbtenancy_v2beta1_namespace_proto_init() { - if File_pbtenancy_v2beta1_namespace_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbtenancy_v2beta1_namespace_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Namespace); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbtenancy_v2beta1_namespace_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbtenancy_v2beta1_namespace_proto_goTypes, - DependencyIndexes: file_pbtenancy_v2beta1_namespace_proto_depIdxs, - MessageInfos: file_pbtenancy_v2beta1_namespace_proto_msgTypes, - }.Build() - File_pbtenancy_v2beta1_namespace_proto = out.File - file_pbtenancy_v2beta1_namespace_proto_rawDesc = nil - file_pbtenancy_v2beta1_namespace_proto_goTypes = nil - file_pbtenancy_v2beta1_namespace_proto_depIdxs = nil -} diff --git a/test/integration/consul-container/test/catalog/catalog_test.go b/test/integration/consul-container/test/catalog/catalog_test.go index 5be52792d8218..b6e821e1f1f7f 100644 --- a/test/integration/consul-container/test/catalog/catalog_test.go +++ b/test/integration/consul-container/test/catalog/catalog_test.go @@ -29,7 +29,7 @@ func TestCatalog(t *testing.T) { client := pbresource.NewResourceServiceClient(followers[0].GetGRPCConn()) t.Run("one-shot", func(t *testing.T) { - catalogtest.RunCatalogV2Beta1IntegrationTest(t, client) + catalogtest.RunCatalogV1Alpha1IntegrationTest(t, client) }) t.Run("lifecycle", func(t *testing.T) { diff --git a/testing/deployer/topology/compile.go b/testing/deployer/topology/compile.go index 7faf74d01a0ee..98f1c1e917e8c 100644 --- a/testing/deployer/topology/compile.go +++ b/testing/deployer/topology/compile.go @@ -203,7 +203,7 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error n.Index = nextIndex nextIndex++ - n.Images = c.Images.OverrideWith(n.Images.ChooseConsul(c.Enterprise)).ChooseNode(n.Kind) + n.Images = c.Images.OverrideWith(n.Images).ChooseNode(n.Kind) n.Cluster = c.Name n.Datacenter = c.Datacenter diff --git a/testing/deployer/topology/images.go b/testing/deployer/topology/images.go index 7adb8d3f7ee65..836ddb091c915 100644 --- a/testing/deployer/topology/images.go +++ b/testing/deployer/topology/images.go @@ -8,12 +8,8 @@ import ( ) type Images struct { - // Consul is the image used for creating the container, - // Use ChooseConsul() to control which image (ConsulCE or ConsulEnterprise) assign to Consul - Consul string `json:",omitempty"` - // ConsulCE sets the CE image - ConsulCE string `json:",omitempty"` - // ConsulEnterprise sets the ent image + Consul string `json:",omitempty"` + ConsulCE string `json:",omitempty"` ConsulEnterprise string `json:",omitempty"` Envoy string Dataplane string @@ -86,7 +82,6 @@ func (i Images) ChooseNode(kind NodeKind) Images { return i } -// ChooseConsul controls which image assigns to Consul func (i Images) ChooseConsul(enterprise bool) Images { if enterprise { i.Consul = i.ConsulEnterprise diff --git a/version/VERSION b/version/VERSION index ee017091ff37b..ee8855caa4a79 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -1.18.0-dev +1.17.0-dev diff --git a/website/content/docs/services/discovery/dns-configuration.mdx b/website/content/docs/services/discovery/dns-configuration.mdx index 5a0d890e79bff..369f8fe50ff79 100644 --- a/website/content/docs/services/discovery/dns-configuration.mdx +++ b/website/content/docs/services/discovery/dns-configuration.mdx @@ -16,7 +16,7 @@ The Consul DNS is the primary interface for querying records when Consul service By default, the Consul DNS listens for queries at `127.0.0.1:8600` and uses the `consul` domain. Specify the following parameters in the agent configuration to determine DNS behavior when querying services: - [`client_addr`](/consul/docs/agent/config/config-files#client_addr) -- [`ports.dns`](/consul/docs/agent/config/config-files#dns_port) : Consul does not use port `53`, which is typically reserved for the default port for DNS resolvers, by default because it requires an escalated privilege to bind to. +- [`ports.dns`](/consul/docs/agent/config/config-files#dns_port) : Consul does not use port `53`, which is typically reserved for the default port for DNS resolvers, by default because it requires an escalated privilege to bind to. - [`recursors`](/consul/docs/agent/config/config-files#recursors) - [`domain`](/consul/docs/agent/config/config-files#domain) - [`alt_domain`](/consul/docs/agent/config/config-files#alt_domain)