From f68994fa0de1cb30233f4b9dd8b2777373ec6a5a Mon Sep 17 00:00:00 2001 From: trujillo-adam Date: Thu, 31 Aug 2023 16:47:46 +0000 Subject: [PATCH] backport of commit baae1ed358f5b79acc30ed9890d5ecd2ab6d4b43 --- .changelog/17155.txt | 3 - .changelog/17481.txt | 3 - .changelog/17593.txt | 3 - .changelog/17694.txt | 3 - .changelog/17754.txt | 4 +- .changelog/17831.txt | 3 - .changelog/18007.txt | 3 - .changelog/18300.txt | 3 - .changelog/18303.txt | 3 + .changelog/18324.txt | 3 - .changelog/18336.txt | 7 - .changelog/18367.txt | 3 - .changelog/18381.txt | 6 + .changelog/18439.txt | 3 - .changelog/18560.txt | 3 - .changelog/18583.txt | 3 - .changelog/18617.txt | 4 + .changelog/18625.txt | 5 + .changelog/18636.txt | 3 + .changelog/18667.txt | 3 + .changelog/_18366.txt | 3 - .changelog/_18422.txt | 3 - .copywrite.hcl | 11 +- .github/ISSUE_TEMPLATE/config.yml | 2 +- .github/dependabot.yml | 2 +- .github/pr-labeler.yml | 2 +- .github/scripts/changelog_checker.sh | 2 +- .github/scripts/get_runner_classes.sh | 32 +- .github/scripts/get_runner_classes_windows.sh | 26 - .github/scripts/metrics_checker.sh | 2 +- .github/scripts/notify_slack.sh | 7 +- .github/scripts/rerun_fails_report.sh | 2 +- .github/scripts/set_test_package_matrix.sh | 2 +- .github/scripts/verify_artifact.sh | 2 +- .github/scripts/verify_bin.sh | 2 +- .github/scripts/verify_deb.sh | 2 +- .github/scripts/verify_docker.sh | 2 +- .github/scripts/verify_envoy_version.sh | 2 +- .github/scripts/verify_rpm.sh | 2 +- .github/workflows/bot-auto-approve.yaml | 2 +- .github/workflows/broken-link-check.yml | 6 +- .github/workflows/build-artifacts.yml | 14 +- .github/workflows/build-distros.yml | 14 +- .github/workflows/build.yml | 36 +- .github/workflows/ce-merge-trigger.yml | 2 +- .github/workflows/changelog-checker.yml | 2 +- .github/workflows/embedded-asset-checker.yml | 2 +- .github/workflows/frontend.yml | 18 +- .github/workflows/go-tests.yml | 90 +- .github/workflows/issue-comment-created.yml | 4 +- .github/workflows/jira-issues.yaml | 14 +- .github/workflows/jira-pr.yaml | 14 +- ...t-1.16.x.yaml => nightly-test-1.12.x.yaml} | 45 +- .github/workflows/nightly-test-1.13.x.yaml | 43 +- .github/workflows/nightly-test-1.14.x.yaml | 43 +- .github/workflows/nightly-test-1.15.x.yaml | 43 +- .../nightly-test-integrations-1.15.x.yml | 320 -- .../nightly-test-integrations-1.16.x.yml | 342 -- .../workflows/nightly-test-integrations.yml | 33 +- .github/workflows/nightly-test-main.yaml | 43 +- .github/workflows/pr-labeler.yml | 2 +- .github/workflows/pr-metrics-test-checker.yml | 2 +- .github/workflows/reusable-check-go-mod.yml | 4 +- .../workflows/reusable-dev-build-windows.yml | 47 - .github/workflows/reusable-dev-build.yml | 14 +- .github/workflows/reusable-lint.yml | 8 +- .github/workflows/reusable-unit-split.yml | 15 +- .github/workflows/reusable-unit.yml | 9 +- .github/workflows/stale.yml | 2 +- .../workflows/test-integrations-windows.yml | 1209 ------ .github/workflows/test-integrations.yml | 133 +- .github/workflows/verify-envoy-version.yml | 2 +- .gitignore | 2 - .golangci.yml | 2 +- .release/ci.hcl | 2 +- .release/docker/docker-entrypoint-ubi.sh | 2 +- .release/docker/docker-entrypoint-windows.sh | 85 - .release/docker/docker-entrypoint.sh | 2 +- .../linux/package/etc/consul.d/consul.hcl | 2 +- .release/release-metadata.hcl | 2 +- .release/security-scan.hcl | 2 +- CHANGELOG.md | 177 +- Dockerfile | 2 +- Dockerfile-windows | 51 - Makefile => GNUmakefile | 431 +- LICENSE | 417 +- README.md | 3 +- acl/MockAuthorizer.go | 2 +- acl/acl.go | 2 +- acl/acl_ce.go | 2 +- acl/acl_test.go | 2 +- acl/authorizer.go | 2 +- acl/authorizer_ce.go | 2 +- acl/authorizer_test.go | 2 +- acl/chained_authorizer.go | 2 +- acl/chained_authorizer_test.go | 2 +- acl/enterprisemeta_ce.go | 2 +- acl/errors.go | 2 +- acl/errors_ce.go | 2 +- acl/errors_test.go | 2 +- acl/policy.go | 2 +- acl/policy_authorizer.go | 2 +- acl/policy_authorizer_ce.go | 2 +- acl/policy_authorizer_test.go | 2 +- acl/policy_ce.go | 2 +- acl/policy_merger.go | 2 +- acl/policy_merger_ce.go | 2 +- acl/policy_test.go | 2 +- acl/resolver/danger.go | 2 +- acl/resolver/result.go | 2 +- acl/static_authorizer.go | 2 +- acl/static_authorizer_test.go | 2 +- acl/testing.go | 2 +- acl/validation.go | 2 +- acl/validation_test.go | 2 +- agent/acl.go | 2 +- agent/acl_ce.go | 2 +- agent/acl_endpoint.go | 3 +- agent/acl_endpoint_test.go | 34 +- agent/acl_test.go | 6 +- agent/ae/ae.go | 2 +- agent/ae/ae_test.go | 2 +- agent/ae/trigger.go | 2 +- agent/agent.go | 159 +- agent/agent_ce.go | 2 +- agent/agent_ce_test.go | 2 +- agent/agent_endpoint.go | 12 +- agent/agent_endpoint_ce.go | 2 +- agent/agent_endpoint_ce_test.go | 2 +- agent/agent_endpoint_test.go | 41 +- agent/agent_test.go | 175 +- agent/apiserver.go | 2 +- agent/apiserver_test.go | 2 +- agent/auto-config/auto_config.go | 2 +- agent/auto-config/auto_config_ce.go | 2 +- agent/auto-config/auto_config_ce_test.go | 2 +- agent/auto-config/auto_config_test.go | 2 +- agent/auto-config/auto_encrypt.go | 2 +- agent/auto-config/auto_encrypt_test.go | 2 +- agent/auto-config/config.go | 2 +- agent/auto-config/config_ce.go | 2 +- agent/auto-config/config_translate.go | 2 +- agent/auto-config/config_translate_test.go | 2 +- agent/auto-config/mock_ce_test.go | 2 +- agent/auto-config/mock_test.go | 2 +- agent/auto-config/persist.go | 2 +- agent/auto-config/run.go | 2 +- agent/auto-config/server_addr.go | 2 +- agent/auto-config/tls.go | 2 +- agent/auto-config/tls_test.go | 2 +- agent/blockingquery/blockingquery.go | 3 - agent/blockingquery/blockingquery_test.go | 3 - agent/cache-types/catalog_datacenters.go | 2 +- agent/cache-types/catalog_datacenters_test.go | 2 +- agent/cache-types/catalog_list_services.go | 2 +- .../cache-types/catalog_list_services_test.go | 2 +- agent/cache-types/catalog_service_list.go | 2 +- .../cache-types/catalog_service_list_test.go | 2 +- agent/cache-types/catalog_services.go | 2 +- agent/cache-types/catalog_services_test.go | 2 +- agent/cache-types/config_entry.go | 2 +- agent/cache-types/config_entry_test.go | 2 +- agent/cache-types/connect_ca_root.go | 2 +- agent/cache-types/connect_ca_root_test.go | 2 +- agent/cache-types/discovery_chain.go | 2 +- agent/cache-types/discovery_chain_test.go | 2 +- agent/cache-types/exported_peered_services.go | 2 +- .../exported_peered_services_test.go | 2 +- .../federation_state_list_gateways.go | 2 +- .../federation_state_list_gateways_test.go | 2 +- agent/cache-types/gateway_services.go | 2 +- agent/cache-types/gateway_services_test.go | 2 +- agent/cache-types/health_services.go | 2 +- agent/cache-types/health_services_test.go | 2 +- agent/cache-types/intention_match.go | 2 +- agent/cache-types/intention_match_test.go | 2 +- agent/cache-types/intention_upstreams.go | 2 +- .../intention_upstreams_destination.go | 2 +- .../intention_upstreams_destination_test.go | 2 +- agent/cache-types/intention_upstreams_test.go | 2 +- agent/cache-types/node_services.go | 2 +- agent/cache-types/node_services_test.go | 2 +- agent/cache-types/options.go | 2 +- agent/cache-types/peered_upstreams.go | 2 +- agent/cache-types/peered_upstreams_test.go | 2 +- agent/cache-types/peerings.go | 2 +- agent/cache-types/peerings_test.go | 2 +- agent/cache-types/prepared_query.go | 2 +- agent/cache-types/prepared_query_test.go | 2 +- agent/cache-types/resolved_service_config.go | 2 +- .../resolved_service_config_test.go | 2 +- agent/cache-types/rpc.go | 2 +- agent/cache-types/service_checks.go | 2 +- agent/cache-types/service_checks_test.go | 2 +- agent/cache-types/service_dump.go | 2 +- agent/cache-types/service_dump_test.go | 2 +- agent/cache-types/service_gateways.go | 2 +- agent/cache-types/service_gateways_test.go | 2 +- agent/cache-types/testing.go | 2 +- agent/cache-types/trust_bundle.go | 2 +- agent/cache-types/trust_bundle_test.go | 2 +- agent/cache-types/trust_bundles.go | 2 +- agent/cache-types/trust_bundles_test.go | 2 +- agent/cache/cache.go | 2 +- agent/cache/cache_test.go | 2 +- agent/cache/entry.go | 2 +- agent/cache/request.go | 2 +- agent/cache/testing.go | 2 +- agent/cache/type.go | 2 +- agent/cache/watch.go | 2 +- agent/cache/watch_test.go | 2 +- agent/catalog_endpoint.go | 2 +- agent/catalog_endpoint_ce.go | 2 +- agent/catalog_endpoint_test.go | 2 +- agent/check.go | 2 +- agent/checks/alias.go | 2 +- agent/checks/alias_test.go | 2 +- agent/checks/check.go | 40 +- agent/checks/check_test.go | 2 +- agent/checks/check_windows_test.go | 2 +- agent/checks/docker.go | 2 +- agent/checks/docker_unix.go | 2 +- agent/checks/docker_windows.go | 2 +- agent/checks/grpc.go | 2 +- agent/checks/grpc_test.go | 2 +- agent/checks/os_service.go | 2 +- agent/checks/os_service_unix.go | 2 +- agent/checks/os_service_windows.go | 2 +- agent/config/agent_limits.go | 2 +- agent/config/builder.go | 20 +- agent/config/builder_ce.go | 2 +- agent/config/builder_ce_test.go | 2 +- agent/config/builder_test.go | 2 +- agent/config/config.go | 3 +- agent/config/config_ce.go | 2 +- agent/config/default.go | 6 +- agent/config/default_ce.go | 2 +- agent/config/deprecated.go | 2 +- agent/config/deprecated_test.go | 2 +- agent/config/doc.go | 2 +- agent/config/file_watcher.go | 2 +- agent/config/file_watcher_test.go | 2 +- agent/config/flags.go | 2 +- agent/config/flags_test.go | 2 +- agent/config/flagset.go | 2 +- agent/config/golden_test.go | 2 +- agent/config/limits.go | 2 +- agent/config/limits_windows.go | 2 +- agent/config/merge.go | 2 +- agent/config/merge_test.go | 2 +- agent/config/ratelimited_file_watcher.go | 2 +- agent/config/ratelimited_file_watcher_test.go | 2 +- agent/config/runtime.go | 2 +- agent/config/runtime_ce.go | 2 +- agent/config/runtime_ce_test.go | 2 +- agent/config/runtime_test.go | 183 +- agent/config/segment_ce.go | 2 +- agent/config/segment_ce_test.go | 2 +- .../TestRuntimeConfig_Sanitize.golden | 2 + agent/config/testdata/full-config.hcl | 2 +- agent/config_endpoint.go | 2 +- agent/config_endpoint_test.go | 2 +- agent/configentry/compare.go | 3 - agent/configentry/compare_test.go | 3 - agent/configentry/config_entry.go | 2 +- agent/configentry/discoverychain.go | 2 +- agent/configentry/doc.go | 2 +- agent/configentry/merge_service_config.go | 8 +- .../configentry/merge_service_config_test.go | 110 +- agent/configentry/resolve.go | 5 +- agent/configentry/resolve_test.go | 2 +- agent/configentry/service_config.go | 2 +- agent/connect/authz.go | 2 +- agent/connect/authz_test.go | 2 +- agent/connect/ca/common.go | 2 +- agent/connect/ca/provider.go | 4 +- agent/connect/ca/provider_aws.go | 2 +- agent/connect/ca/provider_aws_test.go | 2 +- agent/connect/ca/provider_consul.go | 2 +- agent/connect/ca/provider_consul_config.go | 2 +- agent/connect/ca/provider_consul_test.go | 2 +- agent/connect/ca/provider_test.go | 4 +- agent/connect/ca/provider_vault.go | 16 +- agent/connect/ca/provider_vault_auth.go | 2 +- .../ca/provider_vault_auth_alicloud.go | 2 +- .../connect/ca/provider_vault_auth_approle.go | 2 +- agent/connect/ca/provider_vault_auth_aws.go | 2 +- agent/connect/ca/provider_vault_auth_azure.go | 2 +- agent/connect/ca/provider_vault_auth_gcp.go | 2 +- agent/connect/ca/provider_vault_auth_jwt.go | 2 +- agent/connect/ca/provider_vault_auth_k8s.go | 2 +- agent/connect/ca/provider_vault_auth_test.go | 2 +- agent/connect/ca/provider_vault_test.go | 20 +- agent/connect/ca/testing.go | 2 +- agent/connect/common_names.go | 2 +- agent/connect/csr.go | 2 +- agent/connect/csr_test.go | 2 +- agent/connect/generate.go | 2 +- agent/connect/generate_test.go | 2 +- agent/connect/parsing.go | 4 +- agent/connect/sni.go | 2 +- agent/connect/sni_test.go | 2 +- agent/connect/testing_ca.go | 2 +- agent/connect/testing_ca_test.go | 2 +- agent/connect/testing_spiffe.go | 2 +- agent/connect/uri.go | 2 +- agent/connect/uri_agent.go | 2 +- agent/connect/uri_agent_ce.go | 2 +- agent/connect/uri_agent_ce_test.go | 2 +- agent/connect/uri_mesh_gateway.go | 2 +- agent/connect/uri_mesh_gateway_ce.go | 2 +- agent/connect/uri_mesh_gateway_ce_test.go | 2 +- agent/connect/uri_server.go | 2 +- agent/connect/uri_service.go | 2 +- agent/connect/uri_service_ce.go | 2 +- agent/connect/uri_service_ce_test.go | 2 +- agent/connect/uri_signing.go | 2 +- agent/connect/uri_signing_test.go | 2 +- agent/connect/uri_test.go | 2 +- agent/connect/x509_patch.go | 2 +- agent/connect/x509_patch_test.go | 2 +- agent/connect_auth.go | 2 +- agent/connect_ca_endpoint.go | 2 +- agent/connect_ca_endpoint_test.go | 2 +- agent/consul/acl.go | 2 +- agent/consul/acl_authmethod.go | 2 +- agent/consul/acl_authmethod_ce.go | 2 +- agent/consul/acl_ce.go | 2 +- agent/consul/acl_ce_test.go | 2 +- agent/consul/acl_client.go | 2 +- agent/consul/acl_endpoint.go | 16 +- agent/consul/acl_endpoint_ce.go | 2 +- agent/consul/acl_endpoint_test.go | 2 +- agent/consul/acl_replication.go | 2 +- agent/consul/acl_replication_test.go | 7 +- agent/consul/acl_replication_types.go | 3 +- agent/consul/acl_server.go | 2 +- agent/consul/acl_server_ce.go | 2 +- agent/consul/acl_test.go | 2 +- agent/consul/acl_token_exp.go | 2 +- agent/consul/acl_token_exp_test.go | 2 +- agent/consul/auth/binder.go | 2 +- agent/consul/auth/binder_ce.go | 2 +- agent/consul/auth/binder_test.go | 2 +- agent/consul/auth/login.go | 2 +- agent/consul/auth/token_writer.go | 2 +- agent/consul/auth/token_writer_ce.go | 2 +- agent/consul/auth/token_writer_test.go | 2 +- agent/consul/authmethod/authmethods.go | 2 +- agent/consul/authmethod/authmethods_ce.go | 2 +- agent/consul/authmethod/awsauth/aws.go | 2 +- agent/consul/authmethod/awsauth/aws_test.go | 2 +- agent/consul/authmethod/kubeauth/k8s.go | 2 +- agent/consul/authmethod/kubeauth/k8s_ce.go | 2 +- agent/consul/authmethod/kubeauth/k8s_test.go | 2 +- agent/consul/authmethod/kubeauth/testing.go | 2 +- agent/consul/authmethod/ssoauth/sso.go | 2 +- agent/consul/authmethod/ssoauth/sso_ce.go | 2 +- agent/consul/authmethod/ssoauth/sso_test.go | 2 +- agent/consul/authmethod/testauth/testing.go | 2 +- .../consul/authmethod/testauth/testing_ce.go | 2 +- agent/consul/authmethod/testing.go | 2 +- agent/consul/auto_config_backend.go | 4 +- agent/consul/auto_config_backend_test.go | 2 +- agent/consul/auto_config_endpoint.go | 2 +- agent/consul/auto_config_endpoint_test.go | 2 +- agent/consul/auto_encrypt_endpoint.go | 2 +- agent/consul/auto_encrypt_endpoint_test.go | 2 +- agent/consul/autopilot.go | 2 +- agent/consul/autopilot_ce.go | 2 +- agent/consul/autopilot_test.go | 2 +- .../autopilotevents/ready_servers_events.go | 2 +- .../ready_servers_events_test.go | 2 +- agent/consul/catalog_endpoint.go | 2 +- agent/consul/catalog_endpoint_test.go | 2 +- agent/consul/client.go | 17 +- agent/consul/client_serf.go | 2 +- agent/consul/client_test.go | 5 +- agent/consul/cluster_test.go | 2 +- agent/consul/config.go | 2 +- agent/consul/config_ce.go | 2 +- agent/consul/config_cloud.go | 3 - agent/consul/config_endpoint.go | 2 +- agent/consul/config_endpoint_test.go | 2 +- agent/consul/config_replication.go | 2 +- agent/consul/config_replication_test.go | 2 +- agent/consul/config_test.go | 2 +- agent/consul/connect_ca_endpoint.go | 2 +- agent/consul/connect_ca_endpoint_test.go | 2 +- agent/consul/context.go | 2 +- agent/consul/context_test.go | 2 +- agent/consul/controller/controller.go | 2 +- agent/consul/controller/controller_test.go | 2 +- agent/consul/controller/doc.go | 2 +- agent/consul/controller/queue/defer.go | 2 +- agent/consul/controller/queue/queue.go | 2 +- agent/consul/controller/queue/rate.go | 2 +- agent/consul/controller/queue/rate_test.go | 2 +- agent/consul/controller/queue_test.go | 2 +- agent/consul/controller/reconciler.go | 2 +- agent/consul/controller/reconciler_test.go | 2 +- agent/consul/coordinate_endpoint.go | 2 +- agent/consul/coordinate_endpoint_test.go | 2 +- agent/consul/discovery_chain_endpoint.go | 2 +- agent/consul/discovery_chain_endpoint_test.go | 2 +- agent/consul/discoverychain/compile.go | 2 +- agent/consul/discoverychain/compile_ce.go | 2 +- agent/consul/discoverychain/compile_test.go | 2 +- agent/consul/discoverychain/gateway.go | 2 +- .../discoverychain/gateway_httproute.go | 25 +- .../consul/discoverychain/gateway_tcproute.go | 2 +- agent/consul/discoverychain/gateway_test.go | 2 +- agent/consul/discoverychain/string_stack.go | 2 +- .../discoverychain/string_stack_test.go | 2 +- agent/consul/discoverychain/testing.go | 2 +- agent/consul/enterprise_client_ce.go | 2 +- agent/consul/enterprise_config_ce.go | 2 +- agent/consul/enterprise_server_ce.go | 2 +- agent/consul/enterprise_server_ce_test.go | 2 +- agent/consul/federation_state_endpoint.go | 2 +- .../consul/federation_state_endpoint_test.go | 2 +- agent/consul/federation_state_replication.go | 2 +- .../federation_state_replication_test.go | 2 +- agent/consul/filter.go | 2 +- agent/consul/filter_test.go | 2 +- agent/consul/flood.go | 2 +- agent/consul/fsm/commands_ce.go | 2 +- agent/consul/fsm/commands_ce_test.go | 2 +- agent/consul/fsm/fsm.go | 2 +- agent/consul/fsm/fsm_test.go | 2 +- .../fsm/log_verification_chunking_shim.go | 2 +- agent/consul/fsm/snapshot.go | 2 +- agent/consul/fsm/snapshot_ce.go | 2 +- agent/consul/fsm/snapshot_ce_test.go | 2 +- agent/consul/fsm/snapshot_test.go | 2 +- agent/consul/gateway_locator.go | 2 +- agent/consul/gateway_locator_test.go | 2 +- agent/consul/gateways/controller_gateways.go | 2 +- .../gateways/controller_gateways_test.go | 2 +- agent/consul/grpc_integration_test.go | 2 +- agent/consul/health_endpoint.go | 2 +- agent/consul/health_endpoint_test.go | 2 +- agent/consul/helper_test.go | 2 +- agent/consul/intention_endpoint.go | 2 +- agent/consul/intention_endpoint_test.go | 2 +- agent/consul/internal_endpoint.go | 2 +- agent/consul/internal_endpoint_test.go | 2 +- agent/consul/issue_test.go | 2 +- agent/consul/kvs_endpoint.go | 2 +- agent/consul/kvs_endpoint_test.go | 2 +- agent/consul/leader.go | 2 +- agent/consul/leader_ce_test.go | 2 +- agent/consul/leader_connect.go | 2 +- agent/consul/leader_connect_ca.go | 2 +- agent/consul/leader_connect_ca_test.go | 4 +- agent/consul/leader_connect_test.go | 2 +- agent/consul/leader_federation_state_ae.go | 2 +- .../consul/leader_federation_state_ae_test.go | 2 +- agent/consul/leader_intentions.go | 2 +- agent/consul/leader_intentions_ce.go | 2 +- agent/consul/leader_intentions_ce_test.go | 2 +- agent/consul/leader_intentions_test.go | 2 +- agent/consul/leader_log_verification.go | 2 +- agent/consul/leader_metrics.go | 2 +- agent/consul/leader_metrics_test.go | 2 +- agent/consul/leader_peering.go | 2 +- agent/consul/leader_peering_test.go | 2 +- agent/consul/leader_test.go | 4 +- agent/consul/logging.go | 2 +- agent/consul/logging_test.go | 2 +- agent/consul/merge.go | 2 +- agent/consul/merge_ce.go | 2 +- agent/consul/merge_ce_test.go | 2 +- agent/consul/merge_test.go | 2 +- agent/consul/multilimiter/multilimiter.go | 2 +- .../consul/multilimiter/multilimiter_test.go | 2 +- agent/consul/operator_autopilot_endpoint.go | 2 +- .../operator_autopilot_endpoint_test.go | 2 +- agent/consul/operator_backend.go | 2 +- agent/consul/operator_backend_test.go | 2 +- agent/consul/operator_endpoint.go | 2 +- agent/consul/operator_raft_endpoint.go | 2 +- agent/consul/operator_raft_endpoint_test.go | 2 +- agent/consul/operator_usage_endpoint.go | 2 +- agent/consul/options.go | 4 +- agent/consul/options_ce.go | 2 +- agent/consul/peering_backend.go | 2 +- agent/consul/peering_backend_ce.go | 2 +- agent/consul/peering_backend_ce_test.go | 2 +- agent/consul/peering_backend_test.go | 2 +- agent/consul/prepared_query/template.go | 2 +- agent/consul/prepared_query/template_test.go | 2 +- agent/consul/prepared_query/walk.go | 2 +- agent/consul/prepared_query/walk_ce_test.go | 2 +- agent/consul/prepared_query/walk_test.go | 2 +- agent/consul/prepared_query_endpoint.go | 2 +- agent/consul/prepared_query_endpoint_ce.go | 2 +- .../consul/prepared_query_endpoint_ce_test.go | 2 +- agent/consul/prepared_query_endpoint_test.go | 4 +- agent/consul/raft_handle.go | 2 +- agent/consul/raft_rpc.go | 2 +- agent/consul/rate/handler.go | 2 +- agent/consul/rate/handler_ce.go | 2 +- agent/consul/rate/handler_test.go | 2 +- agent/consul/rate/metrics.go | 2 +- agent/consul/replication.go | 2 +- agent/consul/replication_test.go | 2 +- agent/consul/reporting/reporting.go | 2 +- agent/consul/reporting/reporting_ce.go | 2 +- agent/consul/rpc.go | 2 +- agent/consul/rpc_test.go | 2 +- agent/consul/rtt.go | 2 +- agent/consul/rtt_test.go | 2 +- agent/consul/segment_ce.go | 2 +- agent/consul/serf_filter.go | 2 +- agent/consul/serf_test.go | 2 +- agent/consul/server.go | 151 +- agent/consul/server_ce.go | 2 +- agent/consul/server_ce_test.go | 2 +- agent/consul/server_connect.go | 2 +- agent/consul/server_log_verification.go | 2 +- agent/consul/server_lookup.go | 2 +- agent/consul/server_lookup_test.go | 2 +- agent/consul/server_metadata.go | 2 +- agent/consul/server_metadata_test.go | 2 +- agent/consul/server_overview.go | 2 +- agent/consul/server_overview_test.go | 2 +- agent/consul/server_register.go | 2 +- agent/consul/server_serf.go | 2 +- agent/consul/server_test.go | 12 +- agent/consul/servercert/manager.go | 2 +- agent/consul/servercert/manager_test.go | 2 +- agent/consul/session_endpoint.go | 2 +- agent/consul/session_endpoint_test.go | 2 +- agent/consul/session_timers.go | 2 +- agent/consul/session_timers_test.go | 2 +- agent/consul/session_ttl.go | 2 +- agent/consul/session_ttl_test.go | 2 +- agent/consul/snapshot_endpoint.go | 2 +- agent/consul/snapshot_endpoint_test.go | 2 +- agent/consul/state/acl.go | 67 +- agent/consul/state/acl_ce.go | 6 +- agent/consul/state/acl_ce_test.go | 2 +- agent/consul/state/acl_events.go | 2 +- agent/consul/state/acl_events_test.go | 2 +- agent/consul/state/acl_schema.go | 27 +- agent/consul/state/acl_test.go | 135 +- agent/consul/state/autopilot.go | 2 +- agent/consul/state/autopilot_test.go | 2 +- agent/consul/state/catalog.go | 6 +- agent/consul/state/catalog_ce.go | 2 +- agent/consul/state/catalog_ce_test.go | 2 +- agent/consul/state/catalog_events.go | 4 +- agent/consul/state/catalog_events_ce.go | 2 +- agent/consul/state/catalog_events_ce_test.go | 2 +- agent/consul/state/catalog_events_test.go | 2 +- agent/consul/state/catalog_schema.deepcopy.go | 3 - agent/consul/state/catalog_schema.go | 2 +- agent/consul/state/catalog_test.go | 2 +- agent/consul/state/config_entry.go | 2 +- agent/consul/state/config_entry_ce.go | 2 +- agent/consul/state/config_entry_ce_test.go | 2 +- agent/consul/state/config_entry_events.go | 2 +- .../consul/state/config_entry_events_test.go | 2 +- .../state/config_entry_exported_services.go | 2 +- .../config_entry_exported_services_ce.go | 2 +- agent/consul/state/config_entry_intention.go | 2 +- .../consul/state/config_entry_intention_ce.go | 2 +- .../state/config_entry_sameness_group.go | 3 - .../state/config_entry_sameness_group_ce.go | 2 +- .../config_entry_sameness_group_ce_test.go | 2 +- agent/consul/state/config_entry_schema.go | 2 +- agent/consul/state/config_entry_test.go | 2 +- agent/consul/state/connect_ca.go | 2 +- agent/consul/state/connect_ca_events.go | 2 +- agent/consul/state/connect_ca_events_test.go | 2 +- agent/consul/state/connect_ca_test.go | 2 +- agent/consul/state/coordinate.go | 2 +- agent/consul/state/coordinate_ce.go | 2 +- agent/consul/state/coordinate_ce_test.go | 2 +- agent/consul/state/coordinate_test.go | 2 +- agent/consul/state/deep-copy.sh | 3 - agent/consul/state/delay_ce.go | 2 +- agent/consul/state/delay_test.go | 2 +- agent/consul/state/events.go | 2 +- agent/consul/state/events_test.go | 2 +- agent/consul/state/federation_state.go | 2 +- agent/consul/state/graveyard.go | 2 +- agent/consul/state/graveyard_ce.go | 2 +- agent/consul/state/graveyard_test.go | 2 +- agent/consul/state/index_connect_test.go | 2 +- agent/consul/state/indexer.go | 2 +- agent/consul/state/intention.go | 2 +- agent/consul/state/intention_ce.go | 2 +- agent/consul/state/intention_test.go | 2 +- agent/consul/state/kvs.go | 2 +- agent/consul/state/kvs_ce.go | 2 +- agent/consul/state/kvs_ce_test.go | 2 +- agent/consul/state/kvs_test.go | 2 +- agent/consul/state/memdb.go | 2 +- agent/consul/state/memdb_test.go | 2 +- agent/consul/state/operations_ce.go | 2 +- agent/consul/state/peering.go | 2 +- agent/consul/state/peering_ce.go | 2 +- agent/consul/state/peering_ce_test.go | 2 +- agent/consul/state/peering_test.go | 2 +- agent/consul/state/prepared_query.go | 2 +- agent/consul/state/prepared_query_index.go | 2 +- .../consul/state/prepared_query_index_test.go | 2 +- agent/consul/state/prepared_query_test.go | 2 +- agent/consul/state/query.go | 2 +- agent/consul/state/query_ce.go | 2 +- agent/consul/state/schema.go | 2 +- agent/consul/state/schema_ce.go | 2 +- agent/consul/state/schema_ce_test.go | 2 +- agent/consul/state/schema_test.go | 2 +- agent/consul/state/session.go | 2 +- agent/consul/state/session_ce.go | 2 +- agent/consul/state/session_test.go | 2 +- agent/consul/state/state_store.go | 2 +- agent/consul/state/state_store_ce_test.go | 2 +- agent/consul/state/state_store_test.go | 2 +- agent/consul/state/store_integration_test.go | 2 +- agent/consul/state/system_metadata.go | 2 +- agent/consul/state/system_metadata_test.go | 2 +- agent/consul/state/tombstone_gc.go | 2 +- agent/consul/state/tombstone_gc_test.go | 2 +- agent/consul/state/txn.go | 2 +- agent/consul/state/txn_test.go | 2 +- agent/consul/state/usage.go | 2 +- agent/consul/state/usage_ce.go | 2 +- agent/consul/state/usage_test.go | 2 +- agent/consul/stats_fetcher.go | 2 +- agent/consul/stats_fetcher_test.go | 2 +- agent/consul/status_endpoint.go | 2 +- agent/consul/status_endpoint_test.go | 2 +- agent/consul/stream/event.go | 2 +- agent/consul/stream/event_buffer.go | 2 +- agent/consul/stream/event_buffer_test.go | 2 +- agent/consul/stream/event_publisher.go | 2 +- agent/consul/stream/event_publisher_test.go | 2 +- agent/consul/stream/event_snapshot.go | 2 +- agent/consul/stream/event_snapshot_test.go | 2 +- agent/consul/stream/event_test.go | 2 +- agent/consul/stream/noop.go | 2 +- agent/consul/stream/string_types.go | 2 +- agent/consul/stream/subscription.go | 2 +- agent/consul/stream/subscription_test.go | 2 +- agent/consul/subscribe_backend.go | 2 +- agent/consul/subscribe_backend_test.go | 2 +- agent/consul/system_metadata.go | 2 +- agent/consul/system_metadata_test.go | 2 +- agent/consul/tenancy_bridge.go | 15 - agent/consul/tenancy_bridge_ce.go | 29 - agent/consul/txn_endpoint.go | 2 +- agent/consul/txn_endpoint_test.go | 2 +- agent/consul/type_registry.go | 28 - agent/consul/usagemetrics/usagemetrics.go | 2 +- agent/consul/usagemetrics/usagemetrics_ce.go | 2 +- .../usagemetrics/usagemetrics_ce_test.go | 2 +- .../consul/usagemetrics/usagemetrics_test.go | 2 +- agent/consul/util.go | 2 +- agent/consul/util_test.go | 2 +- agent/consul/wanfed/pool.go | 2 +- agent/consul/wanfed/wanfed.go | 2 +- agent/consul/wanfed/wanfed_test.go | 2 +- agent/consul/watch/server_local.go | 2 +- agent/consul/watch/server_local_test.go | 2 +- agent/consul/xdscapacity/capacity.go | 2 +- agent/consul/xdscapacity/capacity_test.go | 2 +- agent/coordinate_endpoint.go | 2 +- agent/coordinate_endpoint_test.go | 2 +- agent/debug/host.go | 2 +- agent/debug/host_test.go | 2 +- agent/delegate_mock_test.go | 7 +- agent/denylist.go | 2 +- agent/denylist_test.go | 2 +- agent/discovery_chain_endpoint.go | 2 +- agent/discovery_chain_endpoint_test.go | 2 +- agent/dns.go | 2 +- agent/dns/dns.go | 2 +- agent/dns/dns_test.go | 2 +- agent/dns/validation.go | 2 +- agent/dns/validation_test.go | 2 +- agent/dns_ce.go | 2 +- agent/dns_ce_test.go | 2 +- agent/dns_test.go | 2 +- agent/enterprise_delegate_ce.go | 2 +- .../builtin/aws-lambda/aws_lambda.go | 2 +- .../builtin/aws-lambda/aws_lambda_test.go | 2 +- .../builtin/ext-authz/ext_authz.go | 19 +- .../builtin/ext-authz/ext_authz_test.go | 2 +- .../builtin/ext-authz/structs.go | 2 +- agent/envoyextensions/builtin/lua/lua.go | 2 +- agent/envoyextensions/builtin/lua/lua_test.go | 2 +- .../otel_access_logging.go | 274 -- .../otel_access_logging_test.go | 113 - .../builtin/otel-access-logging/structs.go | 424 -- .../property-override/property_override.go | 3 - .../property_override_test.go | 3 - .../property-override/structpatcher.go | 3 - .../property-override/structpatcher_test.go | 3 - agent/envoyextensions/builtin/wasm/structs.go | 2 +- agent/envoyextensions/builtin/wasm/wasm.go | 2 +- .../envoyextensions/builtin/wasm/wasm_test.go | 2 +- .../envoyextensions/registered_extensions.go | 24 +- .../registered_extensions_ce.go | 8 - .../registered_extensions_test.go | 2 +- agent/event_endpoint.go | 2 +- agent/event_endpoint_test.go | 2 +- agent/exec/exec.go | 2 +- agent/exec/exec_unix.go | 2 +- agent/exec/exec_windows.go | 2 +- agent/federation_state_endpoint.go | 2 +- agent/grpc-external/forward.go | 2 +- agent/grpc-external/limiter/limiter.go | 2 +- agent/grpc-external/limiter/limiter_test.go | 2 +- agent/grpc-external/options.go | 2 +- agent/grpc-external/options_test.go | 2 +- agent/grpc-external/querymeta.go | 3 - agent/grpc-external/querymeta_test.go | 3 - agent/grpc-external/server.go | 2 +- agent/grpc-external/services/acl/login.go | 2 +- .../grpc-external/services/acl/login_test.go | 2 +- agent/grpc-external/services/acl/logout.go | 2 +- .../grpc-external/services/acl/logout_test.go | 2 +- agent/grpc-external/services/acl/server.go | 2 +- .../grpc-external/services/acl/server_test.go | 2 +- .../services/connectca/server.go | 2 +- .../services/connectca/server_test.go | 2 +- .../grpc-external/services/connectca/sign.go | 2 +- .../services/connectca/sign_test.go | 2 +- .../services/connectca/watch_roots.go | 2 +- .../services/connectca/watch_roots_test.go | 2 +- .../dataplane/get_envoy_bootstrap_params.go | 2 +- .../get_envoy_bootstrap_params_test.go | 2 +- .../dataplane/get_supported_features.go | 2 +- .../dataplane/get_supported_features_test.go | 2 +- .../services/dataplane/server.go | 2 +- .../services/dataplane/server_test.go | 2 +- agent/grpc-external/services/dns/server.go | 2 +- .../grpc-external/services/dns/server_test.go | 2 +- .../services/peerstream/health_snapshot.go | 2 +- .../peerstream/health_snapshot_test.go | 2 +- .../services/peerstream/replication.go | 2 +- .../services/peerstream/server.go | 2 +- .../services/peerstream/server_test.go | 2 +- .../services/peerstream/stream_resources.go | 2 +- .../services/peerstream/stream_test.go | 2 +- .../services/peerstream/stream_tracker.go | 2 +- .../peerstream/stream_tracker_test.go | 2 +- .../peerstream/subscription_blocking.go | 2 +- .../peerstream/subscription_manager.go | 2 +- .../peerstream/subscription_manager_test.go | 2 +- .../services/peerstream/subscription_state.go | 2 +- .../peerstream/subscription_state_test.go | 2 +- .../services/peerstream/subscription_view.go | 2 +- .../peerstream/subscription_view_test.go | 2 +- .../services/peerstream/testing.go | 2 +- .../grpc-external/services/resource/delete.go | 75 +- .../services/resource/delete_test.go | 113 +- agent/grpc-external/services/resource/list.go | 67 +- .../services/resource/list_by_owner.go | 84 +- .../services/resource/list_by_owner_test.go | 157 +- .../services/resource/list_test.go | 53 +- .../services/resource/mock_TenancyBridge.go | 121 - agent/grpc-external/services/resource/read.go | 63 +- .../services/resource/read_test.go | 144 +- .../grpc-external/services/resource/server.go | 79 +- .../services/resource/server_ce.go | 27 - .../services/resource/server_ce_test.go | 17 - .../services/resource/server_test.go | 169 +- .../services/resource/testing/testing.go | 53 +- .../grpc-external/services/resource/watch.go | 63 +- .../services/resource/watch_test.go | 64 +- .../grpc-external/services/resource/write.go | 57 +- .../services/resource/write_status.go | 74 +- .../services/resource/write_status_test.go | 314 +- .../services/resource/write_test.go | 289 +- .../services/serverdiscovery/server.go | 2 +- .../services/serverdiscovery/server_test.go | 2 +- .../services/serverdiscovery/watch_servers.go | 2 +- .../serverdiscovery/watch_servers_test.go | 2 +- agent/grpc-external/stats_test.go | 2 +- agent/grpc-external/testutils/acl.go | 2 +- agent/grpc-external/testutils/fsm.go | 2 +- agent/grpc-external/testutils/server.go | 2 +- agent/grpc-external/utils.go | 2 +- agent/grpc-internal/balancer/balancer.go | 2 +- agent/grpc-internal/balancer/balancer_test.go | 2 +- agent/grpc-internal/balancer/registry.go | 2 +- agent/grpc-internal/client.go | 2 +- agent/grpc-internal/client_test.go | 2 +- agent/grpc-internal/handler.go | 2 +- agent/grpc-internal/handler_test.go | 2 +- agent/grpc-internal/listener.go | 2 +- agent/grpc-internal/pipe.go | 2 +- agent/grpc-internal/pipe_test.go | 2 +- agent/grpc-internal/resolver/registry.go | 2 +- agent/grpc-internal/resolver/resolver.go | 2 +- agent/grpc-internal/resolver/resolver_test.go | 3 - agent/grpc-internal/server_test.go | 2 +- .../services/subscribe/logger.go | 2 +- .../services/subscribe/subscribe.go | 2 +- .../services/subscribe/subscribe_test.go | 2 +- agent/grpc-internal/stats_test.go | 2 +- agent/grpc-internal/tracker.go | 2 +- agent/grpc-middleware/auth_interceptor.go | 2 +- .../grpc-middleware/auth_interceptor_test.go | 2 +- agent/grpc-middleware/handshake.go | 2 +- agent/grpc-middleware/handshake_test.go | 2 +- agent/grpc-middleware/rate.go | 2 +- agent/grpc-middleware/rate_test.go | 2 +- agent/grpc-middleware/recovery.go | 2 +- agent/grpc-middleware/stats.go | 2 +- agent/grpc-middleware/testutil/fake_sink.go | 2 +- .../testutil/testservice/buf.gen.yaml | 2 +- .../testutil/testservice/fake_service.go | 2 +- .../testutil/testservice/simple.pb.go | 2 +- .../testutil/testservice/simple.proto | 2 +- agent/hcp/bootstrap/bootstrap.go | 2 +- agent/hcp/bootstrap/bootstrap_test.go | 3 - agent/hcp/bootstrap/testing.go | 2 +- agent/hcp/client/client.go | 2 +- agent/hcp/client/client_test.go | 3 - agent/hcp/client/metrics_client.go | 3 - agent/hcp/client/metrics_client_test.go | 3 - agent/hcp/client/mock_CloudConfig.go | 3 - agent/hcp/client/telemetry_config.go | 22 +- agent/hcp/client/telemetry_config_test.go | 50 +- agent/hcp/config/config.go | 2 +- agent/hcp/deps.go | 41 +- agent/hcp/deps_test.go | 87 +- agent/hcp/discover/discover.go | 2 +- agent/hcp/manager.go | 2 +- agent/hcp/manager_test.go | 2 +- agent/hcp/scada/capabilities.go | 2 +- agent/hcp/scada/scada.go | 2 +- agent/hcp/telemetry/custom_metrics.go | 3 - agent/hcp/telemetry/doc.go | 3 - agent/hcp/telemetry/gauge_store.go | 3 - agent/hcp/telemetry/gauge_store_test.go | 3 - agent/hcp/telemetry/otel_exporter.go | 9 - agent/hcp/telemetry/otel_exporter_test.go | 20 +- agent/hcp/telemetry/otel_sink.go | 25 +- agent/hcp/telemetry/otel_sink_test.go | 35 +- agent/hcp/telemetry/otlp_transform.go | 13 +- agent/hcp/telemetry/otlp_transform_test.go | 9 +- agent/hcp/telemetry_provider.go | 115 +- agent/hcp/telemetry_provider_test.go | 211 +- agent/hcp/testing.go | 2 +- agent/hcp/testserver/main.go | 2 +- agent/health_endpoint.go | 2 +- agent/health_endpoint_test.go | 2 +- agent/http.go | 18 +- agent/http_ce.go | 2 +- agent/http_ce_test.go | 2 +- agent/http_decode_test.go | 2 +- agent/http_register.go | 2 +- agent/http_test.go | 2 +- agent/intentions_endpoint.go | 2 +- agent/intentions_endpoint_ce_test.go | 2 +- agent/intentions_endpoint_test.go | 2 +- agent/keyring.go | 2 +- agent/keyring_test.go | 2 +- agent/kvs_endpoint.go | 2 +- agent/kvs_endpoint_test.go | 2 +- agent/leafcert/cached_roots.go | 3 - agent/leafcert/cert.go | 3 - agent/leafcert/generate.go | 3 - agent/leafcert/leafcert.go | 3 - agent/leafcert/leafcert_test.go | 3 - agent/leafcert/roots.go | 3 - agent/leafcert/signer_netrpc.go | 3 - agent/leafcert/signer_test.go | 3 - agent/leafcert/structs.go | 3 - agent/leafcert/structs_test.go | 3 - agent/leafcert/util.go | 3 - agent/leafcert/util_test.go | 3 - agent/leafcert/watch.go | 3 - agent/local/state.go | 2 +- agent/local/state_internal_test.go | 2 +- agent/local/state_test.go | 2 +- agent/local/testing.go | 2 +- agent/log-drop/log-drop.go | 2 +- agent/log-drop/log-drop_test.go | 2 +- agent/metadata/build.go | 2 +- agent/metadata/build_test.go | 2 +- agent/metadata/server.go | 2 +- agent/metadata/server_internal_test.go | 2 +- agent/metadata/server_test.go | 2 +- agent/metrics.go | 2 +- agent/metrics/testing.go | 2 +- agent/metrics_test.go | 2 +- agent/mock/notify.go | 2 +- agent/nodeid.go | 2 +- agent/nodeid_test.go | 2 +- agent/notify.go | 2 +- agent/notify_test.go | 2 +- agent/operator_endpoint.go | 2 +- agent/operator_endpoint_ce.go | 2 +- agent/operator_endpoint_ce_test.go | 2 +- agent/operator_endpoint_test.go | 2 +- agent/peering_endpoint.go | 2 +- agent/peering_endpoint_ce_test.go | 2 +- agent/peering_endpoint_test.go | 2 +- agent/pool/conn.go | 2 +- agent/pool/peek.go | 2 +- agent/pool/peek_test.go | 2 +- agent/pool/pool.go | 2 +- agent/prepared_query_endpoint.go | 2 +- agent/prepared_query_endpoint_test.go | 2 +- agent/proxycfg-glue/config_entry.go | 2 +- agent/proxycfg-glue/discovery_chain.go | 2 +- agent/proxycfg-glue/discovery_chain_test.go | 2 +- .../proxycfg-glue/exported_peered_services.go | 2 +- .../exported_peered_services_test.go | 2 +- .../federation_state_list_mesh_gateways.go | 2 +- ...ederation_state_list_mesh_gateways_test.go | 2 +- agent/proxycfg-glue/gateway_services.go | 2 +- agent/proxycfg-glue/gateway_services_test.go | 2 +- agent/proxycfg-glue/glue.go | 5 +- agent/proxycfg-glue/health.go | 2 +- agent/proxycfg-glue/health_blocking.go | 31 +- agent/proxycfg-glue/health_blocking_test.go | 8 +- agent/proxycfg-glue/health_test.go | 2 +- agent/proxycfg-glue/helpers_test.go | 2 +- agent/proxycfg-glue/intention_upstreams.go | 2 +- .../proxycfg-glue/intention_upstreams_test.go | 2 +- agent/proxycfg-glue/intentions.go | 2 +- agent/proxycfg-glue/intentions_ce.go | 2 +- agent/proxycfg-glue/intentions_test.go | 2 +- agent/proxycfg-glue/internal_service_dump.go | 2 +- .../internal_service_dump_test.go | 2 +- agent/proxycfg-glue/leafcerts.go | 2 +- agent/proxycfg-glue/peered_upstreams.go | 2 +- agent/proxycfg-glue/peered_upstreams_test.go | 2 +- agent/proxycfg-glue/peering_list.go | 2 +- agent/proxycfg-glue/peering_list_test.go | 2 +- .../proxycfg-glue/resolved_service_config.go | 2 +- .../resolved_service_config_test.go | 2 +- agent/proxycfg-glue/service_http_checks.go | 2 +- .../proxycfg-glue/service_http_checks_test.go | 2 +- agent/proxycfg-glue/service_list.go | 2 +- agent/proxycfg-glue/service_list_test.go | 2 +- agent/proxycfg-glue/trust_bundle.go | 2 +- agent/proxycfg-glue/trust_bundle_test.go | 2 +- .../proxycfg-sources/catalog/config_source.go | 15 +- .../catalog/config_source_oss.go | 13 - .../catalog/config_source_test.go | 45 +- .../catalog/mock_ConfigManager.go | 30 +- .../catalog/mock_SessionLimiter.go | 21 +- .../proxycfg-sources/catalog/mock_Watcher.go | 40 +- agent/proxycfg-sources/local/config_source.go | 9 +- agent/proxycfg-sources/local/local.go | 2 +- .../local/mock_ConfigManager.go | 30 +- agent/proxycfg-sources/local/sync.go | 5 +- agent/proxycfg-sources/local/sync_test.go | 2 +- agent/proxycfg/api_gateway.go | 2 +- agent/proxycfg/api_gateway_ce.go | 17 - agent/proxycfg/config_snapshot_glue.go | 66 - agent/proxycfg/config_snapshot_glue_test.go | 312 -- agent/proxycfg/connect_proxy.go | 2 +- agent/proxycfg/data_sources.go | 2 +- agent/proxycfg/data_sources_ce.go | 2 +- agent/proxycfg/deep-copy.sh | 2 +- agent/proxycfg/ingress_gateway.go | 2 +- agent/proxycfg/internal/watch/watchmap.go | 2 +- .../proxycfg/internal/watch/watchmap_test.go | 2 +- agent/proxycfg/manager.go | 19 +- agent/proxycfg/manager_test.go | 11 +- agent/proxycfg/mesh_gateway.go | 3 +- agent/proxycfg/mesh_gateway_ce.go | 2 +- agent/proxycfg/naming.go | 2 +- agent/proxycfg/naming_ce.go | 2 +- agent/proxycfg/naming_test.go | 2 +- agent/proxycfg/proxycfg.deepcopy.go | 4 - agent/proxycfg/proxycfg.go | 4 +- agent/proxycfg/snapshot.go | 3 +- agent/proxycfg/snapshot_test.go | 2 +- agent/proxycfg/state.go | 5 +- agent/proxycfg/state_ce_test.go | 2 +- agent/proxycfg/state_test.go | 2 +- agent/proxycfg/terminating_gateway.go | 2 +- agent/proxycfg/testing.go | 62 +- agent/proxycfg/testing_api_gateway.go | 5 +- agent/proxycfg/testing_ce.go | 2 +- agent/proxycfg/testing_connect_proxy.go | 42 +- agent/proxycfg/testing_ingress_gateway.go | 213 +- agent/proxycfg/testing_mesh_gateway.go | 170 +- agent/proxycfg/testing_peering.go | 135 +- agent/proxycfg/testing_terminating_gateway.go | 5 +- agent/proxycfg/testing_tproxy.go | 2 +- agent/proxycfg/testing_upstreams.go | 122 +- agent/proxycfg/testing_upstreams_ce.go | 2 +- agent/proxycfg/upstreams.go | 6 +- agent/proxycfg_test.go | 14 +- agent/reload.go | 2 +- agent/remote_exec.go | 2 +- agent/remote_exec_test.go | 2 +- agent/retry_join.go | 2 +- agent/retry_join_test.go | 2 +- agent/router/grpc.go | 2 +- agent/router/manager.go | 2 +- agent/router/manager_internal_test.go | 2 +- agent/router/manager_test.go | 2 +- agent/router/router.go | 2 +- agent/router/router_test.go | 2 +- agent/router/serf_adapter.go | 2 +- agent/router/serf_flooder.go | 2 +- agent/routine-leak-checker/leak_test.go | 2 +- agent/rpc/middleware/interceptors.go | 2 +- agent/rpc/middleware/interceptors_test.go | 2 +- agent/rpc/middleware/rate_limit_mappings.go | 2 +- agent/rpc/middleware/recovery.go | 2 +- agent/rpc/operator/service.go | 2 +- agent/rpc/operator/service_test.go | 2 +- agent/rpc/peering/service.go | 2 +- agent/rpc/peering/service_ce_test.go | 2 +- agent/rpc/peering/service_test.go | 7 +- agent/rpc/peering/testing.go | 2 +- agent/rpc/peering/testutil_ce_test.go | 2 +- agent/rpc/peering/validate.go | 2 +- agent/rpc/peering/validate_test.go | 2 +- agent/rpcclient/common.go | 2 +- agent/rpcclient/configentry/configentry.go | 2 +- .../rpcclient/configentry/configentry_test.go | 2 +- agent/rpcclient/configentry/view.go | 2 +- agent/rpcclient/configentry/view_test.go | 2 +- agent/rpcclient/health/health.go | 2 +- agent/rpcclient/health/health_test.go | 2 +- agent/rpcclient/health/streaming_test.go | 2 +- agent/rpcclient/health/view.go | 2 +- agent/rpcclient/health/view_test.go | 2 +- agent/service_checks_test.go | 2 +- agent/service_manager.go | 2 +- agent/service_manager_test.go | 2 +- agent/session_endpoint.go | 2 +- agent/session_endpoint_test.go | 2 +- agent/setup.go | 4 +- agent/setup_ce.go | 2 +- agent/sidecar_service.go | 2 +- agent/sidecar_service_test.go | 2 +- agent/signal_unix.go | 2 +- agent/signal_windows.go | 2 +- agent/snapshot_endpoint.go | 2 +- agent/snapshot_endpoint_test.go | 2 +- agent/status_endpoint.go | 2 +- agent/status_endpoint_test.go | 2 +- agent/streaming_test.go | 2 +- agent/structs/acl.go | 5 +- agent/structs/acl_cache.go | 2 +- agent/structs/acl_cache_test.go | 2 +- agent/structs/acl_ce.go | 2 +- agent/structs/acl_test.go | 2 +- agent/structs/aclfilter/filter.go | 2 +- agent/structs/aclfilter/filter_test.go | 2 +- agent/structs/auto_encrypt.go | 2 +- agent/structs/autopilot.go | 2 +- agent/structs/autopilot_ce.go | 2 +- agent/structs/catalog.go | 2 +- agent/structs/catalog_ce.go | 2 +- agent/structs/check_definition.go | 8 +- agent/structs/check_definition_test.go | 2 +- agent/structs/check_type.go | 7 +- agent/structs/config_entry.go | 56 +- agent/structs/config_entry_apigw_jwt_ce.go | 13 - agent/structs/config_entry_ce.go | 13 +- agent/structs/config_entry_ce_test.go | 2 +- agent/structs/config_entry_discoverychain.go | 2 +- .../structs/config_entry_discoverychain_ce.go | 2 +- .../config_entry_discoverychain_ce_test.go | 2 +- .../config_entry_discoverychain_test.go | 2 +- agent/structs/config_entry_exports.go | 2 +- agent/structs/config_entry_exports_ce.go | 2 +- agent/structs/config_entry_exports_ce_test.go | 2 +- agent/structs/config_entry_exports_test.go | 2 +- agent/structs/config_entry_gateways.go | 13 +- agent/structs/config_entry_gateways_test.go | 2 +- .../config_entry_inline_certificate.go | 3 +- .../config_entry_inline_certificate_test.go | 2 +- agent/structs/config_entry_intentions.go | 2 +- agent/structs/config_entry_intentions_ce.go | 2 +- .../config_entry_intentions_ce_test.go | 2 +- agent/structs/config_entry_intentions_test.go | 2 +- agent/structs/config_entry_jwt_provider.go | 2 +- agent/structs/config_entry_jwt_provider_ce.go | 2 +- .../structs/config_entry_jwt_provider_test.go | 2 +- agent/structs/config_entry_mesh.go | 2 +- agent/structs/config_entry_mesh_ce.go | 2 +- agent/structs/config_entry_mesh_test.go | 2 +- agent/structs/config_entry_routes.go | 22 +- agent/structs/config_entry_routes_test.go | 2 +- agent/structs/config_entry_sameness_group.go | 2 +- .../structs/config_entry_sameness_group_ce.go | 2 +- agent/structs/config_entry_status.go | 2 +- agent/structs/config_entry_test.go | 2 +- agent/structs/connect.go | 2 +- agent/structs/connect_ca.go | 2 +- agent/structs/connect_ca_test.go | 2 +- agent/structs/connect_ce.go | 2 +- agent/structs/connect_proxy_config.go | 2 +- agent/structs/connect_proxy_config_ce.go | 2 +- agent/structs/connect_proxy_config_test.go | 2 +- agent/structs/deep-copy.sh | 2 +- agent/structs/discovery_chain.go | 2 +- agent/structs/discovery_chain_ce.go | 2 +- agent/structs/envoy_extension.go | 2 +- agent/structs/errors.go | 2 +- agent/structs/federation_state.go | 2 +- agent/structs/identity.go | 2 +- agent/structs/intention.go | 2 +- agent/structs/intention_ce.go | 2 +- agent/structs/intention_test.go | 2 +- agent/structs/operator.go | 2 +- agent/structs/peering.go | 2 +- agent/structs/prepared_query.go | 4 +- agent/structs/prepared_query_test.go | 2 +- agent/structs/protobuf_compat.go | 2 +- agent/structs/service_definition.go | 2 +- agent/structs/service_definition_test.go | 2 +- agent/structs/snapshot.go | 2 +- agent/structs/structs.deepcopy.go | 80 - agent/structs/structs.deepcopy_ce.go | 17 - agent/structs/structs.go | 32 +- agent/structs/structs_ce.go | 2 +- agent/structs/structs_ce_test.go | 2 +- agent/structs/structs_ext_test.go | 2 +- agent/structs/structs_filtering_test.go | 2 +- agent/structs/structs_test.go | 48 +- agent/structs/system_metadata.go | 2 +- agent/structs/testing.go | 2 +- agent/structs/testing_catalog.go | 11 +- agent/structs/testing_connect_proxy_config.go | 2 +- agent/structs/testing_intention.go | 2 +- agent/structs/testing_service_definition.go | 2 +- agent/structs/txn.go | 2 +- agent/submatview/handler.go | 2 +- agent/submatview/local_materializer.go | 2 +- agent/submatview/local_materializer_test.go | 2 +- agent/submatview/materializer.go | 2 +- agent/submatview/rpc_materializer.go | 2 +- agent/submatview/store.go | 2 +- agent/submatview/store_integration_test.go | 2 +- agent/submatview/store_test.go | 2 +- agent/submatview/streaming_test.go | 2 +- agent/systemd/notify.go | 2 +- agent/testagent.go | 2 +- agent/testagent_test.go | 2 +- agent/token/persistence.go | 2 +- agent/token/persistence_test.go | 2 +- agent/token/store.go | 2 +- agent/token/store_ce.go | 2 +- agent/token/store_test.go | 2 +- agent/translate_addr.go | 2 +- agent/txn_endpoint.go | 3 +- agent/txn_endpoint_test.go | 2 +- agent/ui_endpoint.go | 3 +- agent/ui_endpoint_ce_test.go | 2 +- agent/ui_endpoint_test.go | 2 +- agent/uiserver/buf_index_fs.go | 2 +- agent/uiserver/buffered_file.go | 2 +- agent/uiserver/redirect_fs.go | 2 +- agent/uiserver/ui_template_data.go | 2 +- agent/uiserver/uiserver.go | 2 +- agent/uiserver/uiserver_test.go | 2 +- agent/user_event.go | 2 +- agent/user_event_test.go | 2 +- agent/util.go | 2 +- agent/util_test.go | 2 +- agent/watch_handler.go | 2 +- agent/watch_handler_test.go | 2 +- agent/xds/accesslogs/accesslogs.go | 2 +- agent/xds/clusters.go | 99 +- agent/xds/clusters_test.go | 337 +- agent/xds/{config => }/config.go | 8 +- agent/xds/{config => }/config_test.go | 4 +- agent/xds/configfetcher/config_fetcher.go | 10 - agent/xds/delta.go | 230 +- agent/xds/delta_envoy_extender_ce_test.go | 8 +- agent/xds/delta_envoy_extender_test.go | 2 +- agent/xds/delta_test.go | 25 +- agent/xds/endpoints.go | 107 +- agent/xds/endpoints_test.go | 173 +- agent/xds/extensionruntime/runtime_config.go | 2 +- .../runtime_config_ce_test.go | 2 +- agent/xds/failover_policy.go | 8 +- agent/xds/failover_policy_ce.go | 2 +- agent/xds/golden_test.go | 2 +- agent/xds/gw_per_route_filters_ce.go | 24 - agent/xds/jwt_authn.go | 2 +- agent/xds/jwt_authn_ce.go | 25 - agent/xds/jwt_authn_test.go | 2 +- agent/xds/listeners.go | 44 +- agent/xds/listeners_apigateway.go | 34 +- agent/xds/listeners_ingress.go | 5 +- agent/xds/listeners_test.go | 166 +- agent/xds/locality_policy.go | 23 - agent/xds/locality_policy_ce.go | 16 - agent/xds/naming.go | 19 + agent/xds/naming/naming.go | 29 - agent/xds/{platform => }/net_fallback.go | 6 +- agent/xds/{platform => }/net_linux.go | 6 +- agent/xds/protocol_trace.go | 17 +- agent/xds/proxystateconverter/clusters.go | 1251 ------ agent/xds/proxystateconverter/converter.go | 136 - agent/xds/proxystateconverter/endpoints.go | 671 ---- .../proxystateconverter/failover_policy.go | 158 - .../proxystateconverter/failover_policy_ce.go | 15 - agent/xds/proxystateconverter/listeners.go | 1693 -------- .../proxystateconverter/locality_policy.go | 21 - .../proxystateconverter/locality_policy_ce.go | 15 - agent/xds/proxystateconverter/routes.go | 777 ---- agent/xds/rbac.go | 33 +- agent/xds/rbac_test.go | 2 +- agent/xds/resources.go | 7 +- agent/xds/resources_ce_test.go | 6 +- agent/xds/resources_test.go | 248 +- agent/xds/{response => }/response.go | 16 +- agent/xds/routes.go | 84 +- agent/xds/routes_test.go | 122 +- agent/xds/secrets.go | 2 +- agent/xds/server.go | 65 +- agent/xds/server_ce.go | 2 +- agent/xds/testcommon/testcommon.go | 2 +- ...oute-and-inline-certificate.latest.golden} | 0 ...-route-timeoutfilter-one-set.latest.golden | 55 - ...multiple-inline-certificates.latest.golden | 55 - ...oxy-with-chain-and-overrides.latest.golden | 40 +- ...nnect-proxy-with-chain-http2.latest.golden | 135 - ...d-upstreams-escape-overrides.latest.golden | 135 - ...-with-peered-upstreams-http2.latest.golden | 163 - ...thcheck-zero-consecutive_5xx.latest.golden | 133 - ...upstream-with-prepared-query.latest.golden | 136 - ...nnect-proxy-with-chain-http2.latest.golden | 135 - .../clusters/expose-checks.latest.golden | 57 - ...efaults-passive-health-check.latest.golden | 13 +- ...efaults-passive-health-check.latest.golden | 86 +- ...service-passive-health-check.latest.golden | 83 +- ...ing-federation-control-plane.latest.golden | 205 - ...ed-services-http-with-router.latest.golden | 117 +- ...ith-imported-peered-services.latest.golden | 68 +- ...oute-and-inline-certificate.latest.golden} | 0 ...-route-timeoutfilter-one-set.latest.golden | 41 - ...multiple-inline-certificates.latest.golden | 5 - ...d-upstreams-escape-overrides.latest.golden | 29 - ...-with-peered-upstreams-http2.latest.golden | 29 - ...ing-federation-control-plane.latest.golden | 249 -- ...ed-services-http-with-router.latest.golden | 100 - ...route-and-inline-certificate.latest.golden | 54 + ...-route-timeoutfilter-one-set.latest.golden | 85 - .../api-gateway-with-http-route.latest.golden | 85 - ...multiple-inline-certificates.latest.golden | 102 - ...oxy-with-chain-and-overrides.latest.golden | 2 +- ...d-upstreams-escape-overrides.latest.golden | 114 - ...-with-peered-upstreams-http2.latest.golden | 189 - ...h-tproxy-and-permissive-mtls.latest.golden | 6 +- ...upstream-with-prepared-query.latest.golden | 114 - .../expose-checks-grpc.latest.golden | 143 - ...ecks-http-with-bind-override.latest.golden | 142 - ...est.golden => expose-checks.latest.golden} | 0 ...ixed-cipher-suites-listeners.latest.golden | 166 - ...-mixed-max-version-listeners.latest.golden | 238 -- ...ing-federation-control-plane.latest.golden | 181 - ...ateway-custom-trace-listener.latest.golden | 246 -- ...oute-and-inline-certificate.latest.golden} | 3 +- .../api-gateway-with-http-route.latest.golden | 59 - ...multiple-inline-certificates.latest.golden | 5 - ...connect-proxy-lb-in-resolver.latest.golden | 5 - ...nnect-proxy-resolver-with-lb.latest.golden | 30 - ...t-proxy-route-to-lb-resolver.latest.golden | 38 - ...ct-proxy-splitter-overweight.latest.golden | 99 - ...d-upstreams-escape-overrides.latest.golden | 5 - ...-with-peered-upstreams-http2.latest.golden | 5 - .../ingress-lb-in-resolver.latest.golden | 5 - ...erminating-gateway-lb-config.latest.golden | 137 +- ...-route-timeoutfilter-one-set.latest.golden | 5 - .../api-gateway-with-http-route.latest.golden | 5 - ...multiple-inline-certificates.latest.golden | 5 - ...d-upstreams-escape-overrides.latest.golden | 5 - ...-with-peered-upstreams-http2.latest.golden | 5 - ...-upstreams-listener-override.latest.golden | 5 - agent/xds/testing.go | 2 +- .../validateupstream_test.go | 2 +- agent/xds/xds.go | 2 +- agent/xds/xds_protocol_helpers_test.go | 51 +- agent/xds/z_xds_packages_test.go | 2 +- agent/xdsv2/cluster_resources.go | 348 -- agent/xdsv2/endpoint_resources.go | 61 - agent/xdsv2/listener_resources.go | 984 ----- agent/xdsv2/resources.go | 75 - agent/xdsv2/route_resources.go | 525 --- api/LICENSE | 365 -- api/acl.go | 45 + api/acl_test.go | 83 + api/agent.go | 1 + api/agent_test.go | 15 - api/config_entry.go | 53 +- api/config_entry_gateways.go | 40 - api/config_entry_gateways_test.go | 147 - api/config_entry_routes.go | 26 +- api/config_entry_routes_test.go | 134 - api/health.go | 1 + api/watch/funcs_test.go | 104 - buf.work.yaml | 2 +- build-support/docker/Build-Go.dockerfile | 2 +- build-support/docker/Build-UI.dockerfile | 2 +- .../docker/Consul-Dev-Dbg.dockerfile | 2 +- .../docker/Consul-Dev-Multiarch.dockerfile | 2 +- build-support/docker/Consul-Dev.dockerfile | 2 +- build-support/functions/00-vars.sh | 2 +- build-support/functions/10-util.sh | 2 +- build-support/functions/20-build.sh | 2 +- build-support/functions/30-release.sh | 2 +- build-support/scripts/build-date.sh | 2 +- build-support/scripts/build-docker.sh | 2 +- .../scripts/check-allowed-imports.sh | 124 - build-support/scripts/devtools.sh | 2 +- .../scripts/envoy-library-references.sh | 2 +- build-support/scripts/functions.sh | 2 +- build-support/scripts/protobuf.sh | 12 +- build-support/scripts/release.sh | 2 +- build-support/scripts/version.sh | 2 +- .../windows/Dockerfile-consul-dev-windows | 4 - .../windows/Dockerfile-consul-local-windows | 52 - .../windows/Dockerfile-openzipkin-windows | 12 - .../windows/build-consul-dev-image.sh | 17 - .../windows/build-consul-local-images.sh | 95 - .../windows/build-test-sds-server-image.sh | 8 - build-support/windows/windows-test.md | 119 - command/acl/acl.go | 2 +- command/acl/acl_helpers.go | 2 +- command/acl/acl_test.go | 2 +- command/acl/agenttokens/agent_tokens.go | 2 +- command/acl/agenttokens/agent_tokens_test.go | 2 +- command/acl/authmethod/authmethod.go | 2 +- .../authmethod/create/authmethod_create.go | 2 +- .../authmethod/create/authmethod_create_ce.go | 2 +- .../create/authmethod_create_test.go | 2 +- .../authmethod/delete/authmethod_delete.go | 2 +- .../delete/authmethod_delete_test.go | 2 +- command/acl/authmethod/formatter.go | 2 +- .../acl/authmethod/list/authmethod_list.go | 2 +- .../authmethod/list/authmethod_list_test.go | 2 +- .../acl/authmethod/read/authmethod_read.go | 2 +- .../authmethod/read/authmethod_read_test.go | 2 +- .../authmethod/update/authmethod_update.go | 2 +- .../authmethod/update/authmethod_update_ce.go | 2 +- .../update/authmethod_update_test.go | 2 +- command/acl/bindingrule/bindingrule.go | 2 +- .../bindingrule/create/bindingrule_create.go | 2 +- .../create/bindingrule_create_test.go | 2 +- .../bindingrule/delete/bindingrule_delete.go | 2 +- .../delete/bindingrule_delete_test.go | 2 +- command/acl/bindingrule/formatter.go | 2 +- .../acl/bindingrule/list/bindingrule_list.go | 2 +- .../bindingrule/list/bindingrule_list_test.go | 2 +- .../acl/bindingrule/read/bindingrule_read.go | 2 +- .../bindingrule/read/bindingrule_read_test.go | 2 +- .../bindingrule/update/bindingrule_update.go | 2 +- .../update/bindingrule_update_test.go | 2 +- command/acl/bootstrap/bootstrap.go | 2 +- command/acl/bootstrap/bootstrap_test.go | 2 +- command/acl/policy/create/policy_create.go | 2 +- .../acl/policy/create/policy_create_test.go | 2 +- command/acl/policy/delete/policy_delete.go | 2 +- .../acl/policy/delete/policy_delete_test.go | 2 +- command/acl/policy/formatter.go | 2 +- command/acl/policy/list/policy_list.go | 2 +- command/acl/policy/list/policy_list_test.go | 2 +- command/acl/policy/policy.go | 2 +- command/acl/policy/read/policy_read.go | 2 +- command/acl/policy/read/policy_read_test.go | 2 +- command/acl/policy/update/policy_update.go | 2 +- .../acl/policy/update/policy_update_test.go | 2 +- command/acl/role/create/role_create.go | 2 +- command/acl/role/create/role_create_test.go | 2 +- command/acl/role/delete/role_delete.go | 2 +- command/acl/role/delete/role_delete_test.go | 2 +- command/acl/role/formatter.go | 2 +- command/acl/role/formatter_test.go | 2 +- command/acl/role/list/role_list.go | 2 +- command/acl/role/list/role_list_test.go | 2 +- command/acl/role/read/role_read.go | 2 +- command/acl/role/read/role_read_test.go | 2 +- command/acl/role/role.go | 2 +- command/acl/role/update/role_update.go | 2 +- command/acl/role/update/role_update_test.go | 2 +- command/acl/token/clone/token_clone.go | 2 +- command/acl/token/clone/token_clone_test.go | 2 +- command/acl/token/create/token_create.go | 2 +- command/acl/token/create/token_create_test.go | 2 +- command/acl/token/delete/token_delete.go | 2 +- command/acl/token/delete/token_delete_test.go | 2 +- command/acl/token/formatter.go | 2 +- command/acl/token/formatter_ce_test.go | 2 +- command/acl/token/formatter_test.go | 2 +- command/acl/token/list/token_list.go | 2 +- command/acl/token/list/token_list_test.go | 2 +- command/acl/token/read/token_read.go | 2 +- command/acl/token/read/token_read_test.go | 2 +- command/acl/token/token.go | 2 +- command/acl/token/update/token_update.go | 2 +- command/acl/token/update/token_update_test.go | 2 +- command/agent/agent.go | 2 +- command/agent/agent_test.go | 2 +- command/agent/startup_logger.go | 2 +- command/catalog/catalog.go | 2 +- command/catalog/catalog_test.go | 2 +- command/catalog/helpers.go | 2 +- command/catalog/helpers_ce.go | 2 +- .../list/dc/catalog_list_datacenters.go | 2 +- .../list/dc/catalog_list_datacenters_test.go | 2 +- .../catalog/list/nodes/catalog_list_nodes.go | 2 +- .../list/nodes/catalog_list_nodes_test.go | 2 +- .../list/services/catalog_list_services.go | 2 +- .../services/catalog_list_services_test.go | 2 +- command/cli/cli.go | 2 +- command/cli/formatting.go | 2 +- command/config/config.go | 2 +- command/config/delete/config_delete.go | 2 +- command/config/delete/config_delete_test.go | 2 +- command/config/list/config_list.go | 2 +- command/config/list/config_list_test.go | 2 +- command/config/read/config_read.go | 2 +- command/config/read/config_read_test.go | 2 +- command/config/write/config_write.go | 68 +- command/config/write/config_write_test.go | 2 +- command/connect/ca/ca.go | 2 +- command/connect/ca/ca_test.go | 2 +- command/connect/ca/get/connect_ca_get.go | 2 +- command/connect/ca/get/connect_ca_get_test.go | 2 +- command/connect/ca/set/connect_ca_set.go | 2 +- command/connect/ca/set/connect_ca_set_test.go | 2 +- command/connect/connect.go | 2 +- command/connect/connect_test.go | 2 +- command/connect/envoy/bootstrap_config.go | 2 +- .../connect/envoy/bootstrap_config_test.go | 2 +- command/connect/envoy/bootstrap_tpl.go | 4 +- command/connect/envoy/envoy.go | 4 +- command/connect/envoy/envoy_ce_test.go | 2 +- command/connect/envoy/envoy_test.go | 2 +- command/connect/envoy/exec.go | 2 +- command/connect/envoy/exec_supported.go | 58 - command/connect/envoy/exec_test.go | 2 +- command/connect/envoy/exec_unix.go | 53 +- command/connect/envoy/exec_unsupported.go | 6 +- command/connect/envoy/exec_windows.go | 112 - command/connect/envoy/exec_windows_arm64.go | 83 - command/connect/envoy/flags.go | 2 +- command/connect/envoy/flags_test.go | 2 +- .../connect_envoy_pipe-bootstrap.go | 2 +- .../connect_envoy_pipe-bootstrap_test.go | 2 +- command/connect/expose/expose.go | 2 +- command/connect/expose/expose_test.go | 2 +- command/connect/proxy/flag_upstreams.go | 2 +- command/connect/proxy/flag_upstreams_test.go | 2 +- command/connect/proxy/proxy.go | 2 +- command/connect/proxy/proxy_test.go | 2 +- command/connect/proxy/register.go | 2 +- command/connect/proxy/register_test.go | 2 +- .../redirecttraffic/redirect_traffic.go | 2 +- .../redirecttraffic/redirect_traffic_test.go | 2 +- command/debug/debug.go | 2 +- command/debug/debug_test.go | 2 +- command/event/event.go | 2 +- command/event/event_test.go | 2 +- command/exec/exec.go | 2 +- command/exec/exec_test.go | 2 +- command/flags/config.go | 2 +- command/flags/config_test.go | 2 +- command/flags/flag_map_value.go | 2 +- command/flags/flag_map_value_test.go | 2 +- command/flags/flag_slice_value.go | 2 +- command/flags/flag_slice_value_test.go | 2 +- command/flags/http.go | 2 +- command/flags/http_test.go | 2 +- command/flags/merge.go | 2 +- command/flags/usage.go | 2 +- command/forceleave/forceleave.go | 2 +- command/forceleave/forceleave_test.go | 2 +- command/helpers/decode_shim.go | 2 +- command/helpers/helpers.go | 18 +- command/helpers/helpers_test.go | 2 +- command/info/info.go | 2 +- command/info/info_test.go | 2 +- command/intention/check/check.go | 2 +- command/intention/check/check_test.go | 2 +- command/intention/create/create.go | 2 +- command/intention/create/create_test.go | 2 +- command/intention/delete/delete.go | 2 +- command/intention/delete/delete_test.go | 2 +- command/intention/format.go | 2 +- command/intention/get/get.go | 2 +- command/intention/get/get_test.go | 2 +- command/intention/helpers.go | 2 +- command/intention/helpers_test.go | 2 +- command/intention/intention.go | 2 +- command/intention/intention_test.go | 2 +- command/intention/list/intention_list.go | 2 +- command/intention/list/intention_list_test.go | 2 +- command/intention/match/match.go | 2 +- command/intention/match/match_test.go | 2 +- command/join/join.go | 2 +- command/join/join_test.go | 2 +- command/keygen/keygen.go | 2 +- command/keygen/keygen_test.go | 2 +- command/keyring/keyring.go | 2 +- command/keyring/keyring_test.go | 2 +- command/kv/del/kv_delete.go | 2 +- command/kv/del/kv_delete_test.go | 2 +- command/kv/exp/kv_export.go | 2 +- command/kv/exp/kv_export_test.go | 2 +- command/kv/get/kv_get.go | 2 +- command/kv/get/kv_get_test.go | 2 +- command/kv/imp/kv_import.go | 2 +- command/kv/imp/kv_import_test.go | 2 +- command/kv/impexp/kvimpexp.go | 2 +- command/kv/kv.go | 2 +- command/kv/kv_test.go | 2 +- command/kv/put/kv_put.go | 2 +- command/kv/put/kv_put_test.go | 2 +- command/leave/leave.go | 2 +- command/leave/leave_test.go | 2 +- command/lock/lock.go | 2 +- command/lock/lock_test.go | 2 +- command/lock/util_unix.go | 2 +- command/lock/util_windows.go | 2 +- command/login/aws.go | 2 +- command/login/login.go | 2 +- command/login/login_ce.go | 2 +- command/login/login_test.go | 2 +- command/logout/logout.go | 2 +- command/logout/logout_test.go | 2 +- command/maint/maint.go | 2 +- command/maint/maint_test.go | 2 +- command/members/members.go | 2 +- command/members/members_test.go | 2 +- command/monitor/monitor.go | 2 +- command/monitor/monitor_test.go | 2 +- .../autopilot/get/operator_autopilot_get.go | 2 +- .../get/operator_autopilot_get_test.go | 2 +- .../operator/autopilot/operator_autopilot.go | 2 +- .../autopilot/operator_autopilot_test.go | 2 +- .../autopilot/set/operator_autopilot_set.go | 2 +- .../set/operator_autopilot_set_test.go | 2 +- command/operator/autopilot/state/formatter.go | 2 +- .../state/operator_autopilot_state.go | 2 +- .../state/operator_autopilot_state_test.go | 2 +- command/operator/operator.go | 2 +- command/operator/operator_test.go | 2 +- .../raft/listpeers/operator_raft_list.go | 2 +- .../raft/listpeers/operator_raft_list_test.go | 2 +- command/operator/raft/operator_raft.go | 2 +- command/operator/raft/operator_raft_test.go | 2 +- .../raft/removepeer/operator_raft_remove.go | 2 +- .../removepeer/operator_raft_remove_test.go | 2 +- .../raft/transferleader/transfer_leader.go | 2 +- .../transferleader/transfer_leader_test.go | 2 +- .../usage/instances/usage_instances.go | 2 +- .../usage/instances/usage_instances_ce.go | 2 +- .../instances/usage_instances_ce_test.go | 2 +- .../usage/instances/usage_instances_test.go | 2 +- command/operator/usage/usage.go | 2 +- command/peering/delete/delete.go | 2 +- command/peering/delete/delete_test.go | 2 +- command/peering/establish/establish.go | 2 +- command/peering/establish/establish_test.go | 2 +- command/peering/generate/generate.go | 2 +- command/peering/generate/generate_test.go | 2 +- command/peering/list/list.go | 2 +- command/peering/list/list_test.go | 2 +- command/peering/peering.go | 2 +- command/peering/read/read.go | 2 +- command/peering/read/read_test.go | 2 +- command/registry.go | 2 +- command/registry_ce.go | 2 +- command/reload/reload.go | 2 +- command/reload/reload_test.go | 2 +- command/rtt/rtt.go | 2 +- command/rtt/rtt_test.go | 2 +- command/services/config.go | 2 +- command/services/config_test.go | 2 +- command/services/deregister/deregister.go | 2 +- .../services/deregister/deregister_test.go | 2 +- command/services/export/export.go | 3 - command/services/export/export_test.go | 3 - command/services/register/register.go | 2 +- command/services/register/register_test.go | 2 +- command/services/services.go | 2 +- command/services/services_test.go | 2 +- command/snapshot/inspect/formatter.go | 2 +- command/snapshot/inspect/formatter_test.go | 2 +- command/snapshot/inspect/snapshot_inspect.go | 2 +- .../snapshot/inspect/snapshot_inspect_test.go | 2 +- command/snapshot/restore/snapshot_restore.go | 2 +- .../snapshot/restore/snapshot_restore_test.go | 2 +- command/snapshot/save/snapshot_save.go | 63 +- command/snapshot/save/snapshot_save_test.go | 67 +- command/snapshot/snapshot_command.go | 2 +- command/snapshot/snapshot_command_test.go | 2 +- command/tls/ca/create/tls_ca_create.go | 2 +- command/tls/ca/create/tls_ca_create_test.go | 2 +- command/tls/ca/tls_ca.go | 2 +- command/tls/ca/tls_ca_test.go | 2 +- command/tls/cert/create/tls_cert_create.go | 2 +- .../tls/cert/create/tls_cert_create_test.go | 2 +- command/tls/cert/tls_cert.go | 2 +- command/tls/cert/tls_cert_test.go | 2 +- command/tls/tls.go | 2 +- command/tls/tls_test.go | 2 +- .../troubleshoot/proxy/troubleshoot_proxy.go | 2 +- command/troubleshoot/troubleshoot.go | 2 +- command/troubleshoot/troubleshoot_test.go | 2 +- .../upstreams/troubleshoot_upstreams.go | 2 +- command/validate/validate.go | 2 +- command/validate/validate_test.go | 2 +- command/version/formatter.go | 2 +- command/version/formatter_test.go | 2 +- command/version/version.go | 2 +- command/version/version_test.go | 2 +- command/watch/watch.go | 2 +- command/watch/watch_test.go | 2 +- connect/certgen/certgen.go | 2 +- connect/example_test.go | 2 +- connect/proxy/config.go | 2 +- connect/proxy/config_test.go | 2 +- connect/proxy/conn.go | 2 +- connect/proxy/conn_test.go | 2 +- connect/proxy/listener.go | 2 +- connect/proxy/listener_test.go | 2 +- connect/proxy/proxy.go | 2 +- connect/proxy/proxy_test.go | 2 +- connect/proxy/testing.go | 2 +- connect/resolver.go | 2 +- connect/resolver_test.go | 2 +- connect/service.go | 2 +- connect/service_test.go | 2 +- connect/testing.go | 2 +- connect/tls.go | 4 +- connect/tls_test.go | 2 +- docs/README.md | 6 +- docs/resources/guide.md | 18 +- .../extensioncommon/basic_envoy_extender.go | 2 +- .../basic_extension_adapter.go | 2 +- .../extensioncommon/envoy_extender.go | 4 +- .../extensioncommon/envoy_extender_test.go | 3 - envoyextensions/extensioncommon/resources.go | 12 +- .../extensioncommon/resources_test.go | 2 +- .../extensioncommon/runtime_config.go | 2 +- .../extensioncommon/runtime_config_test.go | 2 +- .../upstream_envoy_extender.go | 2 +- envoyextensions/go.mod | 5 +- envoyextensions/go.sum | 2 + envoyextensions/xdscommon/envoy_versioning.go | 2 +- .../xdscommon/envoy_versioning_test.go | 4 +- envoyextensions/xdscommon/proxysupport.go | 4 +- .../xdscommon/proxysupport_test.go | 2 +- envoyextensions/xdscommon/xdscommon.go | 2 +- envoyextensions/xdscommon/xdscommon_test.go | 3 - fixup_acl_move.sh | 2 +- go.mod | 13 +- go.sum | 33 +- grafana/README.md | 4 - .../consul-k8s-control-plane-monitoring.json | 3467 ----------------- internal/catalog/catalogtest/run_test.go | 8 - .../catalogtest/test_integration_v1alpha1.go | 4 - .../catalogtest/test_lifecycle_v1alpha1.go | 709 ---- internal/catalog/exports.go | 66 +- .../controllers/endpoints/controller.go | 2 +- .../controllers/endpoints/controller_test.go | 3 - .../endpoints/reconciliation_data.go | 3 - .../endpoints/reconciliation_data_test.go | 3 - .../internal/controllers/endpoints/status.go | 2 +- .../controllers/failover/controller.go | 276 -- .../controllers/failover/controller_test.go | 268 -- .../internal/controllers/failover/status.go | 84 - .../controllers/nodehealth/controller.go | 2 +- .../controllers/nodehealth/controller_test.go | 2 +- .../internal/controllers/nodehealth/status.go | 2 +- .../catalog/internal/controllers/register.go | 5 +- .../controllers/workloadhealth/controller.go | 3 - .../workloadhealth/controller_test.go | 2 +- .../controllers/workloadhealth/status.go | 3 - .../mappers/failovermapper/failover_mapper.go | 64 - .../failovermapper/failover_mapper_test.go | 190 - .../mappers/nodemapper/node_mapper.go | 3 - .../mappers/nodemapper/node_mapper_test.go | 3 - .../selectiontracker/selection_tracker.go | 2 +- .../selection_tracker_test.go | 3 - internal/catalog/internal/types/dns_policy.go | 2 +- .../catalog/internal/types/dns_policy_test.go | 2 +- internal/catalog/internal/types/errors.go | 2 +- .../catalog/internal/types/errors_test.go | 2 +- .../catalog/internal/types/failover_policy.go | 265 -- .../internal/types/failover_policy_test.go | 599 --- .../catalog/internal/types/health_checks.go | 2 +- .../internal/types/health_checks_test.go | 2 +- .../catalog/internal/types/health_status.go | 2 +- .../internal/types/health_status_test.go | 2 +- internal/catalog/internal/types/node.go | 2 +- internal/catalog/internal/types/node_test.go | 2 +- internal/catalog/internal/types/service.go | 16 +- .../internal/types/service_endpoints.go | 47 +- .../internal/types/service_endpoints_test.go | 132 +- .../catalog/internal/types/service_test.go | 40 +- internal/catalog/internal/types/types.go | 3 +- internal/catalog/internal/types/types_test.go | 2 +- internal/catalog/internal/types/validators.go | 34 +- .../catalog/internal/types/validators_test.go | 7 +- .../catalog/internal/types/virtual_ips.go | 2 +- .../internal/types/virtual_ips_test.go | 2 +- internal/catalog/internal/types/workload.go | 16 +- .../catalog/internal/types/workload_test.go | 33 +- internal/controller/api.go | 72 +- internal/controller/api_test.go | 48 +- internal/controller/controller.go | 100 +- internal/controller/dependency_mappers.go | 11 - .../controller/dependency_mappers_test.go | 3 - internal/controller/doc.go | 2 +- internal/controller/lease.go | 3 - internal/controller/manager.go | 3 - internal/controller/supervisor.go | 3 - internal/controller/supervisor_test.go | 3 - internal/go-sso/oidcauth/auth.go | 2 +- internal/go-sso/oidcauth/config.go | 2 +- internal/go-sso/oidcauth/config_test.go | 2 +- .../go-sso/oidcauth/internal/strutil/util.go | 2 +- .../oidcauth/internal/strutil/util_test.go | 2 +- internal/go-sso/oidcauth/jwt.go | 2 +- internal/go-sso/oidcauth/jwt_test.go | 2 +- internal/go-sso/oidcauth/oidc.go | 2 +- internal/go-sso/oidcauth/oidc_test.go | 2 +- .../go-sso/oidcauth/oidcauthtest/testing.go | 2 +- internal/go-sso/oidcauth/oidcjwt.go | 2 +- internal/go-sso/oidcauth/oidcjwt_test.go | 2 +- internal/go-sso/oidcauth/util.go | 2 +- internal/go-sso/oidcauth/util_test.go | 2 +- internal/mesh/exports.go | 46 +- .../mesh/internal/controllers/register.go | 22 - .../internal/controllers/xds/controller.go | 184 - .../controllers/xds/controller_test.go | 736 ---- .../controllers/xds/endpoint_builder.go | 75 - .../controllers/xds/endpoint_builder_test.go | 236 -- .../internal/controllers/xds/mock_updater.go | 112 - .../controllers/xds/proxy_tracker_watch.go | 21 - .../controllers/xds/reconciliation_data.go | 61 - .../internal/controllers/xds/status/status.go | 104 - .../mesh/internal/types/computed_routes.go | 77 - .../internal/types/computed_routes_test.go | 92 - internal/mesh/internal/types/decoded.go | 20 - .../mesh/internal/types/destination_policy.go | 226 -- .../internal/types/destination_policy_test.go | 510 --- internal/mesh/internal/types/grpc_route.go | 237 -- .../mesh/internal/types/grpc_route_test.go | 523 --- internal/mesh/internal/types/http_route.go | 349 -- .../mesh/internal/types/http_route_test.go | 980 ----- .../internal/types/proxy_configuration.go | 9 +- .../internal/types/proxy_state_template.go | 62 - internal/mesh/internal/types/tcp_route.go | 95 - .../mesh/internal/types/tcp_route_test.go | 79 - internal/mesh/internal/types/types.go | 9 +- internal/mesh/internal/types/types_test.go | 2 +- internal/mesh/internal/types/upstreams.go | 4 +- .../internal/types/upstreams_configuration.go | 32 - internal/mesh/internal/types/util.go | 52 - internal/mesh/internal/types/xroute.go | 296 -- .../mesh/proxy-snapshot/proxy_snapshot.go | 17 - .../mesh/proxy-tracker/mock_SessionLimiter.go | 53 - .../mesh/proxy-tracker/proxy_state_exports.go | 42 - internal/mesh/proxy-tracker/proxy_tracker.go | 281 -- .../mesh/proxy-tracker/proxy_tracker_test.go | 344 -- internal/protohcl/any.go | 117 - internal/protohcl/attributes.go | 157 - internal/protohcl/blocks.go | 115 - internal/protohcl/cty.go | 149 - internal/protohcl/decoder.go | 287 -- internal/protohcl/doc.go | 79 - internal/protohcl/naming.go | 21 - internal/protohcl/oneof.go | 54 - internal/protohcl/primitives.go | 141 - internal/protohcl/testproto/buf.gen.yaml | 12 - internal/protohcl/testproto/example.pb.go | 997 ----- internal/protohcl/testproto/example.proto | 77 - internal/protohcl/unmarshal.go | 137 - internal/protohcl/unmarshal_test.go | 560 --- internal/protohcl/well_known_types.go | 421 -- internal/radix/doc.go | 3 - internal/radix/radix.go | 3 - internal/radix/radix_test.go | 3 - internal/resource/authz_ce.go | 17 - internal/resource/decode.go | 69 - internal/resource/decode_test.go | 113 - internal/resource/demo/controller.go | 2 +- internal/resource/demo/controller_test.go | 2 +- internal/resource/demo/demo.go | 68 +- internal/resource/equality.go | 22 +- internal/resource/equality_test.go | 306 +- internal/resource/errors.go | 31 +- internal/resource/errors_test.go | 2 +- internal/resource/http/http.go | 294 -- internal/resource/http/http_test.go | 596 --- .../resource/mappers/bimapper/bimapper.go | 304 -- .../mappers/bimapper/bimapper_test.go | 356 -- internal/resource/reaper/controller.go | 2 +- internal/resource/reaper/controller_test.go | 2 +- internal/resource/reference.go | 25 +- internal/resource/refkey.go | 93 - internal/resource/refkey_test.go | 87 - internal/resource/registry.go | 51 +- internal/resource/registry_test.go | 14 +- internal/resource/resourcetest/builder.go | 79 +- internal/resource/resourcetest/client.go | 81 +- internal/resource/resourcetest/decode.go | 20 - internal/resource/resourcetest/fs.go | 3 - internal/resource/resourcetest/require.go | 29 - internal/resource/resourcetest/testing.go | 7 +- internal/resource/resourcetest/validation.go | 30 - internal/resource/stringer.go | 60 - internal/resource/tenancy.go | 80 - internal/resource/tombstone.go | 3 - internal/resourcehcl/any.go | 49 - internal/resourcehcl/naming.go | 38 - .../testdata/gvk-no-arguments.error | 1 - .../resourcehcl/testdata/gvk-no-arguments.hcl | 4 - .../resourcehcl/testdata/invalid-group.error | 1 - .../resourcehcl/testdata/invalid-group.hcl | 8 - .../resourcehcl/testdata/invalid-gvk.error | 1 - internal/resourcehcl/testdata/invalid-gvk.hcl | 4 - .../testdata/invalid-metadata.error | 1 - .../resourcehcl/testdata/invalid-metadata.hcl | 8 - .../resourcehcl/testdata/invalid-name.error | 1 - .../resourcehcl/testdata/invalid-name.hcl | 4 - .../testdata/no-blocks-any-first.golden | 1 - .../testdata/no-blocks-any-first.hcl | 8 - .../resourcehcl/testdata/no-blocks.golden | 1 - internal/resourcehcl/testdata/no-blocks.hcl | 33 - internal/resourcehcl/testdata/owner.golden | 1 - internal/resourcehcl/testdata/owner.hcl | 9 - .../resourcehcl/testdata/simple-gvk.golden | 1 - internal/resourcehcl/testdata/simple-gvk.hcl | 13 - .../resourcehcl/testdata/type-block.golden | 1 - internal/resourcehcl/testdata/type-block.hcl | 8 - .../testdata/unknown-field-block.error | 1 - .../testdata/unknown-field-block.hcl | 3 - .../testdata/unknown-field-object.error | 1 - .../testdata/unknown-field-object.hcl | 3 - .../resourcehcl/testdata/unknown-type.error | 1 - .../resourcehcl/testdata/unknown-type.hcl | 8 - .../resourcehcl/testdata/upstreams.golden | 1 - internal/resourcehcl/testdata/upstreams.hcl | 25 - internal/resourcehcl/unmarshal.go | 55 - internal/resourcehcl/unmarshal_test.go | 106 - internal/storage/conformance/conformance.go | 2 +- internal/storage/inmem/backend.go | 2 +- internal/storage/inmem/backend_test.go | 2 +- internal/storage/inmem/event_index.go | 2 +- internal/storage/inmem/schema.go | 2 +- internal/storage/inmem/snapshot.go | 2 +- internal/storage/inmem/snapshot_test.go | 2 +- internal/storage/inmem/store.go | 2 +- internal/storage/inmem/watch.go | 2 +- internal/storage/raft/backend.go | 2 +- internal/storage/raft/conformance_test.go | 2 +- internal/storage/raft/forwarding.go | 2 +- internal/storage/storage.go | 2 +- internal/testing/golden/golden.go | 2 +- .../e2e/consul/agent/structs/structs.go | 2 +- .../e2e/consul/proto/pbcommon/common.go | 2 +- .../tools/proto-gen-rpc-glue/e2e/source.pb.go | 2 +- internal/tools/proto-gen-rpc-glue/main.go | 2 +- .../tools/proto-gen-rpc-glue/main_test.go | 2 +- .../protoc-gen-consul-rate-limit/main.go | 2 +- .../postprocess/main.go | 2 +- ipaddr/detect.go | 2 +- ipaddr/detect_test.go | 2 +- ipaddr/ipaddr.go | 2 +- ipaddr/ipaddr_test.go | 2 +- lib/cluster.go | 2 +- lib/cluster_test.go | 2 +- lib/decode/decode.go | 2 +- lib/decode/decode_test.go | 2 +- lib/eof.go | 2 +- lib/eof_test.go | 2 +- lib/file/atomic.go | 2 +- lib/file/atomic_test.go | 2 +- lib/hoststats/collector.go | 3 - lib/hoststats/cpu.go | 3 - lib/hoststats/cpu_test.go | 3 - lib/hoststats/host.go | 3 - lib/hoststats/metrics.go | 3 - lib/json.go | 2 +- lib/map_walker.go | 2 +- lib/map_walker_test.go | 2 +- lib/maps/maps.go | 2 +- lib/maps/maps_test.go | 2 +- lib/math.go | 2 +- lib/math_test.go | 2 +- lib/mutex/mutex.go | 2 +- lib/mutex/mutex_test.go | 2 +- lib/path.go | 2 +- lib/retry/retry.go | 2 +- lib/retry/retry_test.go | 2 +- lib/routine/routine.go | 2 +- lib/routine/routine_test.go | 2 +- lib/rtt.go | 2 +- lib/rtt_test.go | 2 +- lib/semaphore/semaphore.go | 2 +- lib/semaphore/semaphore_test.go | 2 +- lib/serf/serf.go | 2 +- lib/stop_context.go | 2 +- lib/stop_context_test.go | 2 +- lib/strings.go | 2 +- lib/stringslice/stringslice.go | 2 +- lib/stringslice/stringslice_test.go | 2 +- lib/telemetry.go | 2 +- lib/telemetry_test.go | 2 +- lib/template/hil.go | 2 +- lib/template/hil_test.go | 2 +- lib/translate.go | 2 +- lib/translate_test.go | 2 +- lib/ttlcache/eviction.go | 2 +- lib/ttlcache/eviction_test.go | 2 +- lib/useragent.go | 2 +- lib/useragent_test.go | 2 +- lib/uuid.go | 2 +- logging/gated_writer.go | 2 +- logging/gated_writer_test.go | 2 +- logging/grpc.go | 2 +- logging/grpc_test.go | 2 +- logging/log_levels.go | 2 +- logging/logfile.go | 35 +- logging/logfile_bsd.go | 16 + logging/logfile_linux.go | 17 + logging/logfile_solaris.go | 17 + logging/logfile_test.go | 18 +- logging/logfile_windows.go | 14 + logging/logger.go | 2 +- logging/logger_test.go | 2 +- logging/monitor/monitor.go | 2 +- logging/monitor/monitor_test.go | 2 +- logging/names.go | 2 +- logging/syslog.go | 2 +- logging/syslog_test.go | 2 +- logging/syslog_unsupported_test.go | 2 +- main.go | 2 +- proto-public/LICENSE | 365 -- .../v1alpha1/failover_policy.pb.binary.go | 38 - .../pbcatalog/v1alpha1/failover_policy.pb.go | 457 --- .../pbcatalog/v1alpha1/failover_policy.proto | 47 - .../v1alpha1/failover_policy_extras.go | 65 - .../v1alpha1/failover_policy_extras_test.go | 171 - .../pbcatalog/v1alpha1/protocol.pb.go | 90 +- .../pbcatalog/v1alpha1/protocol.proto | 12 +- .../pbcatalog/v1alpha1/selector.pb.go | 53 +- .../pbcatalog/v1alpha1/selector.proto | 1 - proto-public/pbcatalog/v1alpha1/service.pb.go | 2 +- .../pbcatalog/v1alpha1/workload.pb.go | 2 +- .../pbmesh/v1alpha1/common.pb.binary.go | 28 - proto-public/pbmesh/v1alpha1/common.pb.go | 307 -- proto-public/pbmesh/v1alpha1/common.proto | 64 - .../v1alpha1/computed_routes.pb.binary.go | 128 - .../pbmesh/v1alpha1/computed_routes.pb.go | 1321 ------- .../pbmesh/v1alpha1/computed_routes.proto | 99 - proto-public/pbmesh/v1alpha1/connection.pb.go | 172 +- proto-public/pbmesh/v1alpha1/connection.proto | 16 +- .../v1alpha1/destination_policy.pb.binary.go | 88 - .../pbmesh/v1alpha1/destination_policy.pb.go | 1091 ------ .../pbmesh/v1alpha1/destination_policy.proto | 147 - .../pbmesh/v1alpha1/grpc_route.pb.binary.go | 78 - proto-public/pbmesh/v1alpha1/grpc_route.pb.go | 887 ----- proto-public/pbmesh/v1alpha1/grpc_route.proto | 121 - .../pbmesh/v1alpha1/http_route.pb.binary.go | 118 - proto-public/pbmesh/v1alpha1/http_route.pb.go | 1441 ------- proto-public/pbmesh/v1alpha1/http_route.proto | 259 -- .../v1alpha1/http_route_retries.pb.binary.go | 18 - .../pbmesh/v1alpha1/http_route_retries.pb.go | 206 - .../pbmesh/v1alpha1/http_route_retries.proto | 25 - .../v1alpha1/http_route_timeouts.pb.binary.go | 18 - .../pbmesh/v1alpha1/http_route_timeouts.pb.go | 223 -- .../pbmesh/v1alpha1/http_route_timeouts.proto | 41 - .../pbproxystate/access_logs.pb.binary.go | 18 - .../v1alpha1/pbproxystate/access_logs.pb.go | 325 -- .../v1alpha1/pbproxystate/access_logs.proto | 32 - .../pbproxystate/address.pb.binary.go | 28 - .../v1alpha1/pbproxystate/address.pb.go | 254 -- .../v1alpha1/pbproxystate/address.proto | 20 - .../pbproxystate/cluster.pb.binary.go | 258 -- .../v1alpha1/pbproxystate/cluster.pb.go | 2554 ------------ .../v1alpha1/pbproxystate/cluster.proto | 180 - .../pbproxystate/endpoints.pb.binary.go | 28 - .../v1alpha1/pbproxystate/endpoints.pb.go | 386 -- .../v1alpha1/pbproxystate/endpoints.proto | 29 - .../pbproxystate/escape_hatches.pb.binary.go | 18 - .../pbproxystate/escape_hatches.pb.go | 173 - .../pbproxystate/escape_hatches.proto | 11 - .../header_mutations.pb.binary.go | 68 - .../pbproxystate/header_mutations.pb.go | 693 ---- .../pbproxystate/header_mutations.proto | 47 - .../pbproxystate/intentions.pb.binary.go | 28 - .../v1alpha1/pbproxystate/intentions.pb.go | 211 - .../v1alpha1/pbproxystate/intentions.proto | 10 - .../pbproxystate/listener.pb.binary.go | 78 - .../v1alpha1/pbproxystate/listener.pb.go | 1269 ------ .../v1alpha1/pbproxystate/listener.proto | 132 - .../pbproxystate/references.pb.binary.go | 38 - .../v1alpha1/pbproxystate/references.pb.go | 371 -- .../v1alpha1/pbproxystate/references.proto | 29 - .../v1alpha1/pbproxystate/route.pb.binary.go | 178 - .../pbmesh/v1alpha1/pbproxystate/route.pb.go | 1891 --------- .../pbmesh/v1alpha1/pbproxystate/route.proto | 136 - .../transport_socket.pb.binary.go | 138 - .../pbproxystate/transport_socket.pb.go | 1505 ------- .../pbproxystate/transport_socket.proto | 137 - ...ration.pb.binary.go => proxy.pb.binary.go} | 22 +- proto-public/pbmesh/v1alpha1/proxy.pb.go | 816 ++++ ...{proxy_configuration.proto => proxy.proto} | 74 +- .../pbmesh/v1alpha1/proxy_configuration.pb.go | 1214 ------ .../pbmesh/v1alpha1/proxy_state.pb.binary.go | 28 - .../pbmesh/v1alpha1/proxy_state.pb.go | 563 --- .../pbmesh/v1alpha1/proxy_state.proto | 55 - .../pbmesh/v1alpha1/tcp_route.pb.binary.go | 38 - proto-public/pbmesh/v1alpha1/tcp_route.pb.go | 362 -- proto-public/pbmesh/v1alpha1/tcp_route.proto | 56 - .../pbmesh/v1alpha1/upstreams.pb.binary.go | 34 +- proto-public/pbmesh/v1alpha1/upstreams.pb.go | 628 ++- proto-public/pbmesh/v1alpha1/upstreams.proto | 82 +- .../upstreams_configuration.pb.binary.go | 58 - .../v1alpha1/upstreams_configuration.pb.go | 695 ---- .../v1alpha1/upstreams_configuration.proto | 104 - proto-public/pbmesh/v1alpha1/xroute_addons.go | 91 - .../pbmesh/v1alpha1/xroute_addons_test.go | 174 - proto/buf.gen.yaml | 2 +- proto/buf.yaml | 4 +- proto/private/pbacl/acl.go | 2 +- proto/private/pbacl/acl.pb.go | 2 +- proto/private/pbacl/acl.proto | 2 +- proto/private/pbautoconf/auto_config.go | 2 +- proto/private/pbautoconf/auto_config.pb.go | 2 +- proto/private/pbautoconf/auto_config.proto | 2 +- proto/private/pbautoconf/auto_config_ce.go | 2 +- proto/private/pbcommon/common.go | 2 +- proto/private/pbcommon/common.pb.go | 2 +- proto/private/pbcommon/common.proto | 2 +- proto/private/pbcommon/common_ce.go | 2 +- proto/private/pbcommon/convert_pbstruct.go | 2 +- .../private/pbcommon/convert_pbstruct_test.go | 2 +- proto/private/pbconfig/config.pb.go | 2 +- proto/private/pbconfig/config.proto | 2 +- .../private/pbconfigentry/config_entry.gen.go | 166 - proto/private/pbconfigentry/config_entry.go | 2 +- .../pbconfigentry/config_entry.pb.binary.go | 100 - .../private/pbconfigentry/config_entry.pb.go | 3094 ++++++--------- .../private/pbconfigentry/config_entry.proto | 98 +- .../private/pbconfigentry/config_entry_ce.go | 25 - proto/private/pbconnect/connect.go | 2 +- proto/private/pbconnect/connect.pb.go | 2 +- proto/private/pbconnect/connect.proto | 2 +- proto/private/pbdemo/v1/demo.pb.binary.go | 10 - proto/private/pbdemo/v1/demo.pb.go | 204 +- proto/private/pbdemo/v1/demo.proto | 7 +- proto/private/pbdemo/v2/demo.pb.go | 2 +- proto/private/pbdemo/v2/demo.proto | 2 +- proto/private/pboperator/operator.pb.go | 2 +- proto/private/pboperator/operator.proto | 2 +- proto/private/pbpeering/peering.go | 2 +- proto/private/pbpeering/peering.pb.go | 4 +- proto/private/pbpeering/peering.proto | 4 +- proto/private/pbpeering/peering_ce.go | 2 +- proto/private/pbpeerstream/convert.go | 2 +- proto/private/pbpeerstream/peerstream.go | 2 +- proto/private/pbpeerstream/peerstream.pb.go | 2 +- proto/private/pbpeerstream/peerstream.proto | 2 +- proto/private/pbpeerstream/types.go | 2 +- proto/private/pbservice/convert.go | 2 +- proto/private/pbservice/convert_ce.go | 2 +- proto/private/pbservice/convert_ce_test.go | 2 +- proto/private/pbservice/convert_test.go | 2 +- proto/private/pbservice/healthcheck.gen.go | 4 + proto/private/pbservice/healthcheck.pb.go | 308 +- proto/private/pbservice/healthcheck.proto | 4 +- proto/private/pbservice/ids.go | 2 +- proto/private/pbservice/ids_test.go | 2 +- proto/private/pbservice/node.pb.go | 2 +- proto/private/pbservice/node.proto | 2 +- proto/private/pbservice/service.pb.go | 2 +- proto/private/pbservice/service.proto | 2 +- proto/private/pbstorage/raft.pb.go | 2 +- proto/private/pbstorage/raft.proto | 2 +- proto/private/pbsubscribe/subscribe.go | 2 +- proto/private/pbsubscribe/subscribe.pb.go | 4 +- proto/private/pbsubscribe/subscribe.proto | 2 +- proto/private/prototest/testing.go | 9 +- proto/private/prototest/testing_test.go | 3 - sdk/LICENSE | 365 -- sdk/iptables/iptables.go | 2 +- sdk/testutil/context.go | 8 +- sdk/testutil/retry/counter.go | 23 - sdk/testutil/retry/retry.go | 98 +- sdk/testutil/retry/retry_test.go | 63 - sdk/testutil/retry/timer.go | 43 - sdk/testutil/server.go | 1 - sentinel/evaluator.go | 2 +- sentinel/scope.go | 2 +- sentinel/sentinel_ce.go | 2 +- service_os/service.go | 2 +- service_os/service_windows.go | 2 +- snapshot/archive.go | 2 +- snapshot/archive_test.go | 2 +- snapshot/snapshot.go | 2 +- snapshot/snapshot_test.go | 2 +- test-integ/README.md | 3 - test-integ/go.mod | 246 -- test-integ/go.sum | 1336 ------- test-integ/peering_commontopo/README.md | 66 - .../peering_commontopo/ac1_basic_test.go | 275 -- .../ac2_disco_chain_test.go | 206 - .../ac3_service_defaults_upstream_test.go | 267 -- .../ac4_proxy_defaults_test.go | 216 - .../ac5_1_no_svc_mesh_test.go | 132 - .../ac5_2_pq_failover_test.go | 401 -- .../peering_commontopo/ac6_failovers_test.go | 432 -- .../ac7_1_rotate_gw_test.go | 191 - .../ac7_2_rotate_leader_test.go | 217 -- test-integ/peering_commontopo/asserter.go | 301 -- test-integ/peering_commontopo/commontopo.go | 613 --- .../peering_commontopo/sharedtopology_test.go | 85 - test/bin/cluster.bash | 2 +- test/ca/generate.sh | 2 +- test/client_certs/generate.sh | 2 +- test/hostname/generate.sh | 2 +- .../envoy/Dockerfile-consul-envoy-windows | 12 - .../connect/envoy/Dockerfile-tcpdump-windows | 7 - .../envoy/Dockerfile-test-sds-server-windows | 8 - test/integration/connect/envoy/README.md | 1 - .../integration/connect/envoy/WINDOWS-TEST.md | 40 - .../capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../case-api-gateway-http-hostnames/setup.sh | 2 +- .../case-api-gateway-http-hostnames/vars.sh | 2 +- .../case-api-gateway-http-simple/capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../case-api-gateway-http-simple/setup.sh | 2 +- .../case-api-gateway-http-simple/vars.sh | 2 +- .../capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../service_s3.hcl | 2 +- .../setup.sh | 2 +- .../vars.sh | 2 +- .../capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../setup.sh | 2 +- .../vars.sh | 2 +- .../capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../case-api-gateway-tcp-conflicted/setup.sh | 2 +- .../case-api-gateway-tcp-conflicted/vars.sh | 2 +- .../case-api-gateway-tcp-simple/capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../case-api-gateway-tcp-simple/setup.sh | 2 +- .../envoy/case-api-gateway-tcp-simple/vars.sh | 2 +- .../capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../setup.sh | 2 +- .../vars.sh | 2 +- .../connect/envoy/case-badauthz/capture.sh | 2 +- .../connect/envoy/case-badauthz/setup.sh | 2 +- .../connect/envoy/case-basic/capture.sh | 2 +- .../connect/envoy/case-basic/setup.sh | 2 +- .../connect/envoy/case-centralconf/capture.sh | 2 +- .../envoy/case-centralconf/service_s1.hcl | 2 +- .../envoy/case-centralconf/service_s2.hcl | 2 +- .../connect/envoy/case-centralconf/setup.sh | 2 +- .../alpha/base.hcl | 2 +- .../alpha/service_gateway.hcl | 2 +- .../alpha/service_s1.hcl | 2 +- .../alpha/service_s2.hcl | 2 +- .../alpha/setup.sh | 2 +- .../bind.hcl | 2 +- .../capture.sh | 2 +- .../primary/base.hcl | 2 +- .../primary/service_s1.hcl | 2 +- .../primary/service_s2.hcl | 2 +- .../primary/setup.sh | 2 +- .../vars.sh | 2 +- .../bind.hcl | 2 +- .../capture.sh | 2 +- .../primary/setup.sh | 2 +- .../secondary/join.hcl | 2 +- .../secondary/service_gateway.hcl | 2 +- .../secondary/service_s1.hcl | 2 +- .../secondary/setup.sh | 2 +- .../vars.sh | 2 +- .../bind.hcl | 2 +- .../capture.sh | 2 +- .../primary/setup.sh | 2 +- .../secondary/join.hcl | 2 +- .../secondary/service_gateway.hcl | 2 +- .../secondary/service_s1.hcl | 2 +- .../secondary/setup.sh | 2 +- .../vars.sh | 2 +- .../service_s2-v1.hcl | 2 +- .../service_s2-v2.hcl | 2 +- .../case-cfg-resolver-defaultsubset/setup.sh | 2 +- .../case-cfg-resolver-defaultsubset/vars.sh | 2 +- .../case-cfg-resolver-features/capture.sh | 2 +- .../service_s2-v1.hcl | 2 +- .../service_s2-v2.hcl | 2 +- .../envoy/case-cfg-resolver-features/setup.sh | 2 +- .../envoy/case-cfg-resolver-features/vars.sh | 2 +- .../service_s2-v1.hcl | 2 +- .../setup.sh | 2 +- .../vars.sh | 2 +- .../service_s3-v1.hcl | 2 +- .../service_s3-v2.hcl | 2 +- .../service_s3.hcl | 2 +- .../setup.sh | 2 +- .../case-cfg-resolver-subset-redirect/vars.sh | 2 +- .../service_s3-v1.hcl | 2 +- .../service_s3-v2.hcl | 2 +- .../service_s3.hcl | 2 +- .../case-cfg-resolver-svc-failover/setup.sh | 2 +- .../case-cfg-resolver-svc-failover/vars.sh | 2 +- .../service_s3.hcl | 2 +- .../setup.sh | 2 +- .../vars.sh | 2 +- .../service_s3.hcl | 2 +- .../setup.sh | 2 +- .../vars.sh | 2 +- .../envoy/case-cfg-router-features/capture.sh | 2 +- .../service_s2-v1.hcl | 2 +- .../service_s2-v2.hcl | 2 +- .../envoy/case-cfg-router-features/setup.sh | 2 +- .../envoy/case-cfg-router-features/vars.sh | 2 +- .../alpha/base.hcl | 2 +- .../alpha/service_gateway.hcl | 2 +- .../alpha/service_s1.hcl | 2 +- .../alpha/service_s2.hcl | 2 +- .../alpha/setup.sh | 2 +- .../bind.hcl | 2 +- .../capture.sh | 2 +- .../primary/base.hcl | 2 +- .../primary/service_s1.hcl | 2 +- .../primary/service_s2.hcl | 2 +- .../primary/setup.sh | 2 +- .../case-cfg-splitter-cluster-peering/vars.sh | 2 +- .../case-cfg-splitter-features/capture.sh | 2 +- .../service_s2-v1.hcl | 2 +- .../service_s2-v2.hcl | 2 +- .../envoy/case-cfg-splitter-features/setup.sh | 2 +- .../envoy/case-cfg-splitter-features/vars.sh | 2 +- .../alpha/base.hcl | 2 +- .../alpha/service_gateway.hcl | 2 +- .../alpha/service_s1.hcl | 2 +- .../alpha/service_s2.hcl | 2 +- .../alpha/setup.sh | 2 +- .../bind.hcl | 2 +- .../capture.sh | 2 +- .../primary/base.hcl | 2 +- .../primary/service_ingress.hcl | 2 +- .../primary/setup.sh | 2 +- .../vars.sh | 2 +- .../connect/envoy/case-consul-exec/setup.sh | 2 +- .../connect/envoy/case-consul-exec/vars.sh | 2 +- .../alpha/base.hcl | 2 +- .../alpha/service_gateway.hcl | 2 +- .../alpha/service_s1.hcl | 2 +- .../alpha/service_s2.hcl | 2 +- .../alpha/setup.sh | 2 +- .../bind.hcl | 2 +- .../capture.sh | 2 +- .../primary/base.hcl | 2 +- .../primary/service_gateway.hcl | 2 +- .../primary/service_s1.hcl | 2 +- .../primary/service_s2.hcl | 2 +- .../primary/setup.sh | 2 +- .../case-cross-peer-control-plane-mgw/vars.sh | 2 +- .../alpha/base.hcl | 2 +- .../alpha/service_gateway.hcl | 2 +- .../alpha/service_s1.hcl | 2 +- .../alpha/service_s2.hcl | 2 +- .../alpha/service_s3.hcl | 2 +- .../alpha/setup.sh | 2 +- .../case-cross-peers-http-router/bind.hcl | 2 +- .../case-cross-peers-http-router/capture.sh | 2 +- .../primary/base.hcl | 2 +- .../primary/service_gateway.hcl | 2 +- .../primary/service_s1.hcl | 2 +- .../primary/service_s2.hcl | 2 +- .../primary/setup.sh | 2 +- .../case-cross-peers-http-router/vars.sh | 2 +- .../case-cross-peers-http/alpha/base.hcl | 2 +- .../alpha/service_gateway.hcl | 2 +- .../alpha/service_s1.hcl | 2 +- .../alpha/service_s2.hcl | 2 +- .../case-cross-peers-http/alpha/setup.sh | 2 +- .../envoy/case-cross-peers-http/bind.hcl | 2 +- .../envoy/case-cross-peers-http/capture.sh | 2 +- .../case-cross-peers-http/primary/base.hcl | 2 +- .../primary/service_gateway.hcl | 2 +- .../primary/service_s1.hcl | 2 +- .../primary/service_s2.hcl | 2 +- .../case-cross-peers-http/primary/setup.sh | 2 +- .../envoy/case-cross-peers-http/vars.sh | 2 +- .../alpha/base.hcl | 2 +- .../alpha/service_gateway.hcl | 2 +- .../alpha/service_s1.hcl | 2 +- .../alpha/service_s2.hcl | 2 +- .../alpha/service_s3.hcl | 2 +- .../alpha/setup.sh | 2 +- .../bind.hcl | 2 +- .../capture.sh | 2 +- .../primary/base.hcl | 2 +- .../primary/service_gateway.hcl | 2 +- .../primary/service_s1.hcl | 2 +- .../primary/service_s2.hcl | 2 +- .../primary/setup.sh | 2 +- .../vars.sh | 2 +- .../envoy/case-cross-peers/alpha/base.hcl | 2 +- .../alpha/service_gateway.hcl | 2 +- .../case-cross-peers/alpha/service_s1.hcl | 2 +- .../case-cross-peers/alpha/service_s2.hcl | 2 +- .../envoy/case-cross-peers/alpha/setup.sh | 2 +- .../connect/envoy/case-cross-peers/bind.hcl | 2 +- .../connect/envoy/case-cross-peers/capture.sh | 2 +- .../envoy/case-cross-peers/primary/base.hcl | 2 +- .../primary/service_gateway.hcl | 2 +- .../case-cross-peers/primary/service_s1.hcl | 2 +- .../case-cross-peers/primary/service_s2.hcl | 2 +- .../envoy/case-cross-peers/primary/setup.sh | 2 +- .../connect/envoy/case-cross-peers/vars.sh | 2 +- .../envoy/case-dogstatsd-udp/service_s1.hcl | 2 +- .../connect/envoy/case-dogstatsd-udp/setup.sh | 2 +- .../connect/envoy/case-dogstatsd-udp/vars.sh | 2 +- .../envoy/case-dogstatsd-udp/verify.bats | 9 +- .../envoy/case-expose-checks/capture.sh | 2 +- .../envoy/case-expose-checks/service_s1.hcl | 2 +- .../envoy/case-expose-checks/service_s2.hcl | 2 +- .../connect/envoy/case-expose-checks/setup.sh | 2 +- .../case-gateway-without-services/bind.hcl | 2 +- .../case-gateway-without-services/capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../service_s1.hcl | 2 +- .../service_s2.hcl | 2 +- .../case-gateway-without-services/setup.sh | 2 +- .../case-gateway-without-services/vars.sh | 2 +- .../envoy/case-gateways-local/bind.hcl | 2 +- .../envoy/case-gateways-local/capture.sh | 2 +- .../primary/service_gateway.hcl | 2 +- .../primary/service_s1.hcl | 2 +- .../primary/service_s2.hcl | 2 +- .../case-gateways-local/primary/setup.sh | 2 +- .../case-gateways-local/secondary/join.hcl | 2 +- .../secondary/service_gateway.hcl | 2 +- .../secondary/service_s1.hcl | 2 +- .../case-gateways-local/secondary/setup.sh | 4 +- .../connect/envoy/case-gateways-local/vars.sh | 2 +- .../envoy/case-gateways-remote/bind.hcl | 2 +- .../envoy/case-gateways-remote/capture.sh | 2 +- .../primary/service_s1.hcl | 2 +- .../primary/service_s2.hcl | 2 +- .../case-gateways-remote/primary/setup.sh | 2 +- .../case-gateways-remote/secondary/join.hcl | 2 +- .../secondary/service_gateway.hcl | 2 +- .../secondary/service_s1.hcl | 2 +- .../case-gateways-remote/secondary/setup.sh | 2 +- .../envoy/case-gateways-remote/vars.sh | 2 +- .../connect/envoy/case-grpc/service_s1.hcl | 4 +- .../connect/envoy/case-grpc/service_s2.hcl | 2 +- .../connect/envoy/case-grpc/setup.sh | 2 +- .../connect/envoy/case-grpc/vars.sh | 2 +- .../connect/envoy/case-grpc/verify.bats | 2 +- .../envoy/case-http-badauthz/capture.sh | 2 +- .../envoy/case-http-badauthz/service_s1.hcl | 2 +- .../envoy/case-http-badauthz/service_s2.hcl | 2 +- .../connect/envoy/case-http-badauthz/setup.sh | 6 +- .../connect/envoy/case-http/capture.sh | 2 +- .../connect/envoy/case-http/service_s1.hcl | 2 +- .../connect/envoy/case-http/service_s2.hcl | 2 +- .../connect/envoy/case-http/setup.sh | 2 +- .../case-ingress-gateway-grpc/capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../case-ingress-gateway-grpc/service_s1.hcl | 2 +- .../envoy/case-ingress-gateway-grpc/setup.sh | 2 +- .../envoy/case-ingress-gateway-grpc/vars.sh | 2 +- .../case-ingress-gateway-http/capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../envoy/case-ingress-gateway-http/setup.sh | 2 +- .../envoy/case-ingress-gateway-http/vars.sh | 2 +- .../capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../setup.sh | 2 +- .../vars.sh | 2 +- .../alpha/base.hcl | 2 +- .../alpha/service_gateway.hcl | 2 +- .../alpha/service_s1.hcl | 2 +- .../alpha/service_s2.hcl | 2 +- .../alpha/setup.sh | 2 +- .../bind.hcl | 2 +- .../capture.sh | 2 +- .../primary/base.hcl | 2 +- .../primary/service_ingress.hcl | 2 +- .../primary/service_s1.hcl | 2 +- .../primary/service_s2.hcl | 2 +- .../primary/setup.sh | 2 +- .../vars.sh | 2 +- .../envoy/case-ingress-gateway-sds/capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../envoy/case-ingress-gateway-sds/setup.sh | 2 +- .../envoy/case-ingress-gateway-sds/vars.sh | 2 +- .../case-ingress-gateway-simple/capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../case-ingress-gateway-simple/setup.sh | 2 +- .../envoy/case-ingress-gateway-simple/vars.sh | 2 +- .../envoy/case-ingress-gateway-tls/capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../envoy/case-ingress-gateway-tls/setup.sh | 2 +- .../envoy/case-ingress-gateway-tls/vars.sh | 2 +- .../case-ingress-gateway-tls/verify.bats | 10 +- .../bind.hcl | 2 +- .../capture.sh | 2 +- .../primary/service_gateway.hcl | 2 +- .../primary/service_ingress.hcl | 2 +- .../primary/service_s1.hcl | 2 +- .../primary/service_s2.hcl | 2 +- .../primary/setup.sh | 2 +- .../secondary/join.hcl | 2 +- .../secondary/service_gateway.hcl | 2 +- .../secondary/setup.sh | 2 +- .../vars.sh | 2 +- .../connect/envoy/case-l7-intentions/acl.hcl | 2 +- .../envoy/case-l7-intentions/capture.sh | 2 +- .../connect/envoy/case-l7-intentions/setup.sh | 2 +- .../connect/envoy/case-lua/capture.sh | 2 +- .../connect/envoy/case-lua/service_s1.hcl | 2 +- .../connect/envoy/case-lua/service_s2.hcl | 2 +- .../connect/envoy/case-lua/setup.sh | 2 +- .../connect/envoy/case-lua/vars.sh | 2 +- .../envoy/case-mesh-to-lambda/capture.sh | 2 +- .../case-mesh-to-lambda/service_gateway.hcl | 2 +- .../envoy/case-mesh-to-lambda/service_s1.hcl | 2 +- .../envoy/case-mesh-to-lambda/setup.sh | 2 +- .../connect/envoy/case-mesh-to-lambda/vars.sh | 2 +- .../envoy/case-multidc-rsa-ca/bind.hcl | 2 +- .../envoy/case-multidc-rsa-ca/ca_config.hcl | 2 +- .../envoy/case-multidc-rsa-ca/capture.sh | 2 +- .../primary/service_s1.hcl | 2 +- .../primary/service_s2.hcl | 2 +- .../case-multidc-rsa-ca/primary/setup.sh | 2 +- .../case-multidc-rsa-ca/secondary/join.hcl | 2 +- .../secondary/service_s1.hcl | 2 +- .../case-multidc-rsa-ca/secondary/setup.sh | 2 +- .../connect/envoy/case-multidc-rsa-ca/vars.sh | 2 +- .../connect/envoy/case-prometheus/capture.sh | 2 +- .../envoy/case-prometheus/service_s1.hcl | 2 +- .../envoy/case-prometheus/service_s2.hcl | 2 +- .../connect/envoy/case-prometheus/setup.sh | 2 +- .../envoy/case-property-override/capture.sh | 2 +- .../case-property-override/service_s1.hcl | 2 +- .../case-property-override/service_s2.hcl | 2 +- .../case-property-override/service_s3.hcl | 2 +- .../envoy/case-property-override/setup.sh | 2 +- .../envoy/case-property-override/vars.sh | 2 +- .../envoy/case-stats-proxy/service_s1.hcl | 2 +- .../envoy/case-stats-proxy/service_s2.hcl | 2 +- .../connect/envoy/case-stats-proxy/setup.sh | 2 +- .../envoy/case-stats-proxy/verify.bats | 2 +- .../envoy/case-statsd-udp/service_s1.hcl | 2 +- .../connect/envoy/case-statsd-udp/setup.sh | 2 +- .../connect/envoy/case-statsd-udp/vars.sh | 2 +- .../capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../service_s1.hcl | 2 +- .../service_s4.hcl | 2 +- .../setup.sh | 2 +- .../vars.sh | 2 +- .../service_gateway.hcl | 2 +- .../case-terminating-gateway-simple/setup.sh | 2 +- .../case-terminating-gateway-simple/vars.sh | 2 +- .../capture.sh | 2 +- .../service_gateway.hcl | 2 +- .../service_s2-v1.hcl | 2 +- .../service_s2-v2.hcl | 2 +- .../service_s3.hcl | 2 +- .../case-terminating-gateway-subsets/setup.sh | 2 +- .../case-terminating-gateway-subsets/vars.sh | 2 +- .../bind.hcl | 2 +- .../service_gateway.hcl | 2 +- .../service_s1.hcl | 2 +- .../service_s2.hcl | 2 +- .../setup.sh | 2 +- .../vars.sh | 2 +- .../envoy/case-upstream-config/service_s1.hcl | 2 +- .../envoy/case-upstream-config/service_s2.hcl | 2 +- .../envoy/case-upstream-config/setup.sh | 2 +- .../connect/envoy/case-wanfed-gw/bind.hcl | 2 +- .../connect/envoy/case-wanfed-gw/capture.sh | 2 +- .../case-wanfed-gw/global-setup-windows.sh | 47 - .../envoy/case-wanfed-gw/global-setup.sh | 2 +- .../envoy/case-wanfed-gw/primary/common.hcl | 2 +- .../envoy/case-wanfed-gw/primary/server.hcl | 2 +- .../primary/service_gateway.hcl | 2 +- .../case-wanfed-gw/primary/service_s1.hcl | 2 +- .../case-wanfed-gw/primary/service_s2.hcl | 2 +- .../envoy/case-wanfed-gw/primary/setup.sh | 2 +- .../envoy/case-wanfed-gw/secondary/common.hcl | 2 +- .../envoy/case-wanfed-gw/secondary/server.hcl | 2 +- .../secondary/service_gateway.hcl | 2 +- .../case-wanfed-gw/secondary/service_s1.hcl | 2 +- .../case-wanfed-gw/secondary/service_s2.hcl | 2 +- .../envoy/case-wanfed-gw/secondary/setup.sh | 2 +- .../connect/envoy/case-wanfed-gw/vars.sh | 2 +- .../connect/envoy/case-wasm/capture.sh | 2 +- .../connect/envoy/case-wasm/service_s1.hcl | 2 +- .../connect/envoy/case-wasm/service_s2.hcl | 2 +- .../connect/envoy/case-wasm/setup.sh | 2 +- .../connect/envoy/case-wasm/vars.sh | 2 +- .../connect/envoy/case-zipkin/service_s1.hcl | 2 +- .../connect/envoy/case-zipkin/service_s2.hcl | 2 +- .../connect/envoy/case-zipkin/setup.sh | 2 +- .../connect/envoy/case-zipkin/vars.sh | 2 +- .../connect/envoy/case-zipkin/verify.bats | 7 +- .../connect/envoy/consul-base-cfg/base.hcl | 2 +- .../envoy/consul-base-cfg/service_s1.hcl | 2 +- .../envoy/consul-base-cfg/service_s2.hcl | 2 +- test/integration/connect/envoy/defaults.sh | 2 +- .../connect/envoy/docker-windows.md | 42 - .../connect/envoy/docs/img/linux-arch.png | Bin 63964 -> 0 bytes .../docs/img/windows-arch-singlecontainer.png | Bin 114040 -> 0 bytes .../envoy/docs/img/windows-linux-arch.png | Bin 61475 -> 0 bytes .../docs/windows-testing-architecture.md | 106 - test/integration/connect/envoy/down.sh | 2 +- test/integration/connect/envoy/helpers.bash | 4 +- .../connect/envoy/helpers.windows.bash | 1195 ------ test/integration/connect/envoy/main_test.go | 140 +- test/integration/connect/envoy/run-tests.sh | 16 +- .../connect/envoy/run-tests.windows.sh | 911 ----- .../connect/envoy/test-sds-server/Dockerfile | 2 +- .../envoy/test-sds-server/certs/gen-certs.sh | 2 +- .../connect/envoy/test-sds-server/sds.go | 2 +- .../connect/envoy/windows-troubleshooting.md | 90 - .../consul-container/assets/tproxy-startup.sh | 3 - test/integration/consul-container/go.mod | 148 +- test/integration/consul-container/go.sum | 935 +---- .../consul-container/libs/assert/common.go | 2 +- .../consul-container/libs/assert/envoy.go | 7 +- .../consul-container/libs/assert/grpc.go | 3 +- .../consul-container/libs/assert/peering.go | 16 +- .../consul-container/libs/assert/service.go | 4 +- .../consul-container/libs/cluster/agent.go | 71 +- .../consul-container/libs/cluster/app.go | 2 +- .../consul-container/libs/cluster/builder.go | 2 +- .../consul-container/libs/cluster/cluster.go | 2 +- .../consul-container/libs/cluster/config.go | 2 +- .../libs/cluster/container.go | 55 +- .../libs/cluster/encryption.go | 2 +- .../consul-container/libs/cluster/log.go | 2 +- .../consul-container/libs/cluster/network.go | 3 +- .../consul-container/libs/service/common.go | 2 +- .../consul-container/libs/service/connect.go | 18 +- .../consul-container/libs/service/examples.go | 38 +- .../consul-container/libs/service/gateway.go | 2 +- .../consul-container/libs/service/helpers.go | 116 +- .../consul-container/libs/service/log.go | 2 +- .../consul-container/libs/service/service.go | 2 +- .../libs/topology/peering_topology.go | 20 +- .../libs/topology/service_topology.go | 14 +- .../consul-container/libs/utils/debug.go | 2 +- .../consul-container/libs/utils/defer.go | 2 +- .../consul-container/libs/utils/docker.go | 17 +- .../consul-container/libs/utils/helpers.go | 2 +- .../consul-container/libs/utils/retry.go | 2 +- .../consul-container/libs/utils/tenancy.go | 17 +- .../consul-container/libs/utils/utils.go | 2 +- .../consul-container/libs/utils/version.go | 17 +- .../consul-container/libs/utils/version_ce.go | 2 +- .../test/basic/connect_service_test.go | 57 +- .../test/catalog/catalog_test.go | 38 - .../consul_envoy_version.go | 2 +- .../consul-container/test/debugging.md | 78 - .../test/envoy_extensions/ext_authz_test.go | 2 +- .../testdata/wasm_test_files/Dockerfile | 6 - .../testdata/wasm_test_files/README.md | 14 - .../testdata/wasm_test_files/build.sh | 6 - .../testdata/wasm_test_files/go.mod | 5 - .../testdata/wasm_test_files/go.sum | 6 - .../testdata/wasm_test_files/nginx.conf | 13 - .../wasm_test_files/wasm_add_header.go | 50 - .../wasm_test_files/wasm_add_header.wasm | Bin 400008 -> 0 bytes .../test/envoy_extensions/wasm_test.go | 464 --- .../test/gateways/gateway_endpoint_test.go | 2 +- .../test/gateways/http_route_test.go | 2 +- .../test/gateways/ingress_gateway_test.go | 4 +- .../test/gateways/tenancy_ce.go | 3 - .../test/jwtauth/jwt_auth_test.go | 2 +- .../test/observability/access_logs_test.go | 4 +- .../test/observability/metrics_leader_test.go | 2 +- .../rotate_server_and_ca_then_fail_test.go | 2 +- .../test/ratelimit/ratelimit_test.go | 109 +- .../test/snapshot/snapshot_restore_test.go | 2 +- .../test/tproxy/tproxy_test.go | 2 +- .../test/troubleshoot/troubleshoot_test.go | 4 +- .../test/upgrade/acl_node_test.go | 2 +- .../test/upgrade/basic/basic_test.go | 2 +- .../upgrade/basic/fullstopupgrade_test.go | 2 +- .../test/upgrade/basic/healthcheck_test.go | 2 +- .../test/upgrade/catalog/catalog_test.go | 87 - .../consul-container/test/upgrade/common.go | 5 +- .../test/upgrade/ingress_gateway_grpc_test.go | 2 +- .../test/upgrade/ingress_gateway_sds_test.go | 2 +- .../test/upgrade/ingress_gateway_test.go | 2 +- .../resolver_default_subset_test.go | 6 +- .../peering/peering_control_plane_mgw_test.go | 2 +- .../test/upgrade/peering/peering_http_test.go | 2 +- .../test/util/test_debug_breakpoint_hit.png | Bin 654866 -> 0 bytes .../test/util/test_debug_configuration.png | Bin 294046 -> 0 bytes .../test/util/test_debug_info.png | Bin 622325 -> 0 bytes .../util/test_debug_remote_configuration.png | Bin 285715 -> 0 bytes .../test/util/test_debug_remote_connected.png | Bin 111968 -> 0 bytes .../test/util/test_debug_resume_program.png | Bin 51972 -> 0 bytes .../wanfed/acl_bootstrap_replication_test.go | 2 +- .../test/wanfed/wanfed_peering_test.go | 2 +- test/load/packer/consul-ami/consul.pkr.hcl | 2 +- test/load/packer/consul-ami/scripts/conf.yaml | 2 +- .../packer/consul-ami/scripts/datadog.yaml | 2 +- .../packer/consul-ami/scripts/move-files.sh | 2 +- .../load/packer/loadtest-ami/loadtest.pkr.hcl | 2 +- .../packer/loadtest-ami/scripts/install-k6.sh | 2 +- .../packer/loadtest-ami/scripts/loadtest.js | 2 +- test/load/terraform/consul.tf | 2 +- test/load/terraform/main.tf | 2 +- test/load/terraform/outputs.tf | 2 +- test/load/terraform/providers.tf | 2 +- test/load/terraform/test-servers.tf | 2 +- test/load/terraform/user-data-client.sh | 2 +- test/load/terraform/user-data-server.sh | 2 +- test/load/terraform/variables.tf | 2 +- testing/deployer/.gitignore | 4 - testing/deployer/README.md | 179 - testing/deployer/TODO.md | 9 - testing/deployer/go.mod | 45 - testing/deployer/go.sum | 246 -- testing/deployer/sprawl/acl.go | 335 -- testing/deployer/sprawl/acl_rules.go | 163 - testing/deployer/sprawl/boot.go | 523 --- testing/deployer/sprawl/catalog.go | 428 -- testing/deployer/sprawl/configentries.go | 61 - testing/deployer/sprawl/consul.go | 101 - testing/deployer/sprawl/debug.go | 11 - testing/deployer/sprawl/details.go | 173 - testing/deployer/sprawl/ent.go | 177 - testing/deployer/sprawl/helpers.go | 14 - .../deployer/sprawl/internal/build/docker.go | 86 - .../deployer/sprawl/internal/runner/exec.go | 123 - .../deployer/sprawl/internal/secrets/store.go | 73 - .../deployer/sprawl/internal/tfgen/agent.go | 218 -- .../deployer/sprawl/internal/tfgen/digest.go | 48 - testing/deployer/sprawl/internal/tfgen/dns.go | 183 - .../deployer/sprawl/internal/tfgen/docker.go | 42 - .../sprawl/internal/tfgen/docker_test.go | 18 - testing/deployer/sprawl/internal/tfgen/gen.go | 478 --- testing/deployer/sprawl/internal/tfgen/io.go | 73 - .../deployer/sprawl/internal/tfgen/nodes.go | 252 -- .../deployer/sprawl/internal/tfgen/prelude.go | 19 - .../deployer/sprawl/internal/tfgen/proxy.go | 90 - testing/deployer/sprawl/internal/tfgen/res.go | 98 - .../templates/container-app-dataplane.tf.tmpl | 29 - .../templates/container-app-sidecar.tf.tmpl | 31 - .../tfgen/templates/container-app.tf.tmpl | 25 - .../tfgen/templates/container-consul.tf.tmpl | 40 - .../tfgen/templates/container-coredns.tf.tmpl | 28 - .../tfgen/templates/container-mgw.tf.tmpl | 25 - .../tfgen/templates/container-pause.tf.tmpl | 38 - .../tfgen/templates/container-proxy.tf.tmpl | 33 - .../deployer/sprawl/internal/tfgen/tfgen.go | 18 - testing/deployer/sprawl/peering.go | 168 - testing/deployer/sprawl/sprawl.go | 467 --- .../deployer/sprawl/sprawltest/sprawltest.go | 205 - .../deployer/sprawl/sprawltest/test_test.go | 183 - testing/deployer/sprawl/tls.go | 117 - testing/deployer/topology/compile.go | 674 ---- testing/deployer/topology/default_cdp.go | 6 - testing/deployer/topology/default_consul.go | 7 - testing/deployer/topology/default_envoy.go | 6 - testing/deployer/topology/ids.go | 145 - testing/deployer/topology/images.go | 126 - testing/deployer/topology/images_test.go | 101 - testing/deployer/topology/topology.go | 790 ---- testing/deployer/topology/util.go | 20 - testing/deployer/topology/util_test.go | 14 - testing/deployer/util/consul.go | 66 - testing/deployer/util/files.go | 60 - .../deployer/util/internal/ipamutils/doc.go | 21 - .../deployer/util/internal/ipamutils/utils.go | 120 - .../util/internal/ipamutils/utils_test.go | 105 - testing/deployer/util/net.go | 20 - testrpc/wait.go | 2 +- tlsutil/config.go | 27 +- tlsutil/config_test.go | 10 +- tlsutil/generate.go | 2 +- tlsutil/generate_test.go | 2 +- tools/internal-grpc-proxy/main.go | 2 +- troubleshoot/proxy/certs.go | 2 +- troubleshoot/proxy/certs_test.go | 2 +- troubleshoot/proxy/stats.go | 2 +- troubleshoot/proxy/troubleshoot_proxy.go | 2 +- troubleshoot/proxy/upstreams.go | 2 +- troubleshoot/proxy/upstreams_test.go | 2 +- troubleshoot/proxy/utils.go | 2 +- troubleshoot/proxy/validateupstream.go | 2 +- troubleshoot/proxy/validateupstream_test.go | 2 +- troubleshoot/validate/validate.go | 2 +- troubleshoot/validate/validate_test.go | 2 +- types/area.go | 2 +- types/checks.go | 2 +- types/node_id.go | 2 +- types/tls.go | 2 +- types/tls_test.go | 2 +- .../components/consul/acl/selector/index.hbs | 2 +- .../consul/token/selector/index.hbs | 2 +- .../components/consul/token/selector/index.js | 2 +- .../consul-acls/vendor/consul-acls/routes.js | 2 +- .../vendor/consul-acls/services.js | 2 +- .../app/components/consul/hcp/home/index.hbs | 2 +- .../app/components/consul/hcp/home/index.scss | 2 +- .../components/consul/hcp/home/index.test.js | 2 +- .../consul-hcp/vendor/consul-hcp/routes.js | 2 +- .../consul-hcp/vendor/consul-hcp/services.js | 2 +- .../consul/lock-session/form/index.hbs | 2 +- .../consul/lock-session/form/index.scss | 2 +- .../consul/lock-session/list/index.hbs | 2 +- .../consul/lock-session/list/index.scss | 2 +- .../lock-session/notifications/index.hbs | 2 +- .../app/templates/dc/nodes/show/sessions.hbs | 2 +- .../vendor/consul-lock-sessions/routes.js | 2 +- .../vendor/consul-lock-sessions/services.js | 2 +- .../components/consul/nspace/form/index.hbs | 2 +- .../components/consul/nspace/form/index.js | 2 +- .../components/consul/nspace/list/index.hbs | 2 +- .../consul/nspace/list/pageobject.js | 2 +- .../consul/nspace/notifications/index.hbs | 2 +- .../consul/nspace/search-bar/index.hbs | 2 +- .../consul/nspace/selector/index.hbs | 2 +- .../app/templates/dc/nspaces/edit.hbs | 2 +- .../app/templates/dc/nspaces/index.hbs | 2 +- .../vendor/consul-nspaces/routes.js | 2 +- .../vendor/consul-nspaces/services.js | 2 +- .../consul/partition/form/index.hbs | 2 +- .../consul/partition/list/index.hbs | 2 +- .../consul/partition/list/test-support.js | 2 +- .../consul/partition/notifications/index.hbs | 2 +- .../consul/partition/search-bar/index.hbs | 2 +- .../consul/partition/selector/index.hbs | 2 +- .../app/templates/dc/partitions/edit.hbs | 2 +- .../app/templates/dc/partitions/index.hbs | 2 +- .../vendor/consul-partitions/routes.js | 2 +- .../vendor/consul-partitions/services.js | 2 +- .../consul/peer/address/list/index.hbs | 2 +- .../consul/peer/address/list/index.scss | 2 +- .../consul/peer/bento-box/index.hbs | 2 +- .../components/consul/peer/components.scss | 2 +- .../consul/peer/form/chart.xstate.js | 2 +- .../peer/form/generate/actions/index.hbs | 2 +- .../consul/peer/form/generate/chart.xstate.js | 2 +- .../peer/form/generate/fieldsets/index.hbs | 2 +- .../peer/form/generate/fieldsets/index.js | 2 +- .../consul/peer/form/generate/index.hbs | 2 +- .../app/components/consul/peer/form/index.hbs | 2 +- .../components/consul/peer/form/index.scss | 2 +- .../peer/form/initiate/actions/index.hbs | 2 +- .../peer/form/initiate/fieldsets/index.hbs | 2 +- .../consul/peer/form/initiate/index.hbs | 2 +- .../consul/peer/form/token/actions/index.hbs | 2 +- .../peer/form/token/fieldsets/index.hbs | 4 +- .../app/components/consul/peer/index.scss | 2 +- .../app/components/consul/peer/list/index.hbs | 2 +- .../consul/peer/list/test-support.js | 2 +- .../consul/peer/notifications/index.hbs | 2 +- .../consul/peer/search-bar/index.hbs | 2 +- .../consul/peer/search-bar/index.scss | 2 +- .../components/consul/peer/selector/index.hbs | 2 +- .../app/controllers/dc/peers/index.js | 2 +- .../app/controllers/dc/peers/show/exported.js | 2 +- .../app/controllers/dc/peers/show/index.js | 2 +- .../app/templates/dc/peers/index.hbs | 2 +- .../app/templates/dc/peers/show.hbs | 2 +- .../app/templates/dc/peers/show/addresses.hbs | 2 +- .../app/templates/dc/peers/show/exported.hbs | 2 +- .../app/templates/dc/peers/show/imported.hbs | 2 +- .../app/templates/dc/peers/show/index.hbs | 2 +- .../vendor/consul-peerings/routes.js | 2 +- .../vendor/consul-peerings/services.js | 2 +- ui/packages/consul-ui/.docfy-config.js | 2 +- ui/packages/consul-ui/.eslintrc.js | 2 +- ui/packages/consul-ui/.istanbul.yml | 2 +- ui/packages/consul-ui/.prettierrc.js | 2 +- ui/packages/consul-ui/.template-lintrc.js | 2 +- ui/packages/consul-ui/app/abilities/acl.js | 2 +- .../consul-ui/app/abilities/auth-method.js | 2 +- ui/packages/consul-ui/app/abilities/base.js | 2 +- .../consul-ui/app/abilities/intention.js | 2 +- ui/packages/consul-ui/app/abilities/kv.js | 2 +- .../consul-ui/app/abilities/license.js | 2 +- ui/packages/consul-ui/app/abilities/node.js | 2 +- ui/packages/consul-ui/app/abilities/nspace.js | 2 +- .../consul-ui/app/abilities/overview.js | 2 +- .../consul-ui/app/abilities/partition.js | 2 +- ui/packages/consul-ui/app/abilities/peer.js | 2 +- .../consul-ui/app/abilities/permission.js | 2 +- ui/packages/consul-ui/app/abilities/policy.js | 2 +- ui/packages/consul-ui/app/abilities/role.js | 2 +- ui/packages/consul-ui/app/abilities/server.js | 2 +- .../app/abilities/service-instance.js | 2 +- .../consul-ui/app/abilities/session.js | 2 +- ui/packages/consul-ui/app/abilities/token.js | 2 +- .../consul-ui/app/abilities/upstream.js | 2 +- .../consul-ui/app/abilities/zervice.js | 2 +- ui/packages/consul-ui/app/abilities/zone.js | 2 +- .../consul-ui/app/adapters/application.js | 2 +- .../consul-ui/app/adapters/auth-method.js | 2 +- .../consul-ui/app/adapters/binding-rule.js | 2 +- .../consul-ui/app/adapters/coordinate.js | 2 +- .../consul-ui/app/adapters/discovery-chain.js | 2 +- ui/packages/consul-ui/app/adapters/http.js | 2 +- .../consul-ui/app/adapters/intention.js | 2 +- ui/packages/consul-ui/app/adapters/kv.js | 2 +- ui/packages/consul-ui/app/adapters/node.js | 2 +- ui/packages/consul-ui/app/adapters/nspace.js | 2 +- .../consul-ui/app/adapters/oidc-provider.js | 2 +- .../consul-ui/app/adapters/partition.js | 2 +- .../consul-ui/app/adapters/permission.js | 2 +- ui/packages/consul-ui/app/adapters/policy.js | 2 +- ui/packages/consul-ui/app/adapters/proxy.js | 2 +- ui/packages/consul-ui/app/adapters/role.js | 2 +- .../app/adapters/service-instance.js | 2 +- ui/packages/consul-ui/app/adapters/service.js | 2 +- ui/packages/consul-ui/app/adapters/session.js | 2 +- ui/packages/consul-ui/app/adapters/token.js | 2 +- .../consul-ui/app/adapters/topology.js | 2 +- ui/packages/consul-ui/app/app.js | 2 +- .../consul-ui/app/components/action/index.hbs | 2 +- .../app/components/anchors/index.scss | 2 +- .../app/components/anchors/skin.scss | 2 +- .../app/components/anonymous/index.hbs | 2 +- .../app/components/anonymous/index.js | 2 +- .../app/components/app-error/index.hbs | 2 +- .../app/components/app-view/index.hbs | 2 +- .../app/components/app-view/index.js | 2 +- .../app/components/app-view/index.scss | 2 +- .../app/components/app-view/layout.scss | 2 +- .../app/components/app-view/skin.scss | 2 +- .../consul-ui/app/components/app/index.hbs | 2 +- .../consul-ui/app/components/app/index.js | 2 +- .../consul-ui/app/components/app/index.scss | 2 +- .../app/components/app/notification/index.hbs | 2 +- .../app/components/aria-menu/index.hbs | 2 +- .../app/components/aria-menu/index.js | 2 +- .../components/auth-dialog/chart.xstate.js | 2 +- .../app/components/auth-dialog/index.hbs | 2 +- .../app/components/auth-dialog/index.js | 2 +- .../app/components/auth-form/chart.xstate.js | 2 +- .../app/components/auth-form/index.hbs | 2 +- .../app/components/auth-form/index.js | 2 +- .../app/components/auth-form/index.scss | 2 +- .../app/components/auth-form/layout.scss | 2 +- .../app/components/auth-form/pageobject.js | 2 +- .../app/components/auth-form/skin.scss | 2 +- .../app/components/auth-form/tabs.xstate.js | 2 +- .../app/components/auth-modal/index.scss | 2 +- .../app/components/auth-modal/layout.scss | 2 +- .../app/components/auth-modal/skin.scss | 2 +- .../app/components/auth-profile/index.hbs | 2 +- .../app/components/auth-profile/index.scss | 2 +- .../consul-ui/app/components/badge/debug.scss | 2 +- .../consul-ui/app/components/badge/index.scss | 2 +- .../app/components/brand-loader/index.scss | 2 +- .../app/components/brand-loader/layout.scss | 2 +- .../app/components/brand-loader/skin.scss | 2 +- .../app/components/breadcrumbs/index.scss | 2 +- .../app/components/breadcrumbs/layout.scss | 2 +- .../app/components/breadcrumbs/skin.scss | 2 +- .../app/components/buttons/index.scss | 2 +- .../app/components/buttons/layout.scss | 2 +- .../app/components/buttons/skin.scss | 2 +- .../consul-ui/app/components/card/index.scss | 2 +- .../consul-ui/app/components/card/layout.scss | 2 +- .../consul-ui/app/components/card/skin.scss | 2 +- .../app/components/checkbox-group/index.scss | 2 +- .../app/components/checkbox-group/layout.scss | 2 +- .../app/components/checkbox-group/skin.scss | 2 +- .../app/components/child-selector/index.hbs | 2 +- .../app/components/child-selector/index.js | 2 +- .../app/components/code-editor/index.hbs | 2 +- .../app/components/code-editor/index.js | 2 +- .../app/components/code-editor/index.scss | 2 +- .../app/components/code-editor/layout.scss | 2 +- .../app/components/code-editor/skin.scss | 2 +- .../app/components/composite-row/index.scss | 2 +- .../app/components/composite-row/layout.scss | 2 +- .../components/confirmation-alert/index.hbs | 2 +- .../components/confirmation-alert/index.js | 2 +- .../components/confirmation-dialog/index.hbs | 2 +- .../components/confirmation-dialog/index.js | 2 +- .../components/confirmation-dialog/index.scss | 2 +- .../confirmation-dialog/layout.scss | 2 +- .../components/confirmation-dialog/skin.scss | 2 +- .../components/consul/acl/disabled/index.hbs | 2 +- .../consul/auth-method/binding-list/index.hbs | 2 +- .../components/consul/auth-method/index.scss | 2 +- .../consul/auth-method/list/index.hbs | 2 +- .../consul/auth-method/list/pageobject.js | 2 +- .../consul/auth-method/nspace-list/index.hbs | 2 +- .../consul/auth-method/search-bar/index.hbs | 2 +- .../consul/auth-method/type/index.hbs | 2 +- .../consul/auth-method/view/index.hbs | 2 +- .../components/consul/bucket/list/index.hbs | 2 +- .../components/consul/bucket/list/index.js | 2 +- .../components/consul/bucket/list/index.scss | 2 +- .../consul/datacenter/selector/index.hbs | 2 +- .../consul/discovery-chain/index.hbs | 2 +- .../consul/discovery-chain/index.js | 2 +- .../consul/discovery-chain/index.scss | 2 +- .../consul/discovery-chain/layout.scss | 2 +- .../discovery-chain/resolver-card/index.hbs | 2 +- .../discovery-chain/route-card/index.hbs | 2 +- .../discovery-chain/route-card/index.js | 2 +- .../consul/discovery-chain/skin.scss | 2 +- .../discovery-chain/splitter-card/index.hbs | 2 +- .../consul/discovery-chain/utils.js | 2 +- .../consul/exposed-path/list/index.hbs | 2 +- .../consul/exposed-path/list/index.scss | 2 +- .../consul/external-source/index.hbs | 2 +- .../consul/external-source/index.scss | 2 +- .../consul/health-check/list/index.hbs | 2 +- .../consul/health-check/list/index.scss | 2 +- .../consul/health-check/list/layout.scss | 2 +- .../consul/health-check/list/pageobject.js | 2 +- .../consul/health-check/list/skin.scss | 2 +- .../consul/health-check/search-bar/index.hbs | 2 +- .../consul/instance-checks/index.hbs | 2 +- .../consul/instance-checks/index.scss | 2 +- .../consul/intention/components.scss | 2 +- .../consul/intention/form/fieldsets/index.hbs | 2 +- .../consul/intention/form/fieldsets/index.js | 2 +- .../intention/form/fieldsets/index.scss | 2 +- .../intention/form/fieldsets/layout.scss | 2 +- .../consul/intention/form/fieldsets/skin.scss | 2 +- .../consul/intention/form/index.hbs | 2 +- .../components/consul/intention/form/index.js | 2 +- .../consul/intention/form/index.scss | 2 +- .../components/consul/intention/index.scss | 2 +- .../consul/intention/list/check/index.hbs | 2 +- .../consul/intention/list/components.scss | 2 +- .../consul/intention/list/index.hbs | 2 +- .../components/consul/intention/list/index.js | 2 +- .../consul/intention/list/index.scss | 2 +- .../consul/intention/list/layout.scss | 2 +- .../consul/intention/list/pageobject.js | 2 +- .../consul/intention/list/skin.scss | 2 +- .../consul/intention/list/table/index.hbs | 2 +- .../consul/intention/list/table/index.scss | 2 +- .../notice/custom-resource/index.hbs | 2 +- .../intention/notice/permissions/index.hbs | 2 +- .../consul/intention/notifications/index.hbs | 2 +- .../intention/permission/form/index.hbs | 2 +- .../consul/intention/permission/form/index.js | 2 +- .../intention/permission/form/index.scss | 2 +- .../intention/permission/form/layout.scss | 2 +- .../intention/permission/form/pageobject.js | 2 +- .../intention/permission/form/skin.scss | 2 +- .../permission/header/form/index.hbs | 2 +- .../intention/permission/header/form/index.js | 2 +- .../permission/header/form/pageobject.js | 2 +- .../permission/header/list/index.hbs | 2 +- .../intention/permission/header/list/index.js | 2 +- .../permission/header/list/index.scss | 2 +- .../permission/header/list/layout.scss | 2 +- .../permission/header/list/pageobject.js | 2 +- .../permission/header/list/skin.scss | 2 +- .../intention/permission/list/index.hbs | 2 +- .../consul/intention/permission/list/index.js | 2 +- .../intention/permission/list/index.scss | 2 +- .../intention/permission/list/layout.scss | 2 +- .../intention/permission/list/pageobject.js | 2 +- .../intention/permission/list/skin.scss | 2 +- .../consul/intention/search-bar/index.hbs | 2 +- .../consul/intention/search-bar/index.scss | 2 +- .../consul/intention/view/index.hbs | 2 +- .../components/consul/intention/view/index.js | 2 +- .../app/components/consul/kind/index.hbs | 2 +- .../app/components/consul/kind/index.js | 2 +- .../app/components/consul/kind/index.scss | 2 +- .../app/components/consul/kv/form/index.hbs | 2 +- .../app/components/consul/kv/form/index.js | 2 +- .../app/components/consul/kv/list/index.hbs | 2 +- .../components/consul/kv/list/pageobject.js | 2 +- .../components/consul/kv/search-bar/index.hbs | 2 +- .../app/components/consul/loader/index.hbs | 2 +- .../app/components/consul/loader/index.scss | 2 +- .../app/components/consul/loader/layout.scss | 2 +- .../app/components/consul/loader/skin.scss | 2 +- .../components/consul/metadata/list/index.hbs | 2 +- .../components/consul/metadata/list/index.js | 2 +- .../consul/node-identity/template/index.hbs | 2 +- .../consul/node/agentless-notice/index.hbs | 2 +- .../consul/node/agentless-notice/index.js | 2 +- .../consul/node/agentless-notice/index.scss | 2 +- .../app/components/consul/node/list/index.hbs | 2 +- .../consul/node/peer-info/index.hbs | 2 +- .../consul/node/peer-info/index.scss | 2 +- .../consul/node/search-bar/index.hbs | 260 +- .../app/components/consul/peer/info/index.hbs | 2 +- .../components/consul/peer/info/index.scss | 2 +- .../components/consul/peer/list/index.scss | 2 +- .../components/consul/policy/list/index.hbs | 2 +- .../consul/policy/list/pageobject.js | 2 +- .../consul/policy/notifications/index.hbs | 2 +- .../consul/policy/search-bar/index.hbs | 2 +- .../consul/policy/search-bar/index.js | 2 +- .../app/components/consul/role/list/index.hbs | 2 +- .../components/consul/role/list/pageobject.js | 2 +- .../consul/role/notifications/index.hbs | 2 +- .../consul/role/search-bar/index.hbs | 2 +- .../components/consul/server/card/index.hbs | 2 +- .../components/consul/server/card/index.scss | 2 +- .../components/consul/server/card/layout.scss | 2 +- .../components/consul/server/card/skin.scss | 2 +- .../components/consul/server/list/index.hbs | 2 +- .../components/consul/server/list/index.scss | 2 +- .../service-identity/template/index.hbs | 2 +- .../consul/service-instance/list/index.hbs | 2 +- .../consul/service-instance/list/index.js | 2 +- .../service-instance/search-bar/index.hbs | 2 +- .../components/consul/service/list/index.hbs | 2 +- .../consul/service/search-bar/index.hbs | 2 +- .../consul/service/search-bar/index.js | 2 +- .../app/components/consul/source/index.hbs | 2 +- .../app/components/consul/source/index.scss | 2 +- .../consul/sources-select/index.hbs | 2 +- .../components/consul/token/list/index.hbs | 2 +- .../consul/token/list/pageobject.js | 2 +- .../consul/token/notifications/index.hbs | 2 +- .../consul/token/ruleset/list/index.hbs | 2 +- .../consul/token/ruleset/list/index.js | 2 +- .../consul/token/search-bar/index.hbs | 2 +- .../consul/tomography/graph/index.hbs | 2 +- .../consul/tomography/graph/index.js | 2 +- .../consul/tomography/graph/index.scss | 2 +- .../consul/transparent-proxy/index.hbs | 2 +- .../consul/upstream-instance/list/index.hbs | 2 +- .../consul/upstream-instance/list/index.scss | 2 +- .../upstream-instance/list/pageobject.js | 2 +- .../upstream-instance/search-bar/index.hbs | 2 +- .../components/consul/upstream/list/index.hbs | 2 +- .../consul/upstream/list/index.scss | 2 +- .../consul/upstream/search-bar/index.hbs | 2 +- .../components/copy-button/chart.xstate.js | 2 +- .../app/components/copy-button/index.hbs | 2 +- .../app/components/copy-button/index.js | 2 +- .../app/components/copy-button/index.scss | 2 +- .../app/components/copy-button/layout.scss | 2 +- .../app/components/copy-button/skin.scss | 2 +- .../app/components/copyable-code/index.hbs | 2 +- .../app/components/copyable-code/index.scss | 2 +- .../app/components/csv-list/debug.scss | 2 +- .../app/components/csv-list/index.scss | 2 +- .../app/components/data-collection/index.hbs | 2 +- .../app/components/data-collection/index.js | 2 +- .../app/components/data-form/index.hbs | 2 +- .../app/components/data-form/index.js | 2 +- .../components/data-loader/chart.xstate.js | 2 +- .../app/components/data-loader/index.hbs | 2 +- .../app/components/data-loader/index.js | 2 +- .../app/components/data-sink/index.hbs | 2 +- .../app/components/data-sink/index.js | 2 +- .../app/components/data-source/index.hbs | 2 +- .../app/components/data-source/index.js | 2 +- .../components/data-writer/chart.xstate.js | 2 +- .../app/components/data-writer/index.hbs | 2 +- .../app/components/data-writer/index.js | 2 +- .../app/components/debug/navigation/index.hbs | 2 +- .../components/definition-table/debug.scss | 2 +- .../components/definition-table/index.scss | 2 +- .../components/definition-table/layout.scss | 2 +- .../app/components/definition-table/skin.scss | 2 +- .../components/delete-confirmation/index.hbs | 2 +- .../components/delete-confirmation/index.js | 2 +- .../disclosure-menu/action/index.hbs | 2 +- .../app/components/disclosure-menu/index.hbs | 2 +- .../app/components/disclosure-menu/index.scss | 2 +- .../components/disclosure-menu/menu/index.hbs | 2 +- .../components/disclosure/action/index.hbs | 2 +- .../components/disclosure/details/index.hbs | 2 +- .../app/components/disclosure/index.hbs | 2 +- .../app/components/disclosure/index.js | 2 +- .../app/components/display-toggle/index.scss | 2 +- .../app/components/display-toggle/layout.scss | 2 +- .../app/components/display-toggle/skin.scss | 2 +- .../components/dom-recycling-table/index.scss | 2 +- .../dom-recycling-table/layout.scss | 2 +- .../app/components/empty-state/index.hbs | 2 +- .../app/components/empty-state/index.js | 2 +- .../app/components/empty-state/index.scss | 2 +- .../app/components/empty-state/layout.scss | 2 +- .../app/components/empty-state/pageobject.js | 2 +- .../app/components/empty-state/skin.scss | 2 +- .../app/components/error-state/index.hbs | 2 +- .../app/components/event-source/index.hbs | 2 +- .../app/components/event-source/index.js | 2 +- .../expanded-single-select/index.scss | 2 +- .../expanded-single-select/layout.scss | 2 +- .../expanded-single-select/skin.scss | 2 +- .../app/components/filter-bar/index.scss | 2 +- .../app/components/filter-bar/layout.scss | 2 +- .../app/components/filter-bar/skin.scss | 2 +- .../app/components/form-component/index.hbs | 2 +- .../app/components/form-component/index.js | 2 +- .../app/components/form-elements/index.scss | 2 +- .../app/components/form-elements/layout.scss | 2 +- .../app/components/form-elements/skin.scss | 2 +- .../form-group/element/checkbox/index.hbs | 2 +- .../form-group/element/error/index.hbs | 2 +- .../components/form-group/element/index.hbs | 2 +- .../components/form-group/element/index.js | 2 +- .../form-group/element/label/index.hbs | 2 +- .../form-group/element/radio/index.hbs | 2 +- .../form-group/element/text/index.hbs | 2 +- .../app/components/form-group/index.hbs | 2 +- .../app/components/form-group/index.js | 2 +- .../app/components/form-input/index.hbs | 2 +- .../app/components/freetext-filter/index.hbs | 2 +- .../app/components/freetext-filter/index.js | 2 +- .../app/components/freetext-filter/index.scss | 2 +- .../components/freetext-filter/layout.scss | 2 +- .../components/freetext-filter/pageobject.js | 2 +- .../app/components/freetext-filter/skin.scss | 2 +- .../app/components/hashicorp-consul/index.hbs | 2 +- .../app/components/hashicorp-consul/index.js | 2 +- .../components/hashicorp-consul/index.scss | 2 +- .../components/horizontal-kv-list/debug.scss | 2 +- .../components/horizontal-kv-list/index.scss | 2 +- .../components/horizontal-kv-list/layout.scss | 2 +- .../components/horizontal-kv-list/skin.scss | 2 +- .../app/components/icon-definition/debug.scss | 2 +- .../app/components/icon-definition/index.scss | 2 +- .../app/components/informed-action/index.hbs | 2 +- .../app/components/informed-action/index.scss | 2 +- .../components/informed-action/layout.scss | 2 +- .../app/components/informed-action/skin.scss | 2 +- .../app/components/inline-alert/debug.scss | 2 +- .../app/components/inline-alert/index.scss | 2 +- .../app/components/inline-alert/layout.scss | 2 +- .../app/components/inline-alert/skin.scss | 2 +- .../app/components/inline-code/index.scss | 2 +- .../app/components/inline-code/layout.scss | 2 +- .../app/components/inline-code/skin.scss | 2 +- .../app/components/jwt-source/index.js | 2 +- .../app/components/list-collection/index.hbs | 2 +- .../app/components/list-collection/index.js | 2 +- .../app/components/list-collection/index.scss | 2 +- .../components/list-collection/layout.scss | 2 +- .../app/components/list-collection/skin.scss | 2 +- .../app/components/list-row/index.scss | 2 +- .../app/components/list-row/layout.scss | 2 +- .../app/components/list-row/skin.scss | 2 +- .../main-header-horizontal/index.scss | 2 +- .../main-header-horizontal/layout.scss | 2 +- .../main-header-horizontal/skin.scss | 2 +- .../components/main-nav-horizontal/index.scss | 2 +- .../main-nav-horizontal/layout.scss | 2 +- .../components/main-nav-horizontal/skin.scss | 2 +- .../components/main-nav-vertical/debug.scss | 2 +- .../components/main-nav-vertical/index.scss | 2 +- .../components/main-nav-vertical/layout.scss | 2 +- .../components/main-nav-vertical/skin.scss | 2 +- .../app/components/menu-panel/deprecated.scss | 2 +- .../app/components/menu-panel/index.hbs | 2 +- .../app/components/menu-panel/index.js | 2 +- .../app/components/menu-panel/index.scss | 2 +- .../app/components/menu-panel/layout.scss | 2 +- .../app/components/menu-panel/skin.scss | 2 +- .../app/components/menu/action/index.hbs | 2 +- .../consul-ui/app/components/menu/index.hbs | 2 +- .../app/components/menu/item/index.hbs | 2 +- .../app/components/menu/separator/index.hbs | 2 +- .../app/components/modal-dialog/index.hbs | 2 +- .../app/components/modal-dialog/index.js | 2 +- .../app/components/modal-dialog/index.scss | 2 +- .../app/components/modal-dialog/layout.scss | 2 +- .../app/components/modal-dialog/skin.scss | 2 +- .../app/components/modal-layer/index.hbs | 2 +- .../components/more-popover-menu/index.hbs | 2 +- .../app/components/more-popover-menu/index.js | 2 +- .../components/more-popover-menu/index.scss | 2 +- .../more-popover-menu/pageobject.js | 2 +- .../components/oidc-select/chart.xstate.js | 2 +- .../app/components/oidc-select/index.hbs | 2 +- .../app/components/oidc-select/index.js | 2 +- .../app/components/oidc-select/index.scss | 2 +- .../app/components/oidc-select/layout.scss | 2 +- .../app/components/oidc-select/skin.scss | 2 +- .../app/components/option-input/index.hbs | 2 +- .../consul-ui/app/components/outlet/index.hbs | 2 +- .../consul-ui/app/components/outlet/index.js | 2 +- .../app/components/overlay/index.scss | 2 +- .../app/components/overlay/none.scss | 2 +- .../app/components/overlay/square-tail.scss | 2 +- .../app/components/paged-collection/index.hbs | 2 +- .../app/components/paged-collection/index.js | 2 +- .../components/paged-collection/index.scss | 2 +- .../consul-ui/app/components/panel/debug.scss | 2 +- .../app/components/panel/index.css.js | 2 +- .../consul-ui/app/components/panel/index.scss | 2 +- .../app/components/panel/layout.scss | 2 +- .../consul-ui/app/components/panel/skin.scss | 2 +- .../components/peerings/badge/icon/index.hbs | 2 +- .../app/components/peerings/badge/index.hbs | 2 +- .../app/components/peerings/badge/index.js | 2 +- .../app/components/peerings/badge/index.scss | 2 +- .../components/peerings/provider/index.hbs | 2 +- .../app/components/peerings/provider/index.js | 2 +- .../consul-ui/app/components/pill/index.scss | 2 +- .../consul-ui/app/components/pill/layout.scss | 2 +- .../consul-ui/app/components/pill/skin.scss | 2 +- .../app/components/policy-form/index.hbs | 2 +- .../app/components/policy-form/index.js | 2 +- .../app/components/policy-form/pageobject.js | 2 +- .../app/components/policy-selector/index.hbs | 2 +- .../app/components/policy-selector/index.js | 2 +- .../components/policy-selector/pageobject.js | 2 +- .../app/components/popover-menu/index.hbs | 2 +- .../app/components/popover-menu/index.js | 2 +- .../app/components/popover-menu/index.scss | 2 +- .../app/components/popover-menu/layout.scss | 2 +- .../popover-menu/menu-item/index.hbs | 2 +- .../popover-menu/menu-item/index.js | 2 +- .../popover-menu/menu-separator/index.hbs | 2 +- .../popover-menu/menu-separator/index.js | 2 +- .../app/components/popover-menu/skin.scss | 2 +- .../app/components/popover-select/index.hbs | 2 +- .../app/components/popover-select/index.js | 2 +- .../app/components/popover-select/index.scss | 2 +- .../popover-select/optgroup/index.hbs | 2 +- .../popover-select/option/index.hbs | 2 +- .../components/popover-select/option/index.js | 2 +- .../components/popover-select/pageobject.js | 2 +- .../app/components/power-select/pageobject.js | 2 +- .../app/components/progress/index.hbs | 2 +- .../app/components/progress/index.scss | 2 +- .../app/components/progress/layout.scss | 2 +- .../app/components/progress/skin.scss | 2 +- .../components/providers/dimension/index.hbs | 2 +- .../components/providers/dimension/index.js | 2 +- .../app/components/providers/search/index.hbs | 2 +- .../app/components/providers/search/index.js | 2 +- .../app/components/radio-card/index.hbs | 2 +- .../app/components/radio-card/index.js | 2 +- .../app/components/radio-card/index.scss | 2 +- .../app/components/radio-card/layout.scss | 2 +- .../app/components/radio-card/skin.scss | 2 +- .../app/components/radio-group/index.hbs | 2 +- .../app/components/radio-group/index.js | 2 +- .../app/components/radio-group/index.scss | 2 +- .../app/components/radio-group/layout.scss | 2 +- .../app/components/radio-group/pageobject.js | 2 +- .../app/components/radio-group/skin.scss | 2 +- .../consul-ui/app/components/ref/index.js | 2 +- .../app/components/role-form/index.hbs | 2 +- .../app/components/role-form/index.js | 2 +- .../app/components/role-form/pageobject.js | 2 +- .../app/components/role-selector/index.hbs | 2 +- .../app/components/role-selector/index.js | 2 +- .../app/components/role-selector/index.scss | 2 +- .../components/role-selector/pageobject.js | 2 +- .../app/components/route/announcer/index.hbs | 2 +- .../consul-ui/app/components/route/index.hbs | 2 +- .../consul-ui/app/components/route/index.js | 2 +- .../app/components/route/title/index.hbs | 2 +- .../app/components/route/title/index.scss | 2 +- .../app/components/search-bar/index.hbs | 2 +- .../app/components/search-bar/index.js | 2 +- .../app/components/search-bar/index.scss | 2 +- .../search-bar/remove-filter/index.hbs | 2 +- .../app/components/search-bar/utils.js | 2 +- .../app/components/skip-links/index.scss | 2 +- .../app/components/skip-links/layout.scss | 2 +- .../app/components/skip-links/skin.scss | 2 +- .../app/components/sliding-toggle/index.scss | 2 +- .../app/components/sliding-toggle/layout.scss | 2 +- .../app/components/sliding-toggle/skin.scss | 2 +- .../components/state-chart/action/index.hbs | 2 +- .../components/state-chart/action/index.js | 2 +- .../components/state-chart/guard/index.hbs | 2 +- .../app/components/state-chart/guard/index.js | 2 +- .../app/components/state-chart/index.hbs | 2 +- .../app/components/state-chart/index.js | 2 +- .../app/components/state-machine/index.hbs | 2 +- .../app/components/state-machine/index.js | 2 +- .../consul-ui/app/components/state/index.hbs | 2 +- .../consul-ui/app/components/state/index.js | 2 +- .../app/components/tab-nav/index.hbs | 2 +- .../consul-ui/app/components/tab-nav/index.js | 2 +- .../app/components/tab-nav/index.scss | 2 +- .../app/components/tab-nav/layout.scss | 2 +- .../app/components/tab-nav/pageobject.js | 2 +- .../app/components/tab-nav/skin.scss | 2 +- .../consul-ui/app/components/table/index.scss | 2 +- .../app/components/table/layout.scss | 2 +- .../consul-ui/app/components/table/skin.scss | 2 +- .../components/tabular-collection/index.hbs | 2 +- .../components/tabular-collection/index.js | 2 +- .../components/tabular-collection/index.scss | 2 +- .../app/components/tabular-details/index.hbs | 2 +- .../app/components/tabular-details/index.js | 2 +- .../app/components/tabular-details/index.scss | 2 +- .../components/tabular-details/layout.scss | 2 +- .../app/components/tabular-details/skin.scss | 2 +- .../app/components/tabular-dl/index.scss | 2 +- .../app/components/tabular-dl/layout.scss | 2 +- .../app/components/tabular-dl/skin.scss | 2 +- .../app/components/tag-list/index.hbs | 2 +- .../app/components/tag-list/index.scss | 2 +- .../app/components/text-input/index.hbs | 2 +- .../consul-ui/app/components/tile/debug.scss | 2 +- .../consul-ui/app/components/tile/index.scss | 2 +- .../app/components/toggle-button/index.hbs | 2 +- .../app/components/toggle-button/index.js | 2 +- .../app/components/toggle-button/index.scss | 2 +- .../app/components/toggle-button/layout.scss | 2 +- .../app/components/toggle-button/skin.scss | 2 +- .../app/components/token-list/index.hbs | 2 +- .../app/components/token-list/index.js | 2 +- .../app/components/token-list/pageobject.js | 2 +- .../components/token-source/chart.xstate.js | 2 +- .../app/components/token-source/index.hbs | 2 +- .../app/components/token-source/index.js | 2 +- .../app/components/tooltip-panel/index.scss | 2 +- .../app/components/tooltip-panel/layout.scss | 2 +- .../app/components/tooltip-panel/skin.scss | 2 +- .../app/components/tooltip/index.hbs | 2 +- .../app/components/tooltip/index.scss | 2 +- .../topology-metrics/card/index.hbs | 2 +- .../components/topology-metrics/card/index.js | 2 +- .../topology-metrics/card/index.scss | 2 +- .../topology-metrics/down-lines/index.hbs | 2 +- .../topology-metrics/down-lines/index.js | 2 +- .../app/components/topology-metrics/index.hbs | 2 +- .../app/components/topology-metrics/index.js | 2 +- .../components/topology-metrics/index.scss | 2 +- .../components/topology-metrics/layout.scss | 2 +- .../topology-metrics/notifications/index.hbs | 2 +- .../topology-metrics/popover/index.hbs | 2 +- .../topology-metrics/popover/index.js | 2 +- .../topology-metrics/popover/index.scss | 2 +- .../topology-metrics/series/index.hbs | 2 +- .../topology-metrics/series/index.js | 2 +- .../topology-metrics/series/index.scss | 2 +- .../topology-metrics/series/layout.scss | 2 +- .../topology-metrics/series/skin.scss | 2 +- .../app/components/topology-metrics/skin.scss | 2 +- .../topology-metrics/source-type/index.hbs | 2 +- .../topology-metrics/source-type/index.scss | 2 +- .../topology-metrics/stats/index.hbs | 2 +- .../topology-metrics/stats/index.js | 2 +- .../topology-metrics/stats/index.scss | 2 +- .../topology-metrics/status/index.hbs | 2 +- .../topology-metrics/status/index.scss | 2 +- .../topology-metrics/up-lines/index.hbs | 2 +- .../topology-metrics/up-lines/index.js | 2 +- .../app/components/watcher/index.hbs | 2 +- .../consul-ui/app/components/watcher/index.js | 2 +- .../consul-ui/app/components/yield/index.hbs | 2 +- .../app/controllers/_peered-resource.js | 2 +- .../consul-ui/app/controllers/application.js | 2 +- .../controllers/dc/acls/policies/create.js | 2 +- .../app/controllers/dc/acls/policies/edit.js | 2 +- .../app/controllers/dc/acls/roles/create.js | 2 +- .../app/controllers/dc/acls/roles/edit.js | 2 +- .../app/controllers/dc/acls/tokens/create.js | 2 +- .../app/controllers/dc/acls/tokens/edit.js | 2 +- .../app/controllers/dc/nodes/index.js | 2 +- .../app/controllers/dc/services/index.js | 2 +- .../dc/services/instance/healthchecks.js | 2 +- .../consul-ui/app/decorators/data-source.js | 2 +- .../consul-ui/app/decorators/replace.js | 2 +- ui/packages/consul-ui/app/env.js | 2 +- .../app/filter/predicates/auth-method.js | 2 +- .../app/filter/predicates/health-check.js | 2 +- .../app/filter/predicates/intention.js | 2 +- .../consul-ui/app/filter/predicates/kv.js | 2 +- .../consul-ui/app/filter/predicates/node.js | 11 +- .../consul-ui/app/filter/predicates/peer.js | 2 +- .../consul-ui/app/filter/predicates/policy.js | 2 +- .../app/filter/predicates/service-instance.js | 2 +- .../app/filter/predicates/service.js | 2 +- .../consul-ui/app/filter/predicates/token.js | 2 +- ui/packages/consul-ui/app/formats.js | 2 +- ui/packages/consul-ui/app/forms/intention.js | 2 +- ui/packages/consul-ui/app/forms/kv.js | 2 +- ui/packages/consul-ui/app/forms/policy.js | 2 +- ui/packages/consul-ui/app/forms/role.js | 2 +- ui/packages/consul-ui/app/forms/token.js | 2 +- .../consul-ui/app/helpers/adopt-styles.js | 2 +- ui/packages/consul-ui/app/helpers/atob.js | 2 +- .../consul-ui/app/helpers/cached-model.js | 2 +- .../consul-ui/app/helpers/class-map.js | 2 +- .../consul-ui/app/helpers/collection.js | 2 +- ui/packages/consul-ui/app/helpers/css-map.js | 2 +- ui/packages/consul-ui/app/helpers/css.js | 2 +- .../consul-ui/app/helpers/document-attrs.js | 2 +- .../consul-ui/app/helpers/dom-position.js | 2 +- .../consul-ui/app/helpers/duration-from.js | 2 +- ui/packages/consul-ui/app/helpers/env.js | 2 +- .../consul-ui/app/helpers/flatten-property.js | 2 +- .../app/helpers/format-short-time.js | 2 +- ui/packages/consul-ui/app/helpers/href-to.js | 2 +- .../consul-ui/app/helpers/icon-mapping.js | 2 +- .../consul-ui/app/helpers/icons-debug.js | 2 +- ui/packages/consul-ui/app/helpers/is-href.js | 2 +- ui/packages/consul-ui/app/helpers/is.js | 2 +- .../consul-ui/app/helpers/json-stringify.js | 2 +- ui/packages/consul-ui/app/helpers/last.js | 2 +- .../consul-ui/app/helpers/left-trim.js | 2 +- .../consul-ui/app/helpers/merge-checks.js | 2 +- .../consul-ui/app/helpers/percentage-of.js | 2 +- .../app/helpers/policy/datacenters.js | 2 +- .../consul-ui/app/helpers/policy/group.js | 2 +- .../consul-ui/app/helpers/policy/typeof.js | 2 +- .../consul-ui/app/helpers/refresh-route.js | 2 +- .../consul-ui/app/helpers/render-template.js | 2 +- ui/packages/consul-ui/app/helpers/require.js | 2 +- .../consul-ui/app/helpers/right-trim.js | 2 +- .../consul-ui/app/helpers/route-match.js | 2 +- .../app/helpers/service/card-permissions.js | 2 +- .../app/helpers/service/external-source.js | 2 +- .../app/helpers/service/health-percentage.js | 2 +- ui/packages/consul-ui/app/helpers/slugify.js | 2 +- .../app/helpers/smart-date-format.js | 2 +- ui/packages/consul-ui/app/helpers/split.js | 2 +- .../consul-ui/app/helpers/state-chart.js | 2 +- .../consul-ui/app/helpers/state-matches.js | 2 +- .../consul-ui/app/helpers/style-map.js | 2 +- ui/packages/consul-ui/app/helpers/substr.js | 2 +- .../consul-ui/app/helpers/svg-curve.js | 2 +- .../consul-ui/app/helpers/temporal-format.js | 2 +- .../consul-ui/app/helpers/temporal-within.js | 2 +- ui/packages/consul-ui/app/helpers/test.js | 2 +- ui/packages/consul-ui/app/helpers/to-hash.js | 2 +- ui/packages/consul-ui/app/helpers/to-route.js | 2 +- .../app/helpers/token/is-anonymous.js | 2 +- .../consul-ui/app/helpers/token/is-legacy.js | 2 +- ui/packages/consul-ui/app/helpers/tween-to.js | 2 +- ui/packages/consul-ui/app/helpers/uniq-by.js | 2 +- .../consul-ui/app/helpers/unique-id.js | 2 +- ui/packages/consul-ui/app/helpers/uri.js | 2 +- ui/packages/consul-ui/app/index.html | 2 +- .../app/instance-initializers/container.js | 2 +- .../app/instance-initializers/href-to.js | 2 +- .../instance-initializers/ivy-codemirror.js | 2 +- .../app/instance-initializers/selection.js | 2 +- .../app/locations/fsm-with-optional-test.js | 2 +- .../app/locations/fsm-with-optional.js | 2 +- ui/packages/consul-ui/app/locations/fsm.js | 2 +- .../consul-ui/app/machines/boolean.xstate.js | 2 +- .../consul-ui/app/machines/validate.xstate.js | 2 +- .../consul-ui/app/mixins/policy/as-many.js | 2 +- .../consul-ui/app/mixins/role/as-many.js | 2 +- .../app/mixins/with-blocking-actions.js | 2 +- .../consul-ui/app/models/auth-method.js | 2 +- .../consul-ui/app/models/binding-rule.js | 2 +- .../consul-ui/app/models/coordinate.js | 2 +- ui/packages/consul-ui/app/models/dc.js | 2 +- .../consul-ui/app/models/discovery-chain.js | 2 +- .../consul-ui/app/models/gateway-config.js | 2 +- .../consul-ui/app/models/health-check.js | 2 +- .../intention-permission-http-header.js | 2 +- .../app/models/intention-permission-http.js | 2 +- .../app/models/intention-permission.js | 2 +- ui/packages/consul-ui/app/models/intention.js | 2 +- ui/packages/consul-ui/app/models/kv.js | 2 +- ui/packages/consul-ui/app/models/license.js | 2 +- ui/packages/consul-ui/app/models/node.js | 2 +- ui/packages/consul-ui/app/models/nspace.js | 2 +- .../consul-ui/app/models/oidc-provider.js | 2 +- ui/packages/consul-ui/app/models/partition.js | 2 +- ui/packages/consul-ui/app/models/peer.js | 2 +- .../consul-ui/app/models/permission.js | 2 +- ui/packages/consul-ui/app/models/policy.js | 2 +- ui/packages/consul-ui/app/models/proxy.js | 2 +- ui/packages/consul-ui/app/models/role.js | 2 +- .../consul-ui/app/models/service-instance.js | 2 +- ui/packages/consul-ui/app/models/service.js | 2 +- ui/packages/consul-ui/app/models/session.js | 2 +- ui/packages/consul-ui/app/models/token.js | 2 +- ui/packages/consul-ui/app/models/topology.js | 2 +- .../consul-ui/app/modifiers/aria-menu.js | 2 +- .../consul-ui/app/modifiers/css-prop.js | 2 +- .../consul-ui/app/modifiers/css-props.js | 2 +- .../consul-ui/app/modifiers/did-upsert.js | 2 +- .../consul-ui/app/modifiers/disabled.js | 2 +- .../consul-ui/app/modifiers/notification.js | 2 +- .../consul-ui/app/modifiers/on-outside.js | 2 +- ui/packages/consul-ui/app/modifiers/style.js | 2 +- .../consul-ui/app/modifiers/tooltip.js | 2 +- .../consul-ui/app/modifiers/validate.js | 2 +- .../consul-ui/app/modifiers/with-copyable.js | 2 +- .../consul-ui/app/modifiers/with-overlay.js | 2 +- ui/packages/consul-ui/app/router.js | 2 +- .../consul-ui/app/routes/application.js | 2 +- ui/packages/consul-ui/app/routes/dc.js | 2 +- .../app/routes/dc/acls/auth-methods/index.js | 2 +- .../routes/dc/acls/auth-methods/show/index.js | 2 +- .../app/routes/dc/acls/policies/create.js | 2 +- .../app/routes/dc/acls/policies/edit.js | 2 +- .../app/routes/dc/acls/policies/index.js | 2 +- .../app/routes/dc/acls/roles/create.js | 2 +- .../app/routes/dc/acls/roles/edit.js | 2 +- .../app/routes/dc/acls/roles/index.js | 2 +- .../app/routes/dc/acls/tokens/create.js | 2 +- .../app/routes/dc/acls/tokens/edit.js | 2 +- .../app/routes/dc/acls/tokens/index.js | 2 +- .../consul-ui/app/routes/dc/kv/folder.js | 2 +- .../consul-ui/app/routes/dc/kv/index.js | 2 +- .../app/routes/dc/services/notfound.js | 2 +- .../app/routes/dc/services/show/topology.js | 2 +- .../app/routing/application-debug.js | 2 +- ui/packages/consul-ui/app/routing/route.js | 2 +- ui/packages/consul-ui/app/routing/single.js | 2 +- .../consul-ui/app/search/predicates/acl.js | 2 +- .../app/search/predicates/auth-method.js | 2 +- .../app/search/predicates/health-check.js | 2 +- .../app/search/predicates/intention.js | 2 +- .../consul-ui/app/search/predicates/kv.js | 2 +- .../consul-ui/app/search/predicates/node.js | 2 +- .../consul-ui/app/search/predicates/nspace.js | 2 +- .../consul-ui/app/search/predicates/peer.js | 2 +- .../consul-ui/app/search/predicates/policy.js | 2 +- .../consul-ui/app/search/predicates/role.js | 2 +- .../app/search/predicates/service-instance.js | 2 +- .../app/search/predicates/service.js | 2 +- .../consul-ui/app/search/predicates/token.js | 2 +- .../search/predicates/upstream-instance.js | 2 +- .../consul-ui/app/serializers/application.js | 2 +- .../consul-ui/app/serializers/auth-method.js | 2 +- .../consul-ui/app/serializers/binding-rule.js | 2 +- .../consul-ui/app/serializers/coordinate.js | 2 +- .../app/serializers/discovery-chain.js | 2 +- ui/packages/consul-ui/app/serializers/http.js | 2 +- .../consul-ui/app/serializers/intention.js | 2 +- ui/packages/consul-ui/app/serializers/kv.js | 2 +- ui/packages/consul-ui/app/serializers/node.js | 2 +- .../consul-ui/app/serializers/nspace.js | 2 +- .../app/serializers/oidc-provider.js | 2 +- .../consul-ui/app/serializers/partition.js | 2 +- .../consul-ui/app/serializers/permission.js | 2 +- .../consul-ui/app/serializers/policy.js | 2 +- .../consul-ui/app/serializers/proxy.js | 2 +- ui/packages/consul-ui/app/serializers/role.js | 2 +- .../app/serializers/service-instance.js | 2 +- .../consul-ui/app/serializers/service.js | 2 +- .../consul-ui/app/serializers/session.js | 2 +- .../consul-ui/app/serializers/token.js | 2 +- .../consul-ui/app/serializers/topology.js | 2 +- .../consul-ui/app/services/abilities.js | 2 +- ui/packages/consul-ui/app/services/atob.js | 2 +- .../oauth2-code-with-url-provider.js | 2 +- ui/packages/consul-ui/app/services/btoa.js | 2 +- ui/packages/consul-ui/app/services/change.js | 2 +- .../app/services/client/connections.js | 2 +- .../consul-ui/app/services/client/http.js | 2 +- .../app/services/client/transports/xhr.js | 2 +- .../app/services/clipboard/local-storage.js | 2 +- .../consul-ui/app/services/clipboard/os.js | 2 +- .../app/services/code-mirror/linter.js | 2 +- .../consul-ui/app/services/container.js | 2 +- .../app/services/data-sink/protocols/http.js | 2 +- .../data-sink/protocols/local-storage.js | 2 +- .../app/services/data-sink/service.js | 2 +- .../services/data-source/protocols/http.js | 2 +- .../data-source/protocols/http/blocking.js | 2 +- .../data-source/protocols/http/promise.js | 2 +- .../data-source/protocols/local-storage.js | 2 +- .../app/services/data-source/service.js | 2 +- .../consul-ui/app/services/data-structs.js | 2 +- ui/packages/consul-ui/app/services/dom.js | 2 +- ui/packages/consul-ui/app/services/encoder.js | 2 +- ui/packages/consul-ui/app/services/env.js | 2 +- .../consul-ui/app/services/feedback.js | 2 +- ui/packages/consul-ui/app/services/filter.js | 2 +- ui/packages/consul-ui/app/services/form.js | 2 +- ui/packages/consul-ui/app/services/hcp.js | 2 +- .../consul-ui/app/services/i18n-debug.js | 2 +- .../consul-ui/app/services/local-storage.js | 2 +- ui/packages/consul-ui/app/services/logger.js | 2 +- .../consul-ui/app/services/repository.js | 2 +- .../app/services/repository/auth-method.js | 2 +- .../app/services/repository/binding-rule.js | 2 +- .../app/services/repository/coordinate.js | 2 +- .../consul-ui/app/services/repository/dc.js | 2 +- .../services/repository/discovery-chain.js | 2 +- .../intention-permission-http-header.js | 2 +- .../repository/intention-permission.js | 2 +- .../app/services/repository/intention.js | 2 +- .../consul-ui/app/services/repository/kv.js | 2 +- .../app/services/repository/license.js | 2 +- .../app/services/repository/metrics.js | 2 +- .../consul-ui/app/services/repository/node.js | 2 +- .../app/services/repository/nspace.js | 2 +- .../app/services/repository/oidc-provider.js | 2 +- .../app/services/repository/partition.js | 2 +- .../consul-ui/app/services/repository/peer.js | 2 +- .../app/services/repository/permission.js | 2 +- .../app/services/repository/policy.js | 2 +- .../app/services/repository/proxy.js | 2 +- .../consul-ui/app/services/repository/role.js | 2 +- .../services/repository/service-instance.js | 2 +- .../app/services/repository/service.js | 2 +- .../app/services/repository/session.js | 2 +- .../app/services/repository/token.js | 2 +- .../app/services/repository/topology.js | 2 +- ui/packages/consul-ui/app/services/routlet.js | 2 +- ui/packages/consul-ui/app/services/schema.js | 2 +- ui/packages/consul-ui/app/services/search.js | 2 +- .../consul-ui/app/services/settings.js | 2 +- ui/packages/consul-ui/app/services/sort.js | 2 +- .../app/services/state-with-charts.js | 2 +- ui/packages/consul-ui/app/services/state.js | 2 +- ui/packages/consul-ui/app/services/store.js | 2 +- .../consul-ui/app/services/temporal.js | 2 +- ui/packages/consul-ui/app/services/ticker.js | 2 +- ui/packages/consul-ui/app/services/timeout.js | 2 +- .../consul-ui/app/services/ui-config.js | 2 +- .../app/sort/comparators/auth-method.js | 2 +- .../app/sort/comparators/health-check.js | 2 +- .../app/sort/comparators/intention.js | 2 +- .../consul-ui/app/sort/comparators/kv.js | 2 +- .../consul-ui/app/sort/comparators/node.js | 2 +- .../consul-ui/app/sort/comparators/nspace.js | 2 +- .../app/sort/comparators/partition.js | 2 +- .../consul-ui/app/sort/comparators/peer.js | 2 +- .../consul-ui/app/sort/comparators/policy.js | 2 +- .../consul-ui/app/sort/comparators/role.js | 2 +- .../app/sort/comparators/service-instance.js | 2 +- .../consul-ui/app/sort/comparators/service.js | 2 +- .../consul-ui/app/sort/comparators/token.js | 2 +- .../app/sort/comparators/upstream-instance.js | 2 +- ui/packages/consul-ui/app/storages/base.js | 2 +- ui/packages/consul-ui/app/storages/notices.js | 2 +- ui/packages/consul-ui/app/styles/app.scss | 2 +- .../app/styles/base/animation/index.scss | 2 +- .../app/styles/base/color/index.scss | 2 +- .../styles/base/color/semantic-variables.scss | 2 +- .../base/color/ui/frame-placeholders.scss | 2 +- .../app/styles/base/color/ui/index.scss | 2 +- .../app/styles/base/component/index.scss | 2 +- .../base/decoration/base-placeholders.scss | 2 +- .../base/decoration/base-variables.scss | 2 +- .../app/styles/base/decoration/index.scss | 2 +- .../base/decoration/visually-hidden.css.js | 2 +- .../styles/base/icons/base-keyframes.css.js | 2 +- .../app/styles/base/icons/base-keyframes.scss | 2 +- .../styles/base/icons/base-placeholders.scss | 2 +- .../app/styles/base/icons/debug.scss | 2 +- .../base/icons/icons/activity/index.scss | 2 +- .../base/icons/icons/activity/keyframes.scss | 2 +- .../icons/icons/activity/placeholders.scss | 2 +- .../icons/icons/activity/property-16.scss | 2 +- .../icons/icons/activity/property-24.scss | 2 +- .../icons/icons/alert-circle-fill/index.scss | 2 +- .../icons/alert-circle-fill/keyframes.scss | 2 +- .../icons/alert-circle-fill/placeholders.scss | 2 +- .../icons/alert-circle-fill/property-16.scss | 2 +- .../icons/alert-circle-fill/property-24.scss | 2 +- .../icons/alert-circle-outline/index.scss | 2 +- .../icons/alert-circle-outline/keyframes.scss | 2 +- .../alert-circle-outline/placeholders.scss | 2 +- .../base/icons/icons/alert-circle/index.scss | 2 +- .../icons/icons/alert-circle/keyframes.scss | 2 +- .../icons/alert-circle/placeholders.scss | 2 +- .../icons/icons/alert-circle/property-16.scss | 2 +- .../icons/icons/alert-circle/property-24.scss | 2 +- .../icons/icons/alert-octagon-fill/index.scss | 2 +- .../icons/alert-octagon-fill/keyframes.scss | 2 +- .../alert-octagon-fill/placeholders.scss | 2 +- .../icons/alert-octagon-fill/property-16.scss | 2 +- .../icons/alert-octagon-fill/property-24.scss | 2 +- .../base/icons/icons/alert-octagon/index.scss | 2 +- .../icons/icons/alert-octagon/keyframes.scss | 2 +- .../icons/alert-octagon/placeholders.scss | 2 +- .../icons/alert-octagon/property-16.scss | 2 +- .../icons/alert-octagon/property-24.scss | 2 +- .../icons/alert-triangle-fill/index.scss | 2 +- .../icons/alert-triangle-fill/keyframes.scss | 2 +- .../alert-triangle-fill/placeholders.scss | 2 +- .../alert-triangle-fill/property-16.scss | 2 +- .../alert-triangle-fill/property-24.scss | 2 +- .../icons/icons/alert-triangle/index.scss | 2 +- .../icons/icons/alert-triangle/keyframes.scss | 2 +- .../icons/alert-triangle/placeholders.scss | 2 +- .../icons/alert-triangle/property-16.scss | 2 +- .../icons/alert-triangle/property-24.scss | 2 +- .../base/icons/icons/alibaba-color/index.scss | 2 +- .../icons/icons/alibaba-color/keyframes.scss | 2 +- .../icons/alibaba-color/placeholders.scss | 2 +- .../icons/alibaba-color/property-16.scss | 2 +- .../icons/alibaba-color/property-24.scss | 2 +- .../base/icons/icons/alibaba/index.scss | 2 +- .../base/icons/icons/alibaba/keyframes.scss | 2 +- .../icons/icons/alibaba/placeholders.scss | 2 +- .../base/icons/icons/alibaba/property-16.scss | 2 +- .../base/icons/icons/alibaba/property-24.scss | 2 +- .../base/icons/icons/align-center/index.scss | 2 +- .../icons/icons/align-center/keyframes.scss | 2 +- .../icons/align-center/placeholders.scss | 2 +- .../icons/icons/align-center/property-16.scss | 2 +- .../icons/icons/align-center/property-24.scss | 2 +- .../base/icons/icons/align-justify/index.scss | 2 +- .../icons/icons/align-justify/keyframes.scss | 2 +- .../icons/align-justify/placeholders.scss | 2 +- .../icons/align-justify/property-16.scss | 2 +- .../icons/align-justify/property-24.scss | 2 +- .../base/icons/icons/align-left/index.scss | 2 +- .../icons/icons/align-left/keyframes.scss | 2 +- .../icons/icons/align-left/placeholders.scss | 2 +- .../icons/icons/align-left/property-16.scss | 2 +- .../icons/icons/align-left/property-24.scss | 2 +- .../base/icons/icons/align-right/index.scss | 2 +- .../icons/icons/align-right/keyframes.scss | 2 +- .../icons/icons/align-right/placeholders.scss | 2 +- .../icons/icons/align-right/property-16.scss | 2 +- .../icons/icons/align-right/property-24.scss | 2 +- .../icons/icons/amazon-eks-color/index.scss | 2 +- .../icons/amazon-eks-color/keyframes.scss | 2 +- .../icons/amazon-eks-color/placeholders.scss | 2 +- .../icons/amazon-eks-color/property-16.scss | 2 +- .../icons/amazon-eks-color/property-24.scss | 2 +- .../base/icons/icons/amazon-eks/index.scss | 2 +- .../icons/icons/amazon-eks/keyframes.scss | 2 +- .../icons/icons/amazon-eks/placeholders.scss | 2 +- .../icons/icons/amazon-eks/property-16.scss | 2 +- .../icons/icons/amazon-eks/property-24.scss | 2 +- .../base/icons/icons/apple-color/index.scss | 2 +- .../icons/icons/apple-color/keyframes.scss | 2 +- .../icons/icons/apple-color/placeholders.scss | 2 +- .../icons/icons/apple-color/property-16.scss | 2 +- .../icons/icons/apple-color/property-24.scss | 2 +- .../styles/base/icons/icons/apple/index.scss | 2 +- .../base/icons/icons/apple/keyframes.scss | 2 +- .../base/icons/icons/apple/placeholders.scss | 2 +- .../base/icons/icons/apple/property-16.scss | 2 +- .../base/icons/icons/apple/property-24.scss | 2 +- .../base/icons/icons/archive/index.scss | 2 +- .../base/icons/icons/archive/keyframes.scss | 2 +- .../icons/icons/archive/placeholders.scss | 2 +- .../base/icons/icons/archive/property-16.scss | 2 +- .../base/icons/icons/archive/property-24.scss | 2 +- .../icons/icons/arrow-down-circle/index.scss | 2 +- .../icons/arrow-down-circle/keyframes.scss | 2 +- .../icons/arrow-down-circle/placeholders.scss | 2 +- .../icons/arrow-down-circle/property-16.scss | 2 +- .../icons/arrow-down-circle/property-24.scss | 2 +- .../icons/icons/arrow-down-left/index.scss | 2 +- .../icons/arrow-down-left/keyframes.scss | 2 +- .../icons/arrow-down-left/placeholders.scss | 2 +- .../icons/arrow-down-left/property-16.scss | 2 +- .../icons/arrow-down-left/property-24.scss | 2 +- .../icons/icons/arrow-down-right/index.scss | 2 +- .../icons/arrow-down-right/keyframes.scss | 2 +- .../icons/arrow-down-right/placeholders.scss | 2 +- .../icons/arrow-down-right/property-16.scss | 2 +- .../icons/arrow-down-right/property-24.scss | 2 +- .../base/icons/icons/arrow-down/index.scss | 2 +- .../icons/icons/arrow-down/keyframes.scss | 2 +- .../icons/icons/arrow-down/placeholders.scss | 2 +- .../icons/icons/arrow-down/property-16.scss | 2 +- .../icons/icons/arrow-down/property-24.scss | 2 +- .../icons/icons/arrow-left-circle/index.scss | 2 +- .../icons/arrow-left-circle/keyframes.scss | 2 +- .../icons/arrow-left-circle/placeholders.scss | 2 +- .../icons/arrow-left-circle/property-16.scss | 2 +- .../icons/arrow-left-circle/property-24.scss | 2 +- .../base/icons/icons/arrow-left/index.scss | 2 +- .../icons/icons/arrow-left/keyframes.scss | 2 +- .../icons/icons/arrow-left/placeholders.scss | 2 +- .../icons/icons/arrow-left/property-16.scss | 2 +- .../icons/icons/arrow-left/property-24.scss | 2 +- .../icons/icons/arrow-right-circle/index.scss | 2 +- .../icons/arrow-right-circle/keyframes.scss | 2 +- .../arrow-right-circle/placeholders.scss | 2 +- .../icons/arrow-right-circle/property-16.scss | 2 +- .../icons/arrow-right-circle/property-24.scss | 2 +- .../base/icons/icons/arrow-right/index.scss | 2 +- .../icons/icons/arrow-right/keyframes.scss | 2 +- .../icons/icons/arrow-right/placeholders.scss | 2 +- .../icons/icons/arrow-right/property-16.scss | 2 +- .../icons/icons/arrow-right/property-24.scss | 2 +- .../icons/icons/arrow-up-circle/index.scss | 2 +- .../icons/arrow-up-circle/keyframes.scss | 2 +- .../icons/arrow-up-circle/placeholders.scss | 2 +- .../icons/arrow-up-circle/property-16.scss | 2 +- .../icons/arrow-up-circle/property-24.scss | 2 +- .../base/icons/icons/arrow-up-left/index.scss | 2 +- .../icons/icons/arrow-up-left/keyframes.scss | 2 +- .../icons/arrow-up-left/placeholders.scss | 2 +- .../icons/arrow-up-left/property-16.scss | 2 +- .../icons/arrow-up-left/property-24.scss | 2 +- .../icons/icons/arrow-up-right/index.scss | 2 +- .../icons/icons/arrow-up-right/keyframes.scss | 2 +- .../icons/arrow-up-right/placeholders.scss | 2 +- .../icons/arrow-up-right/property-16.scss | 2 +- .../icons/arrow-up-right/property-24.scss | 2 +- .../base/icons/icons/arrow-up/index.scss | 2 +- .../base/icons/icons/arrow-up/keyframes.scss | 2 +- .../icons/icons/arrow-up/placeholders.scss | 2 +- .../icons/icons/arrow-up/property-16.scss | 2 +- .../icons/icons/arrow-up/property-24.scss | 2 +- .../base/icons/icons/at-sign/index.scss | 2 +- .../base/icons/icons/at-sign/keyframes.scss | 2 +- .../icons/icons/at-sign/placeholders.scss | 2 +- .../base/icons/icons/at-sign/property-16.scss | 2 +- .../base/icons/icons/at-sign/property-24.scss | 2 +- .../base/icons/icons/auth0-color/index.scss | 2 +- .../icons/icons/auth0-color/keyframes.scss | 2 +- .../icons/icons/auth0-color/placeholders.scss | 2 +- .../icons/icons/auth0-color/property-16.scss | 2 +- .../icons/icons/auth0-color/property-24.scss | 2 +- .../styles/base/icons/icons/auth0/index.scss | 2 +- .../base/icons/icons/auth0/keyframes.scss | 2 +- .../base/icons/icons/auth0/placeholders.scss | 2 +- .../base/icons/icons/auth0/property-16.scss | 2 +- .../base/icons/icons/auth0/property-24.scss | 2 +- .../base/icons/icons/auto-apply/index.scss | 2 +- .../icons/icons/auto-apply/keyframes.scss | 2 +- .../icons/icons/auto-apply/placeholders.scss | 2 +- .../icons/icons/auto-apply/property-16.scss | 2 +- .../icons/icons/auto-apply/property-24.scss | 2 +- .../styles/base/icons/icons/award/index.scss | 2 +- .../base/icons/icons/award/keyframes.scss | 2 +- .../base/icons/icons/award/placeholders.scss | 2 +- .../base/icons/icons/award/property-16.scss | 2 +- .../base/icons/icons/award/property-24.scss | 2 +- .../base/icons/icons/azure-color/index.scss | 2 +- .../icons/icons/azure-color/keyframes.scss | 2 +- .../icons/icons/azure-color/placeholders.scss | 2 +- .../icons/icons/azure-color/property-16.scss | 2 +- .../icons/icons/azure-color/property-24.scss | 2 +- .../icons/icons/azure-devops-color/index.scss | 2 +- .../icons/azure-devops-color/keyframes.scss | 2 +- .../azure-devops-color/placeholders.scss | 2 +- .../icons/azure-devops-color/property-16.scss | 2 +- .../icons/azure-devops-color/property-24.scss | 2 +- .../base/icons/icons/azure-devops/index.scss | 2 +- .../icons/icons/azure-devops/keyframes.scss | 2 +- .../icons/azure-devops/placeholders.scss | 2 +- .../icons/icons/azure-devops/property-16.scss | 2 +- .../icons/icons/azure-devops/property-24.scss | 2 +- .../styles/base/icons/icons/azure/index.scss | 2 +- .../base/icons/icons/azure/keyframes.scss | 2 +- .../base/icons/icons/azure/placeholders.scss | 2 +- .../base/icons/icons/azure/property-16.scss | 2 +- .../base/icons/icons/azure/property-24.scss | 2 +- .../base/icons/icons/bank-vault/index.scss | 2 +- .../icons/icons/bank-vault/keyframes.scss | 2 +- .../icons/icons/bank-vault/placeholders.scss | 2 +- .../icons/icons/bank-vault/property-16.scss | 2 +- .../icons/icons/bank-vault/property-24.scss | 2 +- .../base/icons/icons/bar-chart-alt/index.scss | 2 +- .../icons/icons/bar-chart-alt/keyframes.scss | 2 +- .../icons/bar-chart-alt/placeholders.scss | 2 +- .../icons/bar-chart-alt/property-16.scss | 2 +- .../icons/bar-chart-alt/property-24.scss | 2 +- .../base/icons/icons/bar-chart/index.scss | 2 +- .../base/icons/icons/bar-chart/keyframes.scss | 2 +- .../icons/icons/bar-chart/placeholders.scss | 2 +- .../icons/icons/bar-chart/property-16.scss | 2 +- .../icons/icons/bar-chart/property-24.scss | 2 +- .../icons/icons/battery-charging/index.scss | 2 +- .../icons/battery-charging/keyframes.scss | 2 +- .../icons/battery-charging/placeholders.scss | 2 +- .../icons/battery-charging/property-16.scss | 2 +- .../icons/battery-charging/property-24.scss | 2 +- .../base/icons/icons/battery/index.scss | 2 +- .../base/icons/icons/battery/keyframes.scss | 2 +- .../icons/icons/battery/placeholders.scss | 2 +- .../base/icons/icons/battery/property-16.scss | 2 +- .../base/icons/icons/battery/property-24.scss | 2 +- .../styles/base/icons/icons/beaker/index.scss | 2 +- .../base/icons/icons/beaker/keyframes.scss | 2 +- .../base/icons/icons/beaker/placeholders.scss | 2 +- .../base/icons/icons/beaker/property-16.scss | 2 +- .../base/icons/icons/beaker/property-24.scss | 2 +- .../icons/icons/bell-active-fill/index.scss | 2 +- .../icons/bell-active-fill/keyframes.scss | 2 +- .../icons/bell-active-fill/placeholders.scss | 2 +- .../icons/bell-active-fill/property-16.scss | 2 +- .../icons/bell-active-fill/property-24.scss | 2 +- .../base/icons/icons/bell-active/index.scss | 2 +- .../icons/icons/bell-active/keyframes.scss | 2 +- .../icons/icons/bell-active/placeholders.scss | 2 +- .../icons/icons/bell-active/property-16.scss | 2 +- .../icons/icons/bell-active/property-24.scss | 2 +- .../base/icons/icons/bell-off/index.scss | 2 +- .../base/icons/icons/bell-off/keyframes.scss | 2 +- .../icons/icons/bell-off/placeholders.scss | 2 +- .../icons/icons/bell-off/property-16.scss | 2 +- .../icons/icons/bell-off/property-24.scss | 2 +- .../styles/base/icons/icons/bell/index.scss | 2 +- .../base/icons/icons/bell/keyframes.scss | 2 +- .../base/icons/icons/bell/placeholders.scss | 2 +- .../base/icons/icons/bell/property-16.scss | 2 +- .../base/icons/icons/bell/property-24.scss | 2 +- .../icons/icons/bitbucket-color/index.scss | 2 +- .../icons/bitbucket-color/keyframes.scss | 2 +- .../icons/bitbucket-color/placeholders.scss | 2 +- .../icons/bitbucket-color/property-16.scss | 2 +- .../icons/bitbucket-color/property-24.scss | 2 +- .../base/icons/icons/bitbucket/index.scss | 2 +- .../base/icons/icons/bitbucket/keyframes.scss | 2 +- .../icons/icons/bitbucket/placeholders.scss | 2 +- .../icons/icons/bitbucket/property-16.scss | 2 +- .../icons/icons/bitbucket/property-24.scss | 2 +- .../styles/base/icons/icons/bolt/index.scss | 2 +- .../base/icons/icons/bolt/keyframes.scss | 2 +- .../base/icons/icons/bolt/placeholders.scss | 2 +- .../icons/icons/bookmark-add-fill/index.scss | 2 +- .../icons/bookmark-add-fill/keyframes.scss | 2 +- .../icons/bookmark-add-fill/placeholders.scss | 2 +- .../icons/bookmark-add-fill/property-16.scss | 2 +- .../icons/bookmark-add-fill/property-24.scss | 2 +- .../base/icons/icons/bookmark-add/index.scss | 2 +- .../icons/icons/bookmark-add/keyframes.scss | 2 +- .../icons/bookmark-add/placeholders.scss | 2 +- .../icons/icons/bookmark-add/property-16.scss | 2 +- .../icons/icons/bookmark-add/property-24.scss | 2 +- .../base/icons/icons/bookmark-fill/index.scss | 2 +- .../icons/icons/bookmark-fill/keyframes.scss | 2 +- .../icons/bookmark-fill/placeholders.scss | 2 +- .../icons/bookmark-fill/property-16.scss | 2 +- .../icons/bookmark-fill/property-24.scss | 2 +- .../icons/bookmark-remove-fill/index.scss | 2 +- .../icons/bookmark-remove-fill/keyframes.scss | 2 +- .../bookmark-remove-fill/placeholders.scss | 2 +- .../bookmark-remove-fill/property-16.scss | 2 +- .../bookmark-remove-fill/property-24.scss | 2 +- .../icons/icons/bookmark-remove/index.scss | 2 +- .../icons/bookmark-remove/keyframes.scss | 2 +- .../icons/bookmark-remove/placeholders.scss | 2 +- .../icons/bookmark-remove/property-16.scss | 2 +- .../icons/bookmark-remove/property-24.scss | 2 +- .../base/icons/icons/bookmark/index.scss | 2 +- .../base/icons/icons/bookmark/keyframes.scss | 2 +- .../icons/icons/bookmark/placeholders.scss | 2 +- .../icons/icons/bookmark/property-16.scss | 2 +- .../icons/icons/bookmark/property-24.scss | 2 +- .../styles/base/icons/icons/bottom/index.scss | 2 +- .../base/icons/icons/bottom/keyframes.scss | 2 +- .../base/icons/icons/bottom/placeholders.scss | 2 +- .../base/icons/icons/bottom/property-16.scss | 2 +- .../base/icons/icons/bottom/property-24.scss | 2 +- .../icons/icons/boundary-color/index.scss | 2 +- .../icons/icons/boundary-color/keyframes.scss | 2 +- .../icons/boundary-color/placeholders.scss | 2 +- .../icons/boundary-color/property-16.scss | 2 +- .../icons/boundary-color/property-24.scss | 2 +- .../base/icons/icons/boundary/index.scss | 2 +- .../base/icons/icons/boundary/keyframes.scss | 2 +- .../icons/icons/boundary/placeholders.scss | 2 +- .../icons/icons/boundary/property-16.scss | 2 +- .../icons/icons/boundary/property-24.scss | 2 +- .../icons/icons/box-check-fill/index.scss | 2 +- .../icons/icons/box-check-fill/keyframes.scss | 2 +- .../icons/box-check-fill/placeholders.scss | 2 +- .../base/icons/icons/box-outline/index.scss | 2 +- .../icons/icons/box-outline/keyframes.scss | 2 +- .../icons/icons/box-outline/placeholders.scss | 2 +- .../styles/base/icons/icons/box/index.scss | 2 +- .../base/icons/icons/box/keyframes.scss | 2 +- .../base/icons/icons/box/placeholders.scss | 2 +- .../base/icons/icons/box/property-16.scss | 2 +- .../base/icons/icons/box/property-24.scss | 2 +- .../base/icons/icons/briefcase/index.scss | 2 +- .../base/icons/icons/briefcase/keyframes.scss | 2 +- .../icons/icons/briefcase/placeholders.scss | 2 +- .../icons/icons/briefcase/property-16.scss | 2 +- .../icons/icons/briefcase/property-24.scss | 2 +- .../base/icons/icons/broadcast/index.scss | 2 +- .../base/icons/icons/broadcast/keyframes.scss | 2 +- .../icons/icons/broadcast/placeholders.scss | 2 +- .../styles/base/icons/icons/bug/index.scss | 2 +- .../base/icons/icons/bug/keyframes.scss | 2 +- .../base/icons/icons/bug/placeholders.scss | 2 +- .../base/icons/icons/bug/property-16.scss | 2 +- .../base/icons/icons/bug/property-24.scss | 2 +- .../styles/base/icons/icons/build/index.scss | 2 +- .../base/icons/icons/build/keyframes.scss | 2 +- .../base/icons/icons/build/placeholders.scss | 2 +- .../base/icons/icons/build/property-16.scss | 2 +- .../base/icons/icons/build/property-24.scss | 2 +- .../styles/base/icons/icons/bulb/index.scss | 2 +- .../base/icons/icons/bulb/keyframes.scss | 2 +- .../base/icons/icons/bulb/placeholders.scss | 2 +- .../base/icons/icons/bulb/property-16.scss | 2 +- .../base/icons/icons/bulb/property-24.scss | 2 +- .../base/icons/icons/calendar/index.scss | 2 +- .../base/icons/icons/calendar/keyframes.scss | 2 +- .../icons/icons/calendar/placeholders.scss | 2 +- .../icons/icons/calendar/property-16.scss | 2 +- .../icons/icons/calendar/property-24.scss | 2 +- .../base/icons/icons/camera-off/index.scss | 2 +- .../icons/icons/camera-off/keyframes.scss | 2 +- .../icons/icons/camera-off/placeholders.scss | 2 +- .../icons/icons/camera-off/property-16.scss | 2 +- .../icons/icons/camera-off/property-24.scss | 2 +- .../styles/base/icons/icons/camera/index.scss | 2 +- .../base/icons/icons/camera/keyframes.scss | 2 +- .../base/icons/icons/camera/placeholders.scss | 2 +- .../base/icons/icons/camera/property-16.scss | 2 +- .../base/icons/icons/camera/property-24.scss | 2 +- .../icons/icons/cancel-circle-fill/index.scss | 2 +- .../icons/cancel-circle-fill/keyframes.scss | 2 +- .../cancel-circle-fill/placeholders.scss | 2 +- .../icons/cancel-circle-outline/index.scss | 2 +- .../cancel-circle-outline/keyframes.scss | 2 +- .../cancel-circle-outline/placeholders.scss | 2 +- .../base/icons/icons/cancel-plain/index.scss | 2 +- .../icons/icons/cancel-plain/keyframes.scss | 2 +- .../icons/cancel-plain/placeholders.scss | 2 +- .../icons/icons/cancel-square-fill/index.scss | 2 +- .../icons/cancel-square-fill/keyframes.scss | 2 +- .../cancel-square-fill/placeholders.scss | 2 +- .../icons/cancel-square-outline/index.scss | 2 +- .../cancel-square-outline/keyframes.scss | 2 +- .../cancel-square-outline/placeholders.scss | 2 +- .../base/icons/icons/caret-down/index.scss | 2 +- .../icons/icons/caret-down/keyframes.scss | 2 +- .../icons/icons/caret-down/placeholders.scss | 2 +- .../base/icons/icons/caret-up/index.scss | 2 +- .../base/icons/icons/caret-up/keyframes.scss | 2 +- .../icons/icons/caret-up/placeholders.scss | 2 +- .../styles/base/icons/icons/caret/index.scss | 2 +- .../base/icons/icons/caret/keyframes.scss | 2 +- .../base/icons/icons/caret/placeholders.scss | 2 +- .../base/icons/icons/caret/property-16.scss | 2 +- .../base/icons/icons/caret/property-24.scss | 2 +- .../styles/base/icons/icons/cast/index.scss | 2 +- .../base/icons/icons/cast/keyframes.scss | 2 +- .../base/icons/icons/cast/placeholders.scss | 2 +- .../base/icons/icons/cast/property-16.scss | 2 +- .../base/icons/icons/cast/property-24.scss | 2 +- .../base/icons/icons/certificate/index.scss | 2 +- .../icons/icons/certificate/keyframes.scss | 2 +- .../icons/icons/certificate/placeholders.scss | 2 +- .../icons/icons/certificate/property-16.scss | 2 +- .../icons/icons/certificate/property-24.scss | 2 +- .../base/icons/icons/change-circle/index.scss | 2 +- .../icons/icons/change-circle/keyframes.scss | 2 +- .../icons/change-circle/placeholders.scss | 2 +- .../icons/change-circle/property-16.scss | 2 +- .../icons/change-circle/property-24.scss | 2 +- .../base/icons/icons/change-square/index.scss | 2 +- .../icons/icons/change-square/keyframes.scss | 2 +- .../icons/change-square/placeholders.scss | 2 +- .../icons/change-square/property-16.scss | 2 +- .../icons/change-square/property-24.scss | 2 +- .../styles/base/icons/icons/change/index.scss | 2 +- .../base/icons/icons/change/keyframes.scss | 2 +- .../base/icons/icons/change/placeholders.scss | 2 +- .../base/icons/icons/change/property-16.scss | 2 +- .../base/icons/icons/change/property-24.scss | 2 +- .../icons/icons/check-circle-fill/index.scss | 2 +- .../icons/check-circle-fill/keyframes.scss | 2 +- .../icons/check-circle-fill/placeholders.scss | 2 +- .../icons/check-circle-fill/property-16.scss | 2 +- .../icons/check-circle-fill/property-24.scss | 2 +- .../icons/check-circle-outline/index.scss | 2 +- .../icons/check-circle-outline/keyframes.scss | 2 +- .../check-circle-outline/placeholders.scss | 2 +- .../base/icons/icons/check-circle/index.scss | 2 +- .../icons/icons/check-circle/keyframes.scss | 2 +- .../icons/check-circle/placeholders.scss | 2 +- .../icons/icons/check-circle/property-16.scss | 2 +- .../icons/icons/check-circle/property-24.scss | 2 +- .../icons/icons/check-diamond-fill/index.scss | 2 +- .../icons/check-diamond-fill/keyframes.scss | 2 +- .../check-diamond-fill/placeholders.scss | 2 +- .../icons/check-diamond-fill/property-16.scss | 2 +- .../icons/check-diamond-fill/property-24.scss | 2 +- .../base/icons/icons/check-diamond/index.scss | 2 +- .../icons/icons/check-diamond/keyframes.scss | 2 +- .../icons/check-diamond/placeholders.scss | 2 +- .../icons/check-diamond/property-16.scss | 2 +- .../icons/check-diamond/property-24.scss | 2 +- .../icons/icons/check-hexagon-fill/index.scss | 2 +- .../icons/check-hexagon-fill/keyframes.scss | 2 +- .../check-hexagon-fill/placeholders.scss | 2 +- .../icons/check-hexagon-fill/property-16.scss | 2 +- .../icons/check-hexagon-fill/property-24.scss | 2 +- .../base/icons/icons/check-hexagon/index.scss | 2 +- .../icons/icons/check-hexagon/keyframes.scss | 2 +- .../icons/check-hexagon/placeholders.scss | 2 +- .../icons/check-hexagon/property-16.scss | 2 +- .../icons/check-hexagon/property-24.scss | 2 +- .../base/icons/icons/check-plain/index.scss | 2 +- .../icons/icons/check-plain/keyframes.scss | 2 +- .../icons/icons/check-plain/placeholders.scss | 2 +- .../icons/icons/check-square-fill/index.scss | 2 +- .../icons/check-square-fill/keyframes.scss | 2 +- .../icons/check-square-fill/placeholders.scss | 2 +- .../icons/check-square-fill/property-16.scss | 2 +- .../icons/check-square-fill/property-24.scss | 2 +- .../base/icons/icons/check-square/index.scss | 2 +- .../icons/icons/check-square/keyframes.scss | 2 +- .../icons/check-square/placeholders.scss | 2 +- .../icons/icons/check-square/property-16.scss | 2 +- .../icons/icons/check-square/property-24.scss | 2 +- .../styles/base/icons/icons/check/index.scss | 2 +- .../base/icons/icons/check/keyframes.scss | 2 +- .../base/icons/icons/check/placeholders.scss | 2 +- .../base/icons/icons/check/property-16.scss | 2 +- .../base/icons/icons/check/property-24.scss | 2 +- .../base/icons/icons/chevron-down/index.scss | 2 +- .../icons/icons/chevron-down/keyframes.scss | 2 +- .../icons/chevron-down/placeholders.scss | 2 +- .../icons/icons/chevron-down/property-16.scss | 2 +- .../icons/icons/chevron-down/property-24.scss | 2 +- .../base/icons/icons/chevron-left/index.scss | 2 +- .../icons/icons/chevron-left/keyframes.scss | 2 +- .../icons/chevron-left/placeholders.scss | 2 +- .../icons/icons/chevron-left/property-16.scss | 2 +- .../icons/icons/chevron-left/property-24.scss | 2 +- .../base/icons/icons/chevron-right/index.scss | 2 +- .../icons/icons/chevron-right/keyframes.scss | 2 +- .../icons/chevron-right/placeholders.scss | 2 +- .../icons/chevron-right/property-16.scss | 2 +- .../icons/chevron-right/property-24.scss | 2 +- .../base/icons/icons/chevron-up/index.scss | 2 +- .../icons/icons/chevron-up/keyframes.scss | 2 +- .../icons/icons/chevron-up/placeholders.scss | 2 +- .../icons/icons/chevron-up/property-16.scss | 2 +- .../icons/icons/chevron-up/property-24.scss | 2 +- .../base/icons/icons/chevrons-down/index.scss | 2 +- .../icons/icons/chevrons-down/keyframes.scss | 2 +- .../icons/chevrons-down/placeholders.scss | 2 +- .../icons/chevrons-down/property-16.scss | 2 +- .../icons/chevrons-down/property-24.scss | 2 +- .../base/icons/icons/chevrons-left/index.scss | 2 +- .../icons/icons/chevrons-left/keyframes.scss | 2 +- .../icons/chevrons-left/placeholders.scss | 2 +- .../icons/chevrons-left/property-16.scss | 2 +- .../icons/chevrons-left/property-24.scss | 2 +- .../icons/icons/chevrons-right/index.scss | 2 +- .../icons/icons/chevrons-right/keyframes.scss | 2 +- .../icons/chevrons-right/placeholders.scss | 2 +- .../icons/chevrons-right/property-16.scss | 2 +- .../icons/chevrons-right/property-24.scss | 2 +- .../base/icons/icons/chevrons-up/index.scss | 2 +- .../icons/icons/chevrons-up/keyframes.scss | 2 +- .../icons/icons/chevrons-up/placeholders.scss | 2 +- .../icons/icons/chevrons-up/property-16.scss | 2 +- .../icons/icons/chevrons-up/property-24.scss | 2 +- .../base/icons/icons/circle-dot/index.scss | 2 +- .../icons/icons/circle-dot/keyframes.scss | 2 +- .../icons/icons/circle-dot/placeholders.scss | 2 +- .../icons/icons/circle-dot/property-16.scss | 2 +- .../icons/icons/circle-dot/property-24.scss | 2 +- .../base/icons/icons/circle-fill/index.scss | 2 +- .../icons/icons/circle-fill/keyframes.scss | 2 +- .../icons/icons/circle-fill/placeholders.scss | 2 +- .../icons/icons/circle-fill/property-16.scss | 2 +- .../icons/icons/circle-fill/property-24.scss | 2 +- .../base/icons/icons/circle-half/index.scss | 2 +- .../icons/icons/circle-half/keyframes.scss | 2 +- .../icons/icons/circle-half/placeholders.scss | 2 +- .../icons/icons/circle-half/property-16.scss | 2 +- .../icons/icons/circle-half/property-24.scss | 2 +- .../styles/base/icons/icons/circle/index.scss | 2 +- .../base/icons/icons/circle/keyframes.scss | 2 +- .../base/icons/icons/circle/placeholders.scss | 2 +- .../base/icons/icons/circle/property-16.scss | 2 +- .../base/icons/icons/circle/property-24.scss | 2 +- .../icons/icons/clipboard-checked/index.scss | 2 +- .../icons/clipboard-checked/keyframes.scss | 2 +- .../icons/clipboard-checked/placeholders.scss | 2 +- .../icons/clipboard-checked/property-16.scss | 2 +- .../icons/clipboard-checked/property-24.scss | 2 +- .../icons/icons/clipboard-copy/index.scss | 2 +- .../icons/icons/clipboard-copy/keyframes.scss | 2 +- .../icons/clipboard-copy/placeholders.scss | 2 +- .../icons/clipboard-copy/property-16.scss | 2 +- .../icons/clipboard-copy/property-24.scss | 2 +- .../base/icons/icons/clipboard/index.scss | 2 +- .../base/icons/icons/clipboard/keyframes.scss | 2 +- .../icons/icons/clipboard/placeholders.scss | 2 +- .../icons/icons/clipboard/property-16.scss | 2 +- .../icons/icons/clipboard/property-24.scss | 2 +- .../base/icons/icons/clock-fill/index.scss | 2 +- .../icons/icons/clock-fill/keyframes.scss | 2 +- .../icons/icons/clock-fill/placeholders.scss | 2 +- .../base/icons/icons/clock-outline/index.scss | 2 +- .../icons/icons/clock-outline/keyframes.scss | 2 +- .../icons/clock-outline/placeholders.scss | 2 +- .../styles/base/icons/icons/clock/index.scss | 2 +- .../base/icons/icons/clock/keyframes.scss | 2 +- .../base/icons/icons/clock/placeholders.scss | 2 +- .../base/icons/icons/clock/property-16.scss | 2 +- .../base/icons/icons/clock/property-24.scss | 2 +- .../base/icons/icons/cloud-check/index.scss | 2 +- .../icons/icons/cloud-check/keyframes.scss | 2 +- .../icons/icons/cloud-check/placeholders.scss | 2 +- .../icons/icons/cloud-check/property-16.scss | 2 +- .../icons/icons/cloud-check/property-24.scss | 2 +- .../base/icons/icons/cloud-cross/index.scss | 2 +- .../icons/icons/cloud-cross/keyframes.scss | 2 +- .../icons/icons/cloud-cross/placeholders.scss | 2 +- .../icons/icons/cloud-cross/property-16.scss | 2 +- .../icons/icons/cloud-cross/property-24.scss | 2 +- .../icons/icons/cloud-download/index.scss | 2 +- .../icons/icons/cloud-download/keyframes.scss | 2 +- .../icons/cloud-download/placeholders.scss | 2 +- .../icons/cloud-download/property-16.scss | 2 +- .../icons/cloud-download/property-24.scss | 2 +- .../icons/icons/cloud-lightning/index.scss | 2 +- .../icons/cloud-lightning/keyframes.scss | 2 +- .../icons/cloud-lightning/placeholders.scss | 2 +- .../icons/cloud-lightning/property-16.scss | 2 +- .../icons/cloud-lightning/property-24.scss | 2 +- .../base/icons/icons/cloud-lock/index.scss | 2 +- .../icons/icons/cloud-lock/keyframes.scss | 2 +- .../icons/icons/cloud-lock/placeholders.scss | 2 +- .../icons/icons/cloud-lock/property-16.scss | 2 +- .../icons/icons/cloud-lock/property-24.scss | 2 +- .../base/icons/icons/cloud-off/index.scss | 2 +- .../base/icons/icons/cloud-off/keyframes.scss | 2 +- .../icons/icons/cloud-off/placeholders.scss | 2 +- .../icons/icons/cloud-off/property-16.scss | 2 +- .../icons/icons/cloud-off/property-24.scss | 2 +- .../base/icons/icons/cloud-upload/index.scss | 2 +- .../icons/icons/cloud-upload/keyframes.scss | 2 +- .../icons/cloud-upload/placeholders.scss | 2 +- .../icons/icons/cloud-upload/property-16.scss | 2 +- .../icons/icons/cloud-upload/property-24.scss | 2 +- .../base/icons/icons/cloud-x/index.scss | 2 +- .../base/icons/icons/cloud-x/keyframes.scss | 2 +- .../icons/icons/cloud-x/placeholders.scss | 2 +- .../base/icons/icons/cloud-x/property-16.scss | 2 +- .../base/icons/icons/cloud-x/property-24.scss | 2 +- .../styles/base/icons/icons/cloud/index.scss | 2 +- .../base/icons/icons/cloud/keyframes.scss | 2 +- .../base/icons/icons/cloud/placeholders.scss | 2 +- .../base/icons/icons/cloud/property-16.scss | 2 +- .../base/icons/icons/cloud/property-24.scss | 2 +- .../styles/base/icons/icons/code/index.scss | 2 +- .../base/icons/icons/code/keyframes.scss | 2 +- .../base/icons/icons/code/placeholders.scss | 2 +- .../base/icons/icons/code/property-16.scss | 2 +- .../base/icons/icons/code/property-24.scss | 2 +- .../base/icons/icons/codepen-color/index.scss | 2 +- .../icons/icons/codepen-color/keyframes.scss | 2 +- .../icons/codepen-color/placeholders.scss | 2 +- .../icons/codepen-color/property-16.scss | 2 +- .../icons/codepen-color/property-24.scss | 2 +- .../base/icons/icons/codepen/index.scss | 2 +- .../base/icons/icons/codepen/keyframes.scss | 2 +- .../icons/icons/codepen/placeholders.scss | 2 +- .../base/icons/icons/codepen/property-16.scss | 2 +- .../base/icons/icons/codepen/property-24.scss | 2 +- .../base/icons/icons/collections/index.scss | 2 +- .../icons/icons/collections/keyframes.scss | 2 +- .../icons/icons/collections/placeholders.scss | 2 +- .../icons/icons/collections/property-16.scss | 2 +- .../icons/icons/collections/property-24.scss | 2 +- .../base/icons/icons/command/index.scss | 2 +- .../base/icons/icons/command/keyframes.scss | 2 +- .../icons/icons/command/placeholders.scss | 2 +- .../base/icons/icons/command/property-16.scss | 2 +- .../base/icons/icons/command/property-24.scss | 2 +- .../base/icons/icons/compass/index.scss | 2 +- .../base/icons/icons/compass/keyframes.scss | 2 +- .../icons/icons/compass/placeholders.scss | 2 +- .../base/icons/icons/compass/property-16.scss | 2 +- .../base/icons/icons/compass/property-24.scss | 2 +- .../icons/icons/connection-gateway/index.scss | 2 +- .../icons/connection-gateway/keyframes.scss | 2 +- .../connection-gateway/placeholders.scss | 2 +- .../icons/connection-gateway/property-16.scss | 2 +- .../icons/connection-gateway/property-24.scss | 2 +- .../base/icons/icons/connection/index.scss | 2 +- .../icons/icons/connection/keyframes.scss | 2 +- .../icons/icons/connection/placeholders.scss | 2 +- .../icons/icons/connection/property-16.scss | 2 +- .../icons/icons/connection/property-24.scss | 2 +- .../base/icons/icons/console/index.scss | 2 +- .../base/icons/icons/console/keyframes.scss | 2 +- .../icons/icons/console/placeholders.scss | 2 +- .../base/icons/icons/copy-action/index.scss | 2 +- .../icons/icons/copy-action/keyframes.scss | 2 +- .../icons/icons/copy-action/placeholders.scss | 2 +- .../base/icons/icons/copy-success/index.scss | 2 +- .../icons/icons/copy-success/keyframes.scss | 2 +- .../icons/copy-success/placeholders.scss | 2 +- .../icons/icons/corner-down-left/index.scss | 2 +- .../icons/corner-down-left/keyframes.scss | 2 +- .../icons/corner-down-left/placeholders.scss | 2 +- .../icons/corner-down-left/property-16.scss | 2 +- .../icons/corner-down-left/property-24.scss | 2 +- .../icons/icons/corner-down-right/index.scss | 2 +- .../icons/corner-down-right/keyframes.scss | 2 +- .../icons/corner-down-right/placeholders.scss | 2 +- .../icons/corner-down-right/property-16.scss | 2 +- .../icons/corner-down-right/property-24.scss | 2 +- .../icons/icons/corner-left-down/index.scss | 2 +- .../icons/corner-left-down/keyframes.scss | 2 +- .../icons/corner-left-down/placeholders.scss | 2 +- .../icons/corner-left-down/property-16.scss | 2 +- .../icons/corner-left-down/property-24.scss | 2 +- .../icons/icons/corner-left-up/index.scss | 2 +- .../icons/icons/corner-left-up/keyframes.scss | 2 +- .../icons/corner-left-up/placeholders.scss | 2 +- .../icons/corner-left-up/property-16.scss | 2 +- .../icons/corner-left-up/property-24.scss | 2 +- .../icons/icons/corner-right-down/index.scss | 2 +- .../icons/corner-right-down/keyframes.scss | 2 +- .../icons/corner-right-down/placeholders.scss | 2 +- .../icons/corner-right-down/property-16.scss | 2 +- .../icons/corner-right-down/property-24.scss | 2 +- .../icons/icons/corner-right-up/index.scss | 2 +- .../icons/corner-right-up/keyframes.scss | 2 +- .../icons/corner-right-up/placeholders.scss | 2 +- .../icons/corner-right-up/property-16.scss | 2 +- .../icons/corner-right-up/property-24.scss | 2 +- .../icons/icons/corner-up-left/index.scss | 2 +- .../icons/icons/corner-up-left/keyframes.scss | 2 +- .../icons/corner-up-left/placeholders.scss | 2 +- .../icons/corner-up-left/property-16.scss | 2 +- .../icons/corner-up-left/property-24.scss | 2 +- .../icons/icons/corner-up-right/index.scss | 2 +- .../icons/corner-up-right/keyframes.scss | 2 +- .../icons/corner-up-right/placeholders.scss | 2 +- .../icons/corner-up-right/property-16.scss | 2 +- .../icons/corner-up-right/property-24.scss | 2 +- .../styles/base/icons/icons/cpu/index.scss | 2 +- .../base/icons/icons/cpu/keyframes.scss | 2 +- .../base/icons/icons/cpu/placeholders.scss | 2 +- .../base/icons/icons/cpu/property-16.scss | 2 +- .../base/icons/icons/cpu/property-24.scss | 2 +- .../base/icons/icons/credit-card/index.scss | 2 +- .../icons/icons/credit-card/keyframes.scss | 2 +- .../icons/icons/credit-card/placeholders.scss | 2 +- .../icons/icons/credit-card/property-16.scss | 2 +- .../icons/icons/credit-card/property-24.scss | 2 +- .../styles/base/icons/icons/crop/index.scss | 2 +- .../base/icons/icons/crop/keyframes.scss | 2 +- .../base/icons/icons/crop/placeholders.scss | 2 +- .../base/icons/icons/crop/property-16.scss | 2 +- .../base/icons/icons/crop/property-24.scss | 2 +- .../base/icons/icons/crosshair/index.scss | 2 +- .../base/icons/icons/crosshair/keyframes.scss | 2 +- .../icons/icons/crosshair/placeholders.scss | 2 +- .../icons/icons/crosshair/property-16.scss | 2 +- .../icons/icons/crosshair/property-24.scss | 2 +- .../base/icons/icons/dashboard/index.scss | 2 +- .../base/icons/icons/dashboard/keyframes.scss | 2 +- .../icons/icons/dashboard/placeholders.scss | 2 +- .../icons/icons/dashboard/property-16.scss | 2 +- .../icons/icons/dashboard/property-24.scss | 2 +- .../base/icons/icons/database/index.scss | 2 +- .../base/icons/icons/database/keyframes.scss | 2 +- .../icons/icons/database/placeholders.scss | 2 +- .../icons/icons/database/property-16.scss | 2 +- .../icons/icons/database/property-24.scss | 2 +- .../styles/base/icons/icons/delay/index.scss | 2 +- .../base/icons/icons/delay/keyframes.scss | 2 +- .../base/icons/icons/delay/placeholders.scss | 2 +- .../base/icons/icons/delay/property-16.scss | 2 +- .../base/icons/icons/delay/property-24.scss | 2 +- .../styles/base/icons/icons/delete/index.scss | 2 +- .../base/icons/icons/delete/keyframes.scss | 2 +- .../base/icons/icons/delete/placeholders.scss | 2 +- .../base/icons/icons/delete/property-16.scss | 2 +- .../base/icons/icons/delete/property-24.scss | 2 +- .../base/icons/icons/deny-alt/index.scss | 2 +- .../base/icons/icons/deny-alt/keyframes.scss | 2 +- .../icons/icons/deny-alt/placeholders.scss | 2 +- .../base/icons/icons/deny-color/index.scss | 2 +- .../icons/icons/deny-color/keyframes.scss | 2 +- .../icons/icons/deny-color/placeholders.scss | 2 +- .../icons/icons/deny-color/property-16.scss | 2 +- .../icons/icons/deny-color/property-24.scss | 2 +- .../base/icons/icons/deny-default/index.scss | 2 +- .../icons/icons/deny-default/keyframes.scss | 2 +- .../icons/deny-default/placeholders.scss | 2 +- .../base/icons/icons/diamond-fill/index.scss | 2 +- .../icons/icons/diamond-fill/keyframes.scss | 2 +- .../icons/diamond-fill/placeholders.scss | 2 +- .../icons/icons/diamond-fill/property-16.scss | 2 +- .../icons/icons/diamond-fill/property-24.scss | 2 +- .../base/icons/icons/diamond/index.scss | 2 +- .../base/icons/icons/diamond/keyframes.scss | 2 +- .../icons/icons/diamond/placeholders.scss | 2 +- .../base/icons/icons/diamond/property-16.scss | 2 +- .../base/icons/icons/diamond/property-24.scss | 2 +- .../base/icons/icons/disabled/index.scss | 2 +- .../base/icons/icons/disabled/keyframes.scss | 2 +- .../icons/icons/disabled/placeholders.scss | 2 +- .../styles/base/icons/icons/disc/index.scss | 2 +- .../base/icons/icons/disc/keyframes.scss | 2 +- .../base/icons/icons/disc/placeholders.scss | 2 +- .../base/icons/icons/disc/property-16.scss | 2 +- .../base/icons/icons/disc/property-24.scss | 2 +- .../icons/icons/discussion-circle/index.scss | 2 +- .../icons/discussion-circle/keyframes.scss | 2 +- .../icons/discussion-circle/placeholders.scss | 2 +- .../icons/discussion-circle/property-16.scss | 2 +- .../icons/discussion-circle/property-24.scss | 2 +- .../icons/icons/discussion-square/index.scss | 2 +- .../icons/discussion-square/keyframes.scss | 2 +- .../icons/discussion-square/placeholders.scss | 2 +- .../icons/discussion-square/property-16.scss | 2 +- .../icons/discussion-square/property-24.scss | 2 +- .../base/icons/icons/docker-color/index.scss | 2 +- .../icons/icons/docker-color/keyframes.scss | 2 +- .../icons/docker-color/placeholders.scss | 2 +- .../icons/icons/docker-color/property-16.scss | 2 +- .../icons/icons/docker-color/property-24.scss | 2 +- .../styles/base/icons/icons/docker/index.scss | 2 +- .../base/icons/icons/docker/keyframes.scss | 2 +- .../base/icons/icons/docker/placeholders.scss | 2 +- .../base/icons/icons/docker/property-16.scss | 2 +- .../base/icons/icons/docker/property-24.scss | 2 +- .../base/icons/icons/docs-download/index.scss | 2 +- .../icons/icons/docs-download/keyframes.scss | 2 +- .../icons/docs-download/placeholders.scss | 2 +- .../icons/docs-download/property-16.scss | 2 +- .../icons/docs-download/property-24.scss | 2 +- .../base/icons/icons/docs-link/index.scss | 2 +- .../base/icons/icons/docs-link/keyframes.scss | 2 +- .../icons/icons/docs-link/placeholders.scss | 2 +- .../icons/icons/docs-link/property-16.scss | 2 +- .../icons/icons/docs-link/property-24.scss | 2 +- .../styles/base/icons/icons/docs/index.scss | 2 +- .../base/icons/icons/docs/keyframes.scss | 2 +- .../base/icons/icons/docs/placeholders.scss | 2 +- .../base/icons/icons/docs/property-16.scss | 2 +- .../base/icons/icons/docs/property-24.scss | 2 +- .../base/icons/icons/dollar-sign/index.scss | 2 +- .../icons/icons/dollar-sign/keyframes.scss | 2 +- .../icons/icons/dollar-sign/placeholders.scss | 2 +- .../icons/icons/dollar-sign/property-16.scss | 2 +- .../icons/icons/dollar-sign/property-24.scss | 2 +- .../base/icons/icons/dot-half/index.scss | 2 +- .../base/icons/icons/dot-half/keyframes.scss | 2 +- .../icons/icons/dot-half/placeholders.scss | 2 +- .../icons/icons/dot-half/property-16.scss | 2 +- .../icons/icons/dot-half/property-24.scss | 2 +- .../styles/base/icons/icons/dot/index.scss | 2 +- .../base/icons/icons/dot/keyframes.scss | 2 +- .../base/icons/icons/dot/placeholders.scss | 2 +- .../base/icons/icons/dot/property-16.scss | 2 +- .../base/icons/icons/dot/property-24.scss | 2 +- .../base/icons/icons/download/index.scss | 2 +- .../base/icons/icons/download/keyframes.scss | 2 +- .../icons/icons/download/placeholders.scss | 2 +- .../icons/icons/download/property-16.scss | 2 +- .../icons/icons/download/property-24.scss | 2 +- .../base/icons/icons/droplet/index.scss | 2 +- .../base/icons/icons/droplet/keyframes.scss | 2 +- .../icons/icons/droplet/placeholders.scss | 2 +- .../base/icons/icons/droplet/property-16.scss | 2 +- .../base/icons/icons/droplet/property-24.scss | 2 +- .../base/icons/icons/duplicate/index.scss | 2 +- .../base/icons/icons/duplicate/keyframes.scss | 2 +- .../icons/icons/duplicate/placeholders.scss | 2 +- .../icons/icons/duplicate/property-16.scss | 2 +- .../icons/icons/duplicate/property-24.scss | 2 +- .../styles/base/icons/icons/edit/index.scss | 2 +- .../base/icons/icons/edit/keyframes.scss | 2 +- .../base/icons/icons/edit/placeholders.scss | 2 +- .../base/icons/icons/edit/property-16.scss | 2 +- .../base/icons/icons/edit/property-24.scss | 2 +- .../base/icons/icons/enterprise/index.scss | 2 +- .../icons/icons/enterprise/keyframes.scss | 2 +- .../icons/icons/enterprise/placeholders.scss | 2 +- .../icons/icons/enterprise/property-16.scss | 2 +- .../icons/icons/enterprise/property-24.scss | 2 +- .../base/icons/icons/entry-point/index.scss | 2 +- .../icons/icons/entry-point/keyframes.scss | 2 +- .../icons/icons/entry-point/placeholders.scss | 2 +- .../icons/icons/entry-point/property-16.scss | 2 +- .../icons/icons/entry-point/property-24.scss | 2 +- .../icons/envelope-sealed-fill/index.scss | 2 +- .../icons/envelope-sealed-fill/keyframes.scss | 2 +- .../envelope-sealed-fill/placeholders.scss | 2 +- .../icons/envelope-sealed-outline/index.scss | 2 +- .../envelope-sealed-outline/keyframes.scss | 2 +- .../envelope-sealed-outline/placeholders.scss | 2 +- .../envelope-unsealed--outline/index.scss | 2 +- .../envelope-unsealed--outline/keyframes.scss | 2 +- .../placeholders.scss | 2 +- .../icons/envelope-unsealed-fill/index.scss | 2 +- .../envelope-unsealed-fill/keyframes.scss | 2 +- .../envelope-unsealed-fill/placeholders.scss | 2 +- .../styles/base/icons/icons/event/index.scss | 2 +- .../base/icons/icons/event/keyframes.scss | 2 +- .../base/icons/icons/event/placeholders.scss | 2 +- .../base/icons/icons/event/property-16.scss | 2 +- .../base/icons/icons/event/property-24.scss | 2 +- .../base/icons/icons/exit-point/index.scss | 2 +- .../icons/icons/exit-point/keyframes.scss | 2 +- .../icons/icons/exit-point/placeholders.scss | 2 +- .../icons/icons/exit-point/property-16.scss | 2 +- .../icons/icons/exit-point/property-24.scss | 2 +- .../styles/base/icons/icons/exit/index.scss | 2 +- .../base/icons/icons/exit/keyframes.scss | 2 +- .../base/icons/icons/exit/placeholders.scss | 2 +- .../base/icons/icons/expand-less/index.scss | 2 +- .../icons/icons/expand-less/keyframes.scss | 2 +- .../icons/icons/expand-less/placeholders.scss | 2 +- .../base/icons/icons/expand-more/index.scss | 2 +- .../icons/icons/expand-more/keyframes.scss | 2 +- .../icons/icons/expand-more/placeholders.scss | 2 +- .../base/icons/icons/external-link/index.scss | 2 +- .../icons/icons/external-link/keyframes.scss | 2 +- .../icons/external-link/placeholders.scss | 2 +- .../icons/external-link/property-16.scss | 2 +- .../icons/external-link/property-24.scss | 2 +- .../base/icons/icons/eye-off/index.scss | 2 +- .../base/icons/icons/eye-off/keyframes.scss | 2 +- .../icons/icons/eye-off/placeholders.scss | 2 +- .../base/icons/icons/eye-off/property-16.scss | 2 +- .../base/icons/icons/eye-off/property-24.scss | 2 +- .../styles/base/icons/icons/eye/index.scss | 2 +- .../base/icons/icons/eye/keyframes.scss | 2 +- .../base/icons/icons/eye/placeholders.scss | 2 +- .../base/icons/icons/eye/property-16.scss | 2 +- .../base/icons/icons/eye/property-24.scss | 2 +- .../base/icons/icons/f5-color/index.scss | 2 +- .../base/icons/icons/f5-color/keyframes.scss | 2 +- .../icons/icons/f5-color/placeholders.scss | 2 +- .../icons/icons/f5-color/property-16.scss | 2 +- .../icons/icons/f5-color/property-24.scss | 2 +- .../app/styles/base/icons/icons/f5/index.scss | 2 +- .../styles/base/icons/icons/f5/keyframes.scss | 2 +- .../base/icons/icons/f5/placeholders.scss | 2 +- .../base/icons/icons/f5/property-16.scss | 2 +- .../base/icons/icons/f5/property-24.scss | 2 +- .../icons/icons/facebook-color/index.scss | 2 +- .../icons/icons/facebook-color/keyframes.scss | 2 +- .../icons/facebook-color/placeholders.scss | 2 +- .../icons/facebook-color/property-16.scss | 2 +- .../icons/facebook-color/property-24.scss | 2 +- .../base/icons/icons/facebook/index.scss | 2 +- .../base/icons/icons/facebook/keyframes.scss | 2 +- .../icons/icons/facebook/placeholders.scss | 2 +- .../icons/icons/facebook/property-16.scss | 2 +- .../icons/icons/facebook/property-24.scss | 2 +- .../base/icons/icons/fast-forward/index.scss | 2 +- .../icons/icons/fast-forward/keyframes.scss | 2 +- .../icons/fast-forward/placeholders.scss | 2 +- .../icons/icons/fast-forward/property-16.scss | 2 +- .../icons/icons/fast-forward/property-24.scss | 2 +- .../base/icons/icons/file-change/index.scss | 2 +- .../icons/icons/file-change/keyframes.scss | 2 +- .../icons/icons/file-change/placeholders.scss | 2 +- .../icons/icons/file-change/property-16.scss | 2 +- .../icons/icons/file-change/property-24.scss | 2 +- .../base/icons/icons/file-check/index.scss | 2 +- .../icons/icons/file-check/keyframes.scss | 2 +- .../icons/icons/file-check/placeholders.scss | 2 +- .../icons/icons/file-check/property-16.scss | 2 +- .../icons/icons/file-check/property-24.scss | 2 +- .../base/icons/icons/file-diff/index.scss | 2 +- .../base/icons/icons/file-diff/keyframes.scss | 2 +- .../icons/icons/file-diff/placeholders.scss | 2 +- .../icons/icons/file-diff/property-16.scss | 2 +- .../icons/icons/file-diff/property-24.scss | 2 +- .../base/icons/icons/file-fill/index.scss | 2 +- .../base/icons/icons/file-fill/keyframes.scss | 2 +- .../icons/icons/file-fill/placeholders.scss | 2 +- .../base/icons/icons/file-minus/index.scss | 2 +- .../icons/icons/file-minus/keyframes.scss | 2 +- .../icons/icons/file-minus/placeholders.scss | 2 +- .../icons/icons/file-minus/property-16.scss | 2 +- .../icons/icons/file-minus/property-24.scss | 2 +- .../base/icons/icons/file-outline/index.scss | 2 +- .../icons/icons/file-outline/keyframes.scss | 2 +- .../icons/file-outline/placeholders.scss | 2 +- .../base/icons/icons/file-plus/index.scss | 2 +- .../base/icons/icons/file-plus/keyframes.scss | 2 +- .../icons/icons/file-plus/placeholders.scss | 2 +- .../icons/icons/file-plus/property-16.scss | 2 +- .../icons/icons/file-plus/property-24.scss | 2 +- .../base/icons/icons/file-source/index.scss | 2 +- .../icons/icons/file-source/keyframes.scss | 2 +- .../icons/icons/file-source/placeholders.scss | 2 +- .../icons/icons/file-source/property-16.scss | 2 +- .../icons/icons/file-source/property-24.scss | 2 +- .../base/icons/icons/file-text/index.scss | 2 +- .../base/icons/icons/file-text/keyframes.scss | 2 +- .../icons/icons/file-text/placeholders.scss | 2 +- .../icons/icons/file-text/property-16.scss | 2 +- .../icons/icons/file-text/property-24.scss | 2 +- .../styles/base/icons/icons/file-x/index.scss | 2 +- .../base/icons/icons/file-x/keyframes.scss | 2 +- .../base/icons/icons/file-x/placeholders.scss | 2 +- .../base/icons/icons/file-x/property-16.scss | 2 +- .../base/icons/icons/file-x/property-24.scss | 2 +- .../styles/base/icons/icons/file/index.scss | 2 +- .../base/icons/icons/file/keyframes.scss | 2 +- .../base/icons/icons/file/placeholders.scss | 2 +- .../base/icons/icons/file/property-16.scss | 2 +- .../base/icons/icons/file/property-24.scss | 2 +- .../styles/base/icons/icons/files/index.scss | 2 +- .../base/icons/icons/files/keyframes.scss | 2 +- .../base/icons/icons/files/placeholders.scss | 2 +- .../base/icons/icons/files/property-16.scss | 2 +- .../base/icons/icons/files/property-24.scss | 2 +- .../styles/base/icons/icons/film/index.scss | 2 +- .../base/icons/icons/film/keyframes.scss | 2 +- .../base/icons/icons/film/placeholders.scss | 2 +- .../base/icons/icons/film/property-16.scss | 2 +- .../base/icons/icons/film/property-24.scss | 2 +- .../base/icons/icons/filter-circle/index.scss | 2 +- .../icons/icons/filter-circle/keyframes.scss | 2 +- .../icons/filter-circle/placeholders.scss | 2 +- .../icons/filter-circle/property-16.scss | 2 +- .../icons/filter-circle/property-24.scss | 2 +- .../base/icons/icons/filter-fill/index.scss | 2 +- .../icons/icons/filter-fill/keyframes.scss | 2 +- .../icons/icons/filter-fill/placeholders.scss | 2 +- .../icons/icons/filter-fill/property-16.scss | 2 +- .../icons/icons/filter-fill/property-24.scss | 2 +- .../styles/base/icons/icons/filter/index.scss | 2 +- .../base/icons/icons/filter/keyframes.scss | 2 +- .../base/icons/icons/filter/placeholders.scss | 2 +- .../base/icons/icons/filter/property-16.scss | 2 +- .../base/icons/icons/filter/property-24.scss | 2 +- .../base/icons/icons/fingerprint/index.scss | 2 +- .../icons/icons/fingerprint/keyframes.scss | 2 +- .../icons/icons/fingerprint/placeholders.scss | 2 +- .../icons/icons/fingerprint/property-16.scss | 2 +- .../icons/icons/fingerprint/property-24.scss | 2 +- .../styles/base/icons/icons/flag/index.scss | 2 +- .../base/icons/icons/flag/keyframes.scss | 2 +- .../base/icons/icons/flag/placeholders.scss | 2 +- .../base/icons/icons/flag/property-16.scss | 2 +- .../base/icons/icons/flag/property-24.scss | 2 +- .../base/icons/icons/folder-fill/index.scss | 2 +- .../icons/icons/folder-fill/keyframes.scss | 2 +- .../icons/icons/folder-fill/placeholders.scss | 2 +- .../icons/icons/folder-fill/property-16.scss | 2 +- .../icons/icons/folder-fill/property-24.scss | 2 +- .../icons/icons/folder-minus-fill/index.scss | 2 +- .../icons/folder-minus-fill/keyframes.scss | 2 +- .../icons/folder-minus-fill/placeholders.scss | 2 +- .../icons/folder-minus-fill/property-16.scss | 2 +- .../icons/folder-minus-fill/property-24.scss | 2 +- .../base/icons/icons/folder-minus/index.scss | 2 +- .../icons/icons/folder-minus/keyframes.scss | 2 +- .../icons/folder-minus/placeholders.scss | 2 +- .../icons/icons/folder-minus/property-16.scss | 2 +- .../icons/icons/folder-minus/property-24.scss | 2 +- .../icons/icons/folder-outline/index.scss | 2 +- .../icons/icons/folder-outline/keyframes.scss | 2 +- .../icons/folder-outline/placeholders.scss | 2 +- .../icons/icons/folder-plus-fill/index.scss | 2 +- .../icons/folder-plus-fill/keyframes.scss | 2 +- .../icons/folder-plus-fill/placeholders.scss | 2 +- .../icons/folder-plus-fill/property-16.scss | 2 +- .../icons/folder-plus-fill/property-24.scss | 2 +- .../base/icons/icons/folder-plus/index.scss | 2 +- .../icons/icons/folder-plus/keyframes.scss | 2 +- .../icons/icons/folder-plus/placeholders.scss | 2 +- .../icons/icons/folder-plus/property-16.scss | 2 +- .../icons/icons/folder-plus/property-24.scss | 2 +- .../base/icons/icons/folder-star/index.scss | 2 +- .../icons/icons/folder-star/keyframes.scss | 2 +- .../icons/icons/folder-star/placeholders.scss | 2 +- .../icons/icons/folder-star/property-16.scss | 2 +- .../icons/icons/folder-star/property-24.scss | 2 +- .../base/icons/icons/folder-users/index.scss | 2 +- .../icons/icons/folder-users/keyframes.scss | 2 +- .../icons/folder-users/placeholders.scss | 2 +- .../icons/icons/folder-users/property-16.scss | 2 +- .../icons/icons/folder-users/property-24.scss | 2 +- .../styles/base/icons/icons/folder/index.scss | 2 +- .../base/icons/icons/folder/keyframes.scss | 2 +- .../base/icons/icons/folder/placeholders.scss | 2 +- .../base/icons/icons/folder/property-16.scss | 2 +- .../base/icons/icons/folder/property-24.scss | 2 +- .../styles/base/icons/icons/frown/index.scss | 2 +- .../base/icons/icons/frown/keyframes.scss | 2 +- .../base/icons/icons/frown/placeholders.scss | 2 +- .../base/icons/icons/frown/property-16.scss | 2 +- .../base/icons/icons/frown/property-24.scss | 2 +- .../base/icons/icons/gateway/index.scss | 2 +- .../base/icons/icons/gateway/keyframes.scss | 2 +- .../icons/icons/gateway/placeholders.scss | 2 +- .../base/icons/icons/gateway/property-16.scss | 2 +- .../base/icons/icons/gateway/property-24.scss | 2 +- .../base/icons/icons/gcp-color/index.scss | 2 +- .../base/icons/icons/gcp-color/keyframes.scss | 2 +- .../icons/icons/gcp-color/placeholders.scss | 2 +- .../icons/icons/gcp-color/property-16.scss | 2 +- .../icons/icons/gcp-color/property-24.scss | 2 +- .../styles/base/icons/icons/gcp/index.scss | 2 +- .../base/icons/icons/gcp/keyframes.scss | 2 +- .../base/icons/icons/gcp/placeholders.scss | 2 +- .../base/icons/icons/gcp/property-16.scss | 2 +- .../base/icons/icons/gcp/property-24.scss | 2 +- .../base/icons/icons/gift-fill/index.scss | 2 +- .../base/icons/icons/gift-fill/keyframes.scss | 2 +- .../icons/icons/gift-fill/placeholders.scss | 2 +- .../base/icons/icons/gift-outline/index.scss | 2 +- .../icons/icons/gift-outline/keyframes.scss | 2 +- .../icons/gift-outline/placeholders.scss | 2 +- .../styles/base/icons/icons/gift/index.scss | 2 +- .../base/icons/icons/gift/keyframes.scss | 2 +- .../base/icons/icons/gift/placeholders.scss | 2 +- .../base/icons/icons/gift/property-16.scss | 2 +- .../base/icons/icons/gift/property-24.scss | 2 +- .../base/icons/icons/git-branch/index.scss | 2 +- .../icons/icons/git-branch/keyframes.scss | 2 +- .../icons/icons/git-branch/placeholders.scss | 2 +- .../icons/icons/git-branch/property-16.scss | 2 +- .../icons/icons/git-branch/property-24.scss | 2 +- .../base/icons/icons/git-commit/index.scss | 2 +- .../icons/icons/git-commit/keyframes.scss | 2 +- .../icons/icons/git-commit/placeholders.scss | 2 +- .../icons/icons/git-commit/property-16.scss | 2 +- .../icons/icons/git-commit/property-24.scss | 2 +- .../base/icons/icons/git-merge/index.scss | 2 +- .../base/icons/icons/git-merge/keyframes.scss | 2 +- .../icons/icons/git-merge/placeholders.scss | 2 +- .../icons/icons/git-merge/property-16.scss | 2 +- .../icons/icons/git-merge/property-24.scss | 2 +- .../icons/icons/git-pull-request/index.scss | 2 +- .../icons/git-pull-request/keyframes.scss | 2 +- .../icons/git-pull-request/placeholders.scss | 2 +- .../icons/git-pull-request/property-16.scss | 2 +- .../icons/git-pull-request/property-24.scss | 2 +- .../base/icons/icons/git-repo/index.scss | 2 +- .../base/icons/icons/git-repo/keyframes.scss | 2 +- .../icons/icons/git-repo/placeholders.scss | 2 +- .../icons/icons/git-repo/property-16.scss | 2 +- .../icons/icons/git-repo/property-24.scss | 2 +- .../icons/icons/git-repository/index.scss | 2 +- .../icons/icons/git-repository/keyframes.scss | 2 +- .../icons/git-repository/placeholders.scss | 2 +- .../base/icons/icons/github-color/index.scss | 2 +- .../icons/icons/github-color/keyframes.scss | 2 +- .../icons/github-color/placeholders.scss | 2 +- .../icons/icons/github-color/property-16.scss | 2 +- .../icons/icons/github-color/property-24.scss | 2 +- .../styles/base/icons/icons/github/index.scss | 2 +- .../base/icons/icons/github/keyframes.scss | 2 +- .../base/icons/icons/github/placeholders.scss | 2 +- .../base/icons/icons/github/property-16.scss | 2 +- .../base/icons/icons/github/property-24.scss | 2 +- .../base/icons/icons/gitlab-color/index.scss | 2 +- .../icons/icons/gitlab-color/keyframes.scss | 2 +- .../icons/gitlab-color/placeholders.scss | 2 +- .../icons/icons/gitlab-color/property-16.scss | 2 +- .../icons/icons/gitlab-color/property-24.scss | 2 +- .../styles/base/icons/icons/gitlab/index.scss | 2 +- .../base/icons/icons/gitlab/keyframes.scss | 2 +- .../base/icons/icons/gitlab/placeholders.scss | 2 +- .../base/icons/icons/gitlab/property-16.scss | 2 +- .../base/icons/icons/gitlab/property-24.scss | 2 +- .../base/icons/icons/globe-private/index.scss | 2 +- .../icons/icons/globe-private/keyframes.scss | 2 +- .../icons/globe-private/placeholders.scss | 2 +- .../icons/globe-private/property-16.scss | 2 +- .../icons/globe-private/property-24.scss | 2 +- .../styles/base/icons/icons/globe/index.scss | 2 +- .../base/icons/icons/globe/keyframes.scss | 2 +- .../base/icons/icons/globe/placeholders.scss | 2 +- .../base/icons/icons/globe/property-16.scss | 2 +- .../base/icons/icons/globe/property-24.scss | 2 +- .../base/icons/icons/google-color/index.scss | 2 +- .../icons/icons/google-color/keyframes.scss | 2 +- .../icons/google-color/placeholders.scss | 2 +- .../icons/icons/google-color/property-16.scss | 2 +- .../icons/icons/google-color/property-24.scss | 2 +- .../styles/base/icons/icons/google/index.scss | 2 +- .../base/icons/icons/google/keyframes.scss | 2 +- .../base/icons/icons/google/placeholders.scss | 2 +- .../base/icons/icons/google/property-16.scss | 2 +- .../base/icons/icons/google/property-24.scss | 2 +- .../base/icons/icons/grid-alt/index.scss | 2 +- .../base/icons/icons/grid-alt/keyframes.scss | 2 +- .../icons/icons/grid-alt/placeholders.scss | 2 +- .../icons/icons/grid-alt/property-16.scss | 2 +- .../icons/icons/grid-alt/property-24.scss | 2 +- .../styles/base/icons/icons/grid/index.scss | 2 +- .../base/icons/icons/grid/keyframes.scss | 2 +- .../base/icons/icons/grid/placeholders.scss | 2 +- .../base/icons/icons/grid/property-16.scss | 2 +- .../base/icons/icons/grid/property-24.scss | 2 +- .../base/icons/icons/guide-link/index.scss | 2 +- .../icons/icons/guide-link/keyframes.scss | 2 +- .../icons/icons/guide-link/placeholders.scss | 2 +- .../icons/icons/guide-link/property-16.scss | 2 +- .../icons/icons/guide-link/property-24.scss | 2 +- .../styles/base/icons/icons/guide/index.scss | 2 +- .../base/icons/icons/guide/keyframes.scss | 2 +- .../base/icons/icons/guide/placeholders.scss | 2 +- .../base/icons/icons/guide/property-16.scss | 2 +- .../base/icons/icons/guide/property-24.scss | 2 +- .../styles/base/icons/icons/hammer/index.scss | 2 +- .../base/icons/icons/hammer/keyframes.scss | 2 +- .../base/icons/icons/hammer/placeholders.scss | 2 +- .../base/icons/icons/hammer/property-16.scss | 2 +- .../base/icons/icons/hammer/property-24.scss | 2 +- .../base/icons/icons/handshake/index.scss | 2 +- .../base/icons/icons/handshake/keyframes.scss | 2 +- .../icons/icons/handshake/placeholders.scss | 2 +- .../icons/icons/handshake/property-16.scss | 2 +- .../icons/icons/handshake/property-24.scss | 2 +- .../base/icons/icons/hard-drive/index.scss | 2 +- .../icons/icons/hard-drive/keyframes.scss | 2 +- .../icons/icons/hard-drive/placeholders.scss | 2 +- .../icons/icons/hard-drive/property-16.scss | 2 +- .../icons/icons/hard-drive/property-24.scss | 2 +- .../styles/base/icons/icons/hash/index.scss | 2 +- .../base/icons/icons/hash/keyframes.scss | 2 +- .../base/icons/icons/hash/placeholders.scss | 2 +- .../base/icons/icons/hash/property-16.scss | 2 +- .../base/icons/icons/hash/property-24.scss | 2 +- .../icons/icons/hashicorp-color/index.scss | 2 +- .../icons/hashicorp-color/keyframes.scss | 2 +- .../icons/hashicorp-color/placeholders.scss | 2 +- .../icons/hashicorp-color/property-16.scss | 2 +- .../icons/hashicorp-color/property-24.scss | 2 +- .../base/icons/icons/hashicorp/index.scss | 2 +- .../base/icons/icons/hashicorp/keyframes.scss | 2 +- .../icons/icons/hashicorp/placeholders.scss | 2 +- .../icons/icons/hashicorp/property-16.scss | 2 +- .../icons/icons/hashicorp/property-24.scss | 2 +- .../base/icons/icons/hcp-color/index.scss | 2 +- .../base/icons/icons/hcp-color/keyframes.scss | 2 +- .../icons/icons/hcp-color/placeholders.scss | 2 +- .../icons/icons/hcp-color/property-16.scss | 2 +- .../icons/icons/hcp-color/property-24.scss | 2 +- .../styles/base/icons/icons/hcp/index.scss | 2 +- .../base/icons/icons/hcp/keyframes.scss | 2 +- .../base/icons/icons/hcp/placeholders.scss | 2 +- .../base/icons/icons/hcp/property-16.scss | 2 +- .../base/icons/icons/hcp/property-24.scss | 2 +- .../base/icons/icons/headphones/index.scss | 2 +- .../icons/icons/headphones/keyframes.scss | 2 +- .../icons/icons/headphones/placeholders.scss | 2 +- .../icons/icons/headphones/property-16.scss | 2 +- .../icons/icons/headphones/property-24.scss | 2 +- .../styles/base/icons/icons/health/index.scss | 2 +- .../base/icons/icons/health/keyframes.scss | 2 +- .../base/icons/icons/health/placeholders.scss | 2 +- .../base/icons/icons/heart-fill/index.scss | 2 +- .../icons/icons/heart-fill/keyframes.scss | 2 +- .../icons/icons/heart-fill/placeholders.scss | 2 +- .../icons/icons/heart-fill/property-16.scss | 2 +- .../icons/icons/heart-fill/property-24.scss | 2 +- .../base/icons/icons/heart-off/index.scss | 2 +- .../base/icons/icons/heart-off/keyframes.scss | 2 +- .../icons/icons/heart-off/placeholders.scss | 2 +- .../icons/icons/heart-off/property-16.scss | 2 +- .../icons/icons/heart-off/property-24.scss | 2 +- .../styles/base/icons/icons/heart/index.scss | 2 +- .../base/icons/icons/heart/keyframes.scss | 2 +- .../base/icons/icons/heart/placeholders.scss | 2 +- .../base/icons/icons/heart/property-16.scss | 2 +- .../base/icons/icons/heart/property-24.scss | 2 +- .../icons/icons/help-circle-fill/index.scss | 2 +- .../icons/help-circle-fill/keyframes.scss | 2 +- .../icons/help-circle-fill/placeholders.scss | 2 +- .../icons/help-circle-outline/index.scss | 2 +- .../icons/help-circle-outline/keyframes.scss | 2 +- .../help-circle-outline/placeholders.scss | 2 +- .../styles/base/icons/icons/help/index.scss | 2 +- .../base/icons/icons/help/keyframes.scss | 2 +- .../base/icons/icons/help/placeholders.scss | 2 +- .../base/icons/icons/help/property-16.scss | 2 +- .../base/icons/icons/help/property-24.scss | 2 +- .../base/icons/icons/hexagon-fill/index.scss | 2 +- .../icons/icons/hexagon-fill/keyframes.scss | 2 +- .../icons/hexagon-fill/placeholders.scss | 2 +- .../icons/icons/hexagon-fill/property-16.scss | 2 +- .../icons/icons/hexagon-fill/property-24.scss | 2 +- .../base/icons/icons/hexagon/index.scss | 2 +- .../base/icons/icons/hexagon/keyframes.scss | 2 +- .../icons/icons/hexagon/placeholders.scss | 2 +- .../base/icons/icons/hexagon/property-16.scss | 2 +- .../base/icons/icons/hexagon/property-24.scss | 2 +- .../base/icons/icons/history/index.scss | 2 +- .../base/icons/icons/history/keyframes.scss | 2 +- .../icons/icons/history/placeholders.scss | 2 +- .../base/icons/icons/history/property-16.scss | 2 +- .../base/icons/icons/history/property-24.scss | 2 +- .../styles/base/icons/icons/home/index.scss | 2 +- .../base/icons/icons/home/keyframes.scss | 2 +- .../base/icons/icons/home/placeholders.scss | 2 +- .../base/icons/icons/home/property-16.scss | 2 +- .../base/icons/icons/home/property-24.scss | 2 +- .../base/icons/icons/hourglass/index.scss | 2 +- .../base/icons/icons/hourglass/keyframes.scss | 2 +- .../icons/icons/hourglass/placeholders.scss | 2 +- .../icons/icons/hourglass/property-16.scss | 2 +- .../icons/icons/hourglass/property-24.scss | 2 +- .../icons/icons/identity-service/index.scss | 2 +- .../icons/identity-service/keyframes.scss | 2 +- .../icons/identity-service/placeholders.scss | 2 +- .../icons/identity-service/property-16.scss | 2 +- .../icons/identity-service/property-24.scss | 2 +- .../base/icons/icons/identity-user/index.scss | 2 +- .../icons/icons/identity-user/keyframes.scss | 2 +- .../icons/identity-user/placeholders.scss | 2 +- .../icons/identity-user/property-16.scss | 2 +- .../icons/identity-user/property-24.scss | 2 +- .../styles/base/icons/icons/image/index.scss | 2 +- .../base/icons/icons/image/keyframes.scss | 2 +- .../base/icons/icons/image/placeholders.scss | 2 +- .../base/icons/icons/image/property-16.scss | 2 +- .../base/icons/icons/image/property-24.scss | 2 +- .../styles/base/icons/icons/inbox/index.scss | 2 +- .../base/icons/icons/inbox/keyframes.scss | 2 +- .../base/icons/icons/inbox/placeholders.scss | 2 +- .../base/icons/icons/inbox/property-16.scss | 2 +- .../base/icons/icons/inbox/property-24.scss | 2 +- .../app/styles/base/icons/icons/index.scss | 2 +- .../icons/icons/info-circle-fill/index.scss | 2 +- .../icons/info-circle-fill/keyframes.scss | 2 +- .../icons/info-circle-fill/placeholders.scss | 2 +- .../icons/info-circle-outline/index.scss | 2 +- .../icons/info-circle-outline/keyframes.scss | 2 +- .../info-circle-outline/placeholders.scss | 2 +- .../styles/base/icons/icons/info/index.scss | 2 +- .../base/icons/icons/info/keyframes.scss | 2 +- .../base/icons/icons/info/placeholders.scss | 2 +- .../base/icons/icons/info/property-16.scss | 2 +- .../base/icons/icons/info/property-24.scss | 2 +- .../base/icons/icons/jump-link/index.scss | 2 +- .../base/icons/icons/jump-link/keyframes.scss | 2 +- .../icons/icons/jump-link/placeholders.scss | 2 +- .../icons/icons/jump-link/property-16.scss | 2 +- .../icons/icons/jump-link/property-24.scss | 2 +- .../base/icons/icons/key-values/index.scss | 2 +- .../icons/icons/key-values/keyframes.scss | 2 +- .../icons/icons/key-values/placeholders.scss | 2 +- .../icons/icons/key-values/property-16.scss | 2 +- .../icons/icons/key-values/property-24.scss | 2 +- .../styles/base/icons/icons/key/index.scss | 2 +- .../base/icons/icons/key/keyframes.scss | 2 +- .../base/icons/icons/key/placeholders.scss | 2 +- .../base/icons/icons/key/property-16.scss | 2 +- .../base/icons/icons/key/property-24.scss | 2 +- .../base/icons/icons/keychain/index.scss | 2 +- .../base/icons/icons/keychain/keyframes.scss | 2 +- .../icons/icons/keychain/placeholders.scss | 2 +- .../icons/icons/keychain/property-16.scss | 2 +- .../icons/icons/keychain/property-24.scss | 2 +- .../icons/icons/kubernetes-color/index.scss | 2 +- .../icons/kubernetes-color/keyframes.scss | 2 +- .../icons/kubernetes-color/placeholders.scss | 2 +- .../icons/kubernetes-color/property-16.scss | 2 +- .../icons/kubernetes-color/property-24.scss | 2 +- .../base/icons/icons/kubernetes/index.scss | 2 +- .../icons/icons/kubernetes/keyframes.scss | 2 +- .../icons/icons/kubernetes/placeholders.scss | 2 +- .../icons/icons/kubernetes/property-16.scss | 2 +- .../icons/icons/kubernetes/property-24.scss | 2 +- .../base/icons/icons/labyrinth/index.scss | 2 +- .../base/icons/icons/labyrinth/keyframes.scss | 2 +- .../icons/icons/labyrinth/placeholders.scss | 2 +- .../icons/icons/labyrinth/property-16.scss | 2 +- .../icons/icons/labyrinth/property-24.scss | 2 +- .../styles/base/icons/icons/layers/index.scss | 2 +- .../base/icons/icons/layers/keyframes.scss | 2 +- .../base/icons/icons/layers/placeholders.scss | 2 +- .../base/icons/icons/layers/property-16.scss | 2 +- .../base/icons/icons/layers/property-24.scss | 2 +- .../styles/base/icons/icons/layout/index.scss | 2 +- .../base/icons/icons/layout/keyframes.scss | 2 +- .../base/icons/icons/layout/placeholders.scss | 2 +- .../base/icons/icons/layout/property-16.scss | 2 +- .../base/icons/icons/layout/property-24.scss | 2 +- .../base/icons/icons/learn-link/index.scss | 2 +- .../icons/icons/learn-link/keyframes.scss | 2 +- .../icons/icons/learn-link/placeholders.scss | 2 +- .../icons/icons/learn-link/property-16.scss | 2 +- .../icons/icons/learn-link/property-24.scss | 2 +- .../styles/base/icons/icons/learn/index.scss | 2 +- .../base/icons/icons/learn/keyframes.scss | 2 +- .../base/icons/icons/learn/placeholders.scss | 2 +- .../base/icons/icons/learn/property-16.scss | 2 +- .../base/icons/icons/learn/property-24.scss | 2 +- .../base/icons/icons/line-chart-up/index.scss | 2 +- .../icons/icons/line-chart-up/keyframes.scss | 2 +- .../icons/line-chart-up/placeholders.scss | 2 +- .../icons/line-chart-up/property-16.scss | 2 +- .../icons/line-chart-up/property-24.scss | 2 +- .../base/icons/icons/line-chart/index.scss | 2 +- .../icons/icons/line-chart/keyframes.scss | 2 +- .../icons/icons/line-chart/placeholders.scss | 2 +- .../icons/icons/line-chart/property-16.scss | 2 +- .../icons/icons/line-chart/property-24.scss | 2 +- .../styles/base/icons/icons/link/index.scss | 2 +- .../base/icons/icons/link/keyframes.scss | 2 +- .../base/icons/icons/link/placeholders.scss | 2 +- .../base/icons/icons/link/property-16.scss | 2 +- .../base/icons/icons/link/property-24.scss | 2 +- .../icons/icons/linkedin-color/index.scss | 2 +- .../icons/icons/linkedin-color/keyframes.scss | 2 +- .../icons/linkedin-color/placeholders.scss | 2 +- .../icons/linkedin-color/property-16.scss | 2 +- .../icons/linkedin-color/property-24.scss | 2 +- .../base/icons/icons/linkedin/index.scss | 2 +- .../base/icons/icons/linkedin/keyframes.scss | 2 +- .../icons/icons/linkedin/placeholders.scss | 2 +- .../icons/icons/linkedin/property-16.scss | 2 +- .../icons/icons/linkedin/property-24.scss | 2 +- .../styles/base/icons/icons/list/index.scss | 2 +- .../base/icons/icons/list/keyframes.scss | 2 +- .../base/icons/icons/list/placeholders.scss | 2 +- .../base/icons/icons/list/property-16.scss | 2 +- .../base/icons/icons/list/property-24.scss | 2 +- .../base/icons/icons/load-balancer/index.scss | 2 +- .../icons/icons/load-balancer/keyframes.scss | 2 +- .../icons/load-balancer/placeholders.scss | 2 +- .../icons/load-balancer/property-16.scss | 2 +- .../icons/load-balancer/property-24.scss | 2 +- .../icons/icons/loading-motion/index.scss | 2 +- .../icons/icons/loading-motion/keyframes.scss | 2 +- .../icons/loading-motion/placeholders.scss | 2 +- .../icons/loading-motion/property-16.scss | 2 +- .../icons/loading-motion/property-24.scss | 2 +- .../base/icons/icons/loading/index.scss | 2 +- .../base/icons/icons/loading/keyframes.scss | 2 +- .../icons/icons/loading/placeholders.scss | 2 +- .../base/icons/icons/loading/property-16.scss | 2 +- .../base/icons/icons/loading/property-24.scss | 2 +- .../icons/icons/lock-closed-fill/index.scss | 2 +- .../icons/lock-closed-fill/keyframes.scss | 2 +- .../icons/lock-closed-fill/placeholders.scss | 2 +- .../icons/lock-closed-outline/index.scss | 2 +- .../icons/lock-closed-outline/keyframes.scss | 2 +- .../lock-closed-outline/placeholders.scss | 2 +- .../base/icons/icons/lock-closed/index.scss | 2 +- .../icons/icons/lock-closed/keyframes.scss | 2 +- .../icons/icons/lock-closed/placeholders.scss | 2 +- .../base/icons/icons/lock-disabled/index.scss | 2 +- .../icons/icons/lock-disabled/keyframes.scss | 2 +- .../icons/lock-disabled/placeholders.scss | 2 +- .../base/icons/icons/lock-fill/index.scss | 2 +- .../base/icons/icons/lock-fill/keyframes.scss | 2 +- .../icons/icons/lock-fill/placeholders.scss | 2 +- .../icons/icons/lock-fill/property-16.scss | 2 +- .../icons/icons/lock-fill/property-24.scss | 2 +- .../base/icons/icons/lock-off/index.scss | 2 +- .../base/icons/icons/lock-off/keyframes.scss | 2 +- .../icons/icons/lock-off/placeholders.scss | 2 +- .../icons/icons/lock-off/property-16.scss | 2 +- .../icons/icons/lock-off/property-24.scss | 2 +- .../base/icons/icons/lock-open/index.scss | 2 +- .../base/icons/icons/lock-open/keyframes.scss | 2 +- .../icons/icons/lock-open/placeholders.scss | 2 +- .../styles/base/icons/icons/lock/index.scss | 2 +- .../base/icons/icons/lock/keyframes.scss | 2 +- .../base/icons/icons/lock/placeholders.scss | 2 +- .../base/icons/icons/lock/property-16.scss | 2 +- .../base/icons/icons/lock/property-24.scss | 2 +- .../icons/logo-alicloud-color/index.scss | 2 +- .../icons/logo-alicloud-color/keyframes.scss | 2 +- .../logo-alicloud-color/placeholders.scss | 2 +- .../icons/logo-alicloud-monochrome/index.scss | 2 +- .../logo-alicloud-monochrome/keyframes.scss | 2 +- .../placeholders.scss | 2 +- .../icons/icons/logo-auth0-color/index.scss | 2 +- .../icons/logo-auth0-color/keyframes.scss | 2 +- .../icons/logo-auth0-color/placeholders.scss | 2 +- .../icons/icons/logo-aws-color/index.scss | 2 +- .../icons/icons/logo-aws-color/keyframes.scss | 2 +- .../icons/logo-aws-color/placeholders.scss | 2 +- .../icons/logo-aws-monochrome/index.scss | 2 +- .../icons/logo-aws-monochrome/keyframes.scss | 2 +- .../logo-aws-monochrome/placeholders.scss | 2 +- .../icons/icons/logo-azure-color/index.scss | 2 +- .../icons/logo-azure-color/keyframes.scss | 2 +- .../icons/logo-azure-color/placeholders.scss | 2 +- .../icons/logo-azure-dev-ops-color/index.scss | 2 +- .../logo-azure-dev-ops-color/keyframes.scss | 2 +- .../placeholders.scss | 2 +- .../logo-azure-dev-ops-monochrome/index.scss | 2 +- .../keyframes.scss | 2 +- .../placeholders.scss | 2 +- .../icons/logo-azure-monochrome/index.scss | 2 +- .../logo-azure-monochrome/keyframes.scss | 2 +- .../logo-azure-monochrome/placeholders.scss | 2 +- .../icons/logo-bitbucket-color/index.scss | 2 +- .../icons/logo-bitbucket-color/keyframes.scss | 2 +- .../logo-bitbucket-color/placeholders.scss | 2 +- .../logo-bitbucket-monochrome/index.scss | 2 +- .../logo-bitbucket-monochrome/keyframes.scss | 2 +- .../placeholders.scss | 2 +- .../icons/logo-ember-circle-color/index.scss | 2 +- .../logo-ember-circle-color/keyframes.scss | 2 +- .../logo-ember-circle-color/placeholders.scss | 2 +- .../logo-ember-circle-color/property-16.scss | 2 +- .../logo-ember-circle-color/property-24.scss | 2 +- .../icons/icons/logo-gcp-color/index.scss | 2 +- .../icons/icons/logo-gcp-color/keyframes.scss | 2 +- .../icons/logo-gcp-color/placeholders.scss | 2 +- .../icons/logo-gcp-monochrome/index.scss | 2 +- .../icons/logo-gcp-monochrome/keyframes.scss | 2 +- .../logo-gcp-monochrome/placeholders.scss | 2 +- .../icons/icons/logo-github-color/index.scss | 2 +- .../icons/logo-github-color/keyframes.scss | 2 +- .../icons/logo-github-color/placeholders.scss | 2 +- .../icons/logo-github-monochrome/index.scss | 2 +- .../logo-github-monochrome/keyframes.scss | 2 +- .../logo-github-monochrome/placeholders.scss | 2 +- .../icons/icons/logo-gitlab-color/index.scss | 2 +- .../icons/logo-gitlab-color/keyframes.scss | 2 +- .../icons/logo-gitlab-color/placeholders.scss | 2 +- .../icons/logo-gitlab-monochrome/index.scss | 2 +- .../logo-gitlab-monochrome/keyframes.scss | 2 +- .../logo-gitlab-monochrome/placeholders.scss | 2 +- .../icons/icons/logo-glimmer-color/index.scss | 2 +- .../icons/logo-glimmer-color/keyframes.scss | 2 +- .../logo-glimmer-color/placeholders.scss | 2 +- .../icons/logo-glimmer-color/property-16.scss | 2 +- .../icons/logo-glimmer-color/property-24.scss | 2 +- .../icons/icons/logo-google-color/index.scss | 2 +- .../icons/logo-google-color/keyframes.scss | 2 +- .../icons/logo-google-color/placeholders.scss | 2 +- .../icons/logo-google-monochrome/index.scss | 2 +- .../logo-google-monochrome/keyframes.scss | 2 +- .../logo-google-monochrome/placeholders.scss | 2 +- .../icons/logo-hashicorp-color/index.scss | 2 +- .../icons/logo-hashicorp-color/keyframes.scss | 2 +- .../logo-hashicorp-color/placeholders.scss | 2 +- .../logo-hashicorp-color/property-16.scss | 2 +- .../logo-hashicorp-color/property-24.scss | 2 +- .../icons/icons/logo-jwt-color/index.scss | 2 +- .../icons/icons/logo-jwt-color/keyframes.scss | 2 +- .../icons/logo-jwt-color/placeholders.scss | 2 +- .../icons/logo-jwt-color/property-16.scss | 2 +- .../icons/logo-jwt-color/property-24.scss | 2 +- .../icons/logo-kubernetes-color/index.scss | 2 +- .../logo-kubernetes-color/keyframes.scss | 2 +- .../logo-kubernetes-color/placeholders.scss | 2 +- .../logo-kubernetes-monochrome/index.scss | 2 +- .../logo-kubernetes-monochrome/keyframes.scss | 2 +- .../placeholders.scss | 2 +- .../icons/logo-microsoft-color/index.scss | 2 +- .../icons/logo-microsoft-color/keyframes.scss | 2 +- .../logo-microsoft-color/placeholders.scss | 2 +- .../icons/icons/logo-oidc-color/index.scss | 2 +- .../icons/logo-oidc-color/keyframes.scss | 2 +- .../icons/logo-oidc-color/placeholders.scss | 2 +- .../icons/logo-oidc-color/property-16.scss | 2 +- .../icons/logo-oidc-color/property-24.scss | 2 +- .../icons/icons/logo-okta-color/index.scss | 2 +- .../icons/logo-okta-color/keyframes.scss | 2 +- .../icons/logo-okta-color/placeholders.scss | 2 +- .../icons/icons/logo-oracle-color/index.scss | 2 +- .../icons/logo-oracle-color/keyframes.scss | 2 +- .../icons/logo-oracle-color/placeholders.scss | 2 +- .../icons/logo-oracle-monochrome/index.scss | 2 +- .../logo-oracle-monochrome/keyframes.scss | 2 +- .../logo-oracle-monochrome/placeholders.scss | 2 +- .../icons/icons/logo-slack-color/index.scss | 2 +- .../icons/logo-slack-color/keyframes.scss | 2 +- .../icons/logo-slack-color/placeholders.scss | 2 +- .../icons/logo-slack-monochrome/index.scss | 2 +- .../logo-slack-monochrome/keyframes.scss | 2 +- .../logo-slack-monochrome/placeholders.scss | 2 +- .../icons/icons/logo-vmware-color/index.scss | 2 +- .../icons/logo-vmware-color/keyframes.scss | 2 +- .../icons/logo-vmware-color/placeholders.scss | 2 +- .../icons/logo-vmware-monochrome/index.scss | 2 +- .../logo-vmware-monochrome/keyframes.scss | 2 +- .../logo-vmware-monochrome/placeholders.scss | 2 +- .../base/icons/icons/mail-open/index.scss | 2 +- .../base/icons/icons/mail-open/keyframes.scss | 2 +- .../icons/icons/mail-open/placeholders.scss | 2 +- .../icons/icons/mail-open/property-16.scss | 2 +- .../icons/icons/mail-open/property-24.scss | 2 +- .../styles/base/icons/icons/mail/index.scss | 2 +- .../base/icons/icons/mail/keyframes.scss | 2 +- .../base/icons/icons/mail/placeholders.scss | 2 +- .../base/icons/icons/mail/property-16.scss | 2 +- .../base/icons/icons/mail/property-24.scss | 2 +- .../base/icons/icons/mainframe/index.scss | 2 +- .../base/icons/icons/mainframe/keyframes.scss | 2 +- .../icons/icons/mainframe/placeholders.scss | 2 +- .../icons/icons/mainframe/property-16.scss | 2 +- .../icons/icons/mainframe/property-24.scss | 2 +- .../base/icons/icons/map-pin/index.scss | 2 +- .../base/icons/icons/map-pin/keyframes.scss | 2 +- .../icons/icons/map-pin/placeholders.scss | 2 +- .../base/icons/icons/map-pin/property-16.scss | 2 +- .../base/icons/icons/map-pin/property-24.scss | 2 +- .../styles/base/icons/icons/map/index.scss | 2 +- .../base/icons/icons/map/keyframes.scss | 2 +- .../base/icons/icons/map/placeholders.scss | 2 +- .../base/icons/icons/map/property-16.scss | 2 +- .../base/icons/icons/map/property-24.scss | 2 +- .../base/icons/icons/maximize-alt/index.scss | 2 +- .../icons/icons/maximize-alt/keyframes.scss | 2 +- .../icons/maximize-alt/placeholders.scss | 2 +- .../icons/icons/maximize-alt/property-16.scss | 2 +- .../icons/icons/maximize-alt/property-24.scss | 2 +- .../base/icons/icons/maximize/index.scss | 2 +- .../base/icons/icons/maximize/keyframes.scss | 2 +- .../icons/icons/maximize/placeholders.scss | 2 +- .../icons/icons/maximize/property-16.scss | 2 +- .../icons/icons/maximize/property-24.scss | 2 +- .../styles/base/icons/icons/meh/index.scss | 2 +- .../base/icons/icons/meh/keyframes.scss | 2 +- .../base/icons/icons/meh/placeholders.scss | 2 +- .../base/icons/icons/meh/property-16.scss | 2 +- .../base/icons/icons/meh/property-24.scss | 2 +- .../styles/base/icons/icons/menu/index.scss | 2 +- .../base/icons/icons/menu/keyframes.scss | 2 +- .../base/icons/icons/menu/placeholders.scss | 2 +- .../base/icons/icons/menu/property-16.scss | 2 +- .../base/icons/icons/menu/property-24.scss | 2 +- .../styles/base/icons/icons/mesh/index.scss | 2 +- .../base/icons/icons/mesh/keyframes.scss | 2 +- .../base/icons/icons/mesh/placeholders.scss | 2 +- .../base/icons/icons/mesh/property-16.scss | 2 +- .../base/icons/icons/mesh/property-24.scss | 2 +- .../icons/message-circle-fill/index.scss | 2 +- .../icons/message-circle-fill/keyframes.scss | 2 +- .../message-circle-fill/placeholders.scss | 2 +- .../message-circle-fill/property-16.scss | 2 +- .../message-circle-fill/property-24.scss | 2 +- .../icons/icons/message-circle/index.scss | 2 +- .../icons/icons/message-circle/keyframes.scss | 2 +- .../icons/message-circle/placeholders.scss | 2 +- .../icons/message-circle/property-16.scss | 2 +- .../icons/message-circle/property-24.scss | 2 +- .../icons/message-square-fill/index.scss | 2 +- .../icons/message-square-fill/keyframes.scss | 2 +- .../message-square-fill/placeholders.scss | 2 +- .../message-square-fill/property-16.scss | 2 +- .../message-square-fill/property-24.scss | 2 +- .../icons/icons/message-square/index.scss | 2 +- .../icons/icons/message-square/keyframes.scss | 2 +- .../icons/message-square/placeholders.scss | 2 +- .../icons/message-square/property-16.scss | 2 +- .../icons/message-square/property-24.scss | 2 +- .../base/icons/icons/message/index.scss | 2 +- .../base/icons/icons/message/keyframes.scss | 2 +- .../icons/icons/message/placeholders.scss | 2 +- .../base/icons/icons/mic-off/index.scss | 2 +- .../base/icons/icons/mic-off/keyframes.scss | 2 +- .../icons/icons/mic-off/placeholders.scss | 2 +- .../base/icons/icons/mic-off/property-16.scss | 2 +- .../base/icons/icons/mic-off/property-24.scss | 2 +- .../styles/base/icons/icons/mic/index.scss | 2 +- .../base/icons/icons/mic/keyframes.scss | 2 +- .../base/icons/icons/mic/placeholders.scss | 2 +- .../base/icons/icons/mic/property-16.scss | 2 +- .../base/icons/icons/mic/property-24.scss | 2 +- .../icons/icons/microsoft-color/index.scss | 2 +- .../icons/microsoft-color/keyframes.scss | 2 +- .../icons/microsoft-color/placeholders.scss | 2 +- .../icons/microsoft-color/property-16.scss | 2 +- .../icons/microsoft-color/property-24.scss | 2 +- .../base/icons/icons/microsoft/index.scss | 2 +- .../base/icons/icons/microsoft/keyframes.scss | 2 +- .../icons/icons/microsoft/placeholders.scss | 2 +- .../icons/icons/microsoft/property-16.scss | 2 +- .../icons/icons/microsoft/property-24.scss | 2 +- .../base/icons/icons/migrate/index.scss | 2 +- .../base/icons/icons/migrate/keyframes.scss | 2 +- .../icons/icons/migrate/placeholders.scss | 2 +- .../base/icons/icons/migrate/property-16.scss | 2 +- .../base/icons/icons/migrate/property-24.scss | 2 +- .../base/icons/icons/minimize-alt/index.scss | 2 +- .../icons/icons/minimize-alt/keyframes.scss | 2 +- .../icons/minimize-alt/placeholders.scss | 2 +- .../icons/icons/minimize-alt/property-16.scss | 2 +- .../icons/icons/minimize-alt/property-24.scss | 2 +- .../base/icons/icons/minimize/index.scss | 2 +- .../base/icons/icons/minimize/keyframes.scss | 2 +- .../icons/icons/minimize/placeholders.scss | 2 +- .../icons/icons/minimize/property-16.scss | 2 +- .../icons/icons/minimize/property-24.scss | 2 +- .../icons/icons/minus-circle-fill/index.scss | 2 +- .../icons/minus-circle-fill/keyframes.scss | 2 +- .../icons/minus-circle-fill/placeholders.scss | 2 +- .../icons/minus-circle-outline/index.scss | 2 +- .../icons/minus-circle-outline/keyframes.scss | 2 +- .../minus-circle-outline/placeholders.scss | 2 +- .../base/icons/icons/minus-circle/index.scss | 2 +- .../icons/icons/minus-circle/keyframes.scss | 2 +- .../icons/minus-circle/placeholders.scss | 2 +- .../icons/icons/minus-circle/property-16.scss | 2 +- .../icons/icons/minus-circle/property-24.scss | 2 +- .../base/icons/icons/minus-plain/index.scss | 2 +- .../icons/icons/minus-plain/keyframes.scss | 2 +- .../icons/icons/minus-plain/placeholders.scss | 2 +- .../icons/icons/minus-plus-circle/index.scss | 2 +- .../icons/minus-plus-circle/keyframes.scss | 2 +- .../icons/minus-plus-circle/placeholders.scss | 2 +- .../icons/minus-plus-circle/property-16.scss | 2 +- .../icons/minus-plus-circle/property-24.scss | 2 +- .../icons/icons/minus-plus-square/index.scss | 2 +- .../icons/minus-plus-square/keyframes.scss | 2 +- .../icons/minus-plus-square/placeholders.scss | 2 +- .../icons/minus-plus-square/property-16.scss | 2 +- .../icons/minus-plus-square/property-24.scss | 2 +- .../base/icons/icons/minus-plus/index.scss | 2 +- .../icons/icons/minus-plus/keyframes.scss | 2 +- .../icons/icons/minus-plus/placeholders.scss | 2 +- .../icons/icons/minus-plus/property-16.scss | 2 +- .../icons/icons/minus-plus/property-24.scss | 2 +- .../icons/icons/minus-square-fill/index.scss | 2 +- .../icons/minus-square-fill/keyframes.scss | 2 +- .../icons/minus-square-fill/placeholders.scss | 2 +- .../base/icons/icons/minus-square/index.scss | 2 +- .../icons/icons/minus-square/keyframes.scss | 2 +- .../icons/minus-square/placeholders.scss | 2 +- .../icons/icons/minus-square/property-16.scss | 2 +- .../icons/icons/minus-square/property-24.scss | 2 +- .../styles/base/icons/icons/minus/index.scss | 2 +- .../base/icons/icons/minus/keyframes.scss | 2 +- .../base/icons/icons/minus/placeholders.scss | 2 +- .../base/icons/icons/minus/property-16.scss | 2 +- .../base/icons/icons/minus/property-24.scss | 2 +- .../styles/base/icons/icons/module/index.scss | 2 +- .../base/icons/icons/module/keyframes.scss | 2 +- .../base/icons/icons/module/placeholders.scss | 2 +- .../base/icons/icons/module/property-16.scss | 2 +- .../base/icons/icons/module/property-24.scss | 2 +- .../base/icons/icons/monitor/index.scss | 2 +- .../base/icons/icons/monitor/keyframes.scss | 2 +- .../icons/icons/monitor/placeholders.scss | 2 +- .../base/icons/icons/monitor/property-16.scss | 2 +- .../base/icons/icons/monitor/property-24.scss | 2 +- .../styles/base/icons/icons/moon/index.scss | 2 +- .../base/icons/icons/moon/keyframes.scss | 2 +- .../base/icons/icons/moon/placeholders.scss | 2 +- .../base/icons/icons/moon/property-16.scss | 2 +- .../base/icons/icons/moon/property-24.scss | 2 +- .../icons/icons/more-horizontal/index.scss | 2 +- .../icons/more-horizontal/keyframes.scss | 2 +- .../icons/more-horizontal/placeholders.scss | 2 +- .../icons/more-horizontal/property-16.scss | 2 +- .../icons/more-horizontal/property-24.scss | 2 +- .../base/icons/icons/more-vertical/index.scss | 2 +- .../icons/icons/more-vertical/keyframes.scss | 2 +- .../icons/more-vertical/placeholders.scss | 2 +- .../icons/more-vertical/property-16.scss | 2 +- .../icons/more-vertical/property-24.scss | 2 +- .../base/icons/icons/mouse-pointer/index.scss | 2 +- .../icons/icons/mouse-pointer/keyframes.scss | 2 +- .../icons/mouse-pointer/placeholders.scss | 2 +- .../icons/mouse-pointer/property-16.scss | 2 +- .../icons/mouse-pointer/property-24.scss | 2 +- .../styles/base/icons/icons/move/index.scss | 2 +- .../base/icons/icons/move/keyframes.scss | 2 +- .../base/icons/icons/move/placeholders.scss | 2 +- .../base/icons/icons/move/property-16.scss | 2 +- .../base/icons/icons/move/property-24.scss | 2 +- .../styles/base/icons/icons/music/index.scss | 2 +- .../base/icons/icons/music/keyframes.scss | 2 +- .../base/icons/icons/music/placeholders.scss | 2 +- .../base/icons/icons/music/property-16.scss | 2 +- .../base/icons/icons/music/property-24.scss | 2 +- .../icons/icons/navigation-alt/index.scss | 2 +- .../icons/icons/navigation-alt/keyframes.scss | 2 +- .../icons/navigation-alt/placeholders.scss | 2 +- .../icons/navigation-alt/property-16.scss | 2 +- .../icons/navigation-alt/property-24.scss | 2 +- .../base/icons/icons/navigation/index.scss | 2 +- .../icons/icons/navigation/keyframes.scss | 2 +- .../icons/icons/navigation/placeholders.scss | 2 +- .../icons/icons/navigation/property-16.scss | 2 +- .../icons/icons/navigation/property-24.scss | 2 +- .../base/icons/icons/network-alt/index.scss | 2 +- .../icons/icons/network-alt/keyframes.scss | 2 +- .../icons/icons/network-alt/placeholders.scss | 2 +- .../icons/icons/network-alt/property-16.scss | 2 +- .../icons/icons/network-alt/property-24.scss | 2 +- .../base/icons/icons/network/index.scss | 2 +- .../base/icons/icons/network/keyframes.scss | 2 +- .../icons/icons/network/placeholders.scss | 2 +- .../base/icons/icons/network/property-16.scss | 2 +- .../base/icons/icons/network/property-24.scss | 2 +- .../base/icons/icons/newspaper/index.scss | 2 +- .../base/icons/icons/newspaper/keyframes.scss | 2 +- .../icons/icons/newspaper/placeholders.scss | 2 +- .../icons/icons/newspaper/property-16.scss | 2 +- .../icons/icons/newspaper/property-24.scss | 2 +- .../styles/base/icons/icons/node/index.scss | 2 +- .../base/icons/icons/node/keyframes.scss | 2 +- .../base/icons/icons/node/placeholders.scss | 2 +- .../base/icons/icons/node/property-16.scss | 2 +- .../base/icons/icons/node/property-24.scss | 2 +- .../base/icons/icons/nomad-color/index.scss | 2 +- .../icons/icons/nomad-color/keyframes.scss | 2 +- .../icons/icons/nomad-color/placeholders.scss | 2 +- .../icons/icons/nomad-color/property-16.scss | 2 +- .../icons/icons/nomad-color/property-24.scss | 2 +- .../styles/base/icons/icons/nomad/index.scss | 2 +- .../base/icons/icons/nomad/keyframes.scss | 2 +- .../base/icons/icons/nomad/placeholders.scss | 2 +- .../base/icons/icons/nomad/property-16.scss | 2 +- .../base/icons/icons/nomad/property-24.scss | 2 +- .../icons/notification-disabled/index.scss | 2 +- .../notification-disabled/keyframes.scss | 2 +- .../notification-disabled/placeholders.scss | 2 +- .../icons/icons/notification-fill/index.scss | 2 +- .../icons/notification-fill/keyframes.scss | 2 +- .../icons/notification-fill/placeholders.scss | 2 +- .../icons/notification-outline/index.scss | 2 +- .../icons/notification-outline/keyframes.scss | 2 +- .../notification-outline/placeholders.scss | 2 +- .../base/icons/icons/octagon/index.scss | 2 +- .../base/icons/icons/octagon/keyframes.scss | 2 +- .../icons/icons/octagon/placeholders.scss | 2 +- .../base/icons/icons/octagon/property-16.scss | 2 +- .../base/icons/icons/octagon/property-24.scss | 2 +- .../base/icons/icons/okta-color/index.scss | 2 +- .../icons/icons/okta-color/keyframes.scss | 2 +- .../icons/icons/okta-color/placeholders.scss | 2 +- .../icons/icons/okta-color/property-16.scss | 2 +- .../icons/icons/okta-color/property-24.scss | 2 +- .../styles/base/icons/icons/okta/index.scss | 2 +- .../base/icons/icons/okta/keyframes.scss | 2 +- .../base/icons/icons/okta/placeholders.scss | 2 +- .../base/icons/icons/okta/property-16.scss | 2 +- .../base/icons/icons/okta/property-24.scss | 2 +- .../base/icons/icons/oracle-color/index.scss | 2 +- .../icons/icons/oracle-color/keyframes.scss | 2 +- .../icons/oracle-color/placeholders.scss | 2 +- .../icons/icons/oracle-color/property-16.scss | 2 +- .../icons/icons/oracle-color/property-24.scss | 2 +- .../styles/base/icons/icons/oracle/index.scss | 2 +- .../base/icons/icons/oracle/keyframes.scss | 2 +- .../base/icons/icons/oracle/placeholders.scss | 2 +- .../base/icons/icons/oracle/property-16.scss | 2 +- .../base/icons/icons/oracle/property-24.scss | 2 +- .../styles/base/icons/icons/org/index.scss | 2 +- .../base/icons/icons/org/keyframes.scss | 2 +- .../base/icons/icons/org/placeholders.scss | 2 +- .../base/icons/icons/org/property-16.scss | 2 +- .../base/icons/icons/org/property-24.scss | 2 +- .../base/icons/icons/outline/index.scss | 2 +- .../base/icons/icons/outline/keyframes.scss | 2 +- .../icons/icons/outline/placeholders.scss | 2 +- .../base/icons/icons/outline/property-16.scss | 2 +- .../base/icons/icons/outline/property-24.scss | 2 +- .../base/icons/icons/pack-color/index.scss | 2 +- .../icons/icons/pack-color/keyframes.scss | 2 +- .../icons/icons/pack-color/placeholders.scss | 2 +- .../icons/icons/pack-color/property-16.scss | 2 +- .../icons/icons/pack-color/property-24.scss | 2 +- .../styles/base/icons/icons/pack/index.scss | 2 +- .../base/icons/icons/pack/keyframes.scss | 2 +- .../base/icons/icons/pack/placeholders.scss | 2 +- .../base/icons/icons/pack/property-16.scss | 2 +- .../base/icons/icons/pack/property-24.scss | 2 +- .../base/icons/icons/package/index.scss | 2 +- .../base/icons/icons/package/keyframes.scss | 2 +- .../icons/icons/package/placeholders.scss | 2 +- .../base/icons/icons/package/property-16.scss | 2 +- .../base/icons/icons/package/property-24.scss | 2 +- .../base/icons/icons/packer-color/index.scss | 2 +- .../icons/icons/packer-color/keyframes.scss | 2 +- .../icons/packer-color/placeholders.scss | 2 +- .../icons/icons/packer-color/property-16.scss | 2 +- .../icons/icons/packer-color/property-24.scss | 2 +- .../styles/base/icons/icons/packer/index.scss | 2 +- .../base/icons/icons/packer/keyframes.scss | 2 +- .../base/icons/icons/packer/placeholders.scss | 2 +- .../base/icons/icons/packer/property-16.scss | 2 +- .../base/icons/icons/packer/property-24.scss | 2 +- .../base/icons/icons/page-outline/index.scss | 2 +- .../icons/icons/page-outline/keyframes.scss | 2 +- .../icons/page-outline/placeholders.scss | 2 +- .../base/icons/icons/paperclip/index.scss | 2 +- .../base/icons/icons/paperclip/keyframes.scss | 2 +- .../icons/icons/paperclip/placeholders.scss | 2 +- .../icons/icons/paperclip/property-16.scss | 2 +- .../icons/icons/paperclip/property-24.scss | 2 +- .../base/icons/icons/partner/index.scss | 2 +- .../base/icons/icons/partner/keyframes.scss | 2 +- .../icons/icons/partner/placeholders.scss | 2 +- .../styles/base/icons/icons/path/index.scss | 2 +- .../base/icons/icons/path/keyframes.scss | 2 +- .../base/icons/icons/path/placeholders.scss | 2 +- .../base/icons/icons/path/property-16.scss | 2 +- .../base/icons/icons/path/property-24.scss | 2 +- .../base/icons/icons/pause-circle/index.scss | 2 +- .../icons/icons/pause-circle/keyframes.scss | 2 +- .../icons/pause-circle/placeholders.scss | 2 +- .../icons/icons/pause-circle/property-16.scss | 2 +- .../icons/icons/pause-circle/property-24.scss | 2 +- .../styles/base/icons/icons/pause/index.scss | 2 +- .../base/icons/icons/pause/keyframes.scss | 2 +- .../base/icons/icons/pause/placeholders.scss | 2 +- .../base/icons/icons/pause/property-16.scss | 2 +- .../base/icons/icons/pause/property-24.scss | 2 +- .../base/icons/icons/pen-tool/index.scss | 2 +- .../base/icons/icons/pen-tool/keyframes.scss | 2 +- .../icons/icons/pen-tool/placeholders.scss | 2 +- .../icons/icons/pen-tool/property-16.scss | 2 +- .../icons/icons/pen-tool/property-24.scss | 2 +- .../base/icons/icons/pencil-tool/index.scss | 2 +- .../icons/icons/pencil-tool/keyframes.scss | 2 +- .../icons/icons/pencil-tool/placeholders.scss | 2 +- .../icons/icons/pencil-tool/property-16.scss | 2 +- .../icons/icons/pencil-tool/property-24.scss | 2 +- .../base/icons/icons/phone-call/index.scss | 2 +- .../icons/icons/phone-call/keyframes.scss | 2 +- .../icons/icons/phone-call/placeholders.scss | 2 +- .../icons/icons/phone-call/property-16.scss | 2 +- .../icons/icons/phone-call/property-24.scss | 2 +- .../base/icons/icons/phone-off/index.scss | 2 +- .../base/icons/icons/phone-off/keyframes.scss | 2 +- .../icons/icons/phone-off/placeholders.scss | 2 +- .../icons/icons/phone-off/property-16.scss | 2 +- .../icons/icons/phone-off/property-24.scss | 2 +- .../styles/base/icons/icons/phone/index.scss | 2 +- .../base/icons/icons/phone/keyframes.scss | 2 +- .../base/icons/icons/phone/placeholders.scss | 2 +- .../base/icons/icons/phone/property-16.scss | 2 +- .../base/icons/icons/phone/property-24.scss | 2 +- .../base/icons/icons/pie-chart/index.scss | 2 +- .../base/icons/icons/pie-chart/keyframes.scss | 2 +- .../icons/icons/pie-chart/placeholders.scss | 2 +- .../icons/icons/pie-chart/property-16.scss | 2 +- .../icons/icons/pie-chart/property-24.scss | 2 +- .../styles/base/icons/icons/pin/index.scss | 2 +- .../base/icons/icons/pin/keyframes.scss | 2 +- .../base/icons/icons/pin/placeholders.scss | 2 +- .../base/icons/icons/pin/property-16.scss | 2 +- .../base/icons/icons/pin/property-24.scss | 2 +- .../base/icons/icons/play-circle/index.scss | 2 +- .../icons/icons/play-circle/keyframes.scss | 2 +- .../icons/icons/play-circle/placeholders.scss | 2 +- .../icons/icons/play-circle/property-16.scss | 2 +- .../icons/icons/play-circle/property-24.scss | 2 +- .../base/icons/icons/play-fill/index.scss | 2 +- .../base/icons/icons/play-fill/keyframes.scss | 2 +- .../icons/icons/play-fill/placeholders.scss | 2 +- .../base/icons/icons/play-outline/index.scss | 2 +- .../icons/icons/play-outline/keyframes.scss | 2 +- .../icons/play-outline/placeholders.scss | 2 +- .../base/icons/icons/play-plain/index.scss | 2 +- .../icons/icons/play-plain/keyframes.scss | 2 +- .../icons/icons/play-plain/placeholders.scss | 2 +- .../styles/base/icons/icons/play/index.scss | 2 +- .../base/icons/icons/play/keyframes.scss | 2 +- .../base/icons/icons/play/placeholders.scss | 2 +- .../base/icons/icons/play/property-16.scss | 2 +- .../base/icons/icons/play/property-24.scss | 2 +- .../icons/icons/plus-circle-fill/index.scss | 2 +- .../icons/plus-circle-fill/keyframes.scss | 2 +- .../icons/plus-circle-fill/placeholders.scss | 2 +- .../icons/plus-circle-outline/index.scss | 2 +- .../icons/plus-circle-outline/keyframes.scss | 2 +- .../plus-circle-outline/placeholders.scss | 2 +- .../base/icons/icons/plus-circle/index.scss | 2 +- .../icons/icons/plus-circle/keyframes.scss | 2 +- .../icons/icons/plus-circle/placeholders.scss | 2 +- .../icons/icons/plus-circle/property-16.scss | 2 +- .../icons/icons/plus-circle/property-24.scss | 2 +- .../base/icons/icons/plus-plain/index.scss | 2 +- .../icons/icons/plus-plain/keyframes.scss | 2 +- .../icons/icons/plus-plain/placeholders.scss | 2 +- .../icons/icons/plus-square-fill/index.scss | 2 +- .../icons/plus-square-fill/keyframes.scss | 2 +- .../icons/plus-square-fill/placeholders.scss | 2 +- .../base/icons/icons/plus-square/index.scss | 2 +- .../icons/icons/plus-square/keyframes.scss | 2 +- .../icons/icons/plus-square/placeholders.scss | 2 +- .../icons/icons/plus-square/property-16.scss | 2 +- .../icons/icons/plus-square/property-24.scss | 2 +- .../styles/base/icons/icons/plus/index.scss | 2 +- .../base/icons/icons/plus/keyframes.scss | 2 +- .../base/icons/icons/plus/placeholders.scss | 2 +- .../base/icons/icons/plus/property-16.scss | 2 +- .../base/icons/icons/plus/property-24.scss | 2 +- .../styles/base/icons/icons/port/index.scss | 2 +- .../base/icons/icons/port/keyframes.scss | 2 +- .../base/icons/icons/port/placeholders.scss | 2 +- .../base/icons/icons/port/property-16.scss | 2 +- .../base/icons/icons/port/property-24.scss | 2 +- .../styles/base/icons/icons/power/index.scss | 2 +- .../base/icons/icons/power/keyframes.scss | 2 +- .../base/icons/icons/power/placeholders.scss | 2 +- .../base/icons/icons/power/property-16.scss | 2 +- .../base/icons/icons/power/property-24.scss | 2 +- .../base/icons/icons/printer/index.scss | 2 +- .../base/icons/icons/printer/keyframes.scss | 2 +- .../icons/icons/printer/placeholders.scss | 2 +- .../base/icons/icons/printer/property-16.scss | 2 +- .../base/icons/icons/printer/property-24.scss | 2 +- .../base/icons/icons/protocol/index.scss | 2 +- .../base/icons/icons/protocol/keyframes.scss | 2 +- .../icons/icons/protocol/placeholders.scss | 2 +- .../icons/icons/protocol/property-16.scss | 2 +- .../icons/icons/protocol/property-24.scss | 2 +- .../base/icons/icons/provider/index.scss | 2 +- .../base/icons/icons/provider/keyframes.scss | 2 +- .../icons/icons/provider/placeholders.scss | 2 +- .../icons/icons/provider/property-16.scss | 2 +- .../icons/icons/provider/property-24.scss | 2 +- .../icons/icons/public-default/index.scss | 2 +- .../icons/icons/public-default/keyframes.scss | 2 +- .../icons/public-default/placeholders.scss | 2 +- .../base/icons/icons/public-locked/index.scss | 2 +- .../icons/icons/public-locked/keyframes.scss | 2 +- .../icons/public-locked/placeholders.scss | 2 +- .../styles/base/icons/icons/queue/index.scss | 2 +- .../base/icons/icons/queue/keyframes.scss | 2 +- .../base/icons/icons/queue/placeholders.scss | 2 +- .../base/icons/icons/queue/property-16.scss | 2 +- .../base/icons/icons/queue/property-24.scss | 2 +- .../icons/radio-button-checked/index.scss | 2 +- .../icons/radio-button-checked/keyframes.scss | 2 +- .../radio-button-checked/placeholders.scss | 2 +- .../icons/radio-button-unchecked/index.scss | 2 +- .../radio-button-unchecked/keyframes.scss | 2 +- .../radio-button-unchecked/placeholders.scss | 2 +- .../styles/base/icons/icons/radio/index.scss | 2 +- .../base/icons/icons/radio/keyframes.scss | 2 +- .../base/icons/icons/radio/placeholders.scss | 2 +- .../base/icons/icons/radio/property-16.scss | 2 +- .../base/icons/icons/radio/property-24.scss | 2 +- .../styles/base/icons/icons/random/index.scss | 2 +- .../base/icons/icons/random/keyframes.scss | 2 +- .../base/icons/icons/random/placeholders.scss | 2 +- .../base/icons/icons/random/property-16.scss | 2 +- .../base/icons/icons/random/property-24.scss | 2 +- .../base/icons/icons/redirect/index.scss | 2 +- .../base/icons/icons/redirect/keyframes.scss | 2 +- .../icons/icons/redirect/placeholders.scss | 2 +- .../icons/icons/redirect/property-16.scss | 2 +- .../icons/icons/redirect/property-24.scss | 2 +- .../base/icons/icons/refresh-alert/index.scss | 2 +- .../icons/icons/refresh-alert/keyframes.scss | 2 +- .../icons/refresh-alert/placeholders.scss | 2 +- .../icons/icons/refresh-default/index.scss | 2 +- .../icons/refresh-default/keyframes.scss | 2 +- .../icons/refresh-default/placeholders.scss | 2 +- .../styles/base/icons/icons/reload/index.scss | 2 +- .../base/icons/icons/reload/keyframes.scss | 2 +- .../base/icons/icons/reload/placeholders.scss | 2 +- .../base/icons/icons/reload/property-16.scss | 2 +- .../base/icons/icons/reload/property-24.scss | 2 +- .../styles/base/icons/icons/remix/index.scss | 2 +- .../base/icons/icons/remix/keyframes.scss | 2 +- .../base/icons/icons/remix/placeholders.scss | 2 +- .../styles/base/icons/icons/repeat/index.scss | 2 +- .../base/icons/icons/repeat/keyframes.scss | 2 +- .../base/icons/icons/repeat/placeholders.scss | 2 +- .../base/icons/icons/repeat/property-16.scss | 2 +- .../base/icons/icons/repeat/property-24.scss | 2 +- .../icons/icons/replication-direct/index.scss | 2 +- .../icons/replication-direct/keyframes.scss | 2 +- .../replication-direct/placeholders.scss | 2 +- .../icons/replication-direct/property-16.scss | 2 +- .../icons/replication-direct/property-24.scss | 2 +- .../icons/icons/replication-perf/index.scss | 2 +- .../icons/replication-perf/keyframes.scss | 2 +- .../icons/replication-perf/placeholders.scss | 2 +- .../icons/replication-perf/property-16.scss | 2 +- .../icons/replication-perf/property-24.scss | 2 +- .../styles/base/icons/icons/rewind/index.scss | 2 +- .../base/icons/icons/rewind/keyframes.scss | 2 +- .../base/icons/icons/rewind/placeholders.scss | 2 +- .../base/icons/icons/rewind/property-16.scss | 2 +- .../base/icons/icons/rewind/property-24.scss | 2 +- .../styles/base/icons/icons/ribbon/index.scss | 2 +- .../base/icons/icons/ribbon/keyframes.scss | 2 +- .../base/icons/icons/ribbon/placeholders.scss | 2 +- .../styles/base/icons/icons/rocket/index.scss | 2 +- .../base/icons/icons/rocket/keyframes.scss | 2 +- .../base/icons/icons/rocket/placeholders.scss | 2 +- .../base/icons/icons/rocket/property-16.scss | 2 +- .../base/icons/icons/rocket/property-24.scss | 2 +- .../base/icons/icons/rotate-ccw/index.scss | 2 +- .../icons/icons/rotate-ccw/keyframes.scss | 2 +- .../icons/icons/rotate-ccw/placeholders.scss | 2 +- .../icons/icons/rotate-ccw/property-16.scss | 2 +- .../icons/icons/rotate-ccw/property-24.scss | 2 +- .../base/icons/icons/rotate-cw/index.scss | 2 +- .../base/icons/icons/rotate-cw/keyframes.scss | 2 +- .../icons/icons/rotate-cw/placeholders.scss | 2 +- .../icons/icons/rotate-cw/property-16.scss | 2 +- .../icons/icons/rotate-cw/property-24.scss | 2 +- .../styles/base/icons/icons/rss/index.scss | 2 +- .../base/icons/icons/rss/keyframes.scss | 2 +- .../base/icons/icons/rss/placeholders.scss | 2 +- .../base/icons/icons/rss/property-16.scss | 2 +- .../base/icons/icons/rss/property-24.scss | 2 +- .../styles/base/icons/icons/run/index.scss | 2 +- .../base/icons/icons/run/keyframes.scss | 2 +- .../base/icons/icons/run/placeholders.scss | 2 +- .../base/icons/icons/run/property-16.scss | 2 +- .../base/icons/icons/run/property-24.scss | 2 +- .../base/icons/icons/running/index.scss | 2 +- .../base/icons/icons/running/keyframes.scss | 2 +- .../icons/icons/running/placeholders.scss | 2 +- .../base/icons/icons/running/property-16.scss | 2 +- .../base/icons/icons/running/property-24.scss | 2 +- .../styles/base/icons/icons/save/index.scss | 2 +- .../base/icons/icons/save/keyframes.scss | 2 +- .../base/icons/icons/save/placeholders.scss | 2 +- .../base/icons/icons/save/property-16.scss | 2 +- .../base/icons/icons/save/property-24.scss | 2 +- .../base/icons/icons/scissors/index.scss | 2 +- .../base/icons/icons/scissors/keyframes.scss | 2 +- .../icons/icons/scissors/placeholders.scss | 2 +- .../icons/icons/scissors/property-16.scss | 2 +- .../icons/icons/scissors/property-24.scss | 2 +- .../base/icons/icons/search-color/index.scss | 2 +- .../icons/icons/search-color/keyframes.scss | 2 +- .../icons/search-color/placeholders.scss | 2 +- .../icons/icons/search-color/property-16.scss | 2 +- .../icons/icons/search-color/property-24.scss | 2 +- .../styles/base/icons/icons/search/index.scss | 2 +- .../base/icons/icons/search/keyframes.scss | 2 +- .../base/icons/icons/search/placeholders.scss | 2 +- .../base/icons/icons/search/property-16.scss | 2 +- .../base/icons/icons/search/property-24.scss | 2 +- .../styles/base/icons/icons/send/index.scss | 2 +- .../base/icons/icons/send/keyframes.scss | 2 +- .../base/icons/icons/send/placeholders.scss | 2 +- .../base/icons/icons/send/property-16.scss | 2 +- .../base/icons/icons/send/property-24.scss | 2 +- .../icons/icons/server-cluster/index.scss | 2 +- .../icons/icons/server-cluster/keyframes.scss | 2 +- .../icons/server-cluster/placeholders.scss | 2 +- .../icons/server-cluster/property-16.scss | 2 +- .../icons/server-cluster/property-24.scss | 2 +- .../styles/base/icons/icons/server/index.scss | 2 +- .../base/icons/icons/server/keyframes.scss | 2 +- .../base/icons/icons/server/placeholders.scss | 2 +- .../base/icons/icons/server/property-16.scss | 2 +- .../base/icons/icons/server/property-24.scss | 2 +- .../base/icons/icons/serverless/index.scss | 2 +- .../icons/icons/serverless/keyframes.scss | 2 +- .../icons/icons/serverless/placeholders.scss | 2 +- .../icons/icons/serverless/property-16.scss | 2 +- .../icons/icons/serverless/property-24.scss | 2 +- .../base/icons/icons/settings/index.scss | 2 +- .../base/icons/icons/settings/keyframes.scss | 2 +- .../icons/icons/settings/placeholders.scss | 2 +- .../icons/icons/settings/property-16.scss | 2 +- .../icons/icons/settings/property-24.scss | 2 +- .../styles/base/icons/icons/share/index.scss | 2 +- .../base/icons/icons/share/keyframes.scss | 2 +- .../base/icons/icons/share/placeholders.scss | 2 +- .../base/icons/icons/share/property-16.scss | 2 +- .../base/icons/icons/share/property-24.scss | 2 +- .../base/icons/icons/shield-alert/index.scss | 2 +- .../icons/icons/shield-alert/keyframes.scss | 2 +- .../icons/shield-alert/placeholders.scss | 2 +- .../icons/icons/shield-alert/property-16.scss | 2 +- .../icons/icons/shield-alert/property-24.scss | 2 +- .../base/icons/icons/shield-check/index.scss | 2 +- .../icons/icons/shield-check/keyframes.scss | 2 +- .../icons/shield-check/placeholders.scss | 2 +- .../icons/icons/shield-check/property-16.scss | 2 +- .../icons/icons/shield-check/property-24.scss | 2 +- .../base/icons/icons/shield-off/index.scss | 2 +- .../icons/icons/shield-off/keyframes.scss | 2 +- .../icons/icons/shield-off/placeholders.scss | 2 +- .../icons/icons/shield-off/property-16.scss | 2 +- .../icons/icons/shield-off/property-24.scss | 2 +- .../base/icons/icons/shield-x/index.scss | 2 +- .../base/icons/icons/shield-x/keyframes.scss | 2 +- .../icons/icons/shield-x/placeholders.scss | 2 +- .../icons/icons/shield-x/property-16.scss | 2 +- .../icons/icons/shield-x/property-24.scss | 2 +- .../styles/base/icons/icons/shield/index.scss | 2 +- .../base/icons/icons/shield/keyframes.scss | 2 +- .../base/icons/icons/shield/placeholders.scss | 2 +- .../base/icons/icons/shield/property-16.scss | 2 +- .../base/icons/icons/shield/property-24.scss | 2 +- .../base/icons/icons/shopping-bag/index.scss | 2 +- .../icons/icons/shopping-bag/keyframes.scss | 2 +- .../icons/shopping-bag/placeholders.scss | 2 +- .../icons/icons/shopping-bag/property-16.scss | 2 +- .../icons/icons/shopping-bag/property-24.scss | 2 +- .../base/icons/icons/shopping-cart/index.scss | 2 +- .../icons/icons/shopping-cart/keyframes.scss | 2 +- .../icons/shopping-cart/placeholders.scss | 2 +- .../icons/shopping-cart/property-16.scss | 2 +- .../icons/shopping-cart/property-24.scss | 2 +- .../base/icons/icons/shuffle/index.scss | 2 +- .../base/icons/icons/shuffle/keyframes.scss | 2 +- .../icons/icons/shuffle/placeholders.scss | 2 +- .../base/icons/icons/shuffle/property-16.scss | 2 +- .../base/icons/icons/shuffle/property-24.scss | 2 +- .../base/icons/icons/sidebar-hide/index.scss | 2 +- .../icons/icons/sidebar-hide/keyframes.scss | 2 +- .../icons/sidebar-hide/placeholders.scss | 2 +- .../icons/icons/sidebar-hide/property-16.scss | 2 +- .../icons/icons/sidebar-hide/property-24.scss | 2 +- .../base/icons/icons/sidebar-show/index.scss | 2 +- .../icons/icons/sidebar-show/keyframes.scss | 2 +- .../icons/sidebar-show/placeholders.scss | 2 +- .../icons/icons/sidebar-show/property-16.scss | 2 +- .../icons/icons/sidebar-show/property-24.scss | 2 +- .../base/icons/icons/sidebar/index.scss | 2 +- .../base/icons/icons/sidebar/keyframes.scss | 2 +- .../icons/icons/sidebar/placeholders.scss | 2 +- .../base/icons/icons/sidebar/property-16.scss | 2 +- .../base/icons/icons/sidebar/property-24.scss | 2 +- .../base/icons/icons/sign-in/index.scss | 2 +- .../base/icons/icons/sign-in/keyframes.scss | 2 +- .../icons/icons/sign-in/placeholders.scss | 2 +- .../base/icons/icons/sign-in/property-16.scss | 2 +- .../base/icons/icons/sign-in/property-24.scss | 2 +- .../base/icons/icons/sign-out/index.scss | 2 +- .../base/icons/icons/sign-out/keyframes.scss | 2 +- .../icons/icons/sign-out/placeholders.scss | 2 +- .../icons/icons/sign-out/property-16.scss | 2 +- .../icons/icons/sign-out/property-24.scss | 2 +- .../base/icons/icons/skip-back/index.scss | 2 +- .../base/icons/icons/skip-back/keyframes.scss | 2 +- .../icons/icons/skip-back/placeholders.scss | 2 +- .../icons/icons/skip-back/property-16.scss | 2 +- .../icons/icons/skip-back/property-24.scss | 2 +- .../base/icons/icons/skip-forward/index.scss | 2 +- .../icons/icons/skip-forward/keyframes.scss | 2 +- .../icons/skip-forward/placeholders.scss | 2 +- .../icons/icons/skip-forward/property-16.scss | 2 +- .../icons/icons/skip-forward/property-24.scss | 2 +- .../styles/base/icons/icons/skip/index.scss | 2 +- .../base/icons/icons/skip/keyframes.scss | 2 +- .../base/icons/icons/skip/placeholders.scss | 2 +- .../base/icons/icons/skip/property-16.scss | 2 +- .../base/icons/icons/skip/property-24.scss | 2 +- .../base/icons/icons/slack-color/index.scss | 2 +- .../icons/icons/slack-color/keyframes.scss | 2 +- .../icons/icons/slack-color/placeholders.scss | 2 +- .../icons/icons/slack-color/property-16.scss | 2 +- .../icons/icons/slack-color/property-24.scss | 2 +- .../styles/base/icons/icons/slack/index.scss | 2 +- .../base/icons/icons/slack/keyframes.scss | 2 +- .../base/icons/icons/slack/placeholders.scss | 2 +- .../base/icons/icons/slack/property-16.scss | 2 +- .../base/icons/icons/slack/property-24.scss | 2 +- .../base/icons/icons/slash-square/index.scss | 2 +- .../icons/icons/slash-square/keyframes.scss | 2 +- .../icons/slash-square/placeholders.scss | 2 +- .../icons/icons/slash-square/property-16.scss | 2 +- .../icons/icons/slash-square/property-24.scss | 2 +- .../styles/base/icons/icons/slash/index.scss | 2 +- .../base/icons/icons/slash/keyframes.scss | 2 +- .../base/icons/icons/slash/placeholders.scss | 2 +- .../base/icons/icons/slash/property-16.scss | 2 +- .../base/icons/icons/slash/property-24.scss | 2 +- .../base/icons/icons/sliders/index.scss | 2 +- .../base/icons/icons/sliders/keyframes.scss | 2 +- .../icons/icons/sliders/placeholders.scss | 2 +- .../base/icons/icons/sliders/property-16.scss | 2 +- .../base/icons/icons/sliders/property-24.scss | 2 +- .../base/icons/icons/smartphone/index.scss | 2 +- .../icons/icons/smartphone/keyframes.scss | 2 +- .../icons/icons/smartphone/placeholders.scss | 2 +- .../icons/icons/smartphone/property-16.scss | 2 +- .../icons/icons/smartphone/property-24.scss | 2 +- .../styles/base/icons/icons/smile/index.scss | 2 +- .../base/icons/icons/smile/keyframes.scss | 2 +- .../base/icons/icons/smile/placeholders.scss | 2 +- .../base/icons/icons/smile/property-16.scss | 2 +- .../base/icons/icons/smile/property-24.scss | 2 +- .../styles/base/icons/icons/socket/index.scss | 2 +- .../base/icons/icons/socket/keyframes.scss | 2 +- .../base/icons/icons/socket/placeholders.scss | 2 +- .../base/icons/icons/socket/property-16.scss | 2 +- .../base/icons/icons/socket/property-24.scss | 2 +- .../base/icons/icons/sort-asc/index.scss | 2 +- .../base/icons/icons/sort-asc/keyframes.scss | 2 +- .../icons/icons/sort-asc/placeholders.scss | 2 +- .../icons/icons/sort-asc/property-16.scss | 2 +- .../icons/icons/sort-asc/property-24.scss | 2 +- .../base/icons/icons/sort-desc/index.scss | 2 +- .../base/icons/icons/sort-desc/keyframes.scss | 2 +- .../icons/icons/sort-desc/placeholders.scss | 2 +- .../icons/icons/sort-desc/property-16.scss | 2 +- .../icons/icons/sort-desc/property-24.scss | 2 +- .../styles/base/icons/icons/sort/index.scss | 2 +- .../base/icons/icons/sort/keyframes.scss | 2 +- .../base/icons/icons/sort/placeholders.scss | 2 +- .../base/icons/icons/source-file/index.scss | 2 +- .../icons/icons/source-file/keyframes.scss | 2 +- .../icons/icons/source-file/placeholders.scss | 2 +- .../base/icons/icons/speaker/index.scss | 2 +- .../base/icons/icons/speaker/keyframes.scss | 2 +- .../icons/icons/speaker/placeholders.scss | 2 +- .../base/icons/icons/speaker/property-16.scss | 2 +- .../base/icons/icons/speaker/property-24.scss | 2 +- .../base/icons/icons/square-fill/index.scss | 2 +- .../icons/icons/square-fill/keyframes.scss | 2 +- .../icons/icons/square-fill/placeholders.scss | 2 +- .../icons/icons/square-fill/property-16.scss | 2 +- .../icons/icons/square-fill/property-24.scss | 2 +- .../styles/base/icons/icons/square/index.scss | 2 +- .../base/icons/icons/square/keyframes.scss | 2 +- .../base/icons/icons/square/placeholders.scss | 2 +- .../base/icons/icons/square/property-16.scss | 2 +- .../base/icons/icons/square/property-24.scss | 2 +- .../base/icons/icons/star-circle/index.scss | 2 +- .../icons/icons/star-circle/keyframes.scss | 2 +- .../icons/icons/star-circle/placeholders.scss | 2 +- .../icons/icons/star-circle/property-16.scss | 2 +- .../icons/icons/star-circle/property-24.scss | 2 +- .../base/icons/icons/star-fill/index.scss | 2 +- .../base/icons/icons/star-fill/keyframes.scss | 2 +- .../icons/icons/star-fill/placeholders.scss | 2 +- .../icons/icons/star-fill/property-16.scss | 2 +- .../icons/icons/star-fill/property-24.scss | 2 +- .../base/icons/icons/star-off/index.scss | 2 +- .../base/icons/icons/star-off/keyframes.scss | 2 +- .../icons/icons/star-off/placeholders.scss | 2 +- .../icons/icons/star-off/property-16.scss | 2 +- .../icons/icons/star-off/property-24.scss | 2 +- .../base/icons/icons/star-outline/index.scss | 2 +- .../icons/icons/star-outline/keyframes.scss | 2 +- .../icons/star-outline/placeholders.scss | 2 +- .../styles/base/icons/icons/star/index.scss | 2 +- .../base/icons/icons/star/keyframes.scss | 2 +- .../base/icons/icons/star/placeholders.scss | 2 +- .../base/icons/icons/star/property-16.scss | 2 +- .../base/icons/icons/star/property-24.scss | 2 +- .../base/icons/icons/stop-circle/index.scss | 2 +- .../icons/icons/stop-circle/keyframes.scss | 2 +- .../icons/icons/stop-circle/placeholders.scss | 2 +- .../icons/icons/stop-circle/property-16.scss | 2 +- .../icons/icons/stop-circle/property-24.scss | 2 +- .../base/icons/icons/sub-left/index.scss | 2 +- .../base/icons/icons/sub-left/keyframes.scss | 2 +- .../icons/icons/sub-left/placeholders.scss | 2 +- .../base/icons/icons/sub-right/index.scss | 2 +- .../base/icons/icons/sub-right/keyframes.scss | 2 +- .../icons/icons/sub-right/placeholders.scss | 2 +- .../styles/base/icons/icons/sun/index.scss | 2 +- .../base/icons/icons/sun/keyframes.scss | 2 +- .../base/icons/icons/sun/placeholders.scss | 2 +- .../base/icons/icons/sun/property-16.scss | 2 +- .../base/icons/icons/sun/property-24.scss | 2 +- .../base/icons/icons/support/index.scss | 2 +- .../base/icons/icons/support/keyframes.scss | 2 +- .../icons/icons/support/placeholders.scss | 2 +- .../base/icons/icons/support/property-16.scss | 2 +- .../base/icons/icons/support/property-24.scss | 2 +- .../icons/icons/swap-horizontal/index.scss | 2 +- .../icons/swap-horizontal/keyframes.scss | 2 +- .../icons/swap-horizontal/placeholders.scss | 2 +- .../icons/swap-horizontal/property-16.scss | 2 +- .../icons/swap-horizontal/property-24.scss | 2 +- .../base/icons/icons/swap-vertical/index.scss | 2 +- .../icons/icons/swap-vertical/keyframes.scss | 2 +- .../icons/swap-vertical/placeholders.scss | 2 +- .../icons/swap-vertical/property-16.scss | 2 +- .../icons/swap-vertical/property-24.scss | 2 +- .../base/icons/icons/switcher/index.scss | 2 +- .../base/icons/icons/switcher/keyframes.scss | 2 +- .../icons/icons/switcher/placeholders.scss | 2 +- .../icons/icons/switcher/property-16.scss | 2 +- .../icons/icons/switcher/property-24.scss | 2 +- .../base/icons/icons/sync-alert/index.scss | 2 +- .../icons/icons/sync-alert/keyframes.scss | 2 +- .../icons/icons/sync-alert/placeholders.scss | 2 +- .../icons/icons/sync-alert/property-16.scss | 2 +- .../icons/icons/sync-alert/property-24.scss | 2 +- .../base/icons/icons/sync-reverse/index.scss | 2 +- .../icons/icons/sync-reverse/keyframes.scss | 2 +- .../icons/sync-reverse/placeholders.scss | 2 +- .../icons/icons/sync-reverse/property-16.scss | 2 +- .../icons/icons/sync-reverse/property-24.scss | 2 +- .../styles/base/icons/icons/sync/index.scss | 2 +- .../base/icons/icons/sync/keyframes.scss | 2 +- .../base/icons/icons/sync/placeholders.scss | 2 +- .../base/icons/icons/sync/property-16.scss | 2 +- .../base/icons/icons/sync/property-24.scss | 2 +- .../styles/base/icons/icons/tablet/index.scss | 2 +- .../base/icons/icons/tablet/keyframes.scss | 2 +- .../base/icons/icons/tablet/placeholders.scss | 2 +- .../base/icons/icons/tablet/property-16.scss | 2 +- .../base/icons/icons/tablet/property-24.scss | 2 +- .../styles/base/icons/icons/tag/index.scss | 2 +- .../base/icons/icons/tag/keyframes.scss | 2 +- .../base/icons/icons/tag/placeholders.scss | 2 +- .../base/icons/icons/tag/property-16.scss | 2 +- .../base/icons/icons/tag/property-24.scss | 2 +- .../styles/base/icons/icons/target/index.scss | 2 +- .../base/icons/icons/target/keyframes.scss | 2 +- .../base/icons/icons/target/placeholders.scss | 2 +- .../base/icons/icons/target/property-16.scss | 2 +- .../base/icons/icons/target/property-24.scss | 2 +- .../icons/icons/terminal-screen/index.scss | 2 +- .../icons/terminal-screen/keyframes.scss | 2 +- .../icons/terminal-screen/placeholders.scss | 2 +- .../icons/terminal-screen/property-16.scss | 2 +- .../icons/terminal-screen/property-24.scss | 2 +- .../base/icons/icons/terminal/index.scss | 2 +- .../base/icons/icons/terminal/keyframes.scss | 2 +- .../icons/icons/terminal/placeholders.scss | 2 +- .../icons/icons/terminal/property-16.scss | 2 +- .../icons/icons/terminal/property-24.scss | 2 +- .../icons/icons/terraform-color/index.scss | 2 +- .../icons/terraform-color/keyframes.scss | 2 +- .../icons/terraform-color/placeholders.scss | 2 +- .../icons/terraform-color/property-16.scss | 2 +- .../icons/terraform-color/property-24.scss | 2 +- .../base/icons/icons/terraform/index.scss | 2 +- .../base/icons/icons/terraform/keyframes.scss | 2 +- .../icons/icons/terraform/placeholders.scss | 2 +- .../icons/icons/terraform/property-16.scss | 2 +- .../icons/icons/terraform/property-24.scss | 2 +- .../base/icons/icons/thumbs-down/index.scss | 2 +- .../icons/icons/thumbs-down/keyframes.scss | 2 +- .../icons/icons/thumbs-down/placeholders.scss | 2 +- .../icons/icons/thumbs-down/property-16.scss | 2 +- .../icons/icons/thumbs-down/property-24.scss | 2 +- .../base/icons/icons/thumbs-up/index.scss | 2 +- .../base/icons/icons/thumbs-up/keyframes.scss | 2 +- .../icons/icons/thumbs-up/placeholders.scss | 2 +- .../icons/icons/thumbs-up/property-16.scss | 2 +- .../icons/icons/thumbs-up/property-24.scss | 2 +- .../base/icons/icons/toggle-left/index.scss | 2 +- .../icons/icons/toggle-left/keyframes.scss | 2 +- .../icons/icons/toggle-left/placeholders.scss | 2 +- .../icons/icons/toggle-left/property-16.scss | 2 +- .../icons/icons/toggle-left/property-24.scss | 2 +- .../base/icons/icons/toggle-right/index.scss | 2 +- .../icons/icons/toggle-right/keyframes.scss | 2 +- .../icons/toggle-right/placeholders.scss | 2 +- .../icons/icons/toggle-right/property-16.scss | 2 +- .../icons/icons/toggle-right/property-24.scss | 2 +- .../styles/base/icons/icons/token/index.scss | 2 +- .../base/icons/icons/token/keyframes.scss | 2 +- .../base/icons/icons/token/placeholders.scss | 2 +- .../base/icons/icons/token/property-16.scss | 2 +- .../base/icons/icons/token/property-24.scss | 2 +- .../styles/base/icons/icons/tools/index.scss | 2 +- .../base/icons/icons/tools/keyframes.scss | 2 +- .../base/icons/icons/tools/placeholders.scss | 2 +- .../base/icons/icons/tools/property-16.scss | 2 +- .../base/icons/icons/tools/property-24.scss | 2 +- .../styles/base/icons/icons/top/index.scss | 2 +- .../base/icons/icons/top/keyframes.scss | 2 +- .../base/icons/icons/top/placeholders.scss | 2 +- .../base/icons/icons/top/property-16.scss | 2 +- .../base/icons/icons/top/property-24.scss | 2 +- .../styles/base/icons/icons/trash/index.scss | 2 +- .../base/icons/icons/trash/keyframes.scss | 2 +- .../base/icons/icons/trash/placeholders.scss | 2 +- .../base/icons/icons/trash/property-16.scss | 2 +- .../base/icons/icons/trash/property-24.scss | 2 +- .../base/icons/icons/trend-down/index.scss | 2 +- .../icons/icons/trend-down/keyframes.scss | 2 +- .../icons/icons/trend-down/placeholders.scss | 2 +- .../icons/icons/trend-down/property-16.scss | 2 +- .../icons/icons/trend-down/property-24.scss | 2 +- .../base/icons/icons/trend-up/index.scss | 2 +- .../base/icons/icons/trend-up/keyframes.scss | 2 +- .../icons/icons/trend-up/placeholders.scss | 2 +- .../icons/icons/trend-up/property-16.scss | 2 +- .../icons/icons/trend-up/property-24.scss | 2 +- .../base/icons/icons/triangle-fill/index.scss | 2 +- .../icons/icons/triangle-fill/keyframes.scss | 2 +- .../icons/triangle-fill/placeholders.scss | 2 +- .../icons/triangle-fill/property-16.scss | 2 +- .../icons/triangle-fill/property-24.scss | 2 +- .../base/icons/icons/triangle/index.scss | 2 +- .../base/icons/icons/triangle/keyframes.scss | 2 +- .../icons/icons/triangle/placeholders.scss | 2 +- .../icons/icons/triangle/property-16.scss | 2 +- .../icons/icons/triangle/property-24.scss | 2 +- .../styles/base/icons/icons/truck/index.scss | 2 +- .../base/icons/icons/truck/keyframes.scss | 2 +- .../base/icons/icons/truck/placeholders.scss | 2 +- .../base/icons/icons/truck/property-16.scss | 2 +- .../base/icons/icons/truck/property-24.scss | 2 +- .../styles/base/icons/icons/tune/index.scss | 2 +- .../base/icons/icons/tune/keyframes.scss | 2 +- .../base/icons/icons/tune/placeholders.scss | 2 +- .../app/styles/base/icons/icons/tv/index.scss | 2 +- .../styles/base/icons/icons/tv/keyframes.scss | 2 +- .../base/icons/icons/tv/placeholders.scss | 2 +- .../base/icons/icons/tv/property-16.scss | 2 +- .../base/icons/icons/tv/property-24.scss | 2 +- .../base/icons/icons/twitch-color/index.scss | 2 +- .../icons/icons/twitch-color/keyframes.scss | 2 +- .../icons/twitch-color/placeholders.scss | 2 +- .../icons/icons/twitch-color/property-16.scss | 2 +- .../icons/icons/twitch-color/property-24.scss | 2 +- .../styles/base/icons/icons/twitch/index.scss | 2 +- .../base/icons/icons/twitch/keyframes.scss | 2 +- .../base/icons/icons/twitch/placeholders.scss | 2 +- .../base/icons/icons/twitch/property-16.scss | 2 +- .../base/icons/icons/twitch/property-24.scss | 2 +- .../base/icons/icons/twitter-color/index.scss | 2 +- .../icons/icons/twitter-color/keyframes.scss | 2 +- .../icons/twitter-color/placeholders.scss | 2 +- .../icons/twitter-color/property-16.scss | 2 +- .../icons/twitter-color/property-24.scss | 2 +- .../base/icons/icons/twitter/index.scss | 2 +- .../base/icons/icons/twitter/keyframes.scss | 2 +- .../icons/icons/twitter/placeholders.scss | 2 +- .../base/icons/icons/twitter/property-16.scss | 2 +- .../base/icons/icons/twitter/property-24.scss | 2 +- .../styles/base/icons/icons/type/index.scss | 2 +- .../base/icons/icons/type/keyframes.scss | 2 +- .../base/icons/icons/type/placeholders.scss | 2 +- .../base/icons/icons/type/property-16.scss | 2 +- .../base/icons/icons/type/property-24.scss | 2 +- .../base/icons/icons/unfold-close/index.scss | 2 +- .../icons/icons/unfold-close/keyframes.scss | 2 +- .../icons/unfold-close/placeholders.scss | 2 +- .../icons/icons/unfold-close/property-16.scss | 2 +- .../icons/icons/unfold-close/property-24.scss | 2 +- .../base/icons/icons/unfold-less/index.scss | 2 +- .../icons/icons/unfold-less/keyframes.scss | 2 +- .../icons/icons/unfold-less/placeholders.scss | 2 +- .../base/icons/icons/unfold-more/index.scss | 2 +- .../icons/icons/unfold-more/keyframes.scss | 2 +- .../icons/icons/unfold-more/placeholders.scss | 2 +- .../base/icons/icons/unfold-open/index.scss | 2 +- .../icons/icons/unfold-open/keyframes.scss | 2 +- .../icons/icons/unfold-open/placeholders.scss | 2 +- .../icons/icons/unfold-open/property-16.scss | 2 +- .../icons/icons/unfold-open/property-24.scss | 2 +- .../styles/base/icons/icons/union/index.scss | 2 +- .../base/icons/icons/union/keyframes.scss | 2 +- .../base/icons/icons/union/placeholders.scss | 2 +- .../base/icons/icons/union/property-16.scss | 2 +- .../base/icons/icons/union/property-24.scss | 2 +- .../styles/base/icons/icons/unlock/index.scss | 2 +- .../base/icons/icons/unlock/keyframes.scss | 2 +- .../base/icons/icons/unlock/placeholders.scss | 2 +- .../base/icons/icons/unlock/property-16.scss | 2 +- .../base/icons/icons/unlock/property-24.scss | 2 +- .../styles/base/icons/icons/upload/index.scss | 2 +- .../base/icons/icons/upload/keyframes.scss | 2 +- .../base/icons/icons/upload/placeholders.scss | 2 +- .../base/icons/icons/upload/property-16.scss | 2 +- .../base/icons/icons/upload/property-24.scss | 2 +- .../base/icons/icons/user-add/index.scss | 2 +- .../base/icons/icons/user-add/keyframes.scss | 2 +- .../icons/icons/user-add/placeholders.scss | 2 +- .../base/icons/icons/user-check/index.scss | 2 +- .../icons/icons/user-check/keyframes.scss | 2 +- .../icons/icons/user-check/placeholders.scss | 2 +- .../icons/icons/user-check/property-16.scss | 2 +- .../icons/icons/user-check/property-24.scss | 2 +- .../icons/icons/user-circle-fill/index.scss | 2 +- .../icons/user-circle-fill/keyframes.scss | 2 +- .../icons/user-circle-fill/placeholders.scss | 2 +- .../icons/user-circle-fill/property-16.scss | 2 +- .../icons/user-circle-fill/property-24.scss | 2 +- .../base/icons/icons/user-circle/index.scss | 2 +- .../icons/icons/user-circle/keyframes.scss | 2 +- .../icons/icons/user-circle/placeholders.scss | 2 +- .../icons/icons/user-circle/property-16.scss | 2 +- .../icons/icons/user-circle/property-24.scss | 2 +- .../base/icons/icons/user-minus/index.scss | 2 +- .../icons/icons/user-minus/keyframes.scss | 2 +- .../icons/icons/user-minus/placeholders.scss | 2 +- .../icons/icons/user-minus/property-16.scss | 2 +- .../icons/icons/user-minus/property-24.scss | 2 +- .../icons/icons/user-organization/index.scss | 2 +- .../icons/user-organization/keyframes.scss | 2 +- .../icons/user-organization/placeholders.scss | 2 +- .../base/icons/icons/user-plain/index.scss | 2 +- .../icons/icons/user-plain/keyframes.scss | 2 +- .../icons/icons/user-plain/placeholders.scss | 2 +- .../base/icons/icons/user-plus/index.scss | 2 +- .../base/icons/icons/user-plus/keyframes.scss | 2 +- .../icons/icons/user-plus/placeholders.scss | 2 +- .../icons/icons/user-plus/property-16.scss | 2 +- .../icons/icons/user-plus/property-24.scss | 2 +- .../icons/icons/user-square-fill/index.scss | 2 +- .../icons/user-square-fill/keyframes.scss | 2 +- .../icons/user-square-fill/placeholders.scss | 2 +- .../icons/user-square-outline/index.scss | 2 +- .../icons/user-square-outline/keyframes.scss | 2 +- .../user-square-outline/placeholders.scss | 2 +- .../base/icons/icons/user-team/index.scss | 2 +- .../base/icons/icons/user-team/keyframes.scss | 2 +- .../icons/icons/user-team/placeholders.scss | 2 +- .../styles/base/icons/icons/user-x/index.scss | 2 +- .../base/icons/icons/user-x/keyframes.scss | 2 +- .../base/icons/icons/user-x/placeholders.scss | 2 +- .../base/icons/icons/user-x/property-16.scss | 2 +- .../base/icons/icons/user-x/property-24.scss | 2 +- .../styles/base/icons/icons/user/index.scss | 2 +- .../base/icons/icons/user/keyframes.scss | 2 +- .../base/icons/icons/user/placeholders.scss | 2 +- .../base/icons/icons/user/property-16.scss | 2 +- .../base/icons/icons/user/property-24.scss | 2 +- .../styles/base/icons/icons/users/index.scss | 2 +- .../base/icons/icons/users/keyframes.scss | 2 +- .../base/icons/icons/users/placeholders.scss | 2 +- .../base/icons/icons/users/property-16.scss | 2 +- .../base/icons/icons/users/property-24.scss | 2 +- .../base/icons/icons/vagrant-color/index.scss | 2 +- .../icons/icons/vagrant-color/keyframes.scss | 2 +- .../icons/vagrant-color/placeholders.scss | 2 +- .../icons/vagrant-color/property-16.scss | 2 +- .../icons/vagrant-color/property-24.scss | 2 +- .../base/icons/icons/vagrant/index.scss | 2 +- .../base/icons/icons/vagrant/keyframes.scss | 2 +- .../icons/icons/vagrant/placeholders.scss | 2 +- .../base/icons/icons/vagrant/property-16.scss | 2 +- .../base/icons/icons/vagrant/property-24.scss | 2 +- .../base/icons/icons/vault-color/index.scss | 2 +- .../icons/icons/vault-color/keyframes.scss | 2 +- .../icons/icons/vault-color/placeholders.scss | 2 +- .../icons/icons/vault-color/property-16.scss | 2 +- .../icons/icons/vault-color/property-24.scss | 2 +- .../styles/base/icons/icons/vault/index.scss | 2 +- .../base/icons/icons/vault/keyframes.scss | 2 +- .../base/icons/icons/vault/placeholders.scss | 2 +- .../base/icons/icons/vault/property-16.scss | 2 +- .../base/icons/icons/vault/property-24.scss | 2 +- .../base/icons/icons/verified/index.scss | 2 +- .../base/icons/icons/verified/keyframes.scss | 2 +- .../icons/icons/verified/placeholders.scss | 2 +- .../icons/icons/verified/property-16.scss | 2 +- .../icons/icons/verified/property-24.scss | 2 +- .../base/icons/icons/video-off/index.scss | 2 +- .../base/icons/icons/video-off/keyframes.scss | 2 +- .../icons/icons/video-off/placeholders.scss | 2 +- .../icons/icons/video-off/property-16.scss | 2 +- .../icons/icons/video-off/property-24.scss | 2 +- .../styles/base/icons/icons/video/index.scss | 2 +- .../base/icons/icons/video/keyframes.scss | 2 +- .../base/icons/icons/video/placeholders.scss | 2 +- .../base/icons/icons/video/property-16.scss | 2 +- .../base/icons/icons/video/property-24.scss | 2 +- .../icons/icons/visibility-hide/index.scss | 2 +- .../icons/visibility-hide/keyframes.scss | 2 +- .../icons/visibility-hide/placeholders.scss | 2 +- .../icons/icons/visibility-show/index.scss | 2 +- .../icons/visibility-show/keyframes.scss | 2 +- .../icons/visibility-show/placeholders.scss | 2 +- .../base/icons/icons/vmware-color/index.scss | 2 +- .../icons/icons/vmware-color/keyframes.scss | 2 +- .../icons/vmware-color/placeholders.scss | 2 +- .../icons/icons/vmware-color/property-16.scss | 2 +- .../icons/icons/vmware-color/property-24.scss | 2 +- .../styles/base/icons/icons/vmware/index.scss | 2 +- .../base/icons/icons/vmware/keyframes.scss | 2 +- .../base/icons/icons/vmware/placeholders.scss | 2 +- .../base/icons/icons/vmware/property-16.scss | 2 +- .../base/icons/icons/vmware/property-24.scss | 2 +- .../base/icons/icons/volume-2/index.scss | 2 +- .../base/icons/icons/volume-2/keyframes.scss | 2 +- .../icons/icons/volume-2/placeholders.scss | 2 +- .../icons/icons/volume-2/property-16.scss | 2 +- .../icons/icons/volume-2/property-24.scss | 2 +- .../base/icons/icons/volume-down/index.scss | 2 +- .../icons/icons/volume-down/keyframes.scss | 2 +- .../icons/icons/volume-down/placeholders.scss | 2 +- .../icons/icons/volume-down/property-16.scss | 2 +- .../icons/icons/volume-down/property-24.scss | 2 +- .../base/icons/icons/volume-x/index.scss | 2 +- .../base/icons/icons/volume-x/keyframes.scss | 2 +- .../icons/icons/volume-x/placeholders.scss | 2 +- .../icons/icons/volume-x/property-16.scss | 2 +- .../icons/icons/volume-x/property-24.scss | 2 +- .../styles/base/icons/icons/volume/index.scss | 2 +- .../base/icons/icons/volume/keyframes.scss | 2 +- .../base/icons/icons/volume/placeholders.scss | 2 +- .../base/icons/icons/volume/property-16.scss | 2 +- .../base/icons/icons/volume/property-24.scss | 2 +- .../styles/base/icons/icons/wall/index.scss | 2 +- .../base/icons/icons/wall/keyframes.scss | 2 +- .../base/icons/icons/wall/placeholders.scss | 2 +- .../base/icons/icons/wall/property-16.scss | 2 +- .../base/icons/icons/wall/property-24.scss | 2 +- .../styles/base/icons/icons/wand/index.scss | 2 +- .../base/icons/icons/wand/keyframes.scss | 2 +- .../base/icons/icons/wand/placeholders.scss | 2 +- .../base/icons/icons/wand/property-16.scss | 2 +- .../base/icons/icons/wand/property-24.scss | 2 +- .../styles/base/icons/icons/watch/index.scss | 2 +- .../base/icons/icons/watch/keyframes.scss | 2 +- .../base/icons/icons/watch/placeholders.scss | 2 +- .../base/icons/icons/watch/property-16.scss | 2 +- .../base/icons/icons/watch/property-24.scss | 2 +- .../icons/icons/waypoint-color/index.scss | 2 +- .../icons/icons/waypoint-color/keyframes.scss | 2 +- .../icons/waypoint-color/placeholders.scss | 2 +- .../icons/waypoint-color/property-16.scss | 2 +- .../icons/waypoint-color/property-24.scss | 2 +- .../base/icons/icons/waypoint/index.scss | 2 +- .../base/icons/icons/waypoint/keyframes.scss | 2 +- .../icons/icons/waypoint/placeholders.scss | 2 +- .../icons/icons/waypoint/property-16.scss | 2 +- .../icons/icons/waypoint/property-24.scss | 2 +- .../base/icons/icons/webhook/index.scss | 2 +- .../base/icons/icons/webhook/keyframes.scss | 2 +- .../icons/icons/webhook/placeholders.scss | 2 +- .../base/icons/icons/webhook/property-16.scss | 2 +- .../base/icons/icons/webhook/property-24.scss | 2 +- .../base/icons/icons/wifi-off/index.scss | 2 +- .../base/icons/icons/wifi-off/keyframes.scss | 2 +- .../icons/icons/wifi-off/placeholders.scss | 2 +- .../icons/icons/wifi-off/property-16.scss | 2 +- .../icons/icons/wifi-off/property-24.scss | 2 +- .../styles/base/icons/icons/wifi/index.scss | 2 +- .../base/icons/icons/wifi/keyframes.scss | 2 +- .../base/icons/icons/wifi/placeholders.scss | 2 +- .../base/icons/icons/wifi/property-16.scss | 2 +- .../base/icons/icons/wifi/property-24.scss | 2 +- .../styles/base/icons/icons/wrench/index.scss | 2 +- .../base/icons/icons/wrench/keyframes.scss | 2 +- .../base/icons/icons/wrench/placeholders.scss | 2 +- .../base/icons/icons/wrench/property-16.scss | 2 +- .../base/icons/icons/wrench/property-24.scss | 2 +- .../base/icons/icons/x-circle-fill/index.scss | 2 +- .../icons/icons/x-circle-fill/keyframes.scss | 2 +- .../icons/x-circle-fill/placeholders.scss | 2 +- .../icons/x-circle-fill/property-16.scss | 2 +- .../icons/x-circle-fill/property-24.scss | 2 +- .../base/icons/icons/x-circle/index.scss | 2 +- .../base/icons/icons/x-circle/keyframes.scss | 2 +- .../icons/icons/x-circle/placeholders.scss | 2 +- .../icons/icons/x-circle/property-16.scss | 2 +- .../icons/icons/x-circle/property-24.scss | 2 +- .../icons/icons/x-diamond-fill/index.scss | 2 +- .../icons/icons/x-diamond-fill/keyframes.scss | 2 +- .../icons/x-diamond-fill/placeholders.scss | 2 +- .../icons/x-diamond-fill/property-16.scss | 2 +- .../icons/x-diamond-fill/property-24.scss | 2 +- .../base/icons/icons/x-diamond/index.scss | 2 +- .../base/icons/icons/x-diamond/keyframes.scss | 2 +- .../icons/icons/x-diamond/placeholders.scss | 2 +- .../icons/icons/x-diamond/property-16.scss | 2 +- .../icons/icons/x-diamond/property-24.scss | 2 +- .../icons/icons/x-hexagon-fill/index.scss | 2 +- .../icons/icons/x-hexagon-fill/keyframes.scss | 2 +- .../icons/x-hexagon-fill/placeholders.scss | 2 +- .../icons/x-hexagon-fill/property-16.scss | 2 +- .../icons/x-hexagon-fill/property-24.scss | 2 +- .../base/icons/icons/x-hexagon/index.scss | 2 +- .../base/icons/icons/x-hexagon/keyframes.scss | 2 +- .../icons/icons/x-hexagon/placeholders.scss | 2 +- .../icons/icons/x-hexagon/property-16.scss | 2 +- .../icons/icons/x-hexagon/property-24.scss | 2 +- .../base/icons/icons/x-square-fill/index.scss | 2 +- .../icons/icons/x-square-fill/keyframes.scss | 2 +- .../icons/x-square-fill/placeholders.scss | 2 +- .../icons/x-square-fill/property-16.scss | 2 +- .../icons/x-square-fill/property-24.scss | 2 +- .../base/icons/icons/x-square/index.scss | 2 +- .../base/icons/icons/x-square/keyframes.scss | 2 +- .../icons/icons/x-square/placeholders.scss | 2 +- .../icons/icons/x-square/property-16.scss | 2 +- .../icons/icons/x-square/property-24.scss | 2 +- .../app/styles/base/icons/icons/x/index.scss | 2 +- .../styles/base/icons/icons/x/keyframes.scss | 2 +- .../base/icons/icons/x/placeholders.scss | 2 +- .../base/icons/icons/x/property-16.scss | 2 +- .../base/icons/icons/x/property-24.scss | 2 +- .../base/icons/icons/youtube-color/index.scss | 2 +- .../icons/icons/youtube-color/keyframes.scss | 2 +- .../icons/youtube-color/placeholders.scss | 2 +- .../icons/youtube-color/property-16.scss | 2 +- .../icons/youtube-color/property-24.scss | 2 +- .../base/icons/icons/youtube/index.scss | 2 +- .../base/icons/icons/youtube/keyframes.scss | 2 +- .../icons/icons/youtube/placeholders.scss | 2 +- .../base/icons/icons/youtube/property-16.scss | 2 +- .../base/icons/icons/youtube/property-24.scss | 2 +- .../base/icons/icons/zap-off/index.scss | 2 +- .../base/icons/icons/zap-off/keyframes.scss | 2 +- .../icons/icons/zap-off/placeholders.scss | 2 +- .../base/icons/icons/zap-off/property-16.scss | 2 +- .../base/icons/icons/zap-off/property-24.scss | 2 +- .../styles/base/icons/icons/zap/index.scss | 2 +- .../base/icons/icons/zap/keyframes.scss | 2 +- .../base/icons/icons/zap/placeholders.scss | 2 +- .../base/icons/icons/zap/property-16.scss | 2 +- .../base/icons/icons/zap/property-24.scss | 2 +- .../base/icons/icons/zoom-in/index.scss | 2 +- .../base/icons/icons/zoom-in/keyframes.scss | 2 +- .../icons/icons/zoom-in/placeholders.scss | 2 +- .../base/icons/icons/zoom-in/property-16.scss | 2 +- .../base/icons/icons/zoom-in/property-24.scss | 2 +- .../base/icons/icons/zoom-out/index.scss | 2 +- .../base/icons/icons/zoom-out/keyframes.scss | 2 +- .../icons/icons/zoom-out/placeholders.scss | 2 +- .../icons/icons/zoom-out/property-16.scss | 2 +- .../icons/icons/zoom-out/property-24.scss | 2 +- .../app/styles/base/icons/index.scss | 2 +- .../app/styles/base/icons/overrides.scss | 2 +- .../consul-ui/app/styles/base/index.scss | 2 +- .../app/styles/base/reset/base-variables.scss | 2 +- .../app/styles/base/reset/index.scss | 2 +- .../app/styles/base/reset/minireset.scss | 2 +- .../app/styles/base/reset/system.scss | 2 +- .../base/typography/base-keyframes.scss | 2 +- .../base/typography/base-placeholders.scss | 2 +- .../app/styles/base/typography/index.scss | 2 +- .../consul-ui/app/styles/components.scss | 2 +- ui/packages/consul-ui/app/styles/debug.scss | 2 +- ui/packages/consul-ui/app/styles/icons.scss | 2 +- ui/packages/consul-ui/app/styles/layout.scss | 2 +- .../consul-ui/app/styles/layouts/index.scss | 2 +- .../app/styles/prism-coldark-cold.scss | 2 +- .../app/styles/prism-coldark-dark.scss | 2 +- ui/packages/consul-ui/app/styles/routes.scss | 2 +- .../app/styles/routes/dc/acls/index.scss | 2 +- .../styles/routes/dc/intentions/index.scss | 2 +- .../app/styles/routes/dc/kv/index.scss | 2 +- .../app/styles/routes/dc/nodes/index.scss | 2 +- .../styles/routes/dc/overview/license.scss | 2 +- .../routes/dc/overview/serverstatus.scss | 2 +- .../app/styles/routes/dc/services/index.scss | 2 +- .../consul-ui/app/styles/tailwind.scss | 2 +- ui/packages/consul-ui/app/styles/themes.scss | 2 +- .../consul-ui/app/styles/typography.scss | 2 +- .../consul-ui/app/styles/variables.scss | 2 +- .../app/styles/variables/custom-query.scss | 2 +- .../app/styles/variables/layout.scss | 2 +- .../consul-ui/app/styles/variables/skin.scss | 2 +- .../consul-ui/app/templates/application.hbs | 2 +- ui/packages/consul-ui/app/templates/dc.hbs | 2 +- .../consul-ui/app/templates/dc/acls.hbs | 2 +- .../templates/dc/acls/auth-methods/index.hbs | 2 +- .../templates/dc/acls/auth-methods/show.hbs | 2 +- .../dc/acls/auth-methods/show/auth-method.hbs | 2 +- .../acls/auth-methods/show/binding-rules.hbs | 2 +- .../acls/auth-methods/show/nspace-rules.hbs | 2 +- .../consul-ui/app/templates/dc/acls/index.hbs | 2 +- .../app/templates/dc/acls/policies/-form.hbs | 2 +- .../app/templates/dc/acls/policies/edit.hbs | 2 +- .../app/templates/dc/acls/policies/index.hbs | 2 +- .../app/templates/dc/acls/roles/-form.hbs | 2 +- .../app/templates/dc/acls/roles/edit.hbs | 2 +- .../app/templates/dc/acls/roles/index.hbs | 2 +- .../dc/acls/tokens/-fieldsets-legacy.hbs | 2 +- .../templates/dc/acls/tokens/-fieldsets.hbs | 2 +- .../app/templates/dc/acls/tokens/-form.hbs | 2 +- .../app/templates/dc/acls/tokens/edit.hbs | 2 +- .../app/templates/dc/acls/tokens/index.hbs | 2 +- .../app/templates/dc/intentions/edit.hbs | 2 +- .../app/templates/dc/intentions/index.hbs | 2 +- .../consul-ui/app/templates/dc/kv/edit.hbs | 2 +- .../consul-ui/app/templates/dc/kv/index.hbs | 2 +- .../app/templates/dc/nodes/index.hbs | 2 +- .../consul-ui/app/templates/dc/nodes/show.hbs | 2 +- .../templates/dc/nodes/show/healthchecks.hbs | 2 +- .../app/templates/dc/nodes/show/index.hbs | 2 +- .../app/templates/dc/nodes/show/metadata.hbs | 2 +- .../app/templates/dc/nodes/show/rtt.hbs | 2 +- .../app/templates/dc/nodes/show/services.hbs | 2 +- .../app/templates/dc/routing-config.hbs | 2 +- .../app/templates/dc/services/index.hbs | 2 +- .../app/templates/dc/services/instance.hbs | 2 +- .../dc/services/instance/addresses.hbs | 2 +- .../dc/services/instance/exposedpaths.hbs | 2 +- .../dc/services/instance/healthchecks.hbs | 2 +- .../dc/services/instance/metadata.hbs | 2 +- .../dc/services/instance/upstreams.hbs | 2 +- .../app/templates/dc/services/show.hbs | 2 +- .../app/templates/dc/services/show/index.hbs | 2 +- .../templates/dc/services/show/instances.hbs | 2 +- .../templates/dc/services/show/intentions.hbs | 2 +- .../dc/services/show/intentions/edit.hbs | 2 +- .../dc/services/show/intentions/index.hbs | 2 +- .../templates/dc/services/show/routing.hbs | 2 +- .../templates/dc/services/show/services.hbs | 2 +- .../app/templates/dc/services/show/tags.hbs | 2 +- .../templates/dc/services/show/topology.hbs | 2 +- .../templates/dc/services/show/upstreams.hbs | 2 +- .../consul-ui/app/templates/dc/show.hbs | 2 +- .../consul-ui/app/templates/dc/show/index.hbs | 2 +- .../app/templates/dc/show/license.hbs | 2 +- .../app/templates/dc/show/serverstatus.hbs | 2 +- ui/packages/consul-ui/app/templates/debug.hbs | 2 +- ui/packages/consul-ui/app/templates/error.hbs | 2 +- ui/packages/consul-ui/app/templates/index.hbs | 2 +- .../consul-ui/app/templates/loading.hbs | 2 +- .../consul-ui/app/templates/notfound.hbs | 2 +- .../app/templates/oauth-provider-debug.hbs | 2 +- .../consul-ui/app/templates/settings.hbs | 2 +- ui/packages/consul-ui/app/utils/ascend.js | 2 +- ui/packages/consul-ui/app/utils/atob.js | 2 +- ui/packages/consul-ui/app/utils/btoa.js | 2 +- .../consul-ui/app/utils/callable-type.js | 2 +- .../app/utils/create-fingerprinter.js | 2 +- ui/packages/consul-ui/app/utils/distance.js | 2 +- .../app/utils/dom/click-first-anchor.js | 2 +- .../consul-ui/app/utils/dom/closest.js | 2 +- .../app/utils/dom/create-listeners.js | 2 +- .../app/utils/dom/event-source/blocking.js | 2 +- .../app/utils/dom/event-source/cache.js | 2 +- .../app/utils/dom/event-source/callable.js | 2 +- .../app/utils/dom/event-source/index.js | 2 +- .../app/utils/dom/event-source/openable.js | 2 +- .../app/utils/dom/event-source/proxy.js | 2 +- .../app/utils/dom/event-source/resolver.js | 2 +- .../app/utils/dom/event-source/storage.js | 2 +- .../app/utils/dom/get-component-factory.js | 2 +- .../consul-ui/app/utils/dom/is-outside.js | 2 +- .../app/utils/dom/normalize-event.js | 2 +- .../consul-ui/app/utils/dom/qsa-factory.js | 2 +- .../consul-ui/app/utils/dom/sibling.js | 2 +- .../consul-ui/app/utils/editor/lint.js | 2 +- .../consul-ui/app/utils/filter/index.js | 2 +- .../consul-ui/app/utils/form/builder.js | 2 +- .../consul-ui/app/utils/form/changeset.js | 2 +- .../consul-ui/app/utils/get-environment.js | 2 +- .../app/utils/get-form-name-property.js | 2 +- .../app/utils/helpers/call-if-type.js | 2 +- .../consul-ui/app/utils/http/consul.js | 2 +- .../app/utils/http/create-headers.js | 2 +- .../app/utils/http/create-query-params.js | 2 +- .../consul-ui/app/utils/http/create-url.js | 2 +- ui/packages/consul-ui/app/utils/http/error.js | 2 +- .../consul-ui/app/utils/http/headers.js | 2 +- .../consul-ui/app/utils/http/method.js | 2 +- .../consul-ui/app/utils/http/request.js | 2 +- .../consul-ui/app/utils/http/status.js | 2 +- ui/packages/consul-ui/app/utils/http/xhr.js | 2 +- .../app/utils/intl/missing-message.js | 2 +- ui/packages/consul-ui/app/utils/isFolder.js | 2 +- ui/packages/consul-ui/app/utils/keyToArray.js | 2 +- ui/packages/consul-ui/app/utils/left-trim.js | 2 +- ui/packages/consul-ui/app/utils/maybe-call.js | 2 +- .../consul-ui/app/utils/merge-checks.js | 2 +- .../consul-ui/app/utils/minimizeModel.js | 2 +- .../consul-ui/app/utils/non-empty-set.js | 2 +- .../consul-ui/app/utils/path/resolve.js | 2 +- .../consul-ui/app/utils/promisedTimeout.js | 2 +- ui/packages/consul-ui/app/utils/right-trim.js | 2 +- .../app/utils/routing/redirect-to.js | 2 +- .../app/utils/routing/transitionable.js | 2 +- .../consul-ui/app/utils/routing/walk.js | 2 +- .../consul-ui/app/utils/routing/wildcard.js | 2 +- .../consul-ui/app/utils/search/exact.js | 2 +- .../consul-ui/app/utils/search/fuzzy.js | 2 +- .../consul-ui/app/utils/search/predicate.js | 2 +- .../consul-ui/app/utils/search/regexp.js | 2 +- .../app/utils/storage/local-storage.js | 2 +- ui/packages/consul-ui/app/utils/templatize.js | 2 +- .../consul-ui/app/utils/ticker/index.js | 2 +- ui/packages/consul-ui/app/utils/tomography.js | 2 +- ui/packages/consul-ui/app/utils/ucfirst.js | 2 +- .../app/utils/update-array-object.js | 2 +- .../intention-permission-http-header.js | 2 +- .../app/validations/intention-permission.js | 2 +- .../consul-ui/app/validations/intention.js | 2 +- ui/packages/consul-ui/app/validations/kv.js | 2 +- .../consul-ui/app/validations/policy.js | 2 +- ui/packages/consul-ui/app/validations/role.js | 2 +- .../consul-ui/app/validations/sometimes.js | 2 +- .../consul-ui/app/validations/token.js | 2 +- .../blueprints/adapter-test/index.js | 2 +- .../__path__/integration/adapters/__test__.js | 2 +- .../__path__/unit/adapters/__test__.js | 2 +- .../files/__root__/__path__/__name__.js | 2 +- .../consul-ui/blueprints/adapter/index.js | 2 +- .../__templatepath__/__templatename__.hbs | 2 +- .../consul-ui/blueprints/component/index.js | 2 +- .../files/__root__/__path__/__name__.scss | 2 +- .../__root__/__path__/__name__/index.scss | 2 +- .../__root__/__path__/__name__/layout.scss | 2 +- .../__root__/__path__/__name__/skin.scss | 2 +- .../blueprints/css-component/index.js | 2 +- .../consul-ui/blueprints/model-test/index.js | 2 +- .../__root__/__path__/unit/models/__test__.js | 2 +- .../model/files/__root__/__path__/__name__.js | 2 +- .../consul-ui/blueprints/model/index.js | 2 +- .../blueprints/repository-test/index.js | 2 +- .../services/repository/__test__.js | 2 +- .../unit/services/repository/__test__.js | 2 +- .../files/__root__/__path__/__name__.js | 2 +- .../consul-ui/blueprints/repository/index.js | 2 +- .../consul-ui/blueprints/route-test/index.js | 2 +- .../consul-ui/blueprints/route/index.js | 2 +- .../__templatepath__/__templatename__.hbs | 2 +- .../blueprints/serializer-test/index.js | 2 +- .../integration/serializers/__test__.js | 2 +- .../__path__/unit/serializers/__test__.js | 2 +- .../files/__root__/__path__/__name__.js | 2 +- .../consul-ui/blueprints/serializer/index.js | 2 +- .../consul-ui/config/deprecation-workflow.js | 2 +- ui/packages/consul-ui/config/ember-intl.js | 2 +- ui/packages/consul-ui/config/environment.js | 2 +- ui/packages/consul-ui/config/targets.js | 2 +- ui/packages/consul-ui/config/utils.js | 2 +- ui/packages/consul-ui/ember-cli-build.js | 2 +- ui/packages/consul-ui/lib/.eslintrc.js | 2 +- .../lib/colocated-components/index.js | 2 +- .../consul-ui/lib/commands/bin/list.js | 2 +- ui/packages/consul-ui/lib/commands/index.js | 2 +- .../consul-ui/lib/commands/lib/list.js | 2 +- .../consul-ui/lib/custom-element/index.js | 2 +- ui/packages/consul-ui/lib/startup/index.js | 2 +- .../lib/startup/templates/body.html.js | 2 +- .../lib/startup/templates/head.html.js | 2 +- .../node-tests/config/environment.js | 2 +- .../consul-ui/node-tests/config/utils.js | 2 +- ui/packages/consul-ui/server/index.js | 2 +- ui/packages/consul-ui/tailwind.config.js | 2 +- ui/packages/consul-ui/testem.js | 2 +- .../tests/acceptance/hcp-login-test.js | 2 +- .../acceptance/steps/api-prefix-steps.js | 2 +- .../steps/components/acl-filter-steps.js | 2 +- .../steps/components/catalog-filter-steps.js | 2 +- .../steps/components/catalog-toolbar-steps.js | 2 +- .../steps/components/copy-button-steps.js | 2 +- .../steps/components/kv-filter-steps.js | 2 +- .../steps/components/text-input-steps.js | 2 +- .../acceptance/steps/dc/acls/access-steps.js | 2 +- .../steps/dc/acls/auth-methods/index-steps.js | 2 +- .../dc/acls/auth-methods/navigation-steps.js | 2 +- .../dc/acls/auth-methods/sorting-steps.js | 2 +- .../acceptance/steps/dc/acls/index-steps.js | 2 +- .../steps/dc/acls/list-order-steps.js | 2 +- .../policies/as-many/add-existing-steps.js | 2 +- .../dc/acls/policies/as-many/add-new-steps.js | 2 +- .../dc/acls/policies/as-many/list-steps.js | 2 +- .../dc/acls/policies/as-many/nspaces-steps.js | 2 +- .../dc/acls/policies/as-many/remove-steps.js | 2 +- .../dc/acls/policies/as-many/reset-steps.js | 2 +- .../steps/dc/acls/policies/create-steps.js | 2 +- .../steps/dc/acls/policies/delete-steps.js | 2 +- .../steps/dc/acls/policies/index-steps.js | 2 +- .../dc/acls/policies/navigation-steps.js | 2 +- .../steps/dc/acls/policies/sorting-steps.js | 2 +- .../steps/dc/acls/policies/update-steps.js | 2 +- .../dc/acls/policies/view-management-steps.js | 2 +- .../acls/roles/as-many/add-existing-steps.js | 2 +- .../dc/acls/roles/as-many/add-new-steps.js | 2 +- .../steps/dc/acls/roles/as-many/list-steps.js | 2 +- .../dc/acls/roles/as-many/remove-steps.js | 2 +- .../steps/dc/acls/roles/create-steps.js | 2 +- .../steps/dc/acls/roles/index-steps.js | 2 +- .../steps/dc/acls/roles/navigation-steps.js | 2 +- .../steps/dc/acls/roles/sorting-steps.js | 2 +- .../steps/dc/acls/roles/update-steps.js | 2 +- .../acls/tokens/anonymous-no-delete-steps.js | 2 +- .../steps/dc/acls/tokens/clone-steps.js | 2 +- .../steps/dc/acls/tokens/create-steps.js | 2 +- .../steps/dc/acls/tokens/index-steps.js | 2 +- .../dc/acls/tokens/legacy/update-steps.js | 2 +- .../dc/acls/tokens/login-errors-steps.js | 2 +- .../steps/dc/acls/tokens/login-steps.js | 2 +- .../steps/dc/acls/tokens/navigation-steps.js | 2 +- .../dc/acls/tokens/own-no-delete-steps.js | 2 +- .../steps/dc/acls/tokens/sorting-steps.js | 2 +- .../steps/dc/acls/tokens/update-steps.js | 2 +- .../steps/dc/acls/tokens/use-steps.js | 2 +- .../acceptance/steps/dc/acls/update-steps.js | 2 +- .../acceptance/steps/dc/acls/use-steps.js | 2 +- .../tests/acceptance/steps/dc/error-steps.js | 2 +- .../acceptance/steps/dc/forwarding-steps.js | 2 +- .../tests/acceptance/steps/dc/index-steps.js | 2 +- .../steps/dc/intentions/create-steps.js | 2 +- .../steps/dc/intentions/delete-steps.js | 2 +- .../dc/intentions/filtered-select-steps.js | 2 +- .../steps/dc/intentions/form-select-steps.js | 2 +- .../steps/dc/intentions/index-steps.js | 2 +- .../steps/dc/intentions/navigation-steps.js | 2 +- .../dc/intentions/permissions/create-steps.js | 2 +- .../dc/intentions/permissions/warn-steps.js | 2 +- .../steps/dc/intentions/read-only-steps.js | 2 +- .../steps/dc/intentions/sorting-steps.js | 2 +- .../steps/dc/intentions/update-steps.js | 2 +- .../steps/dc/kv/index/view-kvs-steps.js | 2 +- .../acceptance/steps/dc/kvs/create-steps.js | 2 +- .../acceptance/steps/dc/kvs/delete-steps.js | 2 +- .../acceptance/steps/dc/kvs/edit-steps.js | 2 +- .../acceptance/steps/dc/kvs/index-steps.js | 2 +- .../steps/dc/kvs/list-order-steps.js | 2 +- .../steps/dc/kvs/sessions/invalidate-steps.js | 2 +- .../steps/dc/kvs/trailing-slash-steps.js | 2 +- .../acceptance/steps/dc/kvs/update-steps.js | 2 +- .../steps/dc/list-blocking-steps.js | 2 +- .../tests/acceptance/steps/dc/list-steps.js | 2 +- .../steps/dc/nodes/empty-ids-steps.js | 2 +- .../acceptance/steps/dc/nodes/index-steps.js | 2 +- .../steps/dc/nodes/index/view-nodes-steps.js | 2 +- .../steps/dc/nodes/navigation-steps.js | 2 +- .../steps/dc/nodes/no-leader-steps.js | 2 +- .../steps/dc/nodes/services/list-steps.js | 2 +- .../dc/nodes/sessions/invalidate-steps.js | 2 +- .../steps/dc/nodes/sessions/list-steps.js | 2 +- .../acceptance/steps/dc/nodes/show-steps.js | 2 +- .../dc/nodes/show/health-checks-steps.js | 2 +- .../steps/dc/nodes/sorting-steps.js | 2 +- .../steps/dc/nspaces/create-steps.js | 2 +- .../steps/dc/nspaces/delete-steps.js | 2 +- .../steps/dc/nspaces/index-steps.js | 2 +- .../steps/dc/nspaces/manage-steps.js | 2 +- .../steps/dc/nspaces/sorting-steps.js | 2 +- .../steps/dc/nspaces/update-steps.js | 2 +- .../acceptance/steps/dc/peers/create-steps.js | 2 +- .../acceptance/steps/dc/peers/delete-steps.js | 2 +- .../steps/dc/peers/establish-steps.js | 2 +- .../acceptance/steps/dc/peers/index-steps.js | 2 +- .../steps/dc/peers/regenerate-steps.js | 2 +- .../acceptance/steps/dc/peers/show-steps.js | 2 +- .../steps/dc/routing-config-steps.js | 2 +- .../steps/dc/services/dc-switch-steps.js | 2 +- .../steps/dc/services/error-steps.js | 2 +- .../steps/dc/services/index-steps.js | 2 +- .../dc/services/index/view-services-steps.js | 2 +- .../dc/services/instances/error-steps.js | 2 +- .../services/instances/exposed-paths-steps.js | 2 +- .../dc/services/instances/gateway-steps.js | 2 +- .../services/instances/health-checks-steps.js | 2 +- .../dc/services/instances/navigation-steps.js | 2 +- .../dc/services/instances/proxy-steps.js | 2 +- .../steps/dc/services/instances/show-steps.js | 2 +- .../services/instances/sidecar-proxy-steps.js | 2 +- .../dc/services/instances/upstreams-steps.js | 2 +- .../dc/services/instances/with-proxy-steps.js | 2 +- .../services/instances/with-sidecar-steps.js | 2 +- .../steps/dc/services/list-blocking-steps.js | 2 +- .../steps/dc/services/list-steps.js | 2 +- .../steps/dc/services/navigation-steps.js | 2 +- .../steps/dc/services/show-routing-steps.js | 2 +- .../steps/dc/services/show-steps.js | 2 +- .../dc/services/show-with-slashes-steps.js | 2 +- .../steps/dc/services/show/dc-switch-steps.js | 2 +- .../services/show/intentions-error-steps.js | 2 +- .../services/show/intentions/create-steps.js | 2 +- .../services/show/intentions/index-steps.js | 2 +- .../dc/services/show/navigation-steps.js | 2 +- .../steps/dc/services/show/services-steps.js | 2 +- .../steps/dc/services/show/tags-steps.js | 2 +- .../dc/services/show/topology/empty-steps.js | 2 +- .../dc/services/show/topology/index-steps.js | 2 +- .../show/topology/intentions-steps.js | 2 +- .../services/show/topology/metrics-steps.js | 2 +- .../services/show/topology/notices-steps.js | 2 +- .../show/topology/routing-config-steps.js | 2 +- .../dc/services/show/topology/stats-steps.js | 2 +- .../steps/dc/services/show/upstreams-steps.js | 2 +- .../steps/dc/services/sorting-steps.js | 2 +- .../tests/acceptance/steps/deleting-steps.js | 2 +- .../steps/index-forwarding-steps.js | 2 +- .../acceptance/steps/login-errors-steps.js | 2 +- .../tests/acceptance/steps/login-steps.js | 2 +- .../steps/navigation-links-steps.js | 2 +- .../acceptance/steps/nodes/sorting-steps.js | 2 +- .../acceptance/steps/page-navigation-steps.js | 2 +- .../acceptance/steps/settings/show-steps.js | 2 +- .../acceptance/steps/settings/update-steps.js | 2 +- .../tests/acceptance/steps/startup-steps.js | 2 +- .../consul-ui/tests/acceptance/steps/steps.js | 2 +- .../acceptance/steps/submit-blank-steps.js | 2 +- .../acceptance/steps/token-header-steps.js | 2 +- ui/packages/consul-ui/tests/dictionary.js | 2 +- ui/packages/consul-ui/tests/helpers/api.js | 2 +- .../consul-ui/tests/helpers/destroy-app.js | 2 +- .../consul-ui/tests/helpers/flash-message.js | 2 +- .../tests/helpers/get-nspace-runner.js | 2 +- .../consul-ui/tests/helpers/measure.js | 2 +- .../tests/helpers/module-for-acceptance.js | 2 +- .../consul-ui/tests/helpers/normalizers.js | 2 +- ui/packages/consul-ui/tests/helpers/page.js | 2 +- ui/packages/consul-ui/tests/helpers/repo.js | 2 +- .../consul-ui/tests/helpers/set-cookies.js | 2 +- .../consul-ui/tests/helpers/stub-super.js | 2 +- .../consul-ui/tests/helpers/type-to-url.js | 2 +- .../tests/helpers/yadda-annotations.js | 2 +- ui/packages/consul-ui/tests/index.html | 2 +- .../integration/adapters/auth-method-test.js | 2 +- .../integration/adapters/binding-rule-test.js | 2 +- .../integration/adapters/coordinate-test.js | 2 +- .../adapters/discovery-chain-test.js | 2 +- .../integration/adapters/intention-test.js | 2 +- .../tests/integration/adapters/kv-test.js | 2 +- .../tests/integration/adapters/node-test.js | 2 +- .../tests/integration/adapters/nspace-test.js | 2 +- .../adapters/oidc-provider-test.js | 2 +- .../integration/adapters/partition-test.js | 2 +- .../integration/adapters/permission-test.js | 2 +- .../tests/integration/adapters/policy-test.js | 2 +- .../tests/integration/adapters/role-test.js | 2 +- .../adapters/service-instance-test.js | 2 +- .../integration/adapters/service-test.js | 2 +- .../integration/adapters/session-test.js | 2 +- .../tests/integration/adapters/token-test.js | 2 +- .../integration/adapters/topology-test.js | 2 +- .../integration/components/app-view-test.js | 2 +- .../integration/components/aria-menu-test.js | 2 +- .../components/auth-profile-test.js | 2 +- .../components/code-editor-test.js | 2 +- .../components/confirmation-dialog-test.js | 2 +- .../components/consul/bucket/list-test.js | 2 +- .../consul/datacenter/selector-test.js | 2 +- .../components/consul/discovery-chain-test.js | 2 +- .../components/consul/hcp/home-test.js | 2 +- .../consul/intention/permission/form-test.js | 2 +- .../intention/permission/header/form-test.js | 2 +- .../consul/node/agentless-notice-test.js | 2 +- .../components/data-collection-test.js | 2 +- .../components/data-source-test.js | 2 +- .../components/delete-confirmation-test.js | 2 +- .../components/event-source-test.js | 2 +- .../components/freetext-filter-test.js | 2 +- .../components/hashicorp-consul-test.js | 2 +- .../integration/components/jwt-source-test.js | 2 +- .../components/list-collection-test.js | 2 +- .../components/oidc-select-test.js | 2 +- .../components/popover-menu-test.js | 2 +- .../components/radio-group-test.js | 2 +- .../tests/integration/components/ref-test.js | 2 +- .../components/resolver-card-test.js | 2 +- .../integration/components/route-card-test.js | 2 +- .../components/splitter-card-test.js | 2 +- .../integration/components/state-test.js | 2 +- .../integration/components/tab-nav-test.js | 2 +- .../components/tabular-collection-test.js | 2 +- .../components/tabular-details-test.js | 2 +- .../integration/components/tag-list-test.js | 2 +- .../components/toggle-button-test.js | 2 +- .../integration/components/token-list-test.js | 2 +- .../tests/integration/helpers/atob-test.js | 2 +- .../integration/helpers/dom-position-test.js | 2 +- .../integration/helpers/duration-from-test.js | 2 +- .../helpers/format-short-time-test.js | 2 +- .../tests/integration/helpers/is-href-test.js | 2 +- .../tests/integration/helpers/last-test.js | 2 +- .../integration/helpers/left-trim-test.js | 2 +- .../helpers/policy/datacenters-test.js | 2 +- .../integration/helpers/policy/typeof-test.js | 2 +- .../helpers/render-template-test.js | 2 +- .../integration/helpers/right-trim-test.js | 2 +- .../integration/helpers/route-match-test.js | 2 +- .../integration/helpers/searchable-test.js | 2 +- .../helpers/service/card-permissions-test.js | 2 +- .../helpers/service/external-source-test.js | 2 +- .../helpers/service/health-percentage-test.js | 2 +- .../tests/integration/helpers/slugify-test.js | 2 +- .../tests/integration/helpers/split-test.js | 2 +- .../integration/helpers/state-matches-test.js | 2 +- .../tests/integration/helpers/substr-test.js | 2 +- .../integration/helpers/svg-curve-test.js | 2 +- .../helpers/token/is-anonymous-test.js | 2 +- .../helpers/token/is-legacy-test.js | 2 +- .../integration/helpers/tween-to-test.js | 2 +- .../serializers/auth-method-test.js | 2 +- .../serializers/binding-rule-test.js | 2 +- .../serializers/coordinate-test.js | 2 +- .../serializers/discovery-chain-test.js | 2 +- .../integration/serializers/intention-test.js | 2 +- .../tests/integration/serializers/kv-test.js | 2 +- .../integration/serializers/node-test.js | 2 +- .../integration/serializers/nspace-test.js | 2 +- .../serializers/oidc-provider-test.js | 2 +- .../integration/serializers/partition-test.js | 2 +- .../integration/serializers/policy-test.js | 2 +- .../integration/serializers/role-test.js | 2 +- .../serializers/service-instance-test.js | 2 +- .../integration/serializers/service-test.js | 2 +- .../integration/serializers/session-test.js | 2 +- .../integration/serializers/token-test.js | 2 +- .../integration/serializers/topology-test.js | 2 +- .../services/repository/auth-method-test.js | 2 +- .../services/repository/coordinate-test.js | 2 +- .../services/repository/dc-test.js | 2 +- .../repository/discovery-chain-test.js | 2 +- .../services/repository/kv-test.js | 2 +- .../services/repository/node-test.js | 2 +- .../services/repository/policy-test.js | 2 +- .../services/repository/role-test.js | 2 +- .../services/repository/service-test.js | 2 +- .../services/repository/session-test.js | 2 +- .../services/repository/token-test.js | 2 +- .../services/repository/topology-test.js | 2 +- .../integration/services/routlet-test.js | 2 +- .../utils/dom/event-source/callable-test.js | 2 +- .../consul-ui/tests/lib/measure/getMeasure.js | 2 +- .../tests/lib/page-object/createCancelable.js | 2 +- .../tests/lib/page-object/createCreatable.js | 2 +- .../tests/lib/page-object/createDeletable.js | 2 +- .../tests/lib/page-object/createSubmitable.js | 2 +- .../consul-ui/tests/lib/page-object/index.js | 2 +- .../tests/lib/page-object/visitable.js | 2 +- ui/packages/consul-ui/tests/pages.js | 2 +- ui/packages/consul-ui/tests/pages/dc.js | 2 +- .../tests/pages/dc/acls/auth-methods/index.js | 2 +- .../consul-ui/tests/pages/dc/acls/edit.js | 2 +- .../consul-ui/tests/pages/dc/acls/index.js | 2 +- .../tests/pages/dc/acls/policies/edit.js | 2 +- .../tests/pages/dc/acls/policies/index.js | 2 +- .../tests/pages/dc/acls/roles/edit.js | 2 +- .../tests/pages/dc/acls/roles/index.js | 2 +- .../tests/pages/dc/acls/tokens/edit.js | 2 +- .../tests/pages/dc/acls/tokens/index.js | 2 +- .../tests/pages/dc/intentions/edit.js | 2 +- .../tests/pages/dc/intentions/index.js | 2 +- .../consul-ui/tests/pages/dc/kv/edit.js | 2 +- .../consul-ui/tests/pages/dc/kv/index.js | 2 +- .../consul-ui/tests/pages/dc/nodes/index.js | 2 +- .../consul-ui/tests/pages/dc/nodes/show.js | 2 +- .../consul-ui/tests/pages/dc/nspaces/edit.js | 2 +- .../consul-ui/tests/pages/dc/nspaces/index.js | 2 +- .../consul-ui/tests/pages/dc/peers/index.js | 2 +- .../consul-ui/tests/pages/dc/peers/show.js | 2 +- .../tests/pages/dc/routing-config.js | 2 +- .../tests/pages/dc/services/index.js | 2 +- .../tests/pages/dc/services/instance.js | 2 +- .../consul-ui/tests/pages/dc/services/show.js | 2 +- ui/packages/consul-ui/tests/pages/index.js | 2 +- ui/packages/consul-ui/tests/pages/settings.js | 2 +- ui/packages/consul-ui/tests/steps.js | 2 +- .../consul-ui/tests/steps/assertions/dom.js | 2 +- .../consul-ui/tests/steps/assertions/form.js | 2 +- .../consul-ui/tests/steps/assertions/http.js | 2 +- .../consul-ui/tests/steps/assertions/model.js | 2 +- .../consul-ui/tests/steps/assertions/page.js | 2 +- .../consul-ui/tests/steps/debug/index.js | 2 +- .../consul-ui/tests/steps/doubles/http.js | 2 +- .../consul-ui/tests/steps/doubles/model.js | 2 +- .../tests/steps/interactions/click.js | 2 +- .../tests/steps/interactions/form.js | 2 +- .../tests/steps/interactions/visit.js | 2 +- ui/packages/consul-ui/tests/test-helper.js | 2 +- .../consul-ui/tests/unit/abilities/-test.js | 2 +- .../tests/unit/adapters/application-test.js | 2 +- .../tests/unit/adapters/auth-method-test.js | 2 +- .../tests/unit/adapters/binding-rule-test.js | 2 +- .../tests/unit/adapters/coordinate-test.js | 2 +- .../unit/adapters/discovery-chain-test.js | 2 +- .../tests/unit/adapters/http-test.js | 2 +- .../tests/unit/adapters/intention-test.js | 2 +- .../consul-ui/tests/unit/adapters/kv-test.js | 2 +- .../tests/unit/adapters/node-test.js | 2 +- .../tests/unit/adapters/nspace-test.js | 2 +- .../tests/unit/adapters/oidc-provider-test.js | 2 +- .../tests/unit/adapters/partition-test.js | 2 +- .../tests/unit/adapters/permission-test.js | 2 +- .../tests/unit/adapters/policy-test.js | 2 +- .../tests/unit/adapters/proxy-test.js | 2 +- .../tests/unit/adapters/role-test.js | 2 +- .../unit/adapters/service-instance-test.js | 2 +- .../tests/unit/adapters/session-test.js | 2 +- .../tests/unit/adapters/token-test.js | 2 +- .../get-alternate-services-test.js | 2 +- .../discovery-chain/get-resolvers-test.js | 2 +- .../discovery-chain/get-splitters-test.js | 2 +- .../components/search-bar/filters-test.js | 2 +- .../unit/controllers/application-test.js | 2 +- .../dc/acls/policies/create-test.js | 2 +- .../controllers/dc/acls/policies/edit-test.js | 2 +- .../controllers/dc/acls/roles/create-test.js | 2 +- .../controllers/dc/acls/roles/edit-test.js | 2 +- .../controllers/dc/acls/tokens/create-test.js | 2 +- .../controllers/dc/acls/tokens/edit-test.js | 2 +- .../unit/filter/predicates/intention-test.js | 2 +- .../unit/filter/predicates/service-test.js | 2 +- .../tests/unit/helpers/document-attrs-test.js | 2 +- .../unit/helpers/policy/datacenters-test.js | 2 +- .../unit/helpers/token/is-anonymous-test.js | 2 +- .../unit/helpers/token/is-legacy-test.js | 2 +- .../tests/unit/mixins/policy/as-many-test.js | 2 +- .../tests/unit/mixins/role/as-many-test.js | 2 +- .../unit/mixins/with-blocking-actions-test.js | 2 +- .../tests/unit/models/auth-method-test.js | 2 +- .../tests/unit/models/coordinate-test.js | 2 +- .../consul-ui/tests/unit/models/dc-test.js | 2 +- .../tests/unit/models/discovery-chain-test.js | 2 +- .../tests/unit/models/intention-test.js | 2 +- .../consul-ui/tests/unit/models/kv-test.js | 2 +- .../consul-ui/tests/unit/models/node-test.js | 2 +- .../tests/unit/models/oidc-provider-test.js | 2 +- .../tests/unit/models/partition-test.js | 2 +- .../tests/unit/models/permission-test.js | 2 +- .../tests/unit/models/policy-test.js | 2 +- .../consul-ui/tests/unit/models/proxy-test.js | 2 +- .../consul-ui/tests/unit/models/role-test.js | 2 +- .../unit/models/service-instance-test.js | 2 +- .../tests/unit/models/service-test.js | 2 +- .../tests/unit/models/session-test.js | 2 +- .../consul-ui/tests/unit/models/token-test.js | 2 +- .../tests/unit/routes/application-test.js | 2 +- .../consul-ui/tests/unit/routes/dc-test.js | 2 +- .../routes/dc/acls/policies/create-test.js | 2 +- .../unit/routes/dc/acls/policies/edit-test.js | 2 +- .../routes/dc/acls/policies/index-test.js | 2 +- .../unit/routes/dc/acls/roles/create-test.js | 2 +- .../unit/routes/dc/acls/roles/edit-test.js | 2 +- .../unit/routes/dc/acls/roles/index-test.js | 2 +- .../unit/routes/dc/acls/tokens/create-test.js | 2 +- .../unit/routes/dc/acls/tokens/edit-test.js | 2 +- .../unit/routes/dc/acls/tokens/index-test.js | 2 +- .../unit/search/predicates/intention-test.js | 2 +- .../tests/unit/search/predicates/kv-test.js | 2 +- .../tests/unit/search/predicates/node-test.js | 2 +- .../unit/search/predicates/policy-test.js | 2 +- .../tests/unit/search/predicates/role-test.js | 2 +- .../unit/search/predicates/service-test.js | 2 +- .../unit/search/predicates/token-test.js | 2 +- .../unit/serializers/application-test.js | 2 +- .../unit/serializers/auth-method-test.js | 2 +- .../unit/serializers/binding-rule-test.js | 2 +- .../tests/unit/serializers/coordinate-test.js | 2 +- .../unit/serializers/discovery-chain-test.js | 2 +- .../tests/unit/serializers/intention-test.js | 2 +- .../tests/unit/serializers/kv-test.js | 2 +- .../tests/unit/serializers/node-test.js | 2 +- .../tests/unit/serializers/nspace-test.js | 2 +- .../unit/serializers/oidc-provider-test.js | 2 +- .../tests/unit/serializers/partition-test.js | 2 +- .../tests/unit/serializers/permission-test.js | 2 +- .../tests/unit/serializers/policy-test.js | 2 +- .../tests/unit/serializers/proxy-test.js | 2 +- .../tests/unit/serializers/role-test.js | 2 +- .../unit/serializers/service-instance-test.js | 2 +- .../tests/unit/serializers/service-test.js | 2 +- .../tests/unit/serializers/session-test.js | 2 +- .../tests/unit/serializers/token-test.js | 2 +- .../tests/unit/services/atob-test.js | 2 +- .../tests/unit/services/btoa-test.js | 2 +- .../unit/services/client/connections-test.js | 2 +- .../tests/unit/services/client/http-test.js | 2 +- .../services/client/transports/xhr-test.js | 2 +- .../services/clipboard/local-storage-test.js | 2 +- .../tests/unit/services/clipboard/os-test.js | 2 +- .../unit/services/code-mirror/linter-test.js | 2 +- .../data-source/protocols/http-test.js | 2 +- .../protocols/local-storage-test.js | 2 +- .../tests/unit/services/data-structs-test.js | 2 +- .../consul-ui/tests/unit/services/dom-test.js | 2 +- .../tests/unit/services/encoder-test.js | 2 +- .../consul-ui/tests/unit/services/env-test.js | 2 +- .../tests/unit/services/feedback-test.js | 2 +- .../tests/unit/services/form-test.js | 2 +- .../tests/unit/services/logger-test.js | 2 +- .../tests/unit/services/repository-test.js | 2 +- .../services/repository/auth-method-test.js | 2 +- .../services/repository/coordinate-test.js | 2 +- .../tests/unit/services/repository/dc-test.js | 2 +- .../repository/discovery-chain-test.js | 2 +- .../services/repository/intention-test.js | 2 +- .../tests/unit/services/repository/kv-test.js | 2 +- .../unit/services/repository/node-test.js | 2 +- .../unit/services/repository/nspace-test.js | 2 +- .../services/repository/oidc-provider-test.js | 2 +- .../services/repository/partition-test.js | 2 +- .../services/repository/permission-test.js | 2 +- .../unit/services/repository/policy-test.js | 2 +- .../unit/services/repository/role-test.js | 2 +- .../repository/service-instance-test.js | 2 +- .../unit/services/repository/service-test.js | 2 +- .../unit/services/repository/session-test.js | 2 +- .../unit/services/repository/token-test.js | 2 +- .../tests/unit/services/search-test.js | 2 +- .../tests/unit/services/settings-test.js | 2 +- .../tests/unit/services/sort-test.js | 2 +- .../tests/unit/services/state-test.js | 2 +- .../tests/unit/services/store-test.js | 2 +- .../tests/unit/services/temporal-test.js | 2 +- .../tests/unit/services/ticker-test.js | 2 +- .../tests/unit/services/timeout-test.js | 2 +- .../tests/unit/sort/comparators/node-test.js | 2 +- .../unit/sort/comparators/service-test.js | 2 +- .../consul-ui/tests/unit/utils/ascend-test.js | 2 +- .../consul-ui/tests/unit/utils/atob-test.js | 2 +- .../consul-ui/tests/unit/utils/btoa-test.js | 2 +- .../tests/unit/utils/callable-type-test.js | 2 +- .../unit/utils/create-fingerprinter-test.js | 2 +- .../unit/utils/dom/click-first-anchor-test.js | 2 +- .../tests/unit/utils/dom/closest-test.js | 2 +- .../unit/utils/dom/create-listeners-test.js | 2 +- .../utils/dom/event-source/blocking-test.js | 2 +- .../unit/utils/dom/event-source/cache-test.js | 2 +- .../utils/dom/event-source/callable-test.js | 2 +- .../unit/utils/dom/event-source/index-test.js | 2 +- .../utils/dom/event-source/openable-test.js | 2 +- .../unit/utils/dom/event-source/proxy-test.js | 2 +- .../utils/dom/event-source/resolver-test.js | 2 +- .../utils/dom/event-source/storage-test.js | 2 +- .../unit/utils/dom/event-target/rsvp-test.js | 2 +- .../utils/dom/get-component-factory-test.js | 2 +- .../tests/unit/utils/dom/is-outside-test.js | 2 +- .../unit/utils/dom/normalize-event-test.js | 2 +- .../tests/unit/utils/dom/qsa-factory-test.js | 2 +- .../tests/unit/utils/dom/sibling-test.js | 2 +- .../tests/unit/utils/get-environment-test.js | 2 +- .../unit/utils/get-form-name-property-test.js | 2 +- .../unit/utils/helpers/call-if-type-test.js | 2 +- .../unit/utils/http/create-headers-test.js | 2 +- .../utils/http/create-query-params-test.js | 2 +- .../tests/unit/utils/http/create-url-test.js | 2 +- .../tests/unit/utils/http/error-test.js | 2 +- .../tests/unit/utils/http/request-test.js | 2 +- .../tests/unit/utils/http/xhr-test.js | 2 +- .../tests/unit/utils/isFolder-test.js | 2 +- .../tests/unit/utils/keyToArray-test.js | 2 +- .../tests/unit/utils/left-trim-test.js | 2 +- .../tests/unit/utils/maybe-call-test.js | 2 +- .../tests/unit/utils/merge-checks-test.js | 2 +- .../tests/unit/utils/non-empty-set-test.js | 2 +- .../tests/unit/utils/path/resolve-test.js | 2 +- .../tests/unit/utils/promisedTimeout-test.js | 2 +- .../tests/unit/utils/right-trim-test.js | 2 +- .../unit/utils/routing/transitionable-test.js | 2 +- .../tests/unit/utils/routing/walk-test.js | 2 +- .../tests/unit/utils/routing/wildcard-test.js | 2 +- .../unit/utils/storage/local-storage-test.js | 2 +- .../tests/unit/utils/templatize-test.js | 2 +- .../tests/unit/utils/ticker/index-test.js | 2 +- .../tests/unit/utils/ucfirst-test.js | 2 +- .../unit/utils/update-array-object-test.js | 2 +- .../consul-ui/translations/common/en-us.yaml | 2 +- .../translations/components/app/en-us.yaml | 2 +- .../translations/components/consul/en-us.yaml | 2 +- .../components/copy-button/en-us.yaml | 2 +- .../consul-ui/translations/models/en-us.yaml | 2 +- .../consul-ui/translations/routes/en-us.yaml | 2 +- .../vendor/consul-ui/routes-debug.js | 2 +- .../consul-ui/vendor/consul-ui/routes.js | 2 +- .../vendor/consul-ui/services-debug.js | 2 +- .../consul-ui/vendor/consul-ui/services.js | 2 +- ui/packages/consul-ui/vendor/init.js | 2 +- .../vendor/metrics-providers/consul.js | 2 +- .../vendor/metrics-providers/prometheus.js | 2 +- version/VERSION | 2 +- version/fips.go | 3 - version/version.go | 2 +- version/version_test.go | 2 +- website/.eslintrc.js | 2 +- website/.stylelintrc.js | 2 +- website/content/api-docs/acl/index.mdx | 2 +- website/content/api-docs/acl/tokens.mdx | 3 + website/content/api-docs/agent/check.mdx | 4 + website/content/api-docs/catalog.mdx | 2 +- website/content/api-docs/status.mdx | 2 +- website/content/commands/connect/envoy.mdx | 2 +- website/content/commands/debug.mdx | 4 +- website/content/commands/snapshot/agent.mdx | 2 +- website/content/commands/snapshot/save.mdx | 15 + website/content/commands/watch.mdx | 5 - .../content/docs/agent/config/cli-flags.mdx | 2 +- .../docs/agent/config/config-files.mdx | 20 +- website/content/docs/agent/index.mdx | 3 + .../usage/limit-request-rates-from-ips.mdx | 6 +- .../usage/set-global-traffic-rate-limits.mdx | 2 +- website/content/docs/agent/rpc.mdx | 260 ++ website/content/docs/agent/telemetry.mdx | 4 +- .../docs/api-gateway/configuration/routes.mdx | 2 +- .../content/docs/api-gateway/tech-specs.mdx | 2 +- website/content/docs/connect/ca/index.mdx | 21 +- website/content/docs/connect/ca/vault.mdx | 40 +- .../control-plane-request-limit.mdx | 2 +- .../docs/connect/distributed-tracing.mdx | 2 +- .../content/docs/connect/failover/index.mdx | 8 +- .../configuration/ext-authz.mdx | 13 - .../configuration/otel-access-logging.mdx | 390 -- .../envoy-extensions/configuration/wasm.mdx | 4 +- .../proxies/envoy-extensions/index.mdx | 5 - .../envoy-extensions/usage/ext-authz.mdx | 1 + .../proxies/envoy-extensions/usage/lua.mdx | 12 +- .../usage/otel-access-logging.mdx | 146 - .../consul-vs-other/service-mesh-compare.mdx | 2 +- .../content/docs/dynamic-app-config/kv.mdx | 2 +- .../docs/dynamic-app-config/watches.mdx | 1 + .../docs/ecs/configuration-reference.mdx | 3 +- .../docs/ecs/manual/secure-configuration.mdx | 4 +- .../docs/enterprise/admin-partitions.mdx | 7 +- website/content/docs/k8s/compatibility.mdx | 2 +- .../cluster-peering/usage/manage-peering.mdx | 4 +- website/content/docs/k8s/connect/index.mdx | 9 +- .../k8s/connect/onboarding-tproxy-mode.mdx | 5 +- .../multi-cluster/kubernetes.mdx | 11 +- .../multi-cluster/vms-and-kubernetes.mdx | 12 +- website/content/docs/k8s/helm.mdx | 104 +- website/content/docs/k8s/upgrade/index.mdx | 2 +- website/content/docs/nia/configuration.mdx | 2 +- website/content/docs/nia/usage/errors-ref.mdx | 2 +- .../consul-api-gateway/v0_1_x.mdx | 2 +- .../docs/release-notes/consul/v1_16_x.mdx | 12 +- .../content/docs/security/acl/acl-roles.mdx | 4 +- .../docs/security/acl/auth-methods/index.mdx | 2 +- .../docs/security/security-models/core.mdx | 6 + .../checks-configuration-reference.mdx | 6 +- .../services-configuration-reference.mdx | 2 +- .../docs/upgrading/upgrade-specific.mdx | 8 +- website/data/docs-nav-data.json | 13 +- website/prettier.config.js | 2 +- website/public/ie-warning.js | 2 +- website/redirects.js | 2 +- website/scripts/should-build.sh | 2 +- website/scripts/website-build.sh | 2 +- website/scripts/website-start.sh | 2 +- 7199 files changed, 14033 insertions(+), 92858 deletions(-) delete mode 100644 .changelog/17155.txt delete mode 100644 .changelog/17481.txt delete mode 100644 .changelog/17593.txt delete mode 100644 .changelog/17694.txt delete mode 100644 .changelog/17831.txt delete mode 100644 .changelog/18007.txt delete mode 100644 .changelog/18300.txt create mode 100644 .changelog/18303.txt delete mode 100644 .changelog/18324.txt delete mode 100644 .changelog/18336.txt delete mode 100644 .changelog/18367.txt create mode 100644 .changelog/18381.txt delete mode 100644 .changelog/18439.txt delete mode 100644 .changelog/18560.txt delete mode 100644 .changelog/18583.txt create mode 100644 .changelog/18617.txt create mode 100644 .changelog/18625.txt create mode 100644 .changelog/18636.txt create mode 100644 .changelog/18667.txt delete mode 100644 .changelog/_18366.txt delete mode 100644 .changelog/_18422.txt delete mode 100755 .github/scripts/get_runner_classes_windows.sh rename .github/workflows/{nightly-test-1.16.x.yaml => nightly-test-1.12.x.yaml} (75%) delete mode 100644 .github/workflows/nightly-test-integrations-1.15.x.yml delete mode 100644 .github/workflows/nightly-test-integrations-1.16.x.yml delete mode 100644 .github/workflows/reusable-dev-build-windows.yml delete mode 100644 .github/workflows/test-integrations-windows.yml delete mode 100644 .release/docker/docker-entrypoint-windows.sh delete mode 100644 Dockerfile-windows rename Makefile => GNUmakefile (73%) delete mode 100644 agent/consul/tenancy_bridge.go delete mode 100644 agent/consul/tenancy_bridge_ce.go delete mode 100644 agent/consul/type_registry.go delete mode 100644 agent/envoyextensions/builtin/otel-access-logging/otel_access_logging.go delete mode 100644 agent/envoyextensions/builtin/otel-access-logging/otel_access_logging_test.go delete mode 100644 agent/envoyextensions/builtin/otel-access-logging/structs.go delete mode 100644 agent/envoyextensions/registered_extensions_ce.go delete mode 100644 agent/grpc-external/services/resource/mock_TenancyBridge.go delete mode 100644 agent/grpc-external/services/resource/server_ce.go delete mode 100644 agent/grpc-external/services/resource/server_ce_test.go delete mode 100644 agent/proxycfg-sources/catalog/config_source_oss.go delete mode 100644 agent/proxycfg/api_gateway_ce.go delete mode 100644 agent/proxycfg/config_snapshot_glue.go delete mode 100644 agent/proxycfg/config_snapshot_glue_test.go delete mode 100644 agent/structs/config_entry_apigw_jwt_ce.go delete mode 100644 agent/structs/structs.deepcopy_ce.go rename agent/xds/{config => }/config.go (98%) rename agent/xds/{config => }/config_test.go (99%) delete mode 100644 agent/xds/configfetcher/config_fetcher.go delete mode 100644 agent/xds/gw_per_route_filters_ce.go delete mode 100644 agent/xds/jwt_authn_ce.go delete mode 100644 agent/xds/locality_policy.go delete mode 100644 agent/xds/locality_policy_ce.go create mode 100644 agent/xds/naming.go delete mode 100644 agent/xds/naming/naming.go rename agent/xds/{platform => }/net_fallback.go (50%) rename agent/xds/{platform => }/net_linux.go (87%) delete mode 100644 agent/xds/proxystateconverter/clusters.go delete mode 100644 agent/xds/proxystateconverter/converter.go delete mode 100644 agent/xds/proxystateconverter/endpoints.go delete mode 100644 agent/xds/proxystateconverter/failover_policy.go delete mode 100644 agent/xds/proxystateconverter/failover_policy_ce.go delete mode 100644 agent/xds/proxystateconverter/listeners.go delete mode 100644 agent/xds/proxystateconverter/locality_policy.go delete mode 100644 agent/xds/proxystateconverter/locality_policy_ce.go delete mode 100644 agent/xds/proxystateconverter/routes.go rename agent/xds/{response => }/response.go (80%) rename agent/xds/testdata/clusters/{api-gateway-with-http-route.latest.golden => api-gateway-with-http-route-and-inline-certificate.latest.golden} (100%) delete mode 100644 agent/xds/testdata/clusters/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden delete mode 100644 agent/xds/testdata/clusters/api-gateway-with-multiple-inline-certificates.latest.golden delete mode 100644 agent/xds/testdata/clusters/connect-proxy-with-chain-http2.latest.golden delete mode 100644 agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden delete mode 100644 agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-http2.latest.golden delete mode 100644 agent/xds/testdata/clusters/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden delete mode 100644 agent/xds/testdata/clusters/custom-upstream-with-prepared-query.latest.golden delete mode 100644 agent/xds/testdata/clusters/enterprise-connect-proxy-with-chain-http2.latest.golden delete mode 100644 agent/xds/testdata/clusters/expose-checks.latest.golden delete mode 100644 agent/xds/testdata/clusters/mesh-gateway-using-federation-control-plane.latest.golden rename agent/xds/testdata/endpoints/{api-gateway-with-http-route.latest.golden => api-gateway-with-http-route-and-inline-certificate.latest.golden} (100%) delete mode 100644 agent/xds/testdata/endpoints/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden delete mode 100644 agent/xds/testdata/endpoints/api-gateway-with-multiple-inline-certificates.latest.golden delete mode 100644 agent/xds/testdata/endpoints/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden delete mode 100644 agent/xds/testdata/endpoints/connect-proxy-with-peered-upstreams-http2.latest.golden delete mode 100644 agent/xds/testdata/endpoints/mesh-gateway-using-federation-control-plane.latest.golden create mode 100644 agent/xds/testdata/listeners/api-gateway-with-http-route-and-inline-certificate.latest.golden delete mode 100644 agent/xds/testdata/listeners/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden delete mode 100644 agent/xds/testdata/listeners/api-gateway-with-http-route.latest.golden delete mode 100644 agent/xds/testdata/listeners/api-gateway-with-multiple-inline-certificates.latest.golden delete mode 100644 agent/xds/testdata/listeners/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden delete mode 100644 agent/xds/testdata/listeners/connect-proxy-with-peered-upstreams-http2.latest.golden delete mode 100644 agent/xds/testdata/listeners/custom-upstream-with-prepared-query.latest.golden delete mode 100644 agent/xds/testdata/listeners/expose-checks-grpc.latest.golden delete mode 100644 agent/xds/testdata/listeners/expose-checks-http-with-bind-override.latest.golden rename agent/xds/testdata/listeners/{expose-checks-http.latest.golden => expose-checks.latest.golden} (100%) delete mode 100644 agent/xds/testdata/listeners/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden delete mode 100644 agent/xds/testdata/listeners/ingress-with-tls-mixed-max-version-listeners.latest.golden delete mode 100644 agent/xds/testdata/listeners/mesh-gateway-using-federation-control-plane.latest.golden delete mode 100644 agent/xds/testdata/listeners/terminating-gateway-custom-trace-listener.latest.golden rename agent/xds/testdata/routes/{api-gateway-with-http-route-timeoutfilter-one-set.latest.golden => api-gateway-with-http-route-and-inline-certificate.latest.golden} (94%) delete mode 100644 agent/xds/testdata/routes/api-gateway-with-http-route.latest.golden delete mode 100644 agent/xds/testdata/routes/api-gateway-with-multiple-inline-certificates.latest.golden delete mode 100644 agent/xds/testdata/routes/connect-proxy-resolver-with-lb.latest.golden delete mode 100644 agent/xds/testdata/routes/connect-proxy-route-to-lb-resolver.latest.golden delete mode 100644 agent/xds/testdata/routes/connect-proxy-splitter-overweight.latest.golden delete mode 100644 agent/xds/testdata/routes/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden delete mode 100644 agent/xds/testdata/routes/connect-proxy-with-peered-upstreams-http2.latest.golden delete mode 100644 agent/xds/testdata/secrets/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden delete mode 100644 agent/xds/testdata/secrets/api-gateway-with-http-route.latest.golden delete mode 100644 agent/xds/testdata/secrets/api-gateway-with-multiple-inline-certificates.latest.golden delete mode 100644 agent/xds/testdata/secrets/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden delete mode 100644 agent/xds/testdata/secrets/connect-proxy-with-peered-upstreams-http2.latest.golden delete mode 100644 agent/xds/testdata/secrets/connect-proxy-with-peered-upstreams-listener-override.latest.golden delete mode 100644 agent/xdsv2/cluster_resources.go delete mode 100644 agent/xdsv2/endpoint_resources.go delete mode 100644 agent/xdsv2/listener_resources.go delete mode 100644 agent/xdsv2/resources.go delete mode 100644 agent/xdsv2/route_resources.go delete mode 100644 api/LICENSE delete mode 100644 api/config_entry_routes_test.go delete mode 100755 build-support/scripts/check-allowed-imports.sh delete mode 100644 build-support/windows/Dockerfile-consul-dev-windows delete mode 100644 build-support/windows/Dockerfile-consul-local-windows delete mode 100644 build-support/windows/Dockerfile-openzipkin-windows delete mode 100644 build-support/windows/build-consul-dev-image.sh delete mode 100644 build-support/windows/build-consul-local-images.sh delete mode 100644 build-support/windows/build-test-sds-server-image.sh delete mode 100644 build-support/windows/windows-test.md delete mode 100644 command/connect/envoy/exec_supported.go delete mode 100644 command/connect/envoy/exec_windows.go delete mode 100644 command/connect/envoy/exec_windows_arm64.go delete mode 100644 grafana/consul-k8s-control-plane-monitoring.json delete mode 100644 internal/catalog/catalogtest/test_lifecycle_v1alpha1.go delete mode 100644 internal/catalog/internal/controllers/failover/controller.go delete mode 100644 internal/catalog/internal/controllers/failover/controller_test.go delete mode 100644 internal/catalog/internal/controllers/failover/status.go delete mode 100644 internal/catalog/internal/mappers/failovermapper/failover_mapper.go delete mode 100644 internal/catalog/internal/mappers/failovermapper/failover_mapper_test.go delete mode 100644 internal/catalog/internal/types/failover_policy.go delete mode 100644 internal/catalog/internal/types/failover_policy_test.go delete mode 100644 internal/mesh/internal/controllers/register.go delete mode 100644 internal/mesh/internal/controllers/xds/controller.go delete mode 100644 internal/mesh/internal/controllers/xds/controller_test.go delete mode 100644 internal/mesh/internal/controllers/xds/endpoint_builder.go delete mode 100644 internal/mesh/internal/controllers/xds/endpoint_builder_test.go delete mode 100644 internal/mesh/internal/controllers/xds/mock_updater.go delete mode 100644 internal/mesh/internal/controllers/xds/proxy_tracker_watch.go delete mode 100644 internal/mesh/internal/controllers/xds/reconciliation_data.go delete mode 100644 internal/mesh/internal/controllers/xds/status/status.go delete mode 100644 internal/mesh/internal/types/computed_routes.go delete mode 100644 internal/mesh/internal/types/computed_routes_test.go delete mode 100644 internal/mesh/internal/types/decoded.go delete mode 100644 internal/mesh/internal/types/destination_policy.go delete mode 100644 internal/mesh/internal/types/destination_policy_test.go delete mode 100644 internal/mesh/internal/types/grpc_route.go delete mode 100644 internal/mesh/internal/types/grpc_route_test.go delete mode 100644 internal/mesh/internal/types/http_route.go delete mode 100644 internal/mesh/internal/types/http_route_test.go delete mode 100644 internal/mesh/internal/types/proxy_state_template.go delete mode 100644 internal/mesh/internal/types/tcp_route.go delete mode 100644 internal/mesh/internal/types/tcp_route_test.go delete mode 100644 internal/mesh/internal/types/upstreams_configuration.go delete mode 100644 internal/mesh/internal/types/util.go delete mode 100644 internal/mesh/internal/types/xroute.go delete mode 100644 internal/mesh/proxy-snapshot/proxy_snapshot.go delete mode 100644 internal/mesh/proxy-tracker/mock_SessionLimiter.go delete mode 100644 internal/mesh/proxy-tracker/proxy_state_exports.go delete mode 100644 internal/mesh/proxy-tracker/proxy_tracker.go delete mode 100644 internal/mesh/proxy-tracker/proxy_tracker_test.go delete mode 100644 internal/protohcl/any.go delete mode 100644 internal/protohcl/attributes.go delete mode 100644 internal/protohcl/blocks.go delete mode 100644 internal/protohcl/cty.go delete mode 100644 internal/protohcl/decoder.go delete mode 100644 internal/protohcl/doc.go delete mode 100644 internal/protohcl/naming.go delete mode 100644 internal/protohcl/oneof.go delete mode 100644 internal/protohcl/primitives.go delete mode 100644 internal/protohcl/testproto/buf.gen.yaml delete mode 100644 internal/protohcl/testproto/example.pb.go delete mode 100644 internal/protohcl/testproto/example.proto delete mode 100644 internal/protohcl/unmarshal.go delete mode 100644 internal/protohcl/unmarshal_test.go delete mode 100644 internal/protohcl/well_known_types.go delete mode 100644 internal/resource/authz_ce.go delete mode 100644 internal/resource/decode.go delete mode 100644 internal/resource/decode_test.go delete mode 100644 internal/resource/http/http.go delete mode 100644 internal/resource/http/http_test.go delete mode 100644 internal/resource/mappers/bimapper/bimapper.go delete mode 100644 internal/resource/mappers/bimapper/bimapper_test.go delete mode 100644 internal/resource/refkey.go delete mode 100644 internal/resource/refkey_test.go delete mode 100644 internal/resource/resourcetest/decode.go delete mode 100644 internal/resource/resourcetest/validation.go delete mode 100644 internal/resource/stringer.go delete mode 100644 internal/resource/tenancy.go delete mode 100644 internal/resourcehcl/any.go delete mode 100644 internal/resourcehcl/naming.go delete mode 100644 internal/resourcehcl/testdata/gvk-no-arguments.error delete mode 100644 internal/resourcehcl/testdata/gvk-no-arguments.hcl delete mode 100644 internal/resourcehcl/testdata/invalid-group.error delete mode 100644 internal/resourcehcl/testdata/invalid-group.hcl delete mode 100644 internal/resourcehcl/testdata/invalid-gvk.error delete mode 100644 internal/resourcehcl/testdata/invalid-gvk.hcl delete mode 100644 internal/resourcehcl/testdata/invalid-metadata.error delete mode 100644 internal/resourcehcl/testdata/invalid-metadata.hcl delete mode 100644 internal/resourcehcl/testdata/invalid-name.error delete mode 100644 internal/resourcehcl/testdata/invalid-name.hcl delete mode 100644 internal/resourcehcl/testdata/no-blocks-any-first.golden delete mode 100644 internal/resourcehcl/testdata/no-blocks-any-first.hcl delete mode 100644 internal/resourcehcl/testdata/no-blocks.golden delete mode 100644 internal/resourcehcl/testdata/no-blocks.hcl delete mode 100644 internal/resourcehcl/testdata/owner.golden delete mode 100644 internal/resourcehcl/testdata/owner.hcl delete mode 100644 internal/resourcehcl/testdata/simple-gvk.golden delete mode 100644 internal/resourcehcl/testdata/simple-gvk.hcl delete mode 100644 internal/resourcehcl/testdata/type-block.golden delete mode 100644 internal/resourcehcl/testdata/type-block.hcl delete mode 100644 internal/resourcehcl/testdata/unknown-field-block.error delete mode 100644 internal/resourcehcl/testdata/unknown-field-block.hcl delete mode 100644 internal/resourcehcl/testdata/unknown-field-object.error delete mode 100644 internal/resourcehcl/testdata/unknown-field-object.hcl delete mode 100644 internal/resourcehcl/testdata/unknown-type.error delete mode 100644 internal/resourcehcl/testdata/unknown-type.hcl delete mode 100644 internal/resourcehcl/testdata/upstreams.golden delete mode 100644 internal/resourcehcl/testdata/upstreams.hcl delete mode 100644 internal/resourcehcl/unmarshal.go delete mode 100644 internal/resourcehcl/unmarshal_test.go create mode 100644 logging/logfile_bsd.go create mode 100644 logging/logfile_linux.go create mode 100644 logging/logfile_solaris.go create mode 100644 logging/logfile_windows.go delete mode 100644 proto-public/LICENSE delete mode 100644 proto-public/pbcatalog/v1alpha1/failover_policy.pb.binary.go delete mode 100644 proto-public/pbcatalog/v1alpha1/failover_policy.pb.go delete mode 100644 proto-public/pbcatalog/v1alpha1/failover_policy.proto delete mode 100644 proto-public/pbcatalog/v1alpha1/failover_policy_extras.go delete mode 100644 proto-public/pbcatalog/v1alpha1/failover_policy_extras_test.go delete mode 100644 proto-public/pbmesh/v1alpha1/common.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/common.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/common.proto delete mode 100644 proto-public/pbmesh/v1alpha1/computed_routes.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/computed_routes.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/computed_routes.proto delete mode 100644 proto-public/pbmesh/v1alpha1/destination_policy.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/destination_policy.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/destination_policy.proto delete mode 100644 proto-public/pbmesh/v1alpha1/grpc_route.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/grpc_route.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/grpc_route.proto delete mode 100644 proto-public/pbmesh/v1alpha1/http_route.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/http_route.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/http_route.proto delete mode 100644 proto-public/pbmesh/v1alpha1/http_route_retries.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/http_route_retries.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/http_route_retries.proto delete mode 100644 proto-public/pbmesh/v1alpha1/http_route_timeouts.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/http_route_timeouts.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/http_route_timeouts.proto delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/access_logs.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/access_logs.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/access_logs.proto delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/address.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/address.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/address.proto delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/cluster.proto delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/endpoints.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/endpoints.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/endpoints.proto delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/escape_hatches.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/escape_hatches.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/escape_hatches.proto delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/header_mutations.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/header_mutations.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/header_mutations.proto delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/intentions.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/intentions.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/intentions.proto delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/listener.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/listener.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/listener.proto delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/references.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/references.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/references.proto delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/route.proto delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/transport_socket.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/transport_socket.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/pbproxystate/transport_socket.proto rename proto-public/pbmesh/v1alpha1/{proxy_configuration.pb.binary.go => proxy.pb.binary.go} (67%) create mode 100644 proto-public/pbmesh/v1alpha1/proxy.pb.go rename proto-public/pbmesh/v1alpha1/{proxy_configuration.proto => proxy.proto} (60%) delete mode 100644 proto-public/pbmesh/v1alpha1/proxy_configuration.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/proxy_state.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/proxy_state.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/proxy_state.proto delete mode 100644 proto-public/pbmesh/v1alpha1/tcp_route.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/tcp_route.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/tcp_route.proto delete mode 100644 proto-public/pbmesh/v1alpha1/upstreams_configuration.pb.binary.go delete mode 100644 proto-public/pbmesh/v1alpha1/upstreams_configuration.pb.go delete mode 100644 proto-public/pbmesh/v1alpha1/upstreams_configuration.proto delete mode 100644 proto-public/pbmesh/v1alpha1/xroute_addons.go delete mode 100644 proto-public/pbmesh/v1alpha1/xroute_addons_test.go delete mode 100644 proto/private/pbconfigentry/config_entry_ce.go delete mode 100644 sdk/LICENSE delete mode 100644 sdk/testutil/retry/counter.go delete mode 100644 sdk/testutil/retry/timer.go delete mode 100644 test-integ/README.md delete mode 100644 test-integ/go.mod delete mode 100644 test-integ/go.sum delete mode 100644 test-integ/peering_commontopo/README.md delete mode 100644 test-integ/peering_commontopo/ac1_basic_test.go delete mode 100644 test-integ/peering_commontopo/ac2_disco_chain_test.go delete mode 100644 test-integ/peering_commontopo/ac3_service_defaults_upstream_test.go delete mode 100644 test-integ/peering_commontopo/ac4_proxy_defaults_test.go delete mode 100644 test-integ/peering_commontopo/ac5_1_no_svc_mesh_test.go delete mode 100644 test-integ/peering_commontopo/ac5_2_pq_failover_test.go delete mode 100644 test-integ/peering_commontopo/ac6_failovers_test.go delete mode 100644 test-integ/peering_commontopo/ac7_1_rotate_gw_test.go delete mode 100644 test-integ/peering_commontopo/ac7_2_rotate_leader_test.go delete mode 100644 test-integ/peering_commontopo/asserter.go delete mode 100644 test-integ/peering_commontopo/commontopo.go delete mode 100644 test-integ/peering_commontopo/sharedtopology_test.go delete mode 100644 test/integration/connect/envoy/Dockerfile-consul-envoy-windows delete mode 100644 test/integration/connect/envoy/Dockerfile-tcpdump-windows delete mode 100644 test/integration/connect/envoy/Dockerfile-test-sds-server-windows delete mode 100644 test/integration/connect/envoy/WINDOWS-TEST.md delete mode 100644 test/integration/connect/envoy/case-wanfed-gw/global-setup-windows.sh delete mode 100644 test/integration/connect/envoy/docker-windows.md delete mode 100644 test/integration/connect/envoy/docs/img/linux-arch.png delete mode 100644 test/integration/connect/envoy/docs/img/windows-arch-singlecontainer.png delete mode 100644 test/integration/connect/envoy/docs/img/windows-linux-arch.png delete mode 100644 test/integration/connect/envoy/docs/windows-testing-architecture.md delete mode 100644 test/integration/connect/envoy/helpers.windows.bash delete mode 100644 test/integration/connect/envoy/run-tests.windows.sh delete mode 100644 test/integration/connect/envoy/windows-troubleshooting.md delete mode 100644 test/integration/consul-container/test/catalog/catalog_test.go delete mode 100644 test/integration/consul-container/test/debugging.md delete mode 100644 test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/Dockerfile delete mode 100644 test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/README.md delete mode 100755 test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/build.sh delete mode 100644 test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.mod delete mode 100644 test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.sum delete mode 100644 test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/nginx.conf delete mode 100644 test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/wasm_add_header.go delete mode 100755 test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/wasm_add_header.wasm delete mode 100644 test/integration/consul-container/test/envoy_extensions/wasm_test.go delete mode 100644 test/integration/consul-container/test/upgrade/catalog/catalog_test.go delete mode 100644 test/integration/consul-container/test/util/test_debug_breakpoint_hit.png delete mode 100644 test/integration/consul-container/test/util/test_debug_configuration.png delete mode 100644 test/integration/consul-container/test/util/test_debug_info.png delete mode 100644 test/integration/consul-container/test/util/test_debug_remote_configuration.png delete mode 100644 test/integration/consul-container/test/util/test_debug_remote_connected.png delete mode 100644 test/integration/consul-container/test/util/test_debug_resume_program.png delete mode 100644 testing/deployer/.gitignore delete mode 100644 testing/deployer/README.md delete mode 100644 testing/deployer/TODO.md delete mode 100644 testing/deployer/go.mod delete mode 100644 testing/deployer/go.sum delete mode 100644 testing/deployer/sprawl/acl.go delete mode 100644 testing/deployer/sprawl/acl_rules.go delete mode 100644 testing/deployer/sprawl/boot.go delete mode 100644 testing/deployer/sprawl/catalog.go delete mode 100644 testing/deployer/sprawl/configentries.go delete mode 100644 testing/deployer/sprawl/consul.go delete mode 100644 testing/deployer/sprawl/debug.go delete mode 100644 testing/deployer/sprawl/details.go delete mode 100644 testing/deployer/sprawl/ent.go delete mode 100644 testing/deployer/sprawl/helpers.go delete mode 100644 testing/deployer/sprawl/internal/build/docker.go delete mode 100644 testing/deployer/sprawl/internal/runner/exec.go delete mode 100644 testing/deployer/sprawl/internal/secrets/store.go delete mode 100644 testing/deployer/sprawl/internal/tfgen/agent.go delete mode 100644 testing/deployer/sprawl/internal/tfgen/digest.go delete mode 100644 testing/deployer/sprawl/internal/tfgen/dns.go delete mode 100644 testing/deployer/sprawl/internal/tfgen/docker.go delete mode 100644 testing/deployer/sprawl/internal/tfgen/docker_test.go delete mode 100644 testing/deployer/sprawl/internal/tfgen/gen.go delete mode 100644 testing/deployer/sprawl/internal/tfgen/io.go delete mode 100644 testing/deployer/sprawl/internal/tfgen/nodes.go delete mode 100644 testing/deployer/sprawl/internal/tfgen/prelude.go delete mode 100644 testing/deployer/sprawl/internal/tfgen/proxy.go delete mode 100644 testing/deployer/sprawl/internal/tfgen/res.go delete mode 100644 testing/deployer/sprawl/internal/tfgen/templates/container-app-dataplane.tf.tmpl delete mode 100644 testing/deployer/sprawl/internal/tfgen/templates/container-app-sidecar.tf.tmpl delete mode 100644 testing/deployer/sprawl/internal/tfgen/templates/container-app.tf.tmpl delete mode 100644 testing/deployer/sprawl/internal/tfgen/templates/container-consul.tf.tmpl delete mode 100644 testing/deployer/sprawl/internal/tfgen/templates/container-coredns.tf.tmpl delete mode 100644 testing/deployer/sprawl/internal/tfgen/templates/container-mgw.tf.tmpl delete mode 100644 testing/deployer/sprawl/internal/tfgen/templates/container-pause.tf.tmpl delete mode 100644 testing/deployer/sprawl/internal/tfgen/templates/container-proxy.tf.tmpl delete mode 100644 testing/deployer/sprawl/internal/tfgen/tfgen.go delete mode 100644 testing/deployer/sprawl/peering.go delete mode 100644 testing/deployer/sprawl/sprawl.go delete mode 100644 testing/deployer/sprawl/sprawltest/sprawltest.go delete mode 100644 testing/deployer/sprawl/sprawltest/test_test.go delete mode 100644 testing/deployer/sprawl/tls.go delete mode 100644 testing/deployer/topology/compile.go delete mode 100644 testing/deployer/topology/default_cdp.go delete mode 100644 testing/deployer/topology/default_consul.go delete mode 100644 testing/deployer/topology/default_envoy.go delete mode 100644 testing/deployer/topology/ids.go delete mode 100644 testing/deployer/topology/images.go delete mode 100644 testing/deployer/topology/images_test.go delete mode 100644 testing/deployer/topology/topology.go delete mode 100644 testing/deployer/topology/util.go delete mode 100644 testing/deployer/topology/util_test.go delete mode 100644 testing/deployer/util/consul.go delete mode 100644 testing/deployer/util/files.go delete mode 100644 testing/deployer/util/internal/ipamutils/doc.go delete mode 100644 testing/deployer/util/internal/ipamutils/utils.go delete mode 100644 testing/deployer/util/internal/ipamutils/utils_test.go delete mode 100644 testing/deployer/util/net.go create mode 100644 website/content/docs/agent/rpc.mdx delete mode 100644 website/content/docs/connect/proxies/envoy-extensions/configuration/otel-access-logging.mdx delete mode 100644 website/content/docs/connect/proxies/envoy-extensions/usage/otel-access-logging.mdx diff --git a/.changelog/17155.txt b/.changelog/17155.txt deleted file mode 100644 index 03cec33e991af..0000000000000 --- a/.changelog/17155.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -config: Add new `tls.defaults.verify_server_hostname` configuration option. This specifies the default value for any interfaces that support the `verify_server_hostname` option. -``` diff --git a/.changelog/17481.txt b/.changelog/17481.txt deleted file mode 100644 index 89ad16998e836..0000000000000 --- a/.changelog/17481.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -tlsutil: Default setting of ServerName field in outgoing TLS configuration for checks now handled by crypto/tls. -``` diff --git a/.changelog/17593.txt b/.changelog/17593.txt deleted file mode 100644 index 1f84e75f57427..0000000000000 --- a/.changelog/17593.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -docs: fix list of telemetry metrics -``` diff --git a/.changelog/17694.txt b/.changelog/17694.txt deleted file mode 100644 index 703b100d1d3a3..0000000000000 --- a/.changelog/17694.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:feature -Windows: support consul connect envoy command on Windows -``` diff --git a/.changelog/17754.txt b/.changelog/17754.txt index 32272ec1ae911..56ab20dc213ef 100644 --- a/.changelog/17754.txt +++ b/.changelog/17754.txt @@ -1,3 +1,3 @@ ```release-note:feature -ui: Display the Consul agent version in the nodes list, and allow filtering and sorting of nodes based on versions. -``` \ No newline at end of file +ui: consul version is displayed in nodes list with filtering and sorting based on versions +``` diff --git a/.changelog/17831.txt b/.changelog/17831.txt deleted file mode 100644 index 2833bda1d5765..0000000000000 --- a/.changelog/17831.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -ca: Vault CA provider config no longer requires root_pki_path for secondary datacenters -``` diff --git a/.changelog/18007.txt b/.changelog/18007.txt deleted file mode 100644 index b963d2f77fcd6..0000000000000 --- a/.changelog/18007.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -Windows: Integration tests for Consul Windows VMs -``` diff --git a/.changelog/18300.txt b/.changelog/18300.txt deleted file mode 100644 index 717a697777e26..0000000000000 --- a/.changelog/18300.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -connect: update supported envoy versions to 1.24.10, 1.25.9, 1.26.4, 1.27.0 -``` diff --git a/.changelog/18303.txt b/.changelog/18303.txt new file mode 100644 index 0000000000000..4afc4473b7c90 --- /dev/null +++ b/.changelog/18303.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: update supported envoy versions to 1.23.12, 1.24.10, 1.25.9, 1.26.4 +``` diff --git a/.changelog/18324.txt b/.changelog/18324.txt deleted file mode 100644 index 6d1f11a92e969..0000000000000 --- a/.changelog/18324.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:feature -api-gateway: add retry and timeout filters -``` \ No newline at end of file diff --git a/.changelog/18336.txt b/.changelog/18336.txt deleted file mode 100644 index 5d91046ec5efd..0000000000000 --- a/.changelog/18336.txt +++ /dev/null @@ -1,7 +0,0 @@ -```release-note:feature -xds: Add a built-in Envoy extension that appends OpenTelemetry Access Logging (otel-access-logging) to the HTTP Connection Manager filter. -``` - -```release-note:feature -xds: Add support for patching outbound listeners to the built-in Envoy External Authorization extension. -``` diff --git a/.changelog/18367.txt b/.changelog/18367.txt deleted file mode 100644 index 578cf7091853f..0000000000000 --- a/.changelog/18367.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -dev-mode: Fix dev mode has new line in responses. Now new line is added only when url has pretty query parameter. -``` diff --git a/.changelog/18381.txt b/.changelog/18381.txt new file mode 100644 index 0000000000000..f6af62993f596 --- /dev/null +++ b/.changelog/18381.txt @@ -0,0 +1,6 @@ +```release-note:improvement +checks: It is now possible to configure agent TCP checks to use TLS with +optional server SNI and mutual authentication. To use TLS with a TCP check, the +check must enable the `tcp_use_tls` boolean. By default the agent will use the +TLS configuration in the `tls.default` stanza. +``` diff --git a/.changelog/18439.txt b/.changelog/18439.txt deleted file mode 100644 index dd12738d5c387..0000000000000 --- a/.changelog/18439.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:feature -Support custom watches on the Consul Controller framework. -``` diff --git a/.changelog/18560.txt b/.changelog/18560.txt deleted file mode 100644 index 118fad95306d7..0000000000000 --- a/.changelog/18560.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -ui: Use Community verbiage -``` \ No newline at end of file diff --git a/.changelog/18583.txt b/.changelog/18583.txt deleted file mode 100644 index 8121e01ced0db..0000000000000 --- a/.changelog/18583.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:feature -mesh: **(Enterprise only)** Adds rate limiting config to service-defaults -``` diff --git a/.changelog/18617.txt b/.changelog/18617.txt new file mode 100644 index 0000000000000..1f840d836dee4 --- /dev/null +++ b/.changelog/18617.txt @@ -0,0 +1,4 @@ +```release-note:improvement +log: Currently consul logs files like this consul-{timestamp}.log. This change makes sure that there is always +consul.log file with the latest logs in it. +``` \ No newline at end of file diff --git a/.changelog/18625.txt b/.changelog/18625.txt new file mode 100644 index 0000000000000..8474cac8dc1d7 --- /dev/null +++ b/.changelog/18625.txt @@ -0,0 +1,5 @@ +```release-note:improvement +Adds flag -append-filename (which works on values version, dc, node and status) to consul snapshot save command. +Adding the flag -append-filename version,dc,node,status will add consul version, consul datacenter, node name and leader/follower +(status) in the file name given in the snapshot save command before the file extension. +``` diff --git a/.changelog/18636.txt b/.changelog/18636.txt new file mode 100644 index 0000000000000..ff6990f5abcbf --- /dev/null +++ b/.changelog/18636.txt @@ -0,0 +1,3 @@ +```release-note:bug +connect: Fix issue where Envoy endpoints would not populate correctly after a snapshot restore. +``` diff --git a/.changelog/18667.txt b/.changelog/18667.txt new file mode 100644 index 0000000000000..c9ef7b4551217 --- /dev/null +++ b/.changelog/18667.txt @@ -0,0 +1,3 @@ +```release-note:improvement +api: Add support for listing ACL tokens by service name. +``` diff --git a/.changelog/_18366.txt b/.changelog/_18366.txt deleted file mode 100644 index 02a3599c2c27c..0000000000000 --- a/.changelog/_18366.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:feature -config-entry(api-gateway): (Enterprise only) Add GatewayPolicy to APIGateway Config Entry listeners -``` diff --git a/.changelog/_18422.txt b/.changelog/_18422.txt deleted file mode 100644 index 4f0efbbe3b278..0000000000000 --- a/.changelog/_18422.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:feature -config-entry(api-gateway): (Enterprise only) Add JWTFilter to HTTPRoute Filters -``` diff --git a/.copywrite.hcl b/.copywrite.hcl index dbe52115c27ea..fa06f76e2ac69 100644 --- a/.copywrite.hcl +++ b/.copywrite.hcl @@ -1,8 +1,8 @@ schema_version = 1 project { - license = "BUSL-1.1" - copyright_year = 2023 + license = "MPL-2.0" + copyright_year = 2013 # (OPTIONAL) A list of globs that should not have copyright/license headers. # Supports doublestar glob patterns for more flexibility in defining which @@ -19,18 +19,11 @@ project { # ignore specific test data files "agent/uiserver/testdata/**", - "internal/resourcehcl/testdata/**", # generated files "agent/structs/structs.deepcopy.go", "agent/proxycfg/proxycfg.deepcopy.go", "agent/grpc-middleware/rate_limit_mappings.gen.go", "agent/uiserver/dist/**", - - # licensed under MPL - ignoring for now until the copywrite tool can support - # multiple licenses per repo. - "sdk/**", - "api/**", - "proto-public/**", ] } diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 16480bb6f4f94..36f9456693ff3 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 blank_issues_enabled: false contact_links: diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d618028e100bd..05387a7c9b803 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 version: 2 updates: diff --git a/.github/pr-labeler.yml b/.github/pr-labeler.yml index fd39f2ccab423..e10f3c1376ef0 100644 --- a/.github/pr-labeler.yml +++ b/.github/pr-labeler.yml @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 pr/dependencies: - vendor/**/* diff --git a/.github/scripts/changelog_checker.sh b/.github/scripts/changelog_checker.sh index a214ef2477979..e6b4d7f85dcc0 100755 --- a/.github/scripts/changelog_checker.sh +++ b/.github/scripts/changelog_checker.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/.github/scripts/get_runner_classes.sh b/.github/scripts/get_runner_classes.sh index abd3f1bce2d01..2e66a4e344c6c 100755 --- a/.github/scripts/get_runner_classes.sh +++ b/.github/scripts/get_runner_classes.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # # This script generates tag-sets that can be used as runs-on: values to select runners. @@ -8,19 +8,19 @@ set -euo pipefail case "$GITHUB_REPOSITORY" in - *-enterprise) - # shellcheck disable=SC2129 - echo "compute-small=['self-hosted', 'linux', 'small']" >> "$GITHUB_OUTPUT" - echo "compute-medium=['self-hosted', 'linux', 'medium']" >> "$GITHUB_OUTPUT" - echo "compute-large=['self-hosted', 'linux', 'large']" >> "$GITHUB_OUTPUT" - # m5d.8xlarge is equivalent to our xl custom runner in CE - echo "compute-xl=['self-hosted', 'ondemand', 'linux', 'type=m5d.8xlarge']" >> "$GITHUB_OUTPUT" - ;; - *) - # shellcheck disable=SC2129 - echo "compute-small=['custom-linux-s-consul-latest']" >> "$GITHUB_OUTPUT" - echo "compute-medium=['custom-linux-m-consul-latest']" >> "$GITHUB_OUTPUT" - echo "compute-large=['custom-linux-l-consul-latest']" >> "$GITHUB_OUTPUT" - echo "compute-xl=['custom-linux-xl-consul-latest']" >> "$GITHUB_OUTPUT" - ;; +*-enterprise) + # shellcheck disable=SC2129 + echo "compute-small=['self-hosted', 'linux', 'small']" >>"$GITHUB_OUTPUT" + echo "compute-medium=['self-hosted', 'linux', 'medium']" >>"$GITHUB_OUTPUT" + echo "compute-large=['self-hosted', 'linux', 'large']" >>"$GITHUB_OUTPUT" + # m5d.8xlarge is equivalent to our xl custom runner in CE + echo "compute-xl=['self-hosted', 'ondemand', 'linux', 'type=m6a.2xlarge']" >>"$GITHUB_OUTPUT" + ;; +*) + # shellcheck disable=SC2129 + echo "compute-small=['custom-linux-s-consul-latest']" >>"$GITHUB_OUTPUT" + echo "compute-medium=['custom-linux-m-consul-latest']" >>"$GITHUB_OUTPUT" + echo "compute-large=['custom-linux-l-consul-latest']" >>"$GITHUB_OUTPUT" + echo "compute-xl=['custom-linux-xl-consul-latest']" >>"$GITHUB_OUTPUT" + ;; esac diff --git a/.github/scripts/get_runner_classes_windows.sh b/.github/scripts/get_runner_classes_windows.sh deleted file mode 100755 index d9f46488798f9..0000000000000 --- a/.github/scripts/get_runner_classes_windows.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - -# -# This script generates tag-sets that can be used as runs-on: values to select runners. - -set -euo pipefail - -case "$GITHUB_REPOSITORY" in - *-enterprise) - # shellcheck disable=SC2129 - echo "compute-small=['self-hosted', 'windows', 'small']" >> "$GITHUB_OUTPUT" - echo "compute-medium=['self-hosted', 'windows', 'medium']" >> "$GITHUB_OUTPUT" - echo "compute-large=['self-hosted', 'windows', 'large']" >> "$GITHUB_OUTPUT" - # m5d.8xlarge is equivalent to our xl custom runner in CE - echo "compute-xl=['self-hosted', 'ondemand', 'windows', 'type=m5d.8xlarge']" >> "$GITHUB_OUTPUT" - ;; - *) - # shellcheck disable=SC2129 - echo "compute-small=['windows-2019']" >> "$GITHUB_OUTPUT" - echo "compute-medium=['windows-2019']" >> "$GITHUB_OUTPUT" - echo "compute-large=['windows-2019']" >> "$GITHUB_OUTPUT" - echo "compute-xl=['windows-2019']" >> "$GITHUB_OUTPUT" - ;; -esac diff --git a/.github/scripts/metrics_checker.sh b/.github/scripts/metrics_checker.sh index 37659de4df8bd..a34cdf12fbec3 100755 --- a/.github/scripts/metrics_checker.sh +++ b/.github/scripts/metrics_checker.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -uo pipefail diff --git a/.github/scripts/notify_slack.sh b/.github/scripts/notify_slack.sh index 8df3f3f648766..eacefaa91a439 100755 --- a/.github/scripts/notify_slack.sh +++ b/.github/scripts/notify_slack.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 + set -uo pipefail @@ -12,8 +13,8 @@ if [[ $GITHUB_REF_NAME == "main" ]]; then COMMIT_MESSAGE=$(git log -1 --pretty=%B | head -n1) SHORT_REF=$(git rev-parse --short "${GITHUB_SHA}") curl -X POST -H 'Content-type: application/json' \ - --data \ - "{ \ + --data \ + "{ \ \"attachments\": [ \ { \ \"fallback\": \"GitHub Actions workflow failed!\", \ diff --git a/.github/scripts/rerun_fails_report.sh b/.github/scripts/rerun_fails_report.sh index 90bae7a03a59d..ac6b7cf2ff9da 100755 --- a/.github/scripts/rerun_fails_report.sh +++ b/.github/scripts/rerun_fails_report.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # # Add a comment on the github PR if there were any rerun tests. diff --git a/.github/scripts/set_test_package_matrix.sh b/.github/scripts/set_test_package_matrix.sh index da8b6d563c37a..5608a83974024 100755 --- a/.github/scripts/set_test_package_matrix.sh +++ b/.github/scripts/set_test_package_matrix.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail export RUNNER_COUNT=$1 diff --git a/.github/scripts/verify_artifact.sh b/.github/scripts/verify_artifact.sh index 3aa9e0848dfb3..48bfede1cb33f 100755 --- a/.github/scripts/verify_artifact.sh +++ b/.github/scripts/verify_artifact.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/.github/scripts/verify_bin.sh b/.github/scripts/verify_bin.sh index dc5ac9f9f0e34..ff572d87fae9e 100755 --- a/.github/scripts/verify_bin.sh +++ b/.github/scripts/verify_bin.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/.github/scripts/verify_deb.sh b/.github/scripts/verify_deb.sh index c6b6926c5d1a2..84a9a10c85639 100755 --- a/.github/scripts/verify_deb.sh +++ b/.github/scripts/verify_deb.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/.github/scripts/verify_docker.sh b/.github/scripts/verify_docker.sh index ea9180920f8ae..fbbeb7dff464a 100755 --- a/.github/scripts/verify_docker.sh +++ b/.github/scripts/verify_docker.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/.github/scripts/verify_envoy_version.sh b/.github/scripts/verify_envoy_version.sh index f9067eaa37f71..773431f50bc85 100755 --- a/.github/scripts/verify_envoy_version.sh +++ b/.github/scripts/verify_envoy_version.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/.github/scripts/verify_rpm.sh b/.github/scripts/verify_rpm.sh index 96cd658eef3d5..17709a1d90e1b 100755 --- a/.github/scripts/verify_rpm.sh +++ b/.github/scripts/verify_rpm.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/.github/workflows/bot-auto-approve.yaml b/.github/workflows/bot-auto-approve.yaml index 911fc27f46968..2b652388999c2 100644 --- a/.github/workflows/bot-auto-approve.yaml +++ b/.github/workflows/bot-auto-approve.yaml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest if: github.actor == 'hc-github-team-consul-core' steps: - - uses: hmarr/auto-approve-action@44888193675f29a83e04faf4002fa8c0b537b1e4 # v3.2.1 + - uses: hmarr/auto-approve-action@v3 with: review-message: "Auto approved Consul Bot automated PR" github-token: ${{ secrets.MERGE_APPROVE_TOKEN }} diff --git a/.github/workflows/broken-link-check.yml b/.github/workflows/broken-link-check.yml index 2a8d77c5880fd..b7c89ff3e75dc 100644 --- a/.github/workflows/broken-link-check.yml +++ b/.github/workflows/broken-link-check.yml @@ -12,11 +12,11 @@ jobs: linkChecker: runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v3 - name: Run lychee link checker id: lychee - uses: lycheeverse/lychee-action@ec3ed119d4f44ad2673a7232460dc7dff59d2421 # v1.8.0 + uses: lycheeverse/lychee-action@v1.6.1 with: args: ./website/content/docs/ --base https://developer.hashicorp.com/ --exclude-all-private --exclude '\.(svg|gif|jpg|png)' --exclude 'manage\.auth0\.com' --accept 403 --max-concurrency=24 --no-progress --verbose # Fail GitHub action when broken links are found? @@ -26,7 +26,7 @@ jobs: - name: Create GitHub Issue From lychee output file if: env.lychee_exit_code != 0 - uses: peter-evans/create-issue-from-file@433e51abf769039ee20ba1293a088ca19d573b7f # v4.0.1 + uses: peter-evans/create-issue-from-file@v4 with: title: Link Checker Report content-filepath: ./lychee/out.md diff --git a/.github/workflows/build-artifacts.yml b/.github/workflows/build-artifacts.yml index 2977a73b6eb07..f57ea3527d485 100644 --- a/.github/workflows/build-artifacts.yml +++ b/.github/workflows/build-artifacts.yml @@ -13,7 +13,7 @@ permissions: contents: read env: - GOPRIVATE: github.com/hashicorp # Required for enterprise deps + GOPRIVATE: github.com/hashicorp jobs: setup: @@ -25,7 +25,7 @@ jobs: compute-large: ${{ steps.setup-outputs.outputs.compute-large }} compute-xl: ${{ steps.setup-outputs.outputs.compute-xl }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # pin@v3.3.0 - id: setup-outputs name: Setup outputs run: ./.github/scripts/get_runner_classes.sh @@ -56,14 +56,14 @@ jobs: kv/data/github/${{ github.repository }}/dockerhub username | DOCKERHUB_USERNAME; kv/data/github/${{ github.repository }}/dockerhub token | DOCKERHUB_TOKEN; - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # pin@v3.3.0 # NOTE: ENT specific step as we need to set elevated GitHub permissions. - 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 + - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # pin@v3.5.0 with: go-version-file: 'go.mod' @@ -78,17 +78,17 @@ jobs: echo "GITHUB_BUILD_URL=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_ENV - name: Set up Docker Buildx - uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0 + uses: docker/setup-buildx-action@f03ac48505955848960e80bbb68046aa35c7b9e7 # pin@v2.4.1 # NOTE: conditional specific logic as we store secrets in Vault in ENT and use GHA secrets in CE. - name: Login to Docker Hub - uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0 + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # pin@v2.1.0 with: username: ${{ endsWith(github.repository, '-enterprise') && steps.secrets.outputs.DOCKERHUB_USERNAME || secrets.DOCKERHUB_USERNAME }} password: ${{ endsWith(github.repository, '-enterprise') && steps.secrets.outputs.DOCKERHUB_TOKEN || secrets.DOCKERHUB_TOKEN }} - name: Docker build and push - uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825 # v4.1.1 + uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 # pin@v4.0.0 with: context: ./bin file: ./build-support/docker/Consul-Dev.dockerfile diff --git a/.github/workflows/build-distros.yml b/.github/workflows/build-distros.yml index 4d8799a5643d8..10c5208933412 100644 --- a/.github/workflows/build-distros.yml +++ b/.github/workflows/build-distros.yml @@ -17,10 +17,6 @@ env: GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} GOPRIVATE: github.com/hashicorp # Required for enterprise deps -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} - cancel-in-progress: true - jobs: setup: name: Setup @@ -31,7 +27,7 @@ jobs: compute-large: ${{ steps.setup-outputs.outputs.compute-large }} compute-xl: ${{ steps.setup-outputs.outputs.compute-xl }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - id: setup-outputs name: Setup outputs run: ./.github/scripts/get_runner_classes.sh @@ -54,7 +50,7 @@ jobs: XC_OS: "freebsd linux windows" runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - name: Setup Git @@ -78,7 +74,7 @@ jobs: XC_OS: "darwin freebsd linux solaris windows" runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - name: Setup Git @@ -103,7 +99,7 @@ jobs: CGO_ENABLED: 1 GOOS: linux steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - name: Setup Git @@ -129,7 +125,7 @@ jobs: - check-go-mod runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - name: Setup Git diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8af561716a21b..2d357acfb9e14 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,7 @@ jobs: pre-version: ${{ steps.set-product-version.outputs.prerelease-product-version }} shared-ldflags: ${{ steps.shared-ldflags.outputs.shared-ldflags }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - name: set product version id: set-product-version uses: hashicorp/actions-set-product-version@v1 @@ -66,7 +66,7 @@ jobs: filepath: ${{ steps.generate-metadata-file.outputs.filepath }} steps: - name: 'Checkout directory' - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - name: Generate metadata file id: generate-metadata-file uses: hashicorp/actions-generate-metadata@v1 @@ -98,10 +98,10 @@ jobs: name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - name: Setup with node and yarn - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: node-version: '14' cache: 'yarn' @@ -187,10 +187,10 @@ jobs: name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - name: Setup with node and yarn - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: node-version: '14' cache: 'yarn' @@ -238,10 +238,10 @@ jobs: name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - name: Setup with node and yarn - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: node-version: '14' cache: 'yarn' @@ -293,7 +293,7 @@ jobs: version: ${{needs.set-product-version.outputs.product-version}} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 # Strip everything but MAJOR.MINOR from the version string and add a `-dev` suffix # This naming convention will be used ONLY for per-commit dev images @@ -327,7 +327,7 @@ jobs: version: ${{needs.set-product-version.outputs.product-version}} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: hashicorp/actions-docker-build@v1 with: version: ${{env.version}} @@ -347,7 +347,7 @@ jobs: version: ${{needs.set-product-version.outputs.product-version}} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 # Strip everything but MAJOR.MINOR from the version string and add a `-dev` suffix # This naming convention will be used ONLY for per-commit dev images @@ -388,7 +388,7 @@ jobs: name: Verify ${{ matrix.arch }} linux binary steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 if: ${{ endsWith(github.repository, '-enterprise') || matrix.arch != 's390x' }} - name: Download ${{ matrix.arch }} zip @@ -398,7 +398,7 @@ jobs: name: ${{ env.zip_name }} - name: Set up QEMU - uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0 + uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.1.0 if: ${{ matrix.arch == 'arm' || matrix.arch == 'arm64' }} with: # this should be a comma-separated string as opposed to an array @@ -421,7 +421,7 @@ jobs: name: Verify amd64 darwin binary steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - name: Download amd64 darwin zip uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 @@ -452,7 +452,7 @@ jobs: name: Verify ${{ matrix.arch }} debian package steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - name: Set package version run: | @@ -468,7 +468,7 @@ jobs: name: ${{ env.pkg_name }} - name: Set up QEMU - uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0 + uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.1.0 with: platforms: all @@ -493,7 +493,7 @@ jobs: name: Verify ${{ matrix.arch }} rpm steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - name: Set package version run: | @@ -509,7 +509,7 @@ jobs: name: ${{ env.pkg_name }} - name: Set up QEMU - uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0 + uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.1.0 with: platforms: all diff --git a/.github/workflows/ce-merge-trigger.yml b/.github/workflows/ce-merge-trigger.yml index 30a6b5fd90dff..4de4751660d1c 100644 --- a/.github/workflows/ce-merge-trigger.yml +++ b/.github/workflows/ce-merge-trigger.yml @@ -8,7 +8,7 @@ on: - closed branches: - main - - release/** + - 'release/*.*.x' jobs: trigger-ce-merge: diff --git a/.github/workflows/changelog-checker.yml b/.github/workflows/changelog-checker.yml index 62b906eda3e66..d00717e2f0492 100644 --- a/.github/workflows/changelog-checker.yml +++ b/.github/workflows/changelog-checker.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 # by default the checkout action doesn't checkout all branches diff --git a/.github/workflows/embedded-asset-checker.yml b/.github/workflows/embedded-asset-checker.yml index 38879945e209c..4bb07771bd68f 100644 --- a/.github/workflows/embedded-asset-checker.yml +++ b/.github/workflows/embedded-asset-checker.yml @@ -20,7 +20,7 @@ jobs: if: "! ( contains(github.event.pull_request.labels.*.name, 'pr/update-ui-assets') || github.event.pull_request.user.login == 'hc-github-team-consul-core' )" runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 # by default the checkout action doesn't checkout all branches diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 63d02962fb013..defd0b22e380d 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -23,7 +23,7 @@ jobs: compute-large: ${{ steps.setup-outputs.outputs.compute-large }} compute-xl: ${{ steps.setup-outputs.outputs.compute-xl }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # pin@v3.3.0 - id: setup-outputs name: Setup outputs run: ./.github/scripts/get_runner_classes.sh @@ -35,9 +35,9 @@ jobs: run: working-directory: ui steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # pin@v3.3.0 - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # pin@v3.6.0 with: node-version: '16' @@ -55,9 +55,9 @@ jobs: needs: setup runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # pin@v3.3.0 - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # pin@v3.6.0 with: node-version: '16' @@ -74,7 +74,7 @@ jobs: ember-build-test: needs: setup - runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} + runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} strategy: matrix: partition: [1, 2, 3, 4] @@ -84,9 +84,9 @@ jobs: CONSUL_NSPACES_ENABLED: ${{ endsWith(github.repository, '-enterprise') && 1 || 0 }} # NOTE: this should be 1 in ENT. JOBS: 2 # limit parallelism for broccoli-babel-transpiler steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # pin@v3.3.0 - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # pin@v3.6.0 with: node-version: '16' @@ -94,7 +94,7 @@ jobs: run: npm install -g yarn - name: Install Chrome - uses: browser-actions/setup-chrome@c485fa3bab6be59dce18dbc18ef6ab7cbc8ff5f1 # v1.2.0 + uses: browser-actions/setup-chrome@29abc1a83d1d71557708563b4bc962d0f983a376 # pin@v1.2.1 - name: Install dependencies working-directory: ui diff --git a/.github/workflows/go-tests.yml b/.github/workflows/go-tests.yml index db69f2dbbd980..3fb2d66661fcc 100644 --- a/.github/workflows/go-tests.yml +++ b/.github/workflows/go-tests.yml @@ -53,7 +53,7 @@ jobs: compute-large: ${{ steps.setup-outputs.outputs.compute-large }} compute-xl: ${{ steps.setup-outputs.outputs.compute-xl }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - id: setup-outputs name: Setup outputs run: ./.github/scripts/get_runner_classes.sh @@ -73,7 +73,7 @@ jobs: - setup runs-on: ${{ fromJSON(needs.setup.outputs.compute-medium) }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 # 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') }} @@ -96,36 +96,35 @@ jobs: - name: Notify Slack if: ${{ failure() }} run: .github/scripts/notify_slack.sh - # Temporarily changing until the situation with license headers in the generated code can be worked out - # check-generated-deep-copy: - # needs: - # - setup - # runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - # steps: - # - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # # 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: make --always-make deep-copy - # - run: | - # if ! git diff --exit-code; then - # echo "Generated code was not updated correctly" - # exit 1 - # fi - # - name: Notify Slack - # if: ${{ failure() }} - # run: .github/scripts/notify_slack.sh + check-generated-deep-copy: + needs: + - setup + runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} + steps: + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + # 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: make --always-make deep-copy + - run: | + if ! git diff --exit-code; then + echo "Generated code was not updated correctly" + exit 1 + fi + - name: Notify Slack + if: ${{ failure() }} + run: .github/scripts/notify_slack.sh lint-enums: needs: - setup runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 # 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') }} @@ -143,7 +142,7 @@ jobs: - setup runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - name: Setup Git run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" @@ -160,7 +159,7 @@ jobs: - setup runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 # 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') }} @@ -178,7 +177,7 @@ jobs: - setup uses: ./.github/workflows/reusable-lint.yml with: - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} secrets: elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} @@ -189,7 +188,7 @@ jobs: uses: ./.github/workflows/reusable-lint.yml with: go-arch: "386" - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} secrets: elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} @@ -200,7 +199,7 @@ jobs: - setup uses: ./.github/workflows/reusable-dev-build.yml with: - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} secrets: elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} @@ -212,7 +211,7 @@ jobs: # uses: ./.github/workflows/reusable-dev-build.yml # with: # uploaded-binary-name: 'consul-bin-s390x' - # runs-on: ${{ needs.setup.outputs.compute-xl }} + # runs-on: ${{ needs.setup.outputs.compute-large }} # go-arch: "s390x" # repository-name: ${{ github.repository }} # secrets: @@ -226,7 +225,7 @@ jobs: # uses: ./.github/workflows/reusable-dev-build.yml # with: # uploaded-binary-name: 'consul-bin-arm64' - # runs-on: ${{ needs.setup.outputs.compute-xl }} + # runs-on: ${{ needs.setup.outputs.compute-large }} # go-arch: "arm64" # repository-name: ${{ github.repository }} # secrets: @@ -259,7 +258,7 @@ jobs: with: directory: . runner-count: 12 - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} go-tags: "" permissions: @@ -279,7 +278,7 @@ jobs: with: directory: . runner-count: 12 - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" permissions: @@ -299,7 +298,7 @@ jobs: directory: . go-test-flags: 'GO_TEST_FLAGS="-race -gcflags=all=-d=checkptr=0"' package-names-command: "go list ./... | grep -E -v '^github.com/hashicorp/consul/agent(/consul|/local|/routine-leak-checker)?$' | grep -E -v '^github.com/hashicorp/consul(/command|/connect|/snapshot)'" - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" permissions: @@ -319,7 +318,7 @@ jobs: directory: . go-arch: "386" go-test-flags: 'export GO_TEST_FLAGS="-short"' - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" permissions: @@ -340,7 +339,7 @@ jobs: # uploaded-binary-name: 'consul-bin-s390x' # directory: . # go-test-flags: 'export GO_TEST_FLAGS="-short"' - # runs-on: ${{ needs.setup.outputs.compute-xl }} + # runs-on: ${{ needs.setup.outputs.compute-large }} # repository-name: ${{ github.repository }} # go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" # permissions: @@ -358,7 +357,7 @@ jobs: uses: ./.github/workflows/reusable-unit.yml with: directory: envoyextensions - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" permissions: @@ -376,7 +375,7 @@ jobs: uses: ./.github/workflows/reusable-unit.yml with: directory: troubleshoot - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" permissions: @@ -394,7 +393,7 @@ jobs: uses: ./.github/workflows/reusable-unit.yml with: directory: api - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" go-version: "1.19" @@ -413,7 +412,7 @@ jobs: uses: ./.github/workflows/reusable-unit.yml with: directory: api - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" go-version: "1.20" @@ -432,7 +431,7 @@ jobs: uses: ./.github/workflows/reusable-unit.yml with: directory: sdk - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" go-version: "1.19" @@ -451,7 +450,7 @@ jobs: uses: ./.github/workflows/reusable-unit.yml with: directory: sdk - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" go-version: "1.20" @@ -486,8 +485,7 @@ jobs: needs: - conditional-skip - setup - # Reenable later - #- check-generated-deep-copy + - check-generated-deep-copy - check-generated-protobuf - check-go-mod - lint-consul-retry diff --git a/.github/workflows/issue-comment-created.yml b/.github/workflows/issue-comment-created.yml index 42483d92b1645..01e7e13f8bc44 100644 --- a/.github/workflows/issue-comment-created.yml +++ b/.github/workflows/issue-comment-created.yml @@ -11,8 +11,8 @@ jobs: triage: runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 # v1.3.0 + - uses: actions/checkout@v2 + - uses: actions-ecosystem/action-remove-labels@v1 with: labels: | waiting-reply diff --git a/.github/workflows/jira-issues.yaml b/.github/workflows/jira-issues.yaml index c136dfd69a78c..d595e5f5af8c6 100644 --- a/.github/workflows/jira-issues.yaml +++ b/.github/workflows/jira-issues.yaml @@ -16,7 +16,7 @@ jobs: name: Jira Community Issue sync steps: - name: Login - uses: atlassian/gajira-login@ca13f8850ea309cf44a6e4e0c49d9aa48ac3ca4c # v3 + uses: atlassian/gajira-login@v3.0.0 env: JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} @@ -40,7 +40,7 @@ jobs: - name: Create ticket if an issue is filed, or if PR not by a team member is opened if: github.event.action == 'opened' - uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1 + uses: tomhjp/gh-action-jira-create@v0.2.1 with: project: NET issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" @@ -60,7 +60,7 @@ jobs: # Education Jira - name: Create ticket in Education board an issue is filed, or if PR not by a team member is opened if: github.event.action == 'opened' && contains(github.event.issue.labels.*.name, 'type/docs') - uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1 + uses: tomhjp/gh-action-jira-create@v0.2.1 with: project: CE issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" @@ -77,28 +77,28 @@ jobs: - name: Search if: github.event.action != 'opened' id: search - uses: tomhjp/gh-action-jira-search@04700b457f317c3e341ce90da5a3ff4ce058f2fa # v0.2.2 + uses: tomhjp/gh-action-jira-search@v0.2.2 with: # cf[10089] is Issue Link (use JIRA API to retrieve) jql: 'issuetype = "${{ steps.set-ticket-type.outputs.TYPE }}" and cf[10089] = "${{ github.event.issue.html_url || github.event.pull_request.html_url }}"' - name: Sync comment if: github.event.action == 'created' && steps.search.outputs.issue - uses: tomhjp/gh-action-jira-comment@6eb6b9ead70221916b6badd118c24535ed220bd9 # v0.2.0 + uses: tomhjp/gh-action-jira-comment@v0.2.0 with: issue: ${{ steps.search.outputs.issue }} comment: "${{ github.actor }} ${{ github.event.review.state || 'commented' }}:\n\n${{ github.event.comment.body || github.event.review.body }}\n\n${{ github.event.comment.html_url || github.event.review.html_url }}" - name: Close ticket if: ( github.event.action == 'closed' || github.event.action == 'deleted' ) && steps.search.outputs.issue - uses: atlassian/gajira-transition@4749176faf14633954d72af7a44d7f2af01cc92b # v3 + uses: atlassian/gajira-transition@v3.0.1 with: issue: ${{ steps.search.outputs.issue }} transition: "Closed" - name: Reopen ticket if: github.event.action == 'reopened' && steps.search.outputs.issue - uses: atlassian/gajira-transition@4749176faf14633954d72af7a44d7f2af01cc92b # v3 + uses: atlassian/gajira-transition@v3.0.1 with: issue: ${{ steps.search.outputs.issue }} transition: "To Do" diff --git a/.github/workflows/jira-pr.yaml b/.github/workflows/jira-pr.yaml index f63f7af531620..9bce26588ebdd 100644 --- a/.github/workflows/jira-pr.yaml +++ b/.github/workflows/jira-pr.yaml @@ -14,7 +14,7 @@ jobs: name: Jira sync steps: - name: Login - uses: atlassian/gajira-login@ca13f8850ea309cf44a6e4e0c49d9aa48ac3ca4c # v3 + uses: atlassian/gajira-login@v3.0.0 env: JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} @@ -59,7 +59,7 @@ jobs: - name: Create ticket if an issue is filed, or if PR not by a team member is opened if: ( github.event.action == 'opened' && steps.is-team-member.outputs.MESSAGE == 'false' ) - uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1 + uses: tomhjp/gh-action-jira-create@v0.2.1 with: project: NET issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" @@ -79,7 +79,7 @@ jobs: # Education Jira - name: Create ticket in Education board an issue is filed, or if PR not by a team member is opened if: github.event.action == 'opened' && steps.is-team-member.outputs.MESSAGE == 'false' && contains(github.event.issue.labels.*.name, 'type/docs') - uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1 + uses: tomhjp/gh-action-jira-create@v0.2.1 with: project: CE issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" @@ -91,28 +91,28 @@ jobs: - name: Search if: github.event.action != 'opened' id: search - uses: tomhjp/gh-action-jira-search@04700b457f317c3e341ce90da5a3ff4ce058f2fa # v0.2.2 + uses: tomhjp/gh-action-jira-search@v0.2.2 with: # cf[10089] is Issue Link (use JIRA API to retrieve) jql: 'issuetype = "${{ steps.set-ticket-type.outputs.TYPE }}" and cf[10089] = "${{ github.event.issue.html_url || github.event.pull_request.html_url }}"' - name: Sync comment if: github.event.action == 'created' && steps.search.outputs.issue - uses: tomhjp/gh-action-jira-comment@6eb6b9ead70221916b6badd118c24535ed220bd9 # v0.2.0 + uses: tomhjp/gh-action-jira-comment@v0.2.0 with: issue: ${{ steps.search.outputs.issue }} comment: "${{ github.actor }} ${{ github.event.review.state || 'commented' }}:\n\n${{ github.event.comment.body || github.event.review.body }}\n\n${{ github.event.comment.html_url || github.event.review.html_url }}" - name: Close ticket if: ( github.event.action == 'closed' || github.event.action == 'deleted' ) && steps.search.outputs.issue - uses: atlassian/gajira-transition@4749176faf14633954d72af7a44d7f2af01cc92b # v3 + uses: atlassian/gajira-transition@v3.0.1 with: issue: ${{ steps.search.outputs.issue }} transition: "Closed" - name: Reopen ticket if: github.event.action == 'reopened' && steps.search.outputs.issue - uses: atlassian/gajira-transition@4749176faf14633954d72af7a44d7f2af01cc92b # v3 + uses: atlassian/gajira-transition@v3.0.1 with: issue: ${{ steps.search.outputs.issue }} transition: "To Do" diff --git a/.github/workflows/nightly-test-1.16.x.yaml b/.github/workflows/nightly-test-1.12.x.yaml similarity index 75% rename from .github/workflows/nightly-test-1.16.x.yaml rename to .github/workflows/nightly-test-1.12.x.yaml index b441eca5d0f59..c09cc4864b89d 100644 --- a/.github/workflows/nightly-test-1.16.x.yaml +++ b/.github/workflows/nightly-test-1.12.x.yaml @@ -1,28 +1,27 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: MPL-2.0 -name: Nightly Frontend Test 1.16.x +name: Nightly Test 1.12.x on: schedule: - cron: '0 4 * * *' workflow_dispatch: {} env: - EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition - BRANCH: "release/1.16.x" - BRANCH_NAME: "release-1.16.x" # Used for naming artifacts - GOPRIVATE: github.com/hashicorp # Required for enterprise deps + EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition + BRANCH: "release/1.12.x" + BRANCH_NAME: "release-1.12.x" # Used for naming artifacts jobs: frontend-test-workspace-node: runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -49,12 +48,12 @@ jobs: JOBS: 2 CONSUL_NSPACES_ENABLED: 0 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -71,7 +70,7 @@ jobs: run: make build-ci - name: Upload CE Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@v3 with: name: frontend-ce-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -88,12 +87,12 @@ jobs: EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -105,7 +104,7 @@ jobs: run: make deps - name: Download CE Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ce-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -121,12 +120,12 @@ jobs: JOBS: 2 CONSUL_NSPACES_ENABLED: 1 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -143,7 +142,7 @@ jobs: run: make build-ci - name: Upload ENT Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -160,12 +159,12 @@ jobs: EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -177,7 +176,7 @@ jobs: run: make deps - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -191,12 +190,12 @@ jobs: runs-on: ubuntu-latest needs: [frontend-build-ent] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -208,7 +207,7 @@ jobs: run: make deps - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -224,7 +223,7 @@ jobs: steps: - name: Slack Notification id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 + uses: slackapi/slack-github-action@v1.19 with: payload: | { diff --git a/.github/workflows/nightly-test-1.13.x.yaml b/.github/workflows/nightly-test-1.13.x.yaml index f314a475dfbd7..6139eb4bc1e1a 100644 --- a/.github/workflows/nightly-test-1.13.x.yaml +++ b/.github/workflows/nightly-test-1.13.x.yaml @@ -1,28 +1,27 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: MPL-2.0 -name: Nightly Frontend Test 1.13.x +name: Nightly Test 1.13.x on: schedule: - cron: '0 4 * * *' workflow_dispatch: {} env: - EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition + EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition BRANCH: "release/1.13.x" - BRANCH_NAME: "release-1.13.x" # Used for naming artifacts - GOPRIVATE: github.com/hashicorp # Required for enterprise deps + BRANCH_NAME: "release-1.13.x" # Used for naming artifacts jobs: frontend-test-workspace-node: runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -49,12 +48,12 @@ jobs: JOBS: 2 CONSUL_NSPACES_ENABLED: 0 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -71,7 +70,7 @@ jobs: run: make build-ci - name: Upload CE Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@v3 with: name: frontend-ce-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -88,12 +87,12 @@ jobs: EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -105,7 +104,7 @@ jobs: run: make deps - name: Download CE Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ce-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -121,12 +120,12 @@ jobs: JOBS: 2 CONSUL_NSPACES_ENABLED: 1 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -143,7 +142,7 @@ jobs: run: make build-ci - name: Upload ENT Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -160,12 +159,12 @@ jobs: EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -177,7 +176,7 @@ jobs: run: make deps - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -191,12 +190,12 @@ jobs: runs-on: ubuntu-latest needs: [frontend-build-ent] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -208,7 +207,7 @@ jobs: run: make deps - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -224,7 +223,7 @@ jobs: steps: - name: Slack Notification id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 + uses: slackapi/slack-github-action@v1.19 with: payload: | { diff --git a/.github/workflows/nightly-test-1.14.x.yaml b/.github/workflows/nightly-test-1.14.x.yaml index 11fb011d13571..9b310f59065dc 100644 --- a/.github/workflows/nightly-test-1.14.x.yaml +++ b/.github/workflows/nightly-test-1.14.x.yaml @@ -1,28 +1,27 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: MPL-2.0 -name: Nightly Frontend Test 1.14.x +name: Nightly Test 1.14.x on: schedule: - cron: '0 4 * * *' workflow_dispatch: {} env: - EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition + EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition BRANCH: "release/1.14.x" - BRANCH_NAME: "release-1.14.x" # Used for naming artifacts - GOPRIVATE: github.com/hashicorp # Required for enterprise deps + BRANCH_NAME: "release-1.14.x" # Used for naming artifacts jobs: frontend-test-workspace-node: runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -49,12 +48,12 @@ jobs: JOBS: 2 CONSUL_NSPACES_ENABLED: 0 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -71,7 +70,7 @@ jobs: run: make build-ci - name: Upload CE Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@v3 with: name: frontend-ce-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -88,12 +87,12 @@ jobs: EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -105,7 +104,7 @@ jobs: run: make deps - name: Download CE Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ce-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -121,12 +120,12 @@ jobs: JOBS: 2 CONSUL_NSPACES_ENABLED: 1 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -143,7 +142,7 @@ jobs: run: make build-ci - name: Upload ENT Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -160,12 +159,12 @@ jobs: EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -177,7 +176,7 @@ jobs: run: make deps - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -191,12 +190,12 @@ jobs: runs-on: ubuntu-latest needs: [frontend-build-ent] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -208,7 +207,7 @@ jobs: run: make deps - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -224,7 +223,7 @@ jobs: steps: - name: Slack Notification id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 + uses: slackapi/slack-github-action@v1.19 with: payload: | { diff --git a/.github/workflows/nightly-test-1.15.x.yaml b/.github/workflows/nightly-test-1.15.x.yaml index a98eb73070b36..9048abb4a04e4 100644 --- a/.github/workflows/nightly-test-1.15.x.yaml +++ b/.github/workflows/nightly-test-1.15.x.yaml @@ -1,28 +1,27 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: MPL-2.0 -name: Nightly Frontend Test 1.15.x +name: Nightly Test 1.15.x on: schedule: - cron: '0 4 * * *' workflow_dispatch: {} env: - EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition + EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition BRANCH: "release/1.15.x" - BRANCH_NAME: "release-1.15.x" # Used for naming artifacts - GOPRIVATE: github.com/hashicorp # Required for enterprise deps + BRANCH_NAME: "release-1.15.x" # Used for naming artifacts jobs: frontend-test-workspace-node: runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -49,12 +48,12 @@ jobs: JOBS: 2 CONSUL_NSPACES_ENABLED: 0 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -71,7 +70,7 @@ jobs: run: make build-ci - name: Upload CE Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@v3 with: name: frontend-ce-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -88,12 +87,12 @@ jobs: EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -105,7 +104,7 @@ jobs: run: make deps - name: Download CE Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ce-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -121,12 +120,12 @@ jobs: JOBS: 2 CONSUL_NSPACES_ENABLED: 1 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -143,7 +142,7 @@ jobs: run: make build-ci - name: Upload ENT Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -160,12 +159,12 @@ jobs: EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -177,7 +176,7 @@ jobs: run: make deps - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -191,12 +190,12 @@ jobs: runs-on: ubuntu-latest needs: [frontend-build-ent] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -208,7 +207,7 @@ jobs: run: make deps - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -224,7 +223,7 @@ jobs: steps: - name: Slack Notification id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 + uses: slackapi/slack-github-action@v1.19 with: payload: | { diff --git a/.github/workflows/nightly-test-integrations-1.15.x.yml b/.github/workflows/nightly-test-integrations-1.15.x.yml deleted file mode 100644 index 587d5a62f23c4..0000000000000 --- a/.github/workflows/nightly-test-integrations-1.15.x.yml +++ /dev/null @@ -1,320 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Nightly test-integrations 1.15.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.15.x" - BRANCH_NAME: "release-1.15.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.15.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.22.11", "1.23.12", "1.24.10", "1.25.9"] - # 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-xl) }} - 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.22.11", "1.23.12", "1.24.10", "1.25.9"] - 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-xl) }} - 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.14", "1.15"] - 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: 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/nightly-test-integrations-1.16.x.yml b/.github/workflows/nightly-test-integrations-1.16.x.yml deleted file mode 100644 index d4e955ec4985f..0000000000000 --- a/.github/workflows/nightly-test-integrations-1.16.x.yml +++ /dev/null @@ -1,342 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Nightly test-integrations 1.16.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.16.x" - BRANCH_NAME: "release-1.16.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.16.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.10", "1.25.9", "1.26.4", "1.27.0"] - # 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-xl) }} - 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.23.12", "1.24.10", "1.25.9", "1.26.4"] - 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-xl) }} - 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.14", "1.15", "1.16"] - 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/nightly-test-integrations.yml b/.github/workflows/nightly-test-integrations.yml index cfe3041511cca..d4432f27ba86b 100644 --- a/.github/workflows/nightly-test-integrations.yml +++ b/.github/workflows/nightly-test-integrations.yml @@ -42,7 +42,7 @@ jobs: needs: [setup] uses: ./.github/workflows/reusable-dev-build.yml with: - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} uploaded-binary-name: 'consul-bin' secrets: @@ -88,7 +88,7 @@ jobs: } >> "$GITHUB_OUTPUT" envoy-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} + runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} needs: - setup - generate-envoy-job-matrices @@ -99,7 +99,7 @@ jobs: strategy: fail-fast: false matrix: - envoy-version: ["1.24.10", "1.25.9", "1.26.4", "1.27.0"] + envoy-version: ["1.23.12", "1.24.10", "1.25.9", "1.26.4"] xds-target: ["server", "client"] test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} env: @@ -183,7 +183,7 @@ jobs: run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml upgrade-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} + runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} needs: - setup - dev-build @@ -193,7 +193,7 @@ jobs: strategy: fail-fast: false matrix: - consul-version: [ "1.15", "1.16"] + consul-version: ["1.14", "1.15", "1.16"] env: CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} ENVOY_VERSION: "1.24.6" @@ -223,13 +223,11 @@ jobs: 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 + continue-on-error: true + run: 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 + - name: Retry Build consul-envoy:latest-version image + if: steps.buildConsulEnvoyLatestImage.outcome == 'failure' + run: 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 - name: Build consul-envoy:target-version image id: buildConsulEnvoyTargetImage continue-on-error: true @@ -326,14 +324,3 @@ jobs: 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. ${{ 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/nightly-test-main.yaml b/.github/workflows/nightly-test-main.yaml index 2846f5b71c39e..16160175b6815 100644 --- a/.github/workflows/nightly-test-main.yaml +++ b/.github/workflows/nightly-test-main.yaml @@ -1,28 +1,27 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: MPL-2.0 -name: Nightly Frontend Test Main +name: Nightly Test Main on: schedule: - cron: '0 4 * * *' workflow_dispatch: {} env: - EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition + EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition BRANCH: "main" - BRANCH_NAME: "main" # Used for naming artifacts - GOPRIVATE: github.com/hashicorp # Required for enterprise deps + BRANCH_NAME: "main" # Used for naming artifacts jobs: frontend-test-workspace-node: runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -49,12 +48,12 @@ jobs: JOBS: 2 CONSUL_NSPACES_ENABLED: 0 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -71,7 +70,7 @@ jobs: run: make build-ci - name: Upload CE Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@v3 with: name: frontend-ce-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -88,12 +87,12 @@ jobs: EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -105,7 +104,7 @@ jobs: run: make deps - name: Download CE Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ce-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -121,12 +120,12 @@ jobs: JOBS: 2 CONSUL_NSPACES_ENABLED: 1 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -143,7 +142,7 @@ jobs: run: make build-ci - name: Upload ENT Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -160,12 +159,12 @@ jobs: EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -177,7 +176,7 @@ jobs: run: make deps - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -191,12 +190,12 @@ jobs: runs-on: ubuntu-latest needs: [frontend-build-ent] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ env.BRANCH }} # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + - uses: actions/setup-node@v3 with: node-version: 14 cache: 'yarn' @@ -208,7 +207,7 @@ jobs: run: make deps - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@v3 with: name: frontend-ent-${{ env.BRANCH_NAME }} path: ./ui/packages/consul-ui/dist @@ -224,7 +223,7 @@ jobs: steps: - name: Slack Notification id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 + uses: slackapi/slack-github-action@v1.19 with: payload: | { diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index 0d6b71c9f0618..a29cadcb685b4 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -10,7 +10,7 @@ jobs: triage: runs-on: ubuntu-latest steps: - - uses: actions/labeler@0967ca812e7fdc8f5f71402a1b486d5bd061fe20 # v4.2.0 + - uses: actions/labeler@main with: repo-token: "${{ secrets.GITHUB_TOKEN }}" configuration-path: .github/pr-labeler.yml diff --git a/.github/workflows/pr-metrics-test-checker.yml b/.github/workflows/pr-metrics-test-checker.yml index d0bdac04f7e3f..a73f4fbb3ff5a 100644 --- a/.github/workflows/pr-metrics-test-checker.yml +++ b/.github/workflows/pr-metrics-test-checker.yml @@ -14,7 +14,7 @@ jobs: if: "! ( contains(github.event.pull_request.labels.*.name, 'pr/no-metrics-test') || github.event.pull_request.user.login == 'hc-github-team-consul-core' )" runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 name: "checkout repo" with: ref: ${{ github.event.pull_request.head.sha }} diff --git a/.github/workflows/reusable-check-go-mod.yml b/.github/workflows/reusable-check-go-mod.yml index 7fffb616879ef..2078b0c3217d6 100644 --- a/.github/workflows/reusable-check-go-mod.yml +++ b/.github/workflows/reusable-check-go-mod.yml @@ -18,12 +18,12 @@ jobs: runs-on: ${{ fromJSON(inputs.runs-on) }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # pin@v3.3.0 # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - name: Setup Git if: ${{ endsWith(inputs.repository-name, '-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 + - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # pin@v3.5.0 with: go-version-file: 'go.mod' - run: go mod tidy diff --git a/.github/workflows/reusable-dev-build-windows.yml b/.github/workflows/reusable-dev-build-windows.yml deleted file mode 100644 index 01247c477878c..0000000000000 --- a/.github/workflows/reusable-dev-build-windows.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: reusable-dev-build-windows - -on: - workflow_call: - inputs: - uploaded-binary-name: - required: false - type: string - default: "consul.exe" - runs-on: - description: An expression indicating which kind of runners to use. - required: true - type: string - repository-name: - required: true - type: string - go-arch: - required: false - type: string - default: "" - secrets: - elevated-github-token: - required: true -jobs: - build: - runs-on: 'windows-2019' - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(inputs.repository-name, '-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' - - name: Build - env: - GOARCH: ${{ inputs.goarch }} - run: go build . - # save dev build to pass to downstream jobs - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: ${{inputs.uploaded-binary-name}} - path: consul.exe - - name: Notify Slack - if: ${{ failure() }} - run: .github/scripts/notify_slack.sh diff --git a/.github/workflows/reusable-dev-build.yml b/.github/workflows/reusable-dev-build.yml index 99bcb96592c3a..2db9670655e46 100644 --- a/.github/workflows/reusable-dev-build.yml +++ b/.github/workflows/reusable-dev-build.yml @@ -14,10 +14,6 @@ on: repository-name: required: true type: string - branch-name: - required: false - type: string - default: "" go-arch: required: false type: string @@ -29,15 +25,7 @@ jobs: build: runs-on: ${{ fromJSON(inputs.runs-on) }} steps: - # NOTE: This is used for nightly job of building release branch. - - name: Checkout branch ${{ inputs.branch-name }} - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ inputs.branch-name }} - if: inputs.branch-name != '' - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - if: inputs.branch-name == '' + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - name: Setup Git if: ${{ endsWith(inputs.repository-name, '-enterprise') }} diff --git a/.github/workflows/reusable-lint.yml b/.github/workflows/reusable-lint.yml index 903855d99c85c..f7032f9866633 100644 --- a/.github/workflows/reusable-lint.yml +++ b/.github/workflows/reusable-lint.yml @@ -20,7 +20,6 @@ on: env: GOTAGS: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" GOARCH: ${{inputs.go-arch}} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps jobs: lint: @@ -34,21 +33,20 @@ jobs: - "envoyextensions" - "troubleshoot" - "test/integration/consul-container" - - "testing/deployer" fail-fast: true name: lint ${{ matrix.directory }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # pin@v3.3.0 # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - name: Setup Git if: ${{ endsWith(inputs.repository-name, '-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 + - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # pin@v3.5.0 with: go-version-file: 'go.mod' - run: go env - name: lint-${{ matrix.directory }} - uses: golangci/golangci-lint-action@639cd343e1d3b897ff35927a75193d57cfcba299 # v3.6.0 + uses: golangci/golangci-lint-action@08e2f20817b15149a52b5b3ebe7de50aff2ba8c5 # pin@v3.4.0 with: working-directory: ${{ matrix.directory }} version: v1.51.1 diff --git a/.github/workflows/reusable-unit-split.yml b/.github/workflows/reusable-unit-split.yml index 0ec639c28ff20..6c13670e742ed 100644 --- a/.github/workflows/reusable-unit-split.yml +++ b/.github/workflows/reusable-unit-split.yml @@ -51,7 +51,6 @@ env: TOTAL_RUNNERS: ${{inputs.runner-count}} CONSUL_LICENSE: ${{secrets.consul-license}} GOTAGS: ${{ inputs.go-tags}} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps DATADOG_API_KEY: ${{secrets.datadog-api-key}} jobs: @@ -60,8 +59,8 @@ jobs: outputs: package-matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # pin@v3.5.0 with: go-version-file: 'go.mod' - id: set-matrix @@ -83,12 +82,12 @@ jobs: ulimit -Sa echo "Hard limits" ulimit -Ha - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # pin@v3.3.0 # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - name: Setup Git if: ${{ endsWith(inputs.repository-name, '-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 + - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # pin@v3.5.0 with: go-version-file: 'go.mod' cache: true @@ -97,7 +96,7 @@ jobs: working-directory: ${{inputs.directory}} run: go mod download - name: Download consul - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # pin@v3.0.2 with: name: ${{inputs.uploaded-binary-name}} path: ${{inputs.directory}} @@ -164,11 +163,11 @@ jobs: DD_ENV: ci run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" ${{env.TEST_RESULTS}}/gotestsum-report.xml - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # pin@v3.1.2 with: name: test-results path: ${{env.TEST_RESULTS}} - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # pin@v3.1.2 with: name: jsonfile path: /tmp/jsonfile diff --git a/.github/workflows/reusable-unit.yml b/.github/workflows/reusable-unit.yml index 42943954475d3..c49a6291fa2e2 100644 --- a/.github/workflows/reusable-unit.yml +++ b/.github/workflows/reusable-unit.yml @@ -50,14 +50,13 @@ env: GOARCH: ${{inputs.go-arch}} CONSUL_LICENSE: ${{secrets.consul-license}} GOTAGS: ${{ inputs.go-tags}} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps DATADOG_API_KEY: ${{secrets.datadog-api-key}} jobs: go-test: runs-on: ${{ fromJSON(inputs.runs-on) }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # pin@v3.3.0 # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - name: Setup Git if: ${{ endsWith(inputs.repository-name, '-enterprise') }} @@ -77,7 +76,7 @@ jobs: working-directory: ${{inputs.directory}} run: go mod download - name: Download consul - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # pin@v3.0.2 with: name: ${{inputs.uploaded-binary-name}} path: ${{inputs.directory}} @@ -142,11 +141,11 @@ jobs: DD_ENV: ci run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" ${{env.TEST_RESULTS}}/gotestsum-report.xml - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # pin@v3.1.2 with: name: test-results path: ${{env.TEST_RESULTS}} - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # pin@v3.1.2 with: name: jsonfile path: /tmp/jsonfile diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index ff07a961a4e48..f3da6d422b6b1 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -12,7 +12,7 @@ jobs: permissions: pull-requests: write steps: - - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0 + - uses: actions/stale@v4 with: days-before-stale: -1 days-before-close: -1 diff --git a/.github/workflows/test-integrations-windows.yml b/.github/workflows/test-integrations-windows.yml deleted file mode 100644 index c3e977e97d589..0000000000000 --- a/.github/workflows/test-integrations-windows.yml +++ /dev/null @@ -1,1209 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: test-integrations-windows - -on: - schedule: - # * is a special character in YAML so you have to quote this string - # Run nightly at 12AM UTC/8PM EST/5PM PST. - - cron: '0 0 * * *' - -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.9.0" - CONSUL_BINARY_UPLOAD_NAME: consul.exe - # strip the hashicorp/ off the front of github.repository for consul - CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'consul' }} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - -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: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - id: runners - run: .github/scripts/get_runner_classes_windows.sh - - dev-build: - uses: ./.github/workflows/reusable-dev-build-windows.yml - with: - runs-on: ${{ needs.setup.outputs.compute-xl }} - repository-name: ${{ github.repository }} - uploaded-binary-name: 'consul.exe' - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - # NOTE: Jobs needs to be added here manually. Jobs when run together on windows fails intermittently. - # So they are run independently of each other. - envoy-integration-test: - needs: - - setup - - dev-build - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - matrix: - envoy-version: [ "1.24.10", "1.25.9", "1.26.4", "1.27.0" ] - xds-target: [ "server", "client" ] - env: - ENVOY_VERSION: ${{ matrix.envoy-version }} - XDS_TARGET: ${{ matrix.xds-target }} - AWS_LAMBDA_REGION: us-west-2 - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - 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: ${{ github.workspace }} - - - name: Restore mode+x - run: icacls ${{ github.workspace }}\consul.exe /grant:rx Everyone:RX - - - name: Setup TcpDump Docker Image - shell: bash - run: | - cd test/integration/connect/envoy - curl -sSL "https://asheshvidyut-bucket.s3.ap-southeast-2.amazonaws.com/tcpdump.exe" -o tcpdump.exe - docker build -t envoy-tcpdump -f Dockerfile-tcpdump-windows . - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0 - - - name: Docker build consul - run: docker build -t windows/consul -f Dockerfile-windows . - - - name: Docker build consul local - shell: bash - run: cd build-support/windows && ./build-consul-local-images.sh - - - name: Docker build consul dev - shell: bash - run: cd build-support/windows && ./build-consul-dev-image.sh - - # https://hashicorp.atlassian.net/browse/NET-4973 - # ^ Ticket to figure out why grouping test case is failing on Windows Machine - - - name: Envoy Integration Tests for windows case-api-gateway-http-hostnames - shell: bash - if: always() - 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 Integration Test case-api-gateway-http-hostnames" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-http-hostnames" -win=true - - - name: Envoy Integration Tests for windows case-api-gateway-http-simple - shell: bash - if: always() - 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 Integration Test case-api-gateway-http-simple" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-http-simple" -win=true - - - name: Envoy Integration Tests for windows case-api-gateway-http-splitter-targets - shell: bash - if: always() - 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 Integration Test case-api-gateway-http-splitter-targets" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-http-splitter-targets" -win=true - - - name: Envoy Integration Tests for windows case-api-gateway-http-tls-overlapping-hosts - shell: bash - if: always() - 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 Integration Test case-api-gateway-http-tls-overlapping-hosts" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-http-tls-overlapping-hosts" -win=true - - - name: Envoy Integration Tests for windows case-api-gateway-tcp-conflicted - shell: bash - if: always() - 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 Integration Test case-api-gateway-tcp-conflicted" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-tcp-conflicted" -win=true - - - name: Envoy Integration Tests for windows case-api-gateway-tcp-simple - shell: bash - if: always() - 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 Integration Test case-api-gateway-tcp-simple" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-tcp-simple" -win=true - - - name: Envoy Integration Tests for windows case-api-gateway-tcp-tls-overlapping-hosts - shell: bash - if: always() - 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 Integration Test case-api-gateway-tcp-tls-overlapping-hosts" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-tcp-tls-overlapping-hosts" -win=true - - - name: Envoy Integration Tests for windows case-badauthz - shell: bash - if: always() - 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 Integration Test case-badauthz" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-badauthz" -win=true - - - name: Envoy Integration Tests for windows case-basic - shell: bash - if: always() - 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 Integration Test case-basic" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-basic" -win=true - - - name: Envoy Integration Tests for windows case-centralconf - shell: bash - if: always() - 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 Integration Test case-centralconf" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-centralconf" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-cluster-peering-failover - shell: bash - if: always() - 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 Integration Test case-cfg-resolver-cluster-peering-failover" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-cluster-peering-failover" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-dc-failover-gateways-none - shell: bash - if: always() - 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 Integration Test case-cfg-resolver-dc-failover-gateways-none" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-dc-failover-gateways-none" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-dc-failover-gateways-remote - shell: bash - if: always() - 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 Integration Test case-cfg-resolver-dc-failover-gateways-remote" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-dc-failover-gateways-remote" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-defaultsubset - shell: bash - if: always() - 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 Integration Test case-cfg-resolver-defaultsubset" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-defaultsubset" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-features - shell: bash - if: always() - 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 Integration Test case-cfg-resolver-features" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-features" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-subset-onlypassing - shell: bash - if: always() - 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 Integration Test case-cfg-resolver-subset-onlypassing" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-subset-onlypassing" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-subset-redirect - shell: bash - if: always() - 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 Integration Test case-cfg-resolver-subset-redirect" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-subset-redirect" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-svc-failover - shell: bash - if: always() - 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 Integration Test case-cfg-resolver-svc-failover" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-svc-failover" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-svc-redirect-http - shell: bash - if: always() - 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 Integration Test case-cfg-resolver-svc-redirect-http" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-svc-redirect-http" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-svc-redirect-tcp - shell: bash - if: always() - 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 Integration Test case-cfg-resolver-svc-redirect-tcp" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-svc-redirect-tcp" -win=true - - - name: Envoy Integration Tests for windows case-cfg-router-features - shell: bash - if: always() - 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 Integration Test case-cfg-router-features" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-router-features" -win=true - - - name: Envoy Integration Tests for windows case-cfg-splitter-cluster-peering - shell: bash - if: always() - 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 Integration Test case-cfg-splitter-cluster-peering" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-splitter-cluster-peering" -win=true - - - name: Envoy Integration Tests for windows case-cfg-splitter-features - shell: bash - if: always() - 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 Integration Test case-cfg-splitter-features" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-splitter-features" -win=true - - - name: Envoy Integration Tests for windows case-cfg-splitter-peering-ingress-gateways - shell: bash - if: always() - 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 Integration Test case-cfg-splitter-peering-ingress-gateways" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-splitter-peering-ingress-gateways" -win=true - - # This test runs fine on windows machine but fails on CI - # Task to be picked later on - https://hashicorp.atlassian.net/browse/NET-4972 - # - name: Envoy Integration Tests for windows case-consul-exec - # if: always() - # shell: bash - # 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 Integration Test case-consul-exec" - # # shellcheck disable=SC2001 - # go test -v -timeout=30m -tags integration \ - # ./test/integration/connect/envoy -run="TestEnvoy/case-consul-exec" -win=true - - - name: Envoy Integration Tests for windows case-cross-peer-control-plane-mgw - if: always() - shell: bash - 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 Integration Test case-cross-peer-control-plane-mgw" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cross-peer-control-plane-mgw" -win=true - - - name: Envoy Integration Tests for windows case-cross-peers - shell: bash - if: always() - 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 Integration Test case-cross-peers" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cross-peers" -win=true - - - name: Envoy Integration Tests for windows case-cross-peers-http - shell: bash - if: always() - 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 Integration Test case-cross-peers-http" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cross-peers-http" -win=true - - - name: Envoy Integration Tests for windows case-cross-peers-http-router - shell: bash - if: always() - 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 Integration Test case-cross-peers-http-router" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cross-peers-http-router" -win=true - - - name: Envoy Integration Tests for windows case-cross-peers-resolver-redirect-tcp - shell: bash - if: always() - 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 Integration Test case-cross-peers-resolver-redirect-tcp" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cross-peers-resolver-redirect-tcp" -win=true - - - name: Envoy Integration Tests for windows case-dogstatsd-udp - shell: bash - if: always() - 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 Integration Test case-dogstatsd-udp" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-dogstatsd-udp" -win=true - - - name: Envoy Integration Tests for windows case-envoyext-ratelimit - shell: bash - if: always() - 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 Integration Test case-envoyext-ratelimit" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-envoyext-ratelimit" -win=true - - - name: Envoy Integration Tests for windows case-expose-checks - shell: bash - if: always() - 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 Integration Test case-expose-checks" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-expose-checks" -win=true - - - name: Envoy Integration Tests for windows case-gateway-without-services - shell: bash - if: always() - 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 Integration Test case-gateway-without-services" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-gateway-without-services" -win=true - - - name: Envoy Integration Tests for windows case-gateways-local - shell: bash - if: always() - 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 Integration Test case-gateways-local" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-gateways-local" -win=true - - - name: Envoy Integration Tests for windows case-gateways-remote - shell: bash - if: always() - 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 Integration Test case-gateways-remote" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-gateways-remote" -win=true - - - name: Envoy Integration Tests for windows case-grpc - shell: bash - if: always() - 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 Integration Test case-grpc" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-grpc" -win=true - - - name: Envoy Integration Tests for windows case-http - shell: bash - if: always() - 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 Integration Test case-http" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-http" -win=true - - - name: Envoy Integration Tests for windows case-http-badauthz - shell: bash - if: always() - 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 Integration Test case-http-badauthz" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-http-badauthz" -win=true - - - name: Envoy Integration Tests for windows case-ingress-gateway-grpc - shell: bash - if: always() - 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 Integration Test case-ingress-gateway-grpc" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-grpc" -win=true - - - name: Envoy Integration Tests for windows case-ingress-gateway-http - shell: bash - if: always() - 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 Integration Test case-ingress-gateway-http" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-http" -win=true - - - name: Envoy Integration Tests for windows case-ingress-gateway-multiple-services - shell: bash - if: always() - 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 Integration Test case-ingress-gateway-multiple-services" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-multiple-services" -win=true - - - name: Envoy Integration Tests for windows case-ingress-gateway-peering-failover - shell: bash - if: always() - 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 Integration Test case-ingress-gateway-peering-failover" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-peering-failover" -win=true - - - name: Envoy Integration Tests for windows case-ingress-gateway-simple - shell: bash - if: always() - 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 Integration Test case-ingress-gateway-simple" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-simple" -win=true - - - name: Envoy Integration Tests for windows case-ingress-mesh-gateways-resolver - shell: bash - if: always() - 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 Integration Test case-ingress-mesh-gateways-resolver" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-mesh-gateways-resolver" -win=true - - - name: Envoy Integration Tests for windows case-l7-intentions - shell: bash - if: always() - 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 Integration Test case-l7-intentions" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-l7-intentions" -win=true - - - name: Envoy Integration Tests for windows case-multidc-rsa-ca - shell: bash - if: always() - 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 Integration Test case-multidc-rsa-ca" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-multidc-rsa-ca" -win=true - - - name: Envoy Integration Tests for windows case-prometheus - shell: bash - if: always() - 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 Integration Test case-prometheus" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-prometheus" -win=true - - - name: Envoy Integration Tests for windows case-property-override - shell: bash - if: always() - 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 Integration Test case-property-override" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-property-override" -win=true - - - name: Envoy Integration Tests for windows case-stats-proxy - shell: bash - if: always() - 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 Integration Test case-stats-proxy" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-stats-proxy" -win=true - - - name: Envoy Integration Tests for windows case-statsd-udp - shell: bash - if: always() - 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 Integration Test case-statsd-udp" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-statsd-udp" -win=true - - - name: Envoy Integration Tests for windows case-terminating-gateway-hostnames - shell: bash - if: always() - 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 Integration Test case-terminating-gateway-hostnames" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-terminating-gateway-hostnames" -win=true - - - name: Envoy Integration Tests for windows case-terminating-gateway-simple - shell: bash - if: always() - 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 Integration Test case-terminating-gateway-simple" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-terminating-gateway-simple" -win=true - - - name: Envoy Integration Tests for windows case-terminating-gateway-without-services - shell: bash - if: always() - 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 Integration Test case-terminating-gateway-without-services" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-terminating-gateway-without-services" -win=true - - - name: Envoy Integration Tests for windows case-upstream-config - shell: bash - if: always() - 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 Integration Test case-upstream-config" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-upstream-config" -win=true - - - name: Envoy Integration Tests for windows case-wanfed-gw - shell: bash - if: always() - 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 Integration Test case-wanfed-gw" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-wanfed-gw" -win=true - - - name: Envoy Integration Tests for windows case-ingress-gateway-sds - shell: bash - if: always() - 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 Integration Test case-ingress-gateway-sds" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-sds" -win=true - - - name: Envoy Integration Tests for windows case-lua - shell: bash - if: always() - 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 Integration Test case-lua" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-lua" -win=true - - - name: Envoy Integration Tests for windows case-terminating-gateway-subsets - shell: bash - if: always() - 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 Integration Test case-terminating-gateway-subsets" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-terminating-gateway-subsets" -win=true - - # Skipping this because - https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/wasm_filter - # - name: Envoy Integration Tests for windows case-wasm - # shell: bash - # 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 Integration Test case-wasm" - # # shellcheck disable=SC2001 - # go test -v -timeout=30m -tags integration \ - # ./test/integration/connect/envoy -run="TestEnvoy/case-wasm" -win=true - - # Skipping because of - cacert is not available in curl windows - # https://www.phillipsj.net/posts/windows-curl-and-self-signed-certs/ - # - name: Envoy Integration Tests for windows case-ingress-gateway-tls - # shell: bash - # if: always() - # 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 Integration Test case-ingress-gateway-tls" - # # shellcheck disable=SC2001 - # go test -v -timeout=30m -tags integration \ - # ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-tls" -win=true - - - name: Envoy Integration Tests for windows case-mesh-to-lambda - shell: bash - if: always() - 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 Integration Test case-mesh-to-lambda" - # shellcheck disable=SC2001 - go test -v -timeout=30m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-mesh-to-lambda" -win=true - - - # 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 - shell: bash - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/download/v2.17.2/datadog-ci_win-x64.exe" --output "C:/datadog-ci" - icacls C:/datadog-ci /grant:rx Everyone:RX - - - 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: C:/datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - test-integrations-success: - needs: - - envoy-integration-test - runs-on: 'ubuntu-latest' - 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 \ No newline at end of file diff --git a/.github/workflows/test-integrations.yml b/.github/workflows/test-integrations.yml index 6e7bf3e7f03b1..57ee1d7b66202 100644 --- a/.github/workflows/test-integrations.yml +++ b/.github/workflows/test-integrations.yml @@ -55,7 +55,7 @@ jobs: compute-xl: ${{ steps.runners.outputs.compute-xl }} enterprise: ${{ steps.runners.outputs.enterprise }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - id: runners run: .github/scripts/get_runner_classes.sh @@ -63,7 +63,7 @@ jobs: needs: [setup] uses: ./.github/workflows/reusable-dev-build.yml with: - runs-on: ${{ needs.setup.outputs.compute-xl }} + runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} uploaded-binary-name: 'consul-bin' secrets: @@ -82,13 +82,13 @@ jobs: nomad-version: ['v1.3.3', 'v1.2.10', 'v1.1.16'] steps: - name: Checkout Nomad - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 with: repository: hashicorp/nomad ref: ${{ matrix.nomad-version }} - name: Install Go - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 + uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 with: go-version-file: 'go.mod' @@ -158,18 +158,18 @@ jobs: contents: read strategy: matrix: - vault-version: ["1.14.1", "1.13.5", "1.12.9", "1.11.12"] + vault-version: ["1.13.1", "1.12.5", "1.11.9", "1.10.11"] env: VAULT_BINARY_VERSION: ${{ matrix.vault-version }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 # 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 + - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 with: go-version-file: 'go.mod' @@ -252,14 +252,14 @@ jobs: outputs: envoy-matrix: ${{ steps.set-matrix.outputs.envoy-matrix }} steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - 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.10", "1.25.9", "1.26.4", "1.27.0"] + # envoy-version: ["1.23.12", "1.24.10", "1.25.9", "1.26.4"] # xds-target: ["server", "client"] TOTAL_RUNNERS: 4 JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' @@ -282,7 +282,7 @@ jobs: } >> "$GITHUB_OUTPUT" envoy-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} + runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} needs: - setup - generate-envoy-job-matrices @@ -293,7 +293,7 @@ jobs: strategy: fail-fast: false matrix: - envoy-version: ["1.27.0"] + envoy-version: ["1.26.4"] xds-target: ["server", "client"] test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} env: @@ -301,8 +301,8 @@ jobs: XDS_TARGET: ${{ matrix.xds-target }} AWS_LAMBDA_REGION: us-west-2 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 + - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 + - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 with: go-version-file: 'go.mod' @@ -315,7 +315,7 @@ jobs: run: chmod +x ./bin/consul - name: Set up Docker Buildx - uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0 + uses: docker/setup-buildx-action@f03ac48505955848960e80bbb68046aa35c7b9e7 # v2.4.1 - name: Docker build run: docker build -t consul:local -f ./build-support/docker/Consul-Dev.dockerfile ./bin @@ -374,7 +374,7 @@ jobs: run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml compatibility-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} + runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} needs: - setup - dev-build @@ -384,12 +384,8 @@ jobs: env: ENVOY_VERSION: "1.25.4" steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # 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 + - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 + - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 with: go-version-file: 'go.mod' - run: go env @@ -437,7 +433,7 @@ jobs: -tags "${{ env.GOTAGS }}" \ -timeout=30m \ -json \ - `go list -tags "${{ env.GOTAGS }}" ./... | grep -v upgrade | grep -v peering_commontopo` \ + `go list ./... | grep -v upgrade` \ --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ --target-version local \ --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ @@ -483,98 +479,6 @@ jobs: DD_ENV: ci run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - peering_commontopo-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} - needs: - - setup - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - env: - ENVOY_VERSION: "1.24.6" - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # 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: Peering commonTopo Integration Tests - run: | - mkdir -p "${{ env.TEST_RESULTS_DIR }}" - cd ./test-integ/peering_commontopo - 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 \ - --packages="./..." \ - -- \ - go test \ - -tags "${{ env.GOTAGS }}" \ - -timeout=30m \ - -json . \ - --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --target-version local \ - --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --latest-version latest - 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: - conditional-skip @@ -585,7 +489,6 @@ jobs: - generate-envoy-job-matrices - envoy-integration-test - compatibility-integration-test - - peering_commontopo-integration-test runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} if: always() && needs.conditional-skip.outputs.trigger-ci == 'true' steps: diff --git a/.github/workflows/verify-envoy-version.yml b/.github/workflows/verify-envoy-version.yml index 9e8b7e7e89b36..d097e335d37b2 100644 --- a/.github/workflows/verify-envoy-version.yml +++ b/.github/workflows/verify-envoy-version.yml @@ -18,7 +18,7 @@ jobs: verify-envoy-version: runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@v2 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 # by default the checkout action doesn't checkout all branches diff --git a/.gitignore b/.gitignore index 793354db02d52..a48d19b74cc22 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ .vagrant/ /pkg bin/ -workdir/ changelog.tmp exit-code Thumbs.db @@ -69,4 +68,3 @@ override.tf.json terraform.rc /go.work /go.work.sum -.docker diff --git a/.golangci.yml b/.golangci.yml index b0730c9577083..3e45ef464c14c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 linters: disable-all: true diff --git a/.release/ci.hcl b/.release/ci.hcl index d11983b460574..dfe69d2fc1ebd 100644 --- a/.release/ci.hcl +++ b/.release/ci.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 schema = "1" diff --git a/.release/docker/docker-entrypoint-ubi.sh b/.release/docker/docker-entrypoint-ubi.sh index 96e70df925672..a932ad7286e28 100755 --- a/.release/docker/docker-entrypoint-ubi.sh +++ b/.release/docker/docker-entrypoint-ubi.sh @@ -1,6 +1,6 @@ #!/usr/bin/dumb-init /bin/sh # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -e diff --git a/.release/docker/docker-entrypoint-windows.sh b/.release/docker/docker-entrypoint-windows.sh deleted file mode 100644 index f6aac9afaeca7..0000000000000 --- a/.release/docker/docker-entrypoint-windows.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/dumb-init /bin/sh -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - -set -e - -# Note above that we run dumb-init as PID 1 in order to reap zombie processes -# as well as forward signals to all processes in its session. Normally, sh -# wouldn't do either of these functions so we'd leak zombies as well as do -# unclean termination of all our sub-processes. -# As of docker 1.13, using docker run --init achieves the same outcome. - -# You can set CONSUL_BIND_INTERFACE to the name of the interface you'd like to -# bind to and this will look up the IP and pass the proper -bind= option along -# to Consul. -CONSUL_BIND= -if [ -n "$CONSUL_BIND_INTERFACE" ]; then - CONSUL_BIND_ADDRESS=$(ip -o -4 addr list $CONSUL_BIND_INTERFACE | head -n1 | awk '{print $4}' | cut -d/ -f1) - if [ -z "$CONSUL_BIND_ADDRESS" ]; then - echo "Could not find IP for interface '$CONSUL_BIND_INTERFACE', exiting" - exit 1 - fi - - CONSUL_BIND="-bind=$CONSUL_BIND_ADDRESS" - echo "==> Found address '$CONSUL_BIND_ADDRESS' for interface '$CONSUL_BIND_INTERFACE', setting bind option..." -fi - -# You can set CONSUL_CLIENT_INTERFACE to the name of the interface you'd like to -# bind client intefaces (HTTP, DNS, and RPC) to and this will look up the IP and -# pass the proper -client= option along to Consul. -CONSUL_CLIENT= -if [ -n "$CONSUL_CLIENT_INTERFACE" ]; then - CONSUL_CLIENT_ADDRESS=$(ip -o -4 addr list $CONSUL_CLIENT_INTERFACE | head -n1 | awk '{print $4}' | cut -d/ -f1) - if [ -z "$CONSUL_CLIENT_ADDRESS" ]; then - echo "Could not find IP for interface '$CONSUL_CLIENT_INTERFACE', exiting" - exit 1 - fi - - CONSUL_CLIENT="-client=$CONSUL_CLIENT_ADDRESS" - echo "==> Found address '$CONSUL_CLIENT_ADDRESS' for interface '$CONSUL_CLIENT_INTERFACE', setting client option..." -fi - -# CONSUL_DATA_DIR is exposed as a volume for possible persistent storage. The -# CONSUL_CONFIG_DIR isn't exposed as a volume but you can compose additional -# config files in there if you use this image as a base, or use CONSUL_LOCAL_CONFIG -# below. -CONSUL_DATA_DIR=C:\\consul\\data -CONSUL_CONFIG_DIR=C:\\consul\\config - -# You can also set the CONSUL_LOCAL_CONFIG environemnt variable to pass some -# Consul configuration JSON without having to bind any volumes. -if [ -n "$CONSUL_LOCAL_CONFIG" ]; then - echo "$CONSUL_LOCAL_CONFIG" > "$CONSUL_CONFIG_DIR/local.json" -fi - -# If the user is trying to run Consul directly with some arguments, then -# pass them to Consul. -if [ "${1:0:1}" = '-' ]; then - set -- consul "$@" -fi - -# Look for Consul subcommands. -if [ "$1" = 'agent' ]; then - shift - set -- consul agent \ - -data-dir="$CONSUL_DATA_DIR" \ - -config-dir="$CONSUL_CONFIG_DIR" \ - $CONSUL_BIND \ - $CONSUL_CLIENT \ - "$@" -elif [ "$1" = 'version' ]; then - # This needs a special case because there's no help output. - set -- consul "$@" -elif consul --help "$1" 2>&1 | grep -q "consul $1"; then - # We can't use the return code to check for the existence of a subcommand, so - # we have to use grep to look for a pattern in the help output. - set -- consul "$@" -fi - -# NOTE: Unlike in the regular Consul Docker image, we don't have code here -# for changing data-dir directory ownership or using su-exec because OpenShift -# won't run this container as root and so we can't change data dir ownership, -# and there's no need to use su-exec. - -exec "$@" \ No newline at end of file diff --git a/.release/docker/docker-entrypoint.sh b/.release/docker/docker-entrypoint.sh index a544809643e00..c169576b6cf85 100755 --- a/.release/docker/docker-entrypoint.sh +++ b/.release/docker/docker-entrypoint.sh @@ -1,6 +1,6 @@ #!/usr/bin/dumb-init /bin/sh # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -e diff --git a/.release/linux/package/etc/consul.d/consul.hcl b/.release/linux/package/etc/consul.d/consul.hcl index b25f186858564..b54644b2f9ccd 100644 --- a/.release/linux/package/etc/consul.d/consul.hcl +++ b/.release/linux/package/etc/consul.d/consul.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # Full configuration options can be found at https://www.consul.io/docs/agent/config diff --git a/.release/release-metadata.hcl b/.release/release-metadata.hcl index 963192fc4b80e..8de2623fdee4e 100644 --- a/.release/release-metadata.hcl +++ b/.release/release-metadata.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 url_docker_registry_dockerhub = "https://hub.docker.com/r/hashicorp/consul" url_docker_registry_ecr = "https://gallery.ecr.aws/hashicorp/consul" diff --git a/.release/security-scan.hcl b/.release/security-scan.hcl index 0dd5116c6ecef..3029b33273b06 100644 --- a/.release/security-scan.hcl +++ b/.release/security-scan.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 container { dependencies = true diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cd1efb50646e..a7a2c6e24a8a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 1.16.1 (August 8, 2023) +KNOWN ISSUES: + +* connect: Consul versions 1.16.0 and 1.16.1 may have issues when a snapshot restore is performed and the servers are hosting xDS streams. When this bug triggers, it will cause Envoy to incorrectly populate upstream endpoints. This bug only impacts agent-less service mesh and should be fixed in Consul 1.16.2 by [GH-18636](https://github.com/hashicorp/consul/pull/18636). + SECURITY: * Update `golang.org/x/net` to v0.13.0 to address [CVE-2023-3978](https://nvd.nist.gov/vuln/detail/CVE-2023-3978). [[GH-18358](https://github.com/hashicorp/consul/issues/18358)] @@ -57,84 +61,11 @@ we now reject those earlier in the process when we validate the certificate. [[G https://github.com/rboyer/safeio/pull/3 [[GH-18302](https://github.com/hashicorp/consul/issues/18302)] * xds: Prevent partial application of non-Required Envoy extensions in the case of failure. [[GH-18068](https://github.com/hashicorp/consul/issues/18068)] -## 1.15.5 (August 8, 2023) - -SECURITY: - -* Update `golang.org/x/net` to v0.13.0 to address [CVE-2023-3978](https://nvd.nist.gov/vuln/detail/CVE-2023-3978). [[GH-18358](https://github.com/hashicorp/consul/issues/18358)] -* Upgrade golang.org/x/net to address [CVE-2023-29406](https://nvd.nist.gov/vuln/detail/CVE-2023-29406) [[GH-18186](https://github.com/hashicorp/consul/issues/18186)] -* Upgrade to use Go 1.20.6. -This resolves [CVE-2023-29406](https://github.com/advisories/GHSA-f8f7-69v5-w4vx)(`net/http`) for uses of the standard library. -A separate change updates dependencies on `golang.org/x/net` to use `0.12.0`. [[GH-18190](https://github.com/hashicorp/consul/issues/18190)] -* Upgrade to use Go 1.20.7. -This resolves vulnerability [CVE-2023-29409](https://nvd.nist.gov/vuln/detail/CVE-2023-29409)(`crypto/tls`). [[GH-18358](https://github.com/hashicorp/consul/issues/18358)] - -FEATURES: - -* cli: `consul members` command uses `-filter` expression to filter members based on bexpr. [[GH-18223](https://github.com/hashicorp/consul/issues/18223)] -* cli: `consul watch` command uses `-filter` expression to filter response from checks, services, nodes, and service. [[GH-17780](https://github.com/hashicorp/consul/issues/17780)] -* reloadable config: Made enable_debug config reloadable and enable pprof command to work when config toggles to true [[GH-17565](https://github.com/hashicorp/consul/issues/17565)] - -IMPROVEMENTS: - -* Fix some typos in metrics docs [[GH-18080](https://github.com/hashicorp/consul/issues/18080)] -* acl: added builtin ACL policy that provides global read-only access (builtin/global-read-only) [[GH-18319](https://github.com/hashicorp/consul/issues/18319)] -* acl: allow for a single slash character in policy names [[GH-18319](https://github.com/hashicorp/consul/issues/18319)] -* connect: Add capture group labels from Envoy cluster FQDNs to Envoy exported metric labels [[GH-17888](https://github.com/hashicorp/consul/issues/17888)] -* connect: update supported envoy versions to 1.22.11, 1.23.12, 1.24.10, 1.25.9 [[GH-18304](https://github.com/hashicorp/consul/issues/18304)] -* hcp: Add dynamic configuration support for the export of server metrics to HCP. [[GH-18168](https://github.com/hashicorp/consul/issues/18168)] -* hcp: Removes requirement for HCP to provide a management token [[GH-18140](https://github.com/hashicorp/consul/issues/18140)] -* xds: Explicitly enable WebSocket connection upgrades in HTTP connection manager [[GH-18150](https://github.com/hashicorp/consul/issues/18150)] - -BUG FIXES: - -* Fix a bug that wrongly trims domains when there is an overlap with DC name. [[GH-17160](https://github.com/hashicorp/consul/issues/17160)] -* api-gateway: fix race condition in proxy config generation when Consul is notified of the bound-api-gateway config entry before it is notified of the api-gateway config entry. [[GH-18291](https://github.com/hashicorp/consul/issues/18291)] -* connect/ca: Fixes a bug preventing CA configuration updates in secondary datacenters [[GH-17846](https://github.com/hashicorp/consul/issues/17846)] -* connect: Fix incorrect protocol config merging for transparent proxy implicit upstreams. [[GH-17894](https://github.com/hashicorp/consul/issues/17894)] -* connect: Removes the default health check from the `consul connect envoy` command when starting an API Gateway. -This health check would always fail. [[GH-18011](https://github.com/hashicorp/consul/issues/18011)] -* connect: fix a bug with Envoy potentially starting with incomplete configuration by not waiting enough for initial xDS configuration. [[GH-18024](https://github.com/hashicorp/consul/issues/18024)] -* snapshot: fix access denied and handle is invalid when we call snapshot save on windows - skip sync() for folders in windows in -https://github.com/rboyer/safeio/pull/3 [[GH-18302](https://github.com/hashicorp/consul/issues/18302)] - -## 1.14.9 (August 8, 2023) - -SECURITY: - -* Update `golang.org/x/net` to v0.13.0 to address [CVE-2023-3978](https://nvd.nist.gov/vuln/detail/CVE-2023-3978). [[GH-18358](https://github.com/hashicorp/consul/issues/18358)] -* Upgrade golang.org/x/net to address [CVE-2023-29406](https://nvd.nist.gov/vuln/detail/CVE-2023-29406) [[GH-18186](https://github.com/hashicorp/consul/issues/18186)] -* Upgrade to use Go 1.20.6. -This resolves [CVE-2023-29406](https://github.com/advisories/GHSA-f8f7-69v5-w4vx)(`net/http`) for uses of the standard library. -A separate change updates dependencies on `golang.org/x/net` to use `0.12.0`. [[GH-18190](https://github.com/hashicorp/consul/issues/18190)] -* Upgrade to use Go 1.20.7. -This resolves vulnerability [CVE-2023-29409](https://nvd.nist.gov/vuln/detail/CVE-2023-29409)(`crypto/tls`). [[GH-18358](https://github.com/hashicorp/consul/issues/18358)] - -FEATURES: - -* cli: `consul members` command uses `-filter` expression to filter members based on bexpr. [[GH-18223](https://github.com/hashicorp/consul/issues/18223)] -* cli: `consul watch` command uses `-filter` expression to filter response from checks, services, nodes, and service. [[GH-17780](https://github.com/hashicorp/consul/issues/17780)] -* reloadable config: Made enable_debug config reloadable and enable pprof command to work when config toggles to true [[GH-17565](https://github.com/hashicorp/consul/issues/17565)] - -IMPROVEMENTS: - -* Fix some typos in metrics docs [[GH-18080](https://github.com/hashicorp/consul/issues/18080)] -* acl: added builtin ACL policy that provides global read-only access (builtin/global-read-only) [[GH-18319](https://github.com/hashicorp/consul/issues/18319)] -* acl: allow for a single slash character in policy names [[GH-18319](https://github.com/hashicorp/consul/issues/18319)] -* connect: update supported envoy versions to 1.21.6, 1.22.11, 1.23.12, 1.24.10 [[GH-18305](https://github.com/hashicorp/consul/issues/18305)] -* hcp: Removes requirement for HCP to provide a management token [[GH-18140](https://github.com/hashicorp/consul/issues/18140)] -* xds: Explicitly enable WebSocket connection upgrades in HTTP connection manager [[GH-18150](https://github.com/hashicorp/consul/issues/18150)] - -BUG FIXES: +## 1.16.0 (June 26, 2023) -* Fix a bug that wrongly trims domains when there is an overlap with DC name. [[GH-17160](https://github.com/hashicorp/consul/issues/17160)] -* connect/ca: Fixes a bug preventing CA configuration updates in secondary datacenters [[GH-17846](https://github.com/hashicorp/consul/issues/17846)] -* connect: Fix incorrect protocol config merging for transparent proxy implicit upstreams. [[GH-17894](https://github.com/hashicorp/consul/issues/17894)] -* connect: fix a bug with Envoy potentially starting with incomplete configuration by not waiting enough for initial xDS configuration. [[GH-18024](https://github.com/hashicorp/consul/issues/18024)] -* snapshot: fix access denied and handle is invalid when we call snapshot save on windows - skip sync() for folders in windows in -https://github.com/rboyer/safeio/pull/3 [[GH-18302](https://github.com/hashicorp/consul/issues/18302)] +KNOWN ISSUES: -## 1.16.0 (June 26, 2023) +* connect: Consul versions 1.16.0 and 1.16.1 may have issues when a snapshot restore is performed and the servers are hosting xDS streams. When this bug triggers, it will cause Envoy to incorrectly populate upstream endpoints. This bug only impacts agent-less service mesh and should be fixed in Consul 1.16.2 by [GH-18636](https://github.com/hashicorp/consul/pull/18636). BREAKING CHANGES: @@ -207,100 +138,6 @@ BUG FIXES: * ui: fixes ui tests run on CI [[GH-16428](https://github.com/hashicorp/consul/issues/16428)] * xds: Fixed a bug where modifying ACLs on a token being actively used for an xDS connection caused all xDS updates to fail. [[GH-17566](https://github.com/hashicorp/consul/issues/17566)] -## 1.15.4 (June 26, 2023) -FEATURES: - -* cli: `consul operator raft list-peers` command shows the number of commits each follower is trailing the leader by to aid in troubleshooting. [[GH-17582](https://github.com/hashicorp/consul/issues/17582)] -* server: **(Enterprise Only)** allow automatic license utilization reporting. [[GH-5102](https://github.com/hashicorp/consul/issues/5102)] - -IMPROVEMENTS: - -* connect: update supported envoy versions to 1.22.11, 1.23.9, 1.24.7, 1.25.6 [[GH-17545](https://github.com/hashicorp/consul/issues/17545)] -* debug: change default setting of consul debug command. now default duration is 5ms and default log level is 'TRACE' [[GH-17596](https://github.com/hashicorp/consul/issues/17596)] -* fix metric names in /docs/agent/telemetry [[GH-17577](https://github.com/hashicorp/consul/issues/17577)] -* gateway: Change status condition reason for invalid certificate on a listener from "Accepted" to "ResolvedRefs". [[GH-17115](https://github.com/hashicorp/consul/issues/17115)] -* systemd: set service type to notify. [[GH-16845](https://github.com/hashicorp/consul/issues/16845)] - -BUG FIXES: - -* cache: fix a few minor goroutine leaks in leaf certs and the agent cache [[GH-17636](https://github.com/hashicorp/consul/issues/17636)] -* docs: fix list of telemetry metrics [[GH-17593](https://github.com/hashicorp/consul/issues/17593)] -* gateways: **(Enterprise only)** Fixed a bug in API gateways where gateway configuration objects in non-default partitions did not reconcile properly. [[GH-17581](https://github.com/hashicorp/consul/issues/17581)] -* gateways: Fixed a bug in API gateways where binding a route that only targets a service imported from a peer results - in the programmed gateway having no routes. [[GH-17609](https://github.com/hashicorp/consul/issues/17609)] -* gateways: Fixed a bug where API gateways were not being taken into account in determining xDS rate limits. [[GH-17631](https://github.com/hashicorp/consul/issues/17631)] -* http: fixed API endpoint `PUT /acl/token/:AccessorID` (update token), no longer requires `AccessorID` in the request body. Web UI can now update tokens. [[GH-17739](https://github.com/hashicorp/consul/issues/17739)] -* namespaces: **(Enterprise only)** fixes a bug where agent health checks stop syncing for all services on a node if the namespace of any service has been removed from the server. -* namespaces: **(Enterprise only)** fixes a bug where namespaces are stuck in a deferred deletion state indefinitely under some conditions. - Also fixes the Consul query metadata present in the HTTP headers of the namespace read and list endpoints. -* peering: Fix a bug that caused server agents to continue cleaning up peering resources even after loss of leadership. [[GH-17483](https://github.com/hashicorp/consul/issues/17483)] -* xds: Fixed a bug where modifying ACLs on a token being actively used for an xDS connection caused all xDS updates to fail. [[GH-17566](https://github.com/hashicorp/consul/issues/17566)] - -## 1.14.8 (June 26, 2023) - -SECURITY: - -* Update to UBI base image to 9.2. [[GH-17513](https://github.com/hashicorp/consul/issues/17513)] - -FEATURES: - -* cli: `consul operator raft list-peers` command shows the number of commits each follower is trailing the leader by to aid in troubleshooting. [[GH-17582](https://github.com/hashicorp/consul/issues/17582)] -* server: **(Enterprise Only)** allow automatic license utilization reporting. [[GH-5102](https://github.com/hashicorp/consul/issues/5102)] - -IMPROVEMENTS: - -* connect: update supported envoy versions to 1.21.6, 1.22.11, 1.23.9, 1.24.7 [[GH-17547](https://github.com/hashicorp/consul/issues/17547)] -* debug: change default setting of consul debug command. now default duration is 5ms and default log level is 'TRACE' [[GH-17596](https://github.com/hashicorp/consul/issues/17596)] -* fix metric names in /docs/agent/telemetry [[GH-17577](https://github.com/hashicorp/consul/issues/17577)] -* peering: gRPC queries for TrustBundleList, TrustBundleRead, PeeringList, and PeeringRead now support blocking semantics, - reducing network and CPU demand. - The HTTP APIs for Peering List and Read have been updated to support blocking. [[GH-17426](https://github.com/hashicorp/consul/issues/17426)] -* raft: Remove expensive reflection from raft/mesh hot path [[GH-16552](https://github.com/hashicorp/consul/issues/16552)] -* systemd: set service type to notify. [[GH-16845](https://github.com/hashicorp/consul/issues/16845)] - -BUG FIXES: - -* cache: fix a few minor goroutine leaks in leaf certs and the agent cache [[GH-17636](https://github.com/hashicorp/consul/issues/17636)] -* connect: reverts #17317 fix that caused a downstream error for Ingress/Mesh/Terminating GWs when their respective config entry does not already exist. [[GH-17541](https://github.com/hashicorp/consul/issues/17541)] -* namespaces: **(Enterprise only)** fixes a bug where agent health checks stop syncing for all services on a node if the namespace of any service has been removed from the server. -* namespaces: **(Enterprise only)** fixes a bug where namespaces are stuck in a deferred deletion state indefinitely under some conditions. - Also fixes the Consul query metadata present in the HTTP headers of the namespace read and list endpoints. -* namespaces: adjusts the return type from HTTP list API to return the `api` module representation of a namespace. - This fixes an error with the `consul namespace list` command when a namespace has a deferred deletion timestamp. -* peering: Fix a bug that caused server agents to continue cleaning up peering resources even after loss of leadership. [[GH-17483](https://github.com/hashicorp/consul/issues/17483)] -* peering: Fix issue where modifying the list of exported services did not correctly replicate changes for services that exist in a non-default namespace. [[GH-17456](https://github.com/hashicorp/consul/issues/17456)] - -## 1.13.9 (June 26, 2023) -BREAKING CHANGES: - -* connect: Disable peering by default in connect proxies for Consul 1.13. This change was made to prevent inefficient polling - queries from having a negative impact on server performance. Peering in Consul 1.13 is an experimental feature and is not - recommended for use in production environments. If you still wish to use the experimental peering feature, ensure - [`peering.enabled = true`](https://developer.hashicorp.com/consul/docs/v1.13.x/agent/config/config-files#peering_enabled) - is set on all clients and servers. [[GH-17731](https://github.com/hashicorp/consul/issues/17731)] - -SECURITY: - -* Update to UBI base image to 9.2. [[GH-17513](https://github.com/hashicorp/consul/issues/17513)] - -FEATURES: - -* server: **(Enterprise Only)** allow automatic license utilization reporting. [[GH-5102](https://github.com/hashicorp/consul/issues/5102)] - -IMPROVEMENTS: - -* debug: change default setting of consul debug command. now default duration is 5ms and default log level is 'TRACE' [[GH-17596](https://github.com/hashicorp/consul/issues/17596)] -* systemd: set service type to notify. [[GH-16845](https://github.com/hashicorp/consul/issues/16845)] - -BUG FIXES: - -* cache: fix a few minor goroutine leaks in leaf certs and the agent cache [[GH-17636](https://github.com/hashicorp/consul/issues/17636)] -* namespaces: **(Enterprise only)** fixes a bug where namespaces are stuck in a deferred deletion state indefinitely under some conditions. - Also fixes the Consul query metadata present in the HTTP headers of the namespace read and list endpoints. -* namespaces: adjusts the return type from HTTP list API to return the `api` module representation of a namespace. - This fixes an error with the `consul namespace list` command when a namespace has a deferred deletion timestamp. -* peering: Fix a bug that caused server agents to continue cleaning up peering resources even after loss of leadership. [[GH-17483](https://github.com/hashicorp/consul/issues/17483)] - ## 1.16.0-rc1 (June 12, 2023) BREAKING CHANGES: diff --git a/Dockerfile b/Dockerfile index 1926c521299a7..7599ec7b35b80 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # This Dockerfile contains multiple targets. # Use 'docker build --target= .' to build one. diff --git a/Dockerfile-windows b/Dockerfile-windows deleted file mode 100644 index 14582908db550..0000000000000 --- a/Dockerfile-windows +++ /dev/null @@ -1,51 +0,0 @@ -FROM mcr.microsoft.com/windows/servercore:ltsc2019 -ARG VERSION=1.16.0 - -ENV chocolateyVersion=1.4.0 - -LABEL org.opencontainers.image.authors="Consul Team " \ - org.opencontainers.image.url="https://www.consul.io/" \ - org.opencontainers.image.documentation="https://www.consul.io/docs" \ - org.opencontainers.image.source="https://github.com/hashicorp/consul" \ - org.opencontainers.image.version=$VERSION \ - org.opencontainers.image.vendor="HashiCorp" \ - org.opencontainers.image.title="consul" \ - org.opencontainers.image.description="Consul is a datacenter runtime that provides service discovery, configuration, and orchestration." \ - version=${VERSION} - -RUN ["powershell", "Set-ExecutionPolicy", "Bypass", "-Scope", "Process", "-Force;"] -RUN ["powershell", "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))"] - -RUN choco install git.install -yf -RUN SETX /M path "%PATH%;C:\Program Files\Git\bin" - -RUN mkdir C:\\consul -RUN mkdir C:\\consul\\data -RUN mkdir C:\\consul\\config - -# Server RPC is used for communication between Consul clients and servers for internal -# request forwarding. -EXPOSE 8300 - -# Serf LAN and WAN (WAN is used only by Consul servers) are used for gossip between -# Consul agents. LAN is within the datacenter and WAN is between just the Consul -# servers in all datacenters. -EXPOSE 8301 8301/udp 8302 8302/udp - -# HTTP and DNS (both TCP and UDP) are the primary interfaces that applications -# use to interact with Consul. -EXPOSE 8500 8600 8600/udp - -#ENV CONSUL_URL=https://releases.hashicorp.com/consul/${VERSION}/consul_${VERSION}_windows_amd64.zip -#RUN curl %CONSUL_URL% -L -o consul.zip -#RUN tar -xf consul.zip -C consul - -COPY consul.exe C:\\consul - -COPY .release/docker/docker-entrypoint-windows.sh C:\\docker-entrypoint-windows.sh -ENTRYPOINT ["bash.exe", "docker-entrypoint-windows.sh"] - -# By default you'll get an insecure single-node development server that stores -# everything in RAM, exposes a web UI and HTTP endpoints, and bootstraps itself. -# Don't use this configuration for production. -CMD ["agent", "-dev", "-client", "0.0.0.0"] diff --git a/Makefile b/GNUmakefile similarity index 73% rename from Makefile rename to GNUmakefile index 4ca2072dbabe8..ae691d2f0e8aa 100644 --- a/Makefile +++ b/GNUmakefile @@ -3,7 +3,6 @@ SHELL = bash - GO_MODULES := $(shell find . -name go.mod -exec dirname {} \; | grep -v "proto-gen-rpc-glue/e2e" | sort) ### @@ -12,7 +11,7 @@ GO_MODULES := $(shell find . -name go.mod -exec dirname {} \; | grep -v "proto-g ### GOLANGCI_LINT_VERSION='v1.51.1' MOCKERY_VERSION='v2.20.0' -BUF_VERSION='v1.26.0' +BUF_VERSION='v1.14.0' PROTOC_GEN_GO_GRPC_VERSION="v1.2.0" MOG_VERSION='v0.4.0' @@ -66,7 +65,13 @@ BUILD_CONTAINER_NAME?=consul-builder CONSUL_IMAGE_VERSION?=latest ENVOY_VERSION?='1.25.4' -CONSUL_VERSION?=$(shell cat version/VERSION) +################ +# CI Variables # +################ +CI_DEV_DOCKER_NAMESPACE?=hashicorpdev +CI_DEV_DOCKER_IMAGE_NAME?=consul +CI_DEV_DOCKER_WORKDIR?=bin/ +################ TEST_MODCACHE?=1 TEST_BUILDCACHE?=1 @@ -146,27 +151,23 @@ ifdef SKIP_DOCKER_BUILD ENVOY_INTEG_DEPS=noop endif -##@ Build - -.PHONY: all -all: dev-build ## Command running by default +all: dev-build # used to make integration dependencies conditional noop: ; -.PHONY: dev -dev: dev-build ## Dev creates binaries for testing locally - these are put into ./bin +# dev creates binaries for testing locally - these are put into ./bin +dev: dev-build -.PHONY: dev-build -dev-build: ## Same as dev +dev-build: mkdir -p bin CGO_ENABLED=0 go install -ldflags "$(GOLDFLAGS)" -tags "$(GOTAGS)" # rm needed due to signature caching (https://apple.stackexchange.com/a/428388) rm -f ./bin/consul cp ${MAIN_GOPATH}/bin/consul ./bin/consul -.PHONY: dev-docker-dbg -dev-docker-dbg: dev-docker ## Build containers for debug mode + +dev-docker-dbg: dev-docker @echo "Pulling consul container image - $(CONSUL_IMAGE_VERSION)" @docker pull hashicorp/consul:$(CONSUL_IMAGE_VERSION) >/dev/null @echo "Building Consul Development container - $(CONSUL_DEV_IMAGE)" @@ -178,8 +179,7 @@ dev-docker-dbg: dev-docker ## Build containers for debug mode --load \ -f $(CURDIR)/build-support/docker/Consul-Dev-Dbg.dockerfile $(CURDIR)/pkg/bin/ -.PHONY: dev-docker -dev-docker: linux dev-build ## Build and tag docker images in dev env +dev-docker: linux dev-build @echo "Pulling consul container image - $(CONSUL_IMAGE_VERSION)" @docker pull hashicorp/consul:$(CONSUL_IMAGE_VERSION) >/dev/null @echo "Building Consul Development container - $(CONSUL_DEV_IMAGE)" @@ -188,20 +188,15 @@ dev-docker: linux dev-build ## Build and tag docker images in dev env @docker buildx use default && docker buildx build -t 'consul:local' -t '$(CONSUL_DEV_IMAGE)' \ --platform linux/$(GOARCH) \ --build-arg CONSUL_IMAGE_VERSION=$(CONSUL_IMAGE_VERSION) \ - --label org.opencontainers.image.version=$(CONSUL_VERSION) \ - --label version=$(CONSUL_VERSION) \ --load \ -f $(CURDIR)/build-support/docker/Consul-Dev-Multiarch.dockerfile $(CURDIR)/pkg/bin/ - docker tag 'consul:local' '$(CONSUL_COMPAT_TEST_IMAGE):local' -.PHONY: check-remote-dev-image-env -check-remote-dev-image-env: ## Check remote dev image env +check-remote-dev-image-env: ifndef REMOTE_DEV_IMAGE $(error REMOTE_DEV_IMAGE is undefined: set this image to /:, e.g. hashicorp/consul-k8s-dev:latest) endif -.PHONY: remote-docker -remote-docker: check-remote-dev-image-env ## Remote docker +remote-docker: check-remote-dev-image-env $(MAKE) GOARCH=amd64 linux $(MAKE) GOARCH=arm64 linux @echo "Pulling consul container image - $(CONSUL_IMAGE_VERSION)" @@ -213,63 +208,39 @@ remote-docker: check-remote-dev-image-env ## Remote docker @docker buildx use consul-builder && docker buildx build -t '$(REMOTE_DEV_IMAGE)' \ --platform linux/amd64,linux/arm64 \ --build-arg CONSUL_IMAGE_VERSION=$(CONSUL_IMAGE_VERSION) \ - --label org.opencontainers.image.version=$(CONSUL_VERSION) \ - --label version=$(CONSUL_VERSION) \ --push \ -f $(CURDIR)/build-support/docker/Consul-Dev-Multiarch.dockerfile $(CURDIR)/pkg/bin/ -linux: ## Linux builds a linux binary compatible with the source platform +# In CI, the linux binary will be attached from a previous step at bin/. This make target +# should only run in CI and not locally. +ci.dev-docker: + @echo "Pulling consul container image - $(CONSUL_IMAGE_VERSION)" + @docker pull hashicorp/consul:$(CONSUL_IMAGE_VERSION) >/dev/null + @echo "Building Consul Development container - $(CI_DEV_DOCKER_IMAGE_NAME)" + @docker build $(NOCACHE) $(QUIET) -t '$(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):$(GIT_COMMIT)' \ + --build-arg CONSUL_IMAGE_VERSION=$(CONSUL_IMAGE_VERSION) \ + --label COMMIT_SHA=$(CIRCLE_SHA1) \ + --label PULL_REQUEST=$(CIRCLE_PULL_REQUEST) \ + --label CIRCLE_BUILD_URL=$(CIRCLE_BUILD_URL) \ + $(CI_DEV_DOCKER_WORKDIR) -f $(CURDIR)/build-support/docker/Consul-Dev.dockerfile + @echo $(DOCKER_PASS) | docker login -u="$(DOCKER_USER)" --password-stdin + @echo "Pushing dev image to: https://cloud.docker.com/u/hashicorpdev/repository/docker/hashicorpdev/consul" + @docker push $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):$(GIT_COMMIT) +ifeq ($(CIRCLE_BRANCH), main) + @docker tag $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):$(GIT_COMMIT) $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):latest + @docker push $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):latest +endif + +# linux builds a linux binary compatible with the source platform +linux: @mkdir -p ./pkg/bin/linux_$(GOARCH) CGO_ENABLED=0 GOOS=linux GOARCH=$(GOARCH) go build -o ./pkg/bin/linux_$(GOARCH) -ldflags "$(GOLDFLAGS)" -tags "$(GOTAGS)" -.PHONY: go-mod-tidy -go-mod-tidy: $(foreach mod,$(GO_MODULES),go-mod-tidy/$(mod)) ## Run go mod tidy in every module - -.PHONY: mod-tidy/% -go-mod-tidy/%: - @echo "--> Running go mod tidy ($*)" - @cd $* && go mod tidy - -##@ Checks - -.PHONY: fmt -fmt: $(foreach mod,$(GO_MODULES),fmt/$(mod)) ## Format go modules - -.PHONY: fmt/% -fmt/%: - @echo "--> Running go fmt ($*)" - @cd $* && gofmt -s -l -w . - -.PHONY: lint -lint: $(foreach mod,$(GO_MODULES),lint/$(mod)) lint-container-test-deps ## Lint go modules and test deps - -.PHONY: lint/% -lint/%: - @echo "--> Running golangci-lint ($*)" - @cd $* && GOWORK=off golangci-lint run --build-tags '$(GOTAGS)' - @echo "--> Running lint-consul-retry ($*)" - @cd $* && GOWORK=off lint-consul-retry - @echo "--> Running enumcover ($*)" - @cd $* && GOWORK=off enumcover ./... - -# check that the test-container module only imports allowlisted packages -# from the root consul module. Generally we don't want to allow these imports. -# In a few specific instances though it is okay to import test definitions and -# helpers from some of the packages in the root module. -.PHONY: lint-container-test-deps -lint-container-test-deps: ## Check that the test-container module only imports allowlisted packages from the root consul module. - @echo "--> Checking container tests for bad dependencies" - @cd test/integration/consul-container && \ - $(CURDIR)/build-support/scripts/check-allowed-imports.sh \ - github.com/hashicorp/consul \ - internal/catalog/catalogtest - -##@ Testing - -.PHONY: cover -cover: cov ## Run tests and generate coverage report +# dist builds binaries for all platforms and packages them for distribution +dist: + @$(SHELL) $(CURDIR)/build-support/scripts/release.sh -t '$(DIST_TAG)' -b '$(DIST_BUILD)' -S '$(DIST_SIGN)' $(DIST_VERSION_ARG) $(DIST_DATE_ARG) $(DIST_REL_ARG) -.PHONY: cov +cover: cov cov: other-consul dev-build go test -tags '$(GOTAGS)' ./... -coverprofile=coverage.out cd sdk && go test -tags '$(GOTAGS)' ./... -coverprofile=../coverage.sdk.part @@ -278,11 +249,17 @@ cov: other-consul dev-build rm -f coverage.{sdk,api}.part go tool cover -html=coverage.out -.PHONY: test test: other-consul dev-build lint test-internal -.PHONY: test-internal -test-internal: ## Test internal +.PHONY: go-mod-tidy +go-mod-tidy: $(foreach mod,$(GO_MODULES),go-mod-tidy/$(mod)) + +.PHONY: mod-tidy/% +go-mod-tidy/%: + @echo "--> Running go mod tidy ($*)" + @cd $* && go mod tidy + +test-internal: @echo "--> Running go test" @rm -f test.log exit-code @# Dump verbose output to test.log so we can surface test names on failure but @@ -311,142 +288,112 @@ test-internal: ## Test internal @grep '^FAIL' test.log || true @if [ "$$(cat exit-code)" == "0" ] ; then echo "PASS" ; exit 0 ; else exit 1 ; fi -.PHONY: test-all -test-all: other-consul dev-build lint $(foreach mod,$(GO_MODULES),test-module/$(mod)) ## Test all +test-all: other-consul dev-build lint $(foreach mod,$(GO_MODULES),test-module/$(mod)) -.PHONY: test-module/% test-module/%: @echo "--> Running go test ($*)" cd $* && go test $(GOTEST_FLAGS) -tags '$(GOTAGS)' ./... -.PHONY: test-race -test-race: ## Test race +test-race: $(MAKE) GOTEST_FLAGS=-race -.PHONY: other-consul -other-consul: ## Checking for other consul instances +test-docker: linux go-build-image + @# -ti run in the foreground showing stdout + @# --rm removes the container once its finished running + @# GO_MODCACHE_VOL - args for mapping in the go module cache + @# GO_BUILD_CACHE_VOL - args for mapping in the go build cache + @# All the env vars are so we pass through all the relevant bits of information + @# Needed for running the tests + @# We map in our local linux_amd64 bin directory as thats where the linux dep + @# target dropped the binary. We could build the binary in the container too + @# but that might take longer as caching gets weird + @# Lastly we map the source dir here to the /consul workdir + @echo "Running tests within a docker container" + @docker run -ti --rm \ + -e 'GOTEST_FLAGS=$(GOTEST_FLAGS)' \ + -e 'GOTAGS=$(GOTAGS)' \ + -e 'GIT_COMMIT=$(GIT_COMMIT)' \ + -e 'GIT_COMMIT_YEAR=$(GIT_COMMIT_YEAR)' \ + -e 'GIT_DIRTY=$(GIT_DIRTY)' \ + $(TEST_PARALLELIZATION) \ + $(TEST_DOCKER_RESOURCE_CONSTRAINTS) \ + $(TEST_MODCACHE_VOL) \ + $(TEST_BUILDCACHE_VOL) \ + -v $(MAIN_GOPATH)/bin/linux_amd64/:/go/bin \ + -v $(shell pwd):/consul \ + $(GO_BUILD_TAG) \ + make test-internal + +other-consul: @echo "--> Checking for other consul instances" @if ps -ef | grep 'consul agent' | grep -v grep ; then \ echo "Found other running consul agents. This may affect your tests." ; \ exit 1 ; \ fi + +.PHONY: fmt +fmt: $(foreach mod,$(GO_MODULES),fmt/$(mod)) -# Use GO_TEST_FLAGS to run specific tests: -# make test-envoy-integ GO_TEST_FLAGS="-run TestEnvoy/case-basic" -# NOTE: Always uses amd64 images, even when running on M1 macs, to match CI/CD environment. -# You can also specify the envoy version (example: 1.27.0) setting the environment variable: ENVOY_VERSION=1.27.0 -.PHONY: test-envoy-integ -test-envoy-integ: $(ENVOY_INTEG_DEPS) ## Run integration tests. - @go test -v -timeout=30m -tags integration $(GO_TEST_FLAGS) ./test/integration/connect/envoy - -# NOTE: Use DOCKER_BUILDKIT=0, if docker build fails to resolve consul:local base image -.PHONY: test-compat-integ-setup -test-compat-integ-setup: dev-docker - @docker tag consul-dev:latest $(CONSUL_COMPAT_TEST_IMAGE):local - @docker run --rm -t $(CONSUL_COMPAT_TEST_IMAGE):local consul version - @# 'consul-envoy:target-version' is needed by compatibility integ test - @docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=$(CONSUL_COMPAT_TEST_IMAGE):local --build-arg ENVOY_VERSION=${ENVOY_VERSION} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - -.PHONY: test-compat-integ -test-compat-integ: test-compat-integ-setup ## Test compat integ -ifeq ("$(GOTESTSUM_PATH)","") - @cd ./test/integration/consul-container && \ - go test \ - -v \ - -timeout=30m \ - ./... \ - --tags $(GOTAGS) \ - --target-image $(CONSUL_COMPAT_TEST_IMAGE) \ - --target-version local \ - --latest-image $(CONSUL_COMPAT_TEST_IMAGE) \ - --latest-version latest -else - @cd ./test/integration/consul-container && \ - gotestsum \ - --format=short-verbose \ - --debug \ - --rerun-fails=3 \ - --packages="./..." \ - -- \ - --tags $(GOTAGS) \ - -timeout=30m \ - ./... \ - --target-image $(CONSUL_COMPAT_TEST_IMAGE) \ - --target-version local \ - --latest-image $(CONSUL_COMPAT_TEST_IMAGE) \ - --latest-version latest -endif +.PHONY: fmt/% +fmt/%: + @echo "--> Running go fmt ($*)" + @cd $* && gofmt -s -l -w . -.PHONY: test-metrics-integ -test-metrics-integ: test-compat-integ-setup ## Test metrics integ - @cd ./test/integration/consul-container && \ - go test -v -timeout=7m ./test/metrics \ - --target-image $(CONSUL_COMPAT_TEST_IMAGE) \ - --target-version local \ - --latest-image $(CONSUL_COMPAT_TEST_IMAGE) \ - --latest-version latest +.PHONY: lint +lint: $(foreach mod,$(GO_MODULES),lint/$(mod)) lint-container-test-deps -.PHONY: test-connect-ca-providers -test-connect-ca-providers: ## Running /agent/connect/ca tests in verbose mode - @echo "Running /agent/connect/ca tests in verbose mode" - @go test -v ./agent/connect/ca - @go test -v ./agent/consul -run Vault - @go test -v ./agent -run Vault +.PHONY: lint/% +lint/%: + @echo "--> Running golangci-lint ($*)" + @cd $* && GOWORK=off golangci-lint run --build-tags '$(GOTAGS)' + @echo "--> Running lint-consul-retry ($*)" + @cd $* && GOWORK=off lint-consul-retry + @echo "--> Running enumcover ($*)" + @cd $* && GOWORK=off enumcover ./... -##@ UI +.PHONY: lint-container-test-deps +lint-container-test-deps: + @echo "--> Checking container tests for bad dependencies" + @cd test/integration/consul-container && ( \ + found="$$(go list -m all | grep -c '^github.com/hashicorp/consul ')" ; \ + if [[ "$$found" != "0" ]]; then \ + echo "test/integration/consul-container: This project should not depend on the root consul module" >&2 ; \ + exit 1 ; \ + fi \ + ) -.PHONY: ui -ui: ui-docker ## Build the static web ui inside a Docker container. For local testing only; do not commit these assets. +# Build the static web ui inside a Docker container. For local testing only; do not commit these assets. +ui: ui-docker +# Build the static web ui with yarn. This is the version to commit. .PHONY: ui-regen -ui-regen: ## Build the static web ui with yarn. This is the version to commit. +ui-regen: cd $(CURDIR)/ui && make && cd .. rm -rf $(CURDIR)/agent/uiserver/dist mv $(CURDIR)/ui/packages/consul-ui/dist $(CURDIR)/agent/uiserver/ -.PHONY: ui-build-image -ui-build-image: ## Building UI build container - @echo "Building UI build container" - @docker build $(NOCACHE) $(QUIET) -t $(UI_BUILD_TAG) - < build-support/docker/Build-UI.dockerfile - -.PHONY: ui-docker -ui-docker: ui-build-image ## Builds ui within docker container and copy all the relevant artifacts out of the containers back to the source - @$(SHELL) $(CURDIR)/build-support/scripts/build-docker.sh ui - -##@ Tools - -.PHONY: tools -tools: ## Installs various supporting Go tools. +tools: @$(SHELL) $(CURDIR)/build-support/scripts/devtools.sh .PHONY: lint-tools -lint-tools: ## Install tools for linting +lint-tools: @$(SHELL) $(CURDIR)/build-support/scripts/devtools.sh -lint +.PHONY: proto-tools +proto-tools: + @$(SHELL) $(CURDIR)/build-support/scripts/devtools.sh -protobuf + .PHONY: codegen-tools -codegen-tools: ## Install tools for codegen +codegen-tools: @$(SHELL) $(CURDIR)/build-support/scripts/devtools.sh -codegen .PHONY: deep-copy -deep-copy: codegen-tools ## Deep copy +deep-copy: codegen-tools @$(SHELL) $(CURDIR)/agent/structs/deep-copy.sh @$(SHELL) $(CURDIR)/agent/proxycfg/deep-copy.sh @$(SHELL) $(CURDIR)/agent/consul/state/deep-copy.sh -print-% : ; @echo $($*) ## utility to echo a makefile variable (i.e. 'make print-GOPATH') - -.PHONY: module-versions -module-versions: ## Print a list of modules which can be updated. Columns are: module current_version date_of_current_version latest_version - @go list -m -u -f '{{if .Update}} {{printf "%-50v %-40s" .Path .Version}} {{with .Time}} {{ .Format "2006-01-02" -}} {{else}} {{printf "%9s" ""}} {{end}} {{ .Update.Version}} {{end}}' all - -.PHONY: docs -docs: ## Point your web browser to http://localhost:3000/consul to live render docs from ./website/ - make -C website - -##@ Release - -.PHONY: version -version: ## Current Consul version +version: @echo -n "Version: " @$(SHELL) $(CURDIR)/build-support/scripts/version.sh @echo -n "Version + release: " @@ -456,20 +403,26 @@ version: ## Current Consul version @echo -n "Version + release + git: " @$(SHELL) $(CURDIR)/build-support/scripts/version.sh -r -g -.PHONY: docker-images + docker-images: go-build-image ui-build-image -.PHONY: go-build-image -go-build-image: ## Building Golang build container +go-build-image: @echo "Building Golang build container" @docker build $(NOCACHE) $(QUIET) -t $(GO_BUILD_TAG) - < build-support/docker/Build-Go.dockerfile -.PHONY: consul-docker -consul-docker: go-build-image ## Builds consul in a docker container and then dumps executable into ./pkg/bin/... +ui-build-image: + @echo "Building UI build container" + @docker build $(NOCACHE) $(QUIET) -t $(UI_BUILD_TAG) - < build-support/docker/Build-UI.dockerfile + +# Builds consul in a docker container and then dumps executable into ./pkg/bin/... +consul-docker: go-build-image @$(SHELL) $(CURDIR)/build-support/scripts/build-docker.sh consul -.PHONY: docker-envoy-integ -docker-envoy-integ: ## Build image used to run integration tests locally. +ui-docker: ui-build-image + @$(SHELL) $(CURDIR)/build-support/scripts/build-docker.sh ui + +# Build image used to run integration tests locally. +docker-envoy-integ: $(MAKE) GOARCH=amd64 linux docker build \ --platform linux/amd64 $(NOCACHE) $(QUIET) \ @@ -478,21 +431,75 @@ docker-envoy-integ: ## Build image used to run integration tests locally. $(CURDIR)/pkg/bin/linux_amd64 \ -f $(CURDIR)/build-support/docker/Consul-Dev.dockerfile -##@ Proto +# Run integration tests. +# Use GO_TEST_FLAGS to run specific tests: +# make test-envoy-integ GO_TEST_FLAGS="-run TestEnvoy/case-basic" +# NOTE: Always uses amd64 images, even when running on M1 macs, to match CI/CD environment. +test-envoy-integ: $(ENVOY_INTEG_DEPS) + @go test -v -timeout=30m -tags integration $(GO_TEST_FLAGS) ./test/integration/connect/envoy -.PHONY: proto -proto: proto-tools proto-gen proto-mocks ## Protobuf setup command +.PHONY: test-compat-integ +test-compat-integ: test-compat-integ-setup +ifeq ("$(GOTESTSUM_PATH)","") + @cd ./test/integration/consul-container && \ + go test \ + -v \ + -timeout=30m \ + ./... \ + --tags $(GOTAGS) \ + --target-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --target-version local \ + --latest-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --latest-version latest +else + @cd ./test/integration/consul-container && \ + gotestsum \ + --format=short-verbose \ + --debug \ + --rerun-fails=3 \ + --packages="./..." \ + -- \ + --tags $(GOTAGS) \ + -timeout=30m \ + ./... \ + --target-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --target-version local \ + --latest-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --latest-version latest +endif -.PHONY: proto-tools -proto-tools: ## Install tools for protobuf - @$(SHELL) $(CURDIR)/build-support/scripts/devtools.sh -protobuf +# NOTE: Use DOCKER_BUILDKIT=0, if docker build fails to resolve consul:local base image +.PHONY: test-compat-integ-setup +test-compat-integ-setup: dev-docker + @docker tag consul-dev:latest $(CONSUL_COMPAT_TEST_IMAGE):local + @docker run --rm -t $(CONSUL_COMPAT_TEST_IMAGE):local consul version + @# 'consul-envoy:target-version' is needed by compatibility integ test + @docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=$(CONSUL_COMPAT_TEST_IMAGE):local --build-arg ENVOY_VERSION=${ENVOY_VERSION} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets + +.PHONY: test-metrics-integ +test-metrics-integ: test-compat-integ-setup + @cd ./test/integration/consul-container && \ + go test -v -timeout=7m ./test/metrics \ + --target-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --target-version local \ + --latest-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --latest-version latest + +test-connect-ca-providers: + @echo "Running /agent/connect/ca tests in verbose mode" + @go test -v ./agent/connect/ca + @go test -v ./agent/consul -run Vault + @go test -v ./agent -run Vault + +.PHONY: proto +proto: proto-tools proto-gen proto-mocks .PHONY: proto-gen -proto-gen: proto-tools ## Regenerates all Go files from protobuf definitions +proto-gen: proto-tools @$(SHELL) $(CURDIR)/build-support/scripts/protobuf.sh .PHONY: proto-mocks -proto-mocks: ## Proto mocks +proto-mocks: for dir in $(MOCKED_PB_DIRS) ; do \ cd proto-public && \ rm -f $$dir/mock*.go && \ @@ -500,11 +507,11 @@ proto-mocks: ## Proto mocks done .PHONY: proto-format -proto-format: proto-tools ## Proto format +proto-format: proto-tools @buf format -w .PHONY: proto-lint -proto-lint: proto-tools ## Proto lint +proto-lint: proto-tools @buf lint @for fn in $$(find proto -name '*.proto'); do \ if [[ "$$fn" = "proto/private/pbsubscribe/subscribe.proto" ]]; then \ @@ -519,14 +526,21 @@ proto-lint: proto-tools ## Proto lint fi \ done -##@ Envoy +# utility to echo a makefile variable (i.e. 'make print-PROTOC_VERSION') +print-% : ; @echo $($*) + +.PHONY: module-versions +# Print a list of modules which can be updated. +# Columns are: module current_version date_of_current_version latest_version +module-versions: + @go list -m -u -f '{{if .Update}} {{printf "%-50v %-40s" .Path .Version}} {{with .Time}} {{ .Format "2006-01-02" -}} {{else}} {{printf "%9s" ""}} {{end}} {{ .Update.Version}} {{end}}' all .PHONY: envoy-library -envoy-library: ## Ensures that all of the protobuf packages present in the github.com/envoyproxy/go-control-plane library are referenced in the consul codebase +envoy-library: @$(SHELL) $(CURDIR)/build-support/scripts/envoy-library-references.sh .PHONY: envoy-regen -envoy-regen: ## Regenerating envoy golden files +envoy-regen: $(info regenerating envoy golden files) @for d in endpoints listeners routes clusters rbac; do \ if [[ -d "agent/xds/testdata/$${d}" ]]; then \ @@ -537,18 +551,17 @@ envoy-regen: ## Regenerating envoy golden files @find "command/connect/envoy/testdata" -name '*.golden' -delete @go test -tags '$(GOTAGS)' ./command/connect/envoy -update -##@ Help - -# The help target prints out all targets with their descriptions organized -# beneath their categories. The categories are represented by '##@' and the -# target descriptions by '##'. The awk commands is responsible for reading the -# entire set of makefiles included in this invocation, looking for lines of the -# file as xyz: ## something, and then pretty-format the target and help. Then, -# if there's a line with ##@ something, that gets pretty-printed as a category. -# More info on the usage of ANSI control characters for terminal formatting: -# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters -# More info on the awk command: -# http://linuxcommand.org/lc3_adv_awk.php +# Point your web browser to http://localhost:3000/consul to live render docs from ./website/ +.PHONY: docs +docs: + make -C website + .PHONY: help -help: ## Display this help. - @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) +help: + $(info available make targets) + $(info ----------------------) + @grep "^[a-z0-9-][a-z0-9.-]*:" GNUmakefile | cut -d':' -f1 | sort + +.PHONY: all bin dev dist cov test test-internal cover lint ui tools +.PHONY: docker-images go-build-image ui-build-image consul-docker ui-docker +.PHONY: version test-envoy-integ diff --git a/LICENSE b/LICENSE index 1f38fcdd11e2d..c72625e4cc88b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,61 +1,356 @@ -License text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved. -“Business Source License” is a trademark of MariaDB Corporation Ab. - -Parameters - -Licensor: HashiCorp, Inc. -Licensed Work: Consul 1.17.0. The Licensed Work is (c) 2023 HashiCorp, Inc. -Additional Use Grant: You may make production use of the Licensed Work, - provided such use does not include offering the Licensed Work - to third parties on a hosted or embedded basis which is - competitive with HashiCorp's products. -Change Date: Four years from the date the Licensed Work is published. -Change License: MPL 2.0 - -For information about alternative licensing arrangements for the Licensed Work, -please contact licensing@hashicorp.com. - -Notice - -Business Source License 1.1 - -Terms - -The Licensor hereby grants you the right to copy, modify, create derivative -works, redistribute, and make non-production use of the Licensed Work. The -Licensor may make an Additional Use Grant, above, permitting limited production use. - -Effective on the Change Date, or the fourth anniversary of the first publicly -available distribution of a specific version of the Licensed Work under this -License, whichever comes first, the Licensor hereby grants you rights under -the terms of the Change License, and the rights granted in the paragraph -above terminate. - -If your use of the Licensed Work does not comply with the requirements -currently in effect as described in this License, you must purchase a -commercial license from the Licensor, its affiliated entities, or authorized -resellers, or you must refrain from using the Licensed Work. - -All copies of the original and modified Licensed Work, and derivative works -of the Licensed Work, are subject to this License. This License applies -separately for each version of the Licensed Work and the Change Date may vary -for each version of the Licensed Work released by Licensor. - -You must conspicuously display this License on each original or modified copy -of the Licensed Work. If you receive the Licensed Work in original or -modified form from a third party, the terms and conditions set forth in this -License apply to your use of that work. - -Any use of the Licensed Work in violation of this License will automatically -terminate your rights under this License for the current and all other -versions of the Licensed Work. - -This License does not grant you any right in any trademark or logo of -Licensor or its affiliates (provided that you may use a trademark or logo of -Licensor as expressly required by this License). - -TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON -AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, -EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND -TITLE. +Copyright (c) 2013 HashiCorp, Inc. + +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by + the Mozilla Public License, v. 2.0. + diff --git a/README.md b/README.md index 870e00f76c761..93e3176cc048a 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,7 @@ Consul provides several key features: discovery prevents routing traffic to unhealthy hosts and enables service level circuit breakers. -* **Dynamic App Configuration** - An HTTP API that allows users to store indexed objects within Consul, - for storing configuration parameters and application metadata. +* **Dynamic App Configuration** - An HTTP API that allows users to store indexed objects, like configuration parameters and application metadata, within Consul. Consul runs on Linux, macOS, FreeBSD, Solaris, and Windows and includes an optional [browser based UI](https://demo.consul.io). A commercial version diff --git a/acl/MockAuthorizer.go b/acl/MockAuthorizer.go index cabdf1b812435..01afb5fea6654 100644 --- a/acl/MockAuthorizer.go +++ b/acl/MockAuthorizer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/acl.go b/acl/acl.go index 753db01516e8c..75789dd17498c 100644 --- a/acl/acl.go +++ b/acl/acl.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/acl_ce.go b/acl/acl_ce.go index 76e77f3b8f46c..58f92022ba55b 100644 --- a/acl/acl_ce.go +++ b/acl/acl_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/acl/acl_test.go b/acl/acl_test.go index de95e91f1264c..3734eb1572fd3 100644 --- a/acl/acl_test.go +++ b/acl/acl_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/authorizer.go b/acl/authorizer.go index 21a7dbc80170e..f4515f11c92ac 100644 --- a/acl/authorizer.go +++ b/acl/authorizer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/authorizer_ce.go b/acl/authorizer_ce.go index 06ec22dae7b43..ed77d5e81d3f7 100644 --- a/acl/authorizer_ce.go +++ b/acl/authorizer_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/acl/authorizer_test.go b/acl/authorizer_test.go index 09cba85fa6b5f..20774841ba8dc 100644 --- a/acl/authorizer_test.go +++ b/acl/authorizer_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/chained_authorizer.go b/acl/chained_authorizer.go index 333ad7e90fd0c..9a681187bc1ed 100644 --- a/acl/chained_authorizer.go +++ b/acl/chained_authorizer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/chained_authorizer_test.go b/acl/chained_authorizer_test.go index a198ab67788b3..c17cbc907bf50 100644 --- a/acl/chained_authorizer_test.go +++ b/acl/chained_authorizer_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/enterprisemeta_ce.go b/acl/enterprisemeta_ce.go index 791776e09b137..8b93fd6807968 100644 --- a/acl/enterprisemeta_ce.go +++ b/acl/enterprisemeta_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/acl/errors.go b/acl/errors.go index 7f4548ed95d62..7302e0392f178 100644 --- a/acl/errors.go +++ b/acl/errors.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/errors_ce.go b/acl/errors_ce.go index 57b0eb32479d9..8c2e84ac5c415 100644 --- a/acl/errors_ce.go +++ b/acl/errors_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/acl/errors_test.go b/acl/errors_test.go index b4e645c073122..4988f695994f6 100644 --- a/acl/errors_test.go +++ b/acl/errors_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/policy.go b/acl/policy.go index ef821563b0ad7..e26c8871314c3 100644 --- a/acl/policy.go +++ b/acl/policy.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/policy_authorizer.go b/acl/policy_authorizer.go index 9043dc40cdbf0..e87635a036df1 100644 --- a/acl/policy_authorizer.go +++ b/acl/policy_authorizer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/policy_authorizer_ce.go b/acl/policy_authorizer_ce.go index ccdb2e758557b..89708a5be9c31 100644 --- a/acl/policy_authorizer_ce.go +++ b/acl/policy_authorizer_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/acl/policy_authorizer_test.go b/acl/policy_authorizer_test.go index d144bc8d8cce3..1c6959527899d 100644 --- a/acl/policy_authorizer_test.go +++ b/acl/policy_authorizer_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/policy_ce.go b/acl/policy_ce.go index ed7eed9917cef..b33c3243364ba 100644 --- a/acl/policy_ce.go +++ b/acl/policy_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/acl/policy_merger.go b/acl/policy_merger.go index 7707c4f9a51e2..df065a9cb1b95 100644 --- a/acl/policy_merger.go +++ b/acl/policy_merger.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/policy_merger_ce.go b/acl/policy_merger_ce.go index 207051f3482ab..b221f25875399 100644 --- a/acl/policy_merger_ce.go +++ b/acl/policy_merger_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/acl/policy_test.go b/acl/policy_test.go index 2ce0b32892fbe..ac23e3c0df3b0 100644 --- a/acl/policy_test.go +++ b/acl/policy_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/resolver/danger.go b/acl/resolver/danger.go index c2ae1a3c40c7a..a72efa9278449 100644 --- a/acl/resolver/danger.go +++ b/acl/resolver/danger.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resolver diff --git a/acl/resolver/result.go b/acl/resolver/result.go index 1e52b1c573168..190d15eca5b8a 100644 --- a/acl/resolver/result.go +++ b/acl/resolver/result.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resolver diff --git a/acl/static_authorizer.go b/acl/static_authorizer.go index 2b62320b0a11c..a6678925695c9 100644 --- a/acl/static_authorizer.go +++ b/acl/static_authorizer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/static_authorizer_test.go b/acl/static_authorizer_test.go index cdaf91ef71020..e94ac44e500f0 100644 --- a/acl/static_authorizer_test.go +++ b/acl/static_authorizer_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/testing.go b/acl/testing.go index ef4d0343c6b9e..1c67458b174f8 100644 --- a/acl/testing.go +++ b/acl/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/validation.go b/acl/validation.go index c0017effa15d7..96119dcc0fbaa 100644 --- a/acl/validation.go +++ b/acl/validation.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/acl/validation_test.go b/acl/validation_test.go index 3bf14719b12ae..d5d01e0e9054e 100644 --- a/acl/validation_test.go +++ b/acl/validation_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/agent/acl.go b/agent/acl.go index 0f64ee62c79e9..381f2c028e4fc 100644 --- a/agent/acl.go +++ b/agent/acl.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/acl_ce.go b/agent/acl_ce.go index 32d076fe1ed16..aa505da1ef49b 100644 --- a/agent/acl_ce.go +++ b/agent/acl_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/acl_endpoint.go b/agent/acl_endpoint.go index 9f38f41f15dbd..3a52b0cf54413 100644 --- a/agent/acl_endpoint.go +++ b/agent/acl_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent @@ -294,6 +294,7 @@ func (s *HTTPHandlers) ACLTokenList(resp http.ResponseWriter, req *http.Request) args.Policy = req.URL.Query().Get("policy") args.Role = req.URL.Query().Get("role") args.AuthMethod = req.URL.Query().Get("authmethod") + args.ServiceName = req.URL.Query().Get("servicename") if err := parseACLAuthMethodEnterpriseMeta(req, &args.ACLAuthMethodEnterpriseMeta); err != nil { return nil, err } diff --git a/agent/acl_endpoint_test.go b/agent/acl_endpoint_test.go index 82b2a9574fcfe..68d1888ff6668 100644 --- a/agent/acl_endpoint_test.go +++ b/agent/acl_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent @@ -1328,6 +1328,38 @@ func TestACL_HTTP(t *testing.T) { require.Error(t, err) testutil.RequireErrorContains(t, err, "Only lowercase alphanumeric") }) + + t.Run("Create with valid service identity", func(t *testing.T) { + tokenInput := &structs.ACLToken{ + Description: "token for service identity sn1", + ServiceIdentities: []*structs.ACLServiceIdentity{ + { + ServiceName: "sn1", + }, + }, + } + + req, _ := http.NewRequest("PUT", "/v1/acl/token", jsonBody(tokenInput)) + req.Header.Add("X-Consul-Token", "root") + resp := httptest.NewRecorder() + _, err := a.srv.ACLTokenCreate(resp, req) + require.NoError(t, err) + }) + + t.Run("List by ServiceName", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/acl/tokens?servicename=sn1", nil) + req.Header.Add("X-Consul-Token", "root") + resp := httptest.NewRecorder() + raw, err := a.srv.ACLTokenList(resp, req) + require.NoError(t, err) + tokens, ok := raw.(structs.ACLTokenListStubs) + require.True(t, ok) + require.Len(t, tokens, 1) + token := tokens[0] + require.Equal(t, "token for service identity sn1", token.Description) + require.Len(t, token.ServiceIdentities, 1) + require.Equal(t, "sn1", token.ServiceIdentities[0].ServiceName) + }) }) } diff --git a/agent/acl_test.go b/agent/acl_test.go index 0958db8db6fb0..40662231ac367 100644 --- a/agent/acl_test.go +++ b/agent/acl_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent @@ -22,7 +22,6 @@ import ( "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/lib" - "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/types" @@ -164,9 +163,6 @@ func (a *TestACLAgent) Stats() map[string]map[string]string { func (a *TestACLAgent) ReloadConfig(_ consul.ReloadableConfig) error { return fmt.Errorf("Unimplemented") } -func (a *TestACLAgent) ResourceServiceClient() pbresource.ResourceServiceClient { - return nil -} func TestACL_Version8EnabledByDefault(t *testing.T) { t.Parallel() diff --git a/agent/ae/ae.go b/agent/ae/ae.go index 65b38e00e4b4c..8c4d8c9972966 100644 --- a/agent/ae/ae.go +++ b/agent/ae/ae.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package ae provides tools to synchronize state between local and remote consul servers. package ae diff --git a/agent/ae/ae_test.go b/agent/ae/ae_test.go index 9e9593f4f92d2..873cd4128db34 100644 --- a/agent/ae/ae_test.go +++ b/agent/ae/ae_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ae diff --git a/agent/ae/trigger.go b/agent/ae/trigger.go index 29bdd988907eb..a320bda526d1f 100644 --- a/agent/ae/trigger.go +++ b/agent/ae/trigger.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ae diff --git a/agent/agent.go b/agent/agent.go index d8eb4cd8fa136..a4c231a2512c7 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent @@ -65,15 +65,12 @@ import ( "github.com/hashicorp/consul/agent/xds" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/api/watch" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/file" "github.com/hashicorp/consul/lib/mutex" "github.com/hashicorp/consul/lib/routine" - "github.com/hashicorp/consul/lib/stringslice" "github.com/hashicorp/consul/logging" - "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/proto/private/pboperator" "github.com/hashicorp/consul/proto/private/pbpeering" "github.com/hashicorp/consul/tlsutil" @@ -201,9 +198,6 @@ type delegate interface { RPC(ctx context.Context, method string, args interface{}, reply interface{}) error - // ResourceServiceClient is a client for the gRPC Resource Service. - ResourceServiceClient() pbresource.ResourceServiceClient - SnapshotRPC(args *structs.SnapshotRequest, in io.Reader, out io.Writer, replyFn structs.SnapshotReplyFn) error Shutdown() error Stats() map[string]map[string]string @@ -653,47 +647,6 @@ func (a *Agent) Start(ctx context.Context) error { return fmt.Errorf("failed to start Consul enterprise component: %v", err) } - // Create proxy config manager now because it is a dependency of creating the proxyWatcher - // which will be passed to consul.NewServer so that it is then passed to the - // controller registration for the XDS controller in v2 mode, and the xds server in v1 and v2 mode. - var intentionDefaultAllow bool - switch a.config.ACLResolverSettings.ACLDefaultPolicy { - case "allow": - intentionDefaultAllow = true - case "deny": - intentionDefaultAllow = false - default: - return fmt.Errorf("unexpected ACL default policy value of %q", a.config.ACLResolverSettings.ACLDefaultPolicy) - } - - go a.baseDeps.ViewStore.Run(&lib.StopChannelContext{StopCh: a.shutdownCh}) - - // Start the proxy config manager. - a.proxyConfig, err = proxycfg.NewManager(proxycfg.ManagerConfig{ - DataSources: a.proxyDataSources(), - Logger: a.logger.Named(logging.ProxyConfig), - Source: &structs.QuerySource{ - Datacenter: a.config.Datacenter, - Segment: a.config.SegmentName, - Node: a.config.NodeName, - NodePartition: a.config.PartitionOrEmpty(), - }, - DNSConfig: proxycfg.DNSConfig{ - Domain: a.config.DNSDomain, - AltDomain: a.config.DNSAltDomain, - }, - TLSConfigurator: a.tlsConfigurator, - IntentionDefaultAllow: intentionDefaultAllow, - UpdateRateLimit: a.config.XDSUpdateRateLimit, - }) - if err != nil { - return err - } - - // proxyWatcher will be used in the creation of the XDS server and also - // in the registration of the xds controller. - proxyWatcher := a.getProxyWatcher() - // Setup either the client or the server. if c.ServerMode { serverLogger := a.baseDeps.Logger.NamedIntercept(logging.ConsulServer) @@ -727,11 +680,7 @@ func (a *Agent) Start(ctx context.Context) error { incomingRPCLimiter, ) - var pt *proxytracker.ProxyTracker - if a.useV2Resources() { - pt = proxyWatcher.(*proxytracker.ProxyTracker) - } - server, err := consul.NewServer(consulCfg, a.baseDeps.Deps, a.externalGRPCServer, incomingRPCLimiter, serverLogger, pt) + server, err := consul.NewServer(consulCfg, a.baseDeps.Deps, a.externalGRPCServer, incomingRPCLimiter, serverLogger) if err != nil { return fmt.Errorf("Failed to start Consul server: %v", err) } @@ -798,6 +747,40 @@ func (a *Agent) Start(ctx context.Context) error { return err } + var intentionDefaultAllow bool + switch a.config.ACLResolverSettings.ACLDefaultPolicy { + case "allow": + intentionDefaultAllow = true + case "deny": + intentionDefaultAllow = false + default: + return fmt.Errorf("unexpected ACL default policy value of %q", a.config.ACLResolverSettings.ACLDefaultPolicy) + } + + go a.baseDeps.ViewStore.Run(&lib.StopChannelContext{StopCh: a.shutdownCh}) + + // Start the proxy config manager. + a.proxyConfig, err = proxycfg.NewManager(proxycfg.ManagerConfig{ + DataSources: a.proxyDataSources(), + Logger: a.logger.Named(logging.ProxyConfig), + Source: &structs.QuerySource{ + Datacenter: a.config.Datacenter, + Segment: a.config.SegmentName, + Node: a.config.NodeName, + NodePartition: a.config.PartitionOrEmpty(), + }, + DNSConfig: proxycfg.DNSConfig{ + Domain: a.config.DNSDomain, + AltDomain: a.config.DNSAltDomain, + }, + TLSConfigurator: a.tlsConfigurator, + IntentionDefaultAllow: intentionDefaultAllow, + UpdateRateLimit: a.config.XDSUpdateRateLimit, + }) + if err != nil { + return err + } + go localproxycfg.Sync( &lib.StopChannelContext{StopCh: a.shutdownCh}, localproxycfg.SyncConfig{ @@ -850,7 +833,7 @@ func (a *Agent) Start(ctx context.Context) error { } // Start grpc and grpc_tls servers. - if err := a.listenAndServeGRPC(proxyWatcher); err != nil { + if err := a.listenAndServeGRPC(); err != nil { return err } @@ -921,42 +904,18 @@ func (a *Agent) Failed() <-chan struct{} { return a.apiServers.failed } -// useV2Resources returns true if "resource-apis" is present in the Experiments -// array of the agent config. -func (a *Agent) useV2Resources() bool { - if stringslice.Contains(a.baseDeps.Experiments, consul.CatalogResourceExperimentName) { - return true - } - return false -} - -// getProxyWatcher returns the proper implementation of the ProxyWatcher interface. -// It will return a ProxyTracker if "resource-apis" experiment is active. Otherwise, -// it will return a ConfigSource. -func (a *Agent) getProxyWatcher() xds.ProxyWatcher { - if a.useV2Resources() { - a.logger.Trace("returning proxyTracker for getProxyWatcher") - return proxytracker.NewProxyTracker(proxytracker.ProxyTrackerConfig{ - Logger: a.logger.Named("proxy-tracker"), - SessionLimiter: a.baseDeps.XDSStreamLimiter, - }) - } else { - a.logger.Trace("returning configSource for getProxyWatcher") - return localproxycfg.NewConfigSource(a.proxyConfig) +func (a *Agent) listenAndServeGRPC() error { + if len(a.config.GRPCAddrs) < 1 && len(a.config.GRPCTLSAddrs) < 1 { + return nil } -} - -// configureXDSServer configures an XDS server with the proper implementation of -// the PRoxyWatcher interface and registers the XDS server with Consul's -// external facing GRPC server. -func (a *Agent) configureXDSServer(proxyWatcher xds.ProxyWatcher) { // TODO(agentless): rather than asserting the concrete type of delegate, we // should add a method to the Delegate interface to build a ConfigSource. + var cfg xds.ProxyConfigSource = localproxycfg.NewConfigSource(a.proxyConfig) if server, ok := a.delegate.(*consul.Server); ok { catalogCfg := catalogproxycfg.NewConfigSource(catalogproxycfg.Config{ NodeName: a.config.NodeName, LocalState: a.State, - LocalConfigSource: proxyWatcher, + LocalConfigSource: cfg, Manager: a.proxyConfig, GetStore: func() catalogproxycfg.Store { return server.FSM().State() }, Logger: a.proxyConfig.Logger.Named("server-catalog"), @@ -966,26 +925,18 @@ func (a *Agent) configureXDSServer(proxyWatcher xds.ProxyWatcher) { <-a.shutdownCh catalogCfg.Shutdown() }() - proxyWatcher = catalogCfg + cfg = catalogCfg } a.xdsServer = xds.NewServer( a.config.NodeName, a.logger.Named(logging.Envoy), - proxyWatcher, + cfg, func(id string) (acl.Authorizer, error) { return a.delegate.ResolveTokenAndDefaultMeta(id, nil, nil) }, a, ) a.xdsServer.Register(a.externalGRPCServer) -} - -func (a *Agent) listenAndServeGRPC(proxyWatcher xds.ProxyWatcher) error { - if len(a.config.GRPCAddrs) < 1 && len(a.config.GRPCTLSAddrs) < 1 { - return nil - } - - a.configureXDSServer(proxyWatcher) // Attempt to spawn listeners var listeners []net.Listener @@ -3066,14 +3017,20 @@ func (a *Agent) addCheck(check *structs.HealthCheck, chkType *structs.CheckType, chkType.Interval = checks.MinInterval } + var tlsClientConfig *tls.Config + if chkType.TCPUseTLS { + tlsClientConfig = a.tlsConfigurator.OutgoingTLSConfigForCheck(chkType.TLSSkipVerify, chkType.TLSServerName) + } + tcp := &checks.CheckTCP{ - CheckID: cid, - ServiceID: sid, - TCP: chkType.TCP, - Interval: chkType.Interval, - Timeout: chkType.Timeout, - Logger: a.logger, - StatusHandler: statusHandler, + CheckID: cid, + ServiceID: sid, + TCP: chkType.TCP, + Interval: chkType.Interval, + Timeout: chkType.Timeout, + Logger: a.logger, + TLSClientConfig: tlsClientConfig, + StatusHandler: statusHandler, } tcp.Start() a.checkTCPs[cid] = tcp @@ -4617,7 +4574,7 @@ func (a *Agent) proxyDataSources() proxycfg.DataSources { // interact with ACLs and the streaming backend. See comments in `proxycfgglue.ServerHealthBlocking` // for more details. // sources.Health = proxycfgglue.ServerHealth(deps, proxycfgglue.ClientHealth(a.rpcClientHealth)) - sources.Health = proxycfgglue.ServerHealthBlocking(deps, proxycfgglue.ClientHealth(a.rpcClientHealth), server.FSM().State()) + sources.Health = proxycfgglue.ServerHealthBlocking(deps, proxycfgglue.ClientHealth(a.rpcClientHealth)) sources.HTTPChecks = proxycfgglue.ServerHTTPChecks(deps, a.config.NodeName, proxycfgglue.CacheHTTPChecks(a.cache), a.State) sources.Intentions = proxycfgglue.ServerIntentions(deps) sources.IntentionUpstreams = proxycfgglue.ServerIntentionUpstreams(deps) diff --git a/agent/agent_ce.go b/agent/agent_ce.go index 37a1804fe2706..e8cfea681b3cb 100644 --- a/agent/agent_ce.go +++ b/agent/agent_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/agent_ce_test.go b/agent/agent_ce_test.go index 07882c7b1eed9..ceb90beb0634c 100644 --- a/agent/agent_ce_test.go +++ b/agent/agent_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/agent_endpoint.go b/agent/agent_endpoint.go index 96857409ce777..23bfa49c88444 100644 --- a/agent/agent_endpoint.go +++ b/agent/agent_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent @@ -11,12 +11,16 @@ import ( "strings" "time" - "github.com/hashicorp/go-bexpr" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-memdb" + "github.com/mitchellh/hashstructure" + + "github.com/hashicorp/consul/envoyextensions/xdscommon" + "github.com/hashicorp/consul/version" + + "github.com/hashicorp/go-bexpr" "github.com/hashicorp/serf/coordinate" "github.com/hashicorp/serf/serf" - "github.com/mitchellh/hashstructure" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -28,13 +32,11 @@ import ( "github.com/hashicorp/consul/agent/structs" token_store "github.com/hashicorp/consul/agent/token" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/logging/monitor" "github.com/hashicorp/consul/types" - "github.com/hashicorp/consul/version" ) type Self struct { diff --git a/agent/agent_endpoint_ce.go b/agent/agent_endpoint_ce.go index cf2984ab5f1d3..48b9c439cac47 100644 --- a/agent/agent_endpoint_ce.go +++ b/agent/agent_endpoint_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/agent_endpoint_ce_test.go b/agent/agent_endpoint_ce_test.go index 6608f40f40417..763a5a006049c 100644 --- a/agent/agent_endpoint_ce_test.go +++ b/agent/agent_endpoint_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/agent_endpoint_test.go b/agent/agent_endpoint_test.go index 32516a76cb464..0a37ae174a190 100644 --- a/agent/agent_endpoint_test.go +++ b/agent/agent_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent @@ -21,6 +21,10 @@ import ( "time" "github.com/armon/go-metrics" + + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/version" + "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-uuid" "github.com/hashicorp/serf/serf" @@ -40,14 +44,12 @@ import ( "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/token" tokenStore "github.com/hashicorp/consul/agent/token" - "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/testrpc" "github.com/hashicorp/consul/types" - "github.com/hashicorp/consul/version" ) func createACLTokenWithAgentReadPolicy(t *testing.T, srv *HTTPHandlers) string { @@ -1601,37 +1603,14 @@ func TestAgent_Metrics_ACLDeny(t *testing.T) { }) } -func newDefaultBaseDeps(t *testing.T) BaseDeps { - dataDir := testutil.TempDir(t, "acl-agent") - logBuffer := testutil.NewLogBuffer(t) - logger := hclog.NewInterceptLogger(nil) - loader := func(source config.Source) (config.LoadResult, error) { - dataDir := fmt.Sprintf(`data_dir = "%s"`, dataDir) - opts := config.LoadOpts{ - HCL: []string{TestConfigHCL(NodeID()), "", dataDir}, - DefaultConfig: source, - } - result, err := config.Load(opts) - if result.RuntimeConfig != nil { - result.RuntimeConfig.Telemetry.Disable = true - } - return result, err - } - bd, err := NewBaseDeps(loader, logBuffer, logger) - require.NoError(t, err) - return bd -} - func TestHTTPHandlers_AgentMetricsStream_ACLDeny(t *testing.T) { - bd := newDefaultBaseDeps(t) + bd := BaseDeps{} bd.Tokens = new(tokenStore.Store) sink := metrics.NewInmemSink(30*time.Millisecond, time.Second) bd.MetricsConfig = &lib.MetricsConfig{ Handler: sink, } - mockDelegate := delegateMock{} - mockDelegate.On("LicenseCheck").Return() - d := fakeResolveTokenDelegate{delegate: &mockDelegate, authorizer: acl.DenyAll()} + d := fakeResolveTokenDelegate{authorizer: acl.DenyAll()} agent := &Agent{ baseDeps: bd, delegate: d, @@ -1654,15 +1633,13 @@ func TestHTTPHandlers_AgentMetricsStream_ACLDeny(t *testing.T) { } func TestHTTPHandlers_AgentMetricsStream(t *testing.T) { - bd := newDefaultBaseDeps(t) + bd := BaseDeps{} bd.Tokens = new(tokenStore.Store) sink := metrics.NewInmemSink(20*time.Millisecond, time.Second) bd.MetricsConfig = &lib.MetricsConfig{ Handler: sink, } - mockDelegate := delegateMock{} - mockDelegate.On("LicenseCheck").Return() - d := fakeResolveTokenDelegate{delegate: &mockDelegate, authorizer: acl.ManageAll()} + d := fakeResolveTokenDelegate{authorizer: acl.ManageAll()} agent := &Agent{ baseDeps: bd, delegate: d, diff --git a/agent/agent_test.go b/agent/agent_test.go index c597f1d5d575c..e952d9dd87a19 100644 --- a/agent/agent_test.go +++ b/agent/agent_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent @@ -14,11 +14,7 @@ import ( "encoding/json" "errors" "fmt" - "github.com/hashicorp/consul/agent/grpc-external/limiter" - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/proxycfg-sources/local" - "github.com/hashicorp/consul/agent/xds" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" + "io" mathrand "math/rand" "net" "net/http" @@ -27,7 +23,6 @@ import ( "os" "path" "path/filepath" - "reflect" "strconv" "strings" "sync" @@ -63,7 +58,6 @@ import ( "github.com/hashicorp/consul/agent/token" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/internal/go-sso/oidcauth/oidcauthtest" - "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/proto/private/pbautoconf" @@ -329,7 +323,6 @@ func TestAgent_HTTPMaxHeaderBytes(t *testing.T) { Tokens: new(token.Store), TLSConfigurator: tlsConf, GRPCConnPool: &fakeGRPCConnPool{}, - Registry: resource.NewRegistry(), }, RuntimeConfig: &config.RuntimeConfig{ HTTPAddrs: []net.Addr{ @@ -352,9 +345,6 @@ func TestAgent_HTTPMaxHeaderBytes(t *testing.T) { require.NoError(t, err) a, err := New(bd) - mockDelegate := delegateMock{} - mockDelegate.On("LicenseCheck").Return() - a.delegate = &mockDelegate require.NoError(t, err) a.startLicenseManager(testutil.TestContext(t)) @@ -973,6 +963,80 @@ func TestAgent_AddServiceWithH2CPINGCheck(t *testing.T) { requireCheckExists(t, a, "test-h2cping-check") } +func startMockTLSServer(t *testing.T) (addr string, closeFunc func() error) { + // Load certificates + cert, err := tls.LoadX509KeyPair("../test/key/ourdomain_server.cer", "../test/key/ourdomain_server.key") + require.NoError(t, err) + // Create a certificate pool + rootCertPool := x509.NewCertPool() + caCert, err := os.ReadFile("../test/ca/root.cer") + require.NoError(t, err) + rootCertPool.AppendCertsFromPEM(caCert) + // Configure TLS + config := &tls.Config{ + Certificates: []tls.Certificate{cert}, + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: rootCertPool, + } + // Start TLS server + ln, err := tls.Listen("tcp", "127.0.0.1:0", config) + require.NoError(t, err) + go func() { + for { + conn, err := ln.Accept() + if err != nil { + return + } + io.Copy(io.Discard, conn) + conn.Close() + } + }() + return ln.Addr().String(), ln.Close +} + +func TestAgent_AddServiceWithTCPTLSCheck(t *testing.T) { + t.Parallel() + dataDir := testutil.TempDir(t, "agent") + a := NewTestAgent(t, ` + data_dir = "`+dataDir+`" + enable_agent_tls_for_checks = true + datacenter = "dc1" + tls { + defaults { + ca_file = "../test/ca/root.cer" + cert_file = "../test/key/ourdomain_server.cer" + key_file = "../test/key/ourdomain_server.key" + } + } + `) + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + // Start mock TCP+TLS server + addr, closeServer := startMockTLSServer(t) + defer closeServer() + check := &structs.HealthCheck{ + Node: "foo", + CheckID: "arbitraryTCPServerTLSCheck", + Name: "arbitraryTCPServerTLSCheck", + Status: api.HealthCritical, + } + chkType := &structs.CheckType{ + TCP: addr, + TCPUseTLS: true, + TLSServerName: "server.dc1.consul", + Interval: 5 * time.Second, + } + err := a.AddCheck(check, chkType, false, "", ConfigSourceLocal) + require.NoError(t, err) + // Retry until the healthcheck is passing. + retry.Run(t, func(r *retry.R) { + status := getCheck(a, "arbitraryTCPServerTLSCheck") + if status.Status != api.HealthPassing { + r.Fatalf("bad: %v", status.Status) + } + }) +} + func TestAgent_AddServiceNoExec(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") @@ -4308,7 +4372,7 @@ func TestAgent_consulConfig_RequestLimits(t *testing.T) { t.Parallel() hcl := ` - limits { + limits { request_limits { mode = "enforcing" read_rate = 8888 @@ -5488,7 +5552,6 @@ func TestAgent_ListenHTTP_MultipleAddresses(t *testing.T) { Tokens: new(token.Store), TLSConfigurator: tlsConf, GRPCConnPool: &fakeGRPCConnPool{}, - Registry: resource.NewRegistry(), }, RuntimeConfig: &config.RuntimeConfig{ HTTPAddrs: []net.Addr{ @@ -5511,9 +5574,6 @@ func TestAgent_ListenHTTP_MultipleAddresses(t *testing.T) { require.NoError(t, err) agent, err := New(bd) - mockDelegate := delegateMock{} - mockDelegate.On("LicenseCheck").Return() - agent.delegate = &mockDelegate require.NoError(t, err) agent.startLicenseManager(testutil.TestContext(t)) @@ -6088,7 +6148,6 @@ func TestAgent_startListeners(t *testing.T) { Logger: hclog.NewInterceptLogger(nil), Tokens: new(token.Store), GRPCConnPool: &fakeGRPCConnPool{}, - Registry: resource.NewRegistry(), }, RuntimeConfig: &config.RuntimeConfig{ HTTPAddrs: []net.Addr{}, @@ -6107,9 +6166,6 @@ func TestAgent_startListeners(t *testing.T) { require.NoError(t, err) agent, err := New(bd) - mockDelegate := delegateMock{} - mockDelegate.On("LicenseCheck").Return() - agent.delegate = &mockDelegate require.NoError(t, err) // use up an address @@ -6232,7 +6288,6 @@ func TestAgent_startListeners_scada(t *testing.T) { HCP: hcp.Deps{ Provider: pvd, }, - Registry: resource.NewRegistry(), }, RuntimeConfig: &config.RuntimeConfig{}, Cache: cache.New(cache.Options{}), @@ -6250,9 +6305,6 @@ func TestAgent_startListeners_scada(t *testing.T) { require.NoError(t, err) agent, err := New(bd) - mockDelegate := delegateMock{} - mockDelegate.On("LicenseCheck").Return() - agent.delegate = &mockDelegate require.NoError(t, err) _, err = agent.startListeners([]net.Addr{c}) @@ -6278,7 +6330,7 @@ func TestAgent_scadaProvider(t *testing.T) { }, Overrides: ` cloud { - resource_id = "organization/0b9de9a3-8403-4ca6-aba8-fca752f42100/project/0b9de9a3-8403-4ca6-aba8-fca752f42100/consul.cluster/0b9de9a3-8403-4ca6-aba8-fca752f42100" + resource_id = "organization/0b9de9a3-8403-4ca6-aba8-fca752f42100/project/0b9de9a3-8403-4ca6-aba8-fca752f42100/consul.cluster/0b9de9a3-8403-4ca6-aba8-fca752f42100" client_id = "test" client_secret = "test" }`, @@ -6296,7 +6348,6 @@ func TestAgent_checkServerLastSeen(t *testing.T) { Logger: hclog.NewInterceptLogger(nil), Tokens: new(token.Store), GRPCConnPool: &fakeGRPCConnPool{}, - Registry: resource.NewRegistry(), }, RuntimeConfig: &config.RuntimeConfig{}, Cache: cache.New(cache.Options{}), @@ -6308,9 +6359,6 @@ func TestAgent_checkServerLastSeen(t *testing.T) { Config: leafcert.Config{}, }) agent, err := New(bd) - mockDelegate := delegateMock{} - mockDelegate.On("LicenseCheck").Return() - agent.delegate = &mockDelegate require.NoError(t, err) // Test that an ErrNotExist OS error is treated as ok. @@ -6364,73 +6412,6 @@ func TestAgent_checkServerLastSeen(t *testing.T) { }) } -func TestAgent_getProxyWatcher(t *testing.T) { - type testcase struct { - description string - getExperiments func() []string - expectedType xds.ProxyWatcher - } - testscases := []testcase{ - { - description: "config source is returned when api-resources experiment is not configured", - expectedType: &local.ConfigSource{}, - getExperiments: func() []string { - return []string{} - }, - }, - { - description: "proxy tracker is returned when api-resources experiment is configured", - expectedType: &proxytracker.ProxyTracker{}, - getExperiments: func() []string { - return []string{consul.CatalogResourceExperimentName} - }, - }, - } - for _, tc := range testscases { - caConfig := tlsutil.Config{} - tlsConf, err := tlsutil.NewConfigurator(caConfig, hclog.New(nil)) - require.NoError(t, err) - - bd := BaseDeps{ - Deps: consul.Deps{ - Logger: hclog.NewInterceptLogger(nil), - Tokens: new(token.Store), - TLSConfigurator: tlsConf, - GRPCConnPool: &fakeGRPCConnPool{}, - Registry: resource.NewRegistry(), - }, - RuntimeConfig: &config.RuntimeConfig{ - HTTPAddrs: []net.Addr{ - &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: freeport.GetOne(t)}, - }, - }, - Cache: cache.New(cache.Options{}), - NetRPC: &LazyNetRPC{}, - } - - bd.XDSStreamLimiter = limiter.NewSessionLimiter() - bd.LeafCertManager = leafcert.NewManager(leafcert.Deps{ - CertSigner: leafcert.NewNetRPCCertSigner(bd.NetRPC), - RootsReader: leafcert.NewCachedRootsReader(bd.Cache, "dc1"), - Config: leafcert.Config{}, - }) - - cfg := config.RuntimeConfig{ - BuildDate: time.Date(2000, 1, 1, 0, 0, 1, 0, time.UTC), - } - bd, err = initEnterpriseBaseDeps(bd, &cfg) - require.NoError(t, err) - - bd.Experiments = tc.getExperiments() - - agent, err := New(bd) - require.NoError(t, err) - agent.proxyConfig, err = proxycfg.NewManager(proxycfg.ManagerConfig{Logger: bd.Logger, Source: &structs.QuerySource{}}) - require.NoError(t, err) - require.IsTypef(t, tc.expectedType, agent.getProxyWatcher(), fmt.Sprintf("Expected proxyWatcher to be of type %s", reflect.TypeOf(tc.expectedType))) - } - -} func getExpectedCaPoolByFile(t *testing.T) *x509.CertPool { pool := x509.NewCertPool() data, err := os.ReadFile("../test/ca/root.cer") diff --git a/agent/apiserver.go b/agent/apiserver.go index 1f386e3f6b171..a45e16a630b1a 100644 --- a/agent/apiserver.go +++ b/agent/apiserver.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/apiserver_test.go b/agent/apiserver_test.go index 848487a78154c..69188c4248176 100644 --- a/agent/apiserver_test.go +++ b/agent/apiserver_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/auto-config/auto_config.go b/agent/auto-config/auto_config.go index a1a5848f623f0..b73951df70d18 100644 --- a/agent/auto-config/auto_config.go +++ b/agent/auto-config/auto_config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autoconf diff --git a/agent/auto-config/auto_config_ce.go b/agent/auto-config/auto_config_ce.go index 5e5d799634637..78c9ee66d97ba 100644 --- a/agent/auto-config/auto_config_ce.go +++ b/agent/auto-config/auto_config_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/auto-config/auto_config_ce_test.go b/agent/auto-config/auto_config_ce_test.go index ff7cbf7472f49..b075ca7686b6e 100644 --- a/agent/auto-config/auto_config_ce_test.go +++ b/agent/auto-config/auto_config_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/auto-config/auto_config_test.go b/agent/auto-config/auto_config_test.go index 7c5c629be2f73..a5ab97e0f45d7 100644 --- a/agent/auto-config/auto_config_test.go +++ b/agent/auto-config/auto_config_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autoconf diff --git a/agent/auto-config/auto_encrypt.go b/agent/auto-config/auto_encrypt.go index 1b77c089f6f60..59af662ee033f 100644 --- a/agent/auto-config/auto_encrypt.go +++ b/agent/auto-config/auto_encrypt.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autoconf diff --git a/agent/auto-config/auto_encrypt_test.go b/agent/auto-config/auto_encrypt_test.go index 10a7c8da46888..2c94b6a5540a0 100644 --- a/agent/auto-config/auto_encrypt_test.go +++ b/agent/auto-config/auto_encrypt_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autoconf diff --git a/agent/auto-config/config.go b/agent/auto-config/config.go index 69eee08bc061b..d0f1670ab73a7 100644 --- a/agent/auto-config/config.go +++ b/agent/auto-config/config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autoconf diff --git a/agent/auto-config/config_ce.go b/agent/auto-config/config_ce.go index 6e7e470f298f5..4162bda4c4896 100644 --- a/agent/auto-config/config_ce.go +++ b/agent/auto-config/config_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/auto-config/config_translate.go b/agent/auto-config/config_translate.go index b60b3388eb2a8..31aeb7cbdb22f 100644 --- a/agent/auto-config/config_translate.go +++ b/agent/auto-config/config_translate.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autoconf diff --git a/agent/auto-config/config_translate_test.go b/agent/auto-config/config_translate_test.go index 8e2cef8c46ea9..9b37c9870e318 100644 --- a/agent/auto-config/config_translate_test.go +++ b/agent/auto-config/config_translate_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autoconf diff --git a/agent/auto-config/mock_ce_test.go b/agent/auto-config/mock_ce_test.go index cb741b6d47540..872aa5e5438f5 100644 --- a/agent/auto-config/mock_ce_test.go +++ b/agent/auto-config/mock_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/auto-config/mock_test.go b/agent/auto-config/mock_test.go index 0ef5084af2640..263befae112cb 100644 --- a/agent/auto-config/mock_test.go +++ b/agent/auto-config/mock_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autoconf diff --git a/agent/auto-config/persist.go b/agent/auto-config/persist.go index 66cda1c41438c..0abaa235451d9 100644 --- a/agent/auto-config/persist.go +++ b/agent/auto-config/persist.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autoconf diff --git a/agent/auto-config/run.go b/agent/auto-config/run.go index ed3389c1880cb..74a78fde9f0d8 100644 --- a/agent/auto-config/run.go +++ b/agent/auto-config/run.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autoconf diff --git a/agent/auto-config/server_addr.go b/agent/auto-config/server_addr.go index 6bca15d42fb8d..c70a6431fb33e 100644 --- a/agent/auto-config/server_addr.go +++ b/agent/auto-config/server_addr.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autoconf diff --git a/agent/auto-config/tls.go b/agent/auto-config/tls.go index 8142a1eeb809b..e39022bc959b7 100644 --- a/agent/auto-config/tls.go +++ b/agent/auto-config/tls.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autoconf diff --git a/agent/auto-config/tls_test.go b/agent/auto-config/tls_test.go index 667c7dfa96e5c..b09ee295e60be 100644 --- a/agent/auto-config/tls_test.go +++ b/agent/auto-config/tls_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autoconf diff --git a/agent/blockingquery/blockingquery.go b/agent/blockingquery/blockingquery.go index 3e073a1ffab2b..cb46110222de0 100644 --- a/agent/blockingquery/blockingquery.go +++ b/agent/blockingquery/blockingquery.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package blockingquery import ( diff --git a/agent/blockingquery/blockingquery_test.go b/agent/blockingquery/blockingquery_test.go index 5861ed3991641..6cfc07c114aa7 100644 --- a/agent/blockingquery/blockingquery_test.go +++ b/agent/blockingquery/blockingquery_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package blockingquery // TODO: move tests from the consul package, rpc_test.go, TestServer_blockingQuery diff --git a/agent/cache-types/catalog_datacenters.go b/agent/cache-types/catalog_datacenters.go index 2a4e64c9e5c1c..12da6e9878e3d 100644 --- a/agent/cache-types/catalog_datacenters.go +++ b/agent/cache-types/catalog_datacenters.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/catalog_datacenters_test.go b/agent/cache-types/catalog_datacenters_test.go index f04bfb4c7b421..bef374d131cda 100644 --- a/agent/cache-types/catalog_datacenters_test.go +++ b/agent/cache-types/catalog_datacenters_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/catalog_list_services.go b/agent/cache-types/catalog_list_services.go index 0a14ed3ef120a..a605c7431388c 100644 --- a/agent/cache-types/catalog_list_services.go +++ b/agent/cache-types/catalog_list_services.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/catalog_list_services_test.go b/agent/cache-types/catalog_list_services_test.go index 623cda2cee3ce..b5da270f962d3 100644 --- a/agent/cache-types/catalog_list_services_test.go +++ b/agent/cache-types/catalog_list_services_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/catalog_service_list.go b/agent/cache-types/catalog_service_list.go index 37ac4ba0f8131..521ed1d3b1ada 100644 --- a/agent/cache-types/catalog_service_list.go +++ b/agent/cache-types/catalog_service_list.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/catalog_service_list_test.go b/agent/cache-types/catalog_service_list_test.go index eb686193cc3ca..995f7e8b6c8c0 100644 --- a/agent/cache-types/catalog_service_list_test.go +++ b/agent/cache-types/catalog_service_list_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/catalog_services.go b/agent/cache-types/catalog_services.go index 8e04997b9f62d..21b472ba3124f 100644 --- a/agent/cache-types/catalog_services.go +++ b/agent/cache-types/catalog_services.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/catalog_services_test.go b/agent/cache-types/catalog_services_test.go index c084de67ccaad..8723b9015d719 100644 --- a/agent/cache-types/catalog_services_test.go +++ b/agent/cache-types/catalog_services_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/config_entry.go b/agent/cache-types/config_entry.go index 98443363c1b87..9748c176d1033 100644 --- a/agent/cache-types/config_entry.go +++ b/agent/cache-types/config_entry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/config_entry_test.go b/agent/cache-types/config_entry_test.go index d892b069e4c7b..11b109d6634a5 100644 --- a/agent/cache-types/config_entry_test.go +++ b/agent/cache-types/config_entry_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/connect_ca_root.go b/agent/cache-types/connect_ca_root.go index 1df3f7c78d837..0d6c8b700ca72 100644 --- a/agent/cache-types/connect_ca_root.go +++ b/agent/cache-types/connect_ca_root.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/connect_ca_root_test.go b/agent/cache-types/connect_ca_root_test.go index 74aa53c31a4c7..c1e906a8b810f 100644 --- a/agent/cache-types/connect_ca_root_test.go +++ b/agent/cache-types/connect_ca_root_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/discovery_chain.go b/agent/cache-types/discovery_chain.go index e27b621061e1d..8f0f177914887 100644 --- a/agent/cache-types/discovery_chain.go +++ b/agent/cache-types/discovery_chain.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/discovery_chain_test.go b/agent/cache-types/discovery_chain_test.go index a9c9783e882bb..b2b279faf7ddd 100644 --- a/agent/cache-types/discovery_chain_test.go +++ b/agent/cache-types/discovery_chain_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/exported_peered_services.go b/agent/cache-types/exported_peered_services.go index 69bd2d92ba71f..3e8f336281446 100644 --- a/agent/cache-types/exported_peered_services.go +++ b/agent/cache-types/exported_peered_services.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/exported_peered_services_test.go b/agent/cache-types/exported_peered_services_test.go index a2d618bb60c52..4848c2fce9dbe 100644 --- a/agent/cache-types/exported_peered_services_test.go +++ b/agent/cache-types/exported_peered_services_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/federation_state_list_gateways.go b/agent/cache-types/federation_state_list_gateways.go index 501a8bcead289..50658777b8d83 100644 --- a/agent/cache-types/federation_state_list_gateways.go +++ b/agent/cache-types/federation_state_list_gateways.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/federation_state_list_gateways_test.go b/agent/cache-types/federation_state_list_gateways_test.go index 04bd661e80fc6..7aaad80ed3b2e 100644 --- a/agent/cache-types/federation_state_list_gateways_test.go +++ b/agent/cache-types/federation_state_list_gateways_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/gateway_services.go b/agent/cache-types/gateway_services.go index 9c13800beeee0..030cec59ef88d 100644 --- a/agent/cache-types/gateway_services.go +++ b/agent/cache-types/gateway_services.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/gateway_services_test.go b/agent/cache-types/gateway_services_test.go index 49be4edf47808..babc30ead3c14 100644 --- a/agent/cache-types/gateway_services_test.go +++ b/agent/cache-types/gateway_services_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/health_services.go b/agent/cache-types/health_services.go index ae8369364743e..dc1a5e6648ad5 100644 --- a/agent/cache-types/health_services.go +++ b/agent/cache-types/health_services.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/health_services_test.go b/agent/cache-types/health_services_test.go index 6e83ec9a40181..e3680eb2d5adb 100644 --- a/agent/cache-types/health_services_test.go +++ b/agent/cache-types/health_services_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/intention_match.go b/agent/cache-types/intention_match.go index fd69eab65c75a..16671328fd2da 100644 --- a/agent/cache-types/intention_match.go +++ b/agent/cache-types/intention_match.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/intention_match_test.go b/agent/cache-types/intention_match_test.go index 26788b679befb..68a467a29d511 100644 --- a/agent/cache-types/intention_match_test.go +++ b/agent/cache-types/intention_match_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/intention_upstreams.go b/agent/cache-types/intention_upstreams.go index a0e1ea0c0fd35..b918a553526ca 100644 --- a/agent/cache-types/intention_upstreams.go +++ b/agent/cache-types/intention_upstreams.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/intention_upstreams_destination.go b/agent/cache-types/intention_upstreams_destination.go index 1b5200a163c2c..8adba2d7e7426 100644 --- a/agent/cache-types/intention_upstreams_destination.go +++ b/agent/cache-types/intention_upstreams_destination.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/intention_upstreams_destination_test.go b/agent/cache-types/intention_upstreams_destination_test.go index 32852891846f0..d4f8602c7d7e9 100644 --- a/agent/cache-types/intention_upstreams_destination_test.go +++ b/agent/cache-types/intention_upstreams_destination_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/intention_upstreams_test.go b/agent/cache-types/intention_upstreams_test.go index 3259969f03a8f..6f695576d0639 100644 --- a/agent/cache-types/intention_upstreams_test.go +++ b/agent/cache-types/intention_upstreams_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/node_services.go b/agent/cache-types/node_services.go index 44dd5624f5658..2b51de9f62f89 100644 --- a/agent/cache-types/node_services.go +++ b/agent/cache-types/node_services.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/node_services_test.go b/agent/cache-types/node_services_test.go index 6f16f93d5d61f..a1412bbe935be 100644 --- a/agent/cache-types/node_services_test.go +++ b/agent/cache-types/node_services_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/options.go b/agent/cache-types/options.go index cd46060f8bce4..cbfa2ff178ef8 100644 --- a/agent/cache-types/options.go +++ b/agent/cache-types/options.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/peered_upstreams.go b/agent/cache-types/peered_upstreams.go index 964b350eb1505..49997ecdf9675 100644 --- a/agent/cache-types/peered_upstreams.go +++ b/agent/cache-types/peered_upstreams.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/peered_upstreams_test.go b/agent/cache-types/peered_upstreams_test.go index 07be6e4188082..1e9dc29fdf4a5 100644 --- a/agent/cache-types/peered_upstreams_test.go +++ b/agent/cache-types/peered_upstreams_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/peerings.go b/agent/cache-types/peerings.go index 53138e5512d8e..e72b43d563129 100644 --- a/agent/cache-types/peerings.go +++ b/agent/cache-types/peerings.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/peerings_test.go b/agent/cache-types/peerings_test.go index 088a077c4f504..75fc21371eb7d 100644 --- a/agent/cache-types/peerings_test.go +++ b/agent/cache-types/peerings_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/prepared_query.go b/agent/cache-types/prepared_query.go index 8a9ec7720959c..995214a1b45b4 100644 --- a/agent/cache-types/prepared_query.go +++ b/agent/cache-types/prepared_query.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/prepared_query_test.go b/agent/cache-types/prepared_query_test.go index 50850c20fe9bc..26ea4d4c0b028 100644 --- a/agent/cache-types/prepared_query_test.go +++ b/agent/cache-types/prepared_query_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/resolved_service_config.go b/agent/cache-types/resolved_service_config.go index 76c333840f5d3..589afbcc6bd1b 100644 --- a/agent/cache-types/resolved_service_config.go +++ b/agent/cache-types/resolved_service_config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/resolved_service_config_test.go b/agent/cache-types/resolved_service_config_test.go index a71cdb7834362..4c8376447ad5f 100644 --- a/agent/cache-types/resolved_service_config_test.go +++ b/agent/cache-types/resolved_service_config_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/rpc.go b/agent/cache-types/rpc.go index 13bfdb3e5a5d7..905547d20fe82 100644 --- a/agent/cache-types/rpc.go +++ b/agent/cache-types/rpc.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/service_checks.go b/agent/cache-types/service_checks.go index 55ea3896f33cb..88a065c94b865 100644 --- a/agent/cache-types/service_checks.go +++ b/agent/cache-types/service_checks.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/service_checks_test.go b/agent/cache-types/service_checks_test.go index 898ea4aa9c937..b936990d91a33 100644 --- a/agent/cache-types/service_checks_test.go +++ b/agent/cache-types/service_checks_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/service_dump.go b/agent/cache-types/service_dump.go index 60c2895aff1f5..3bab11239f04b 100644 --- a/agent/cache-types/service_dump.go +++ b/agent/cache-types/service_dump.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/service_dump_test.go b/agent/cache-types/service_dump_test.go index 3570fc9720a16..8fe39e63b268e 100644 --- a/agent/cache-types/service_dump_test.go +++ b/agent/cache-types/service_dump_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/service_gateways.go b/agent/cache-types/service_gateways.go index a080fc77451ce..d096d136fa2fb 100644 --- a/agent/cache-types/service_gateways.go +++ b/agent/cache-types/service_gateways.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/service_gateways_test.go b/agent/cache-types/service_gateways_test.go index 9f615162b6fb3..c8c62e7c9ad5f 100644 --- a/agent/cache-types/service_gateways_test.go +++ b/agent/cache-types/service_gateways_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/testing.go b/agent/cache-types/testing.go index 3789eff4e2a5e..459feaba9fa37 100644 --- a/agent/cache-types/testing.go +++ b/agent/cache-types/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/trust_bundle.go b/agent/cache-types/trust_bundle.go index 0bac27e2b8c23..301b18977d95c 100644 --- a/agent/cache-types/trust_bundle.go +++ b/agent/cache-types/trust_bundle.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/trust_bundle_test.go b/agent/cache-types/trust_bundle_test.go index f39a15bdc6622..dc39c3555bd51 100644 --- a/agent/cache-types/trust_bundle_test.go +++ b/agent/cache-types/trust_bundle_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/trust_bundles.go b/agent/cache-types/trust_bundles.go index 7098c01af47ad..a485ee53414c0 100644 --- a/agent/cache-types/trust_bundles.go +++ b/agent/cache-types/trust_bundles.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache-types/trust_bundles_test.go b/agent/cache-types/trust_bundles_test.go index f565bab18fdbf..373ba2a8d71f0 100644 --- a/agent/cache-types/trust_bundles_test.go +++ b/agent/cache-types/trust_bundles_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cachetype diff --git a/agent/cache/cache.go b/agent/cache/cache.go index 29f1296f79b92..ed1e4f911ada0 100644 --- a/agent/cache/cache.go +++ b/agent/cache/cache.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package cache provides caching features for data from a Consul server. // diff --git a/agent/cache/cache_test.go b/agent/cache/cache_test.go index 6a4216c85929a..4ab66a29d0bf0 100644 --- a/agent/cache/cache_test.go +++ b/agent/cache/cache_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cache diff --git a/agent/cache/entry.go b/agent/cache/entry.go index 9ee1fc0007fa9..fb8008d8c15ee 100644 --- a/agent/cache/entry.go +++ b/agent/cache/entry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cache diff --git a/agent/cache/request.go b/agent/cache/request.go index 9af73d99687bd..7f66f4ce58819 100644 --- a/agent/cache/request.go +++ b/agent/cache/request.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cache diff --git a/agent/cache/testing.go b/agent/cache/testing.go index b754dae3e76a2..7f0df113bc839 100644 --- a/agent/cache/testing.go +++ b/agent/cache/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cache diff --git a/agent/cache/type.go b/agent/cache/type.go index ccab3216ca837..d58362fd470d7 100644 --- a/agent/cache/type.go +++ b/agent/cache/type.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cache diff --git a/agent/cache/watch.go b/agent/cache/watch.go index 300001240312e..d8693ad032f99 100644 --- a/agent/cache/watch.go +++ b/agent/cache/watch.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cache diff --git a/agent/cache/watch_test.go b/agent/cache/watch_test.go index 41c30f4dbb5cf..e6a5848f4ccdd 100644 --- a/agent/cache/watch_test.go +++ b/agent/cache/watch_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cache diff --git a/agent/catalog_endpoint.go b/agent/catalog_endpoint.go index 1dac61befa475..ad72c4b47f353 100644 --- a/agent/catalog_endpoint.go +++ b/agent/catalog_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/catalog_endpoint_ce.go b/agent/catalog_endpoint_ce.go index a3c8595fbe273..fcd8311356d87 100644 --- a/agent/catalog_endpoint_ce.go +++ b/agent/catalog_endpoint_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/catalog_endpoint_test.go b/agent/catalog_endpoint_test.go index 1b92e29a84d2a..da65097dbb581 100644 --- a/agent/catalog_endpoint_test.go +++ b/agent/catalog_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/check.go b/agent/check.go index 078361be66010..79c030d932424 100644 --- a/agent/check.go +++ b/agent/check.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/checks/alias.go b/agent/checks/alias.go index f75c05b9580bb..5e394105cf1c9 100644 --- a/agent/checks/alias.go +++ b/agent/checks/alias.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package checks diff --git a/agent/checks/alias_test.go b/agent/checks/alias_test.go index 1f5662019929a..70a301d1180ff 100644 --- a/agent/checks/alias_test.go +++ b/agent/checks/alias_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package checks diff --git a/agent/checks/check.go b/agent/checks/check.go index 0c730b5109424..c6472f1fb97e5 100644 --- a/agent/checks/check.go +++ b/agent/checks/check.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package checks @@ -625,19 +625,20 @@ func (c *CheckH2PING) Start() { go c.run() } -// CheckTCP is used to periodically make an TCP/UDP connection to -// determine the health of a given check. +// CheckTCP is used to periodically make a TCP connection to determine the +// health of a given check. // The check is passing if the connection succeeds // The check is critical if the connection returns an error // Supports failures_before_critical and success_before_passing. type CheckTCP struct { - CheckID structs.CheckID - ServiceID structs.ServiceID - TCP string - Interval time.Duration - Timeout time.Duration - Logger hclog.Logger - StatusHandler *StatusHandler + CheckID structs.CheckID + ServiceID structs.ServiceID + TCP string + Interval time.Duration + Timeout time.Duration + Logger hclog.Logger + TLSClientConfig *tls.Config + StatusHandler *StatusHandler dialer *net.Dialer stop bool @@ -694,17 +695,30 @@ func (c *CheckTCP) run() { // check is invoked periodically to perform the TCP check func (c *CheckTCP) check() { - conn, err := c.dialer.Dial(`tcp`, c.TCP) + var conn io.Closer + var err error + var checkType string + + if c.TLSClientConfig == nil { + conn, err = c.dialer.Dial(`tcp`, c.TCP) + checkType = "TCP" + } else { + conn, err = tls.DialWithDialer(c.dialer, `tcp`, c.TCP, c.TLSClientConfig) + checkType = "TCP+TLS" + } + if err != nil { - c.Logger.Warn("Check socket connection failed", + c.Logger.Warn(fmt.Sprintf("Check %s connection failed", checkType), "check", c.CheckID.String(), "error", err, ) c.StatusHandler.updateCheck(c.CheckID, api.HealthCritical, err.Error()) return } + conn.Close() - c.StatusHandler.updateCheck(c.CheckID, api.HealthPassing, fmt.Sprintf("TCP connect %s: Success", c.TCP)) + c.StatusHandler.updateCheck(c.CheckID, api.HealthPassing, fmt.Sprintf("%s connect %s: Success", checkType, c.TCP)) + } // CheckUDP is used to periodically send a UDP datagram to determine the health of a given check. diff --git a/agent/checks/check_test.go b/agent/checks/check_test.go index ae53b477f5554..389b4cb14100a 100644 --- a/agent/checks/check_test.go +++ b/agent/checks/check_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package checks diff --git a/agent/checks/check_windows_test.go b/agent/checks/check_windows_test.go index 05643539be51c..b7c14dd18e853 100644 --- a/agent/checks/check_windows_test.go +++ b/agent/checks/check_windows_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build windows // +build windows diff --git a/agent/checks/docker.go b/agent/checks/docker.go index e3483e073b037..11bcac7e01c84 100644 --- a/agent/checks/docker.go +++ b/agent/checks/docker.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package checks diff --git a/agent/checks/docker_unix.go b/agent/checks/docker_unix.go index 976344aa82d2e..33c8a2b817223 100644 --- a/agent/checks/docker_unix.go +++ b/agent/checks/docker_unix.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !windows // +build !windows diff --git a/agent/checks/docker_windows.go b/agent/checks/docker_windows.go index 6008b695ba1b0..edcb4f380a988 100644 --- a/agent/checks/docker_windows.go +++ b/agent/checks/docker_windows.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package checks diff --git a/agent/checks/grpc.go b/agent/checks/grpc.go index b3bcba20b5a61..87378521c9dfa 100644 --- a/agent/checks/grpc.go +++ b/agent/checks/grpc.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package checks diff --git a/agent/checks/grpc_test.go b/agent/checks/grpc_test.go index e67b453bda62a..4500bcd67f3b5 100644 --- a/agent/checks/grpc_test.go +++ b/agent/checks/grpc_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package checks diff --git a/agent/checks/os_service.go b/agent/checks/os_service.go index 3350c73a2c3b4..af4e9b03ee873 100644 --- a/agent/checks/os_service.go +++ b/agent/checks/os_service.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package checks diff --git a/agent/checks/os_service_unix.go b/agent/checks/os_service_unix.go index a02c8b54a741f..ab004e29fd9c3 100644 --- a/agent/checks/os_service_unix.go +++ b/agent/checks/os_service_unix.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !windows // +build !windows diff --git a/agent/checks/os_service_windows.go b/agent/checks/os_service_windows.go index fd9cc1bd33ecc..8b73ce4ad2091 100644 --- a/agent/checks/os_service_windows.go +++ b/agent/checks/os_service_windows.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build windows // +build windows diff --git a/agent/config/agent_limits.go b/agent/config/agent_limits.go index 7abbb075d3166..fff5e267f203c 100644 --- a/agent/config/agent_limits.go +++ b/agent/config/agent_limits.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/builder.go b/agent/config/builder.go index a3ca1abfd0c17..99d9626542baf 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config @@ -1290,10 +1290,6 @@ func (b *builder) validate(rt RuntimeConfig) error { "1 and 63 bytes.", rt.NodeName) } - if err := rt.StructLocality().Validate(); err != nil { - return fmt.Errorf("locality is invalid: %s", err) - } - if ipaddr.IsAny(rt.AdvertiseAddrLAN.IP) { return fmt.Errorf("Advertise address cannot be 0.0.0.0, :: or [::]") } @@ -1473,7 +1469,7 @@ func (b *builder) validate(rt RuntimeConfig) error { return err } case structs.VaultCAProvider: - if _, err := ca.ParseVaultCAConfig(rt.ConnectCAConfig, rt.PrimaryDatacenter == rt.Datacenter); err != nil { + if _, err := ca.ParseVaultCAConfig(rt.ConnectCAConfig); err != nil { return err } case structs.AWSCAProvider: @@ -1618,6 +1614,7 @@ func (b *builder) checkVal(v *CheckDefinition) *structs.CheckDefinition { Body: stringVal(v.Body), DisableRedirects: boolVal(v.DisableRedirects), TCP: stringVal(v.TCP), + TCPUseTLS: boolVal(v.TCPUseTLS), UDP: stringVal(v.UDP), Interval: b.durationVal(fmt.Sprintf("check[%s].interval", id), v.Interval), DockerContainerID: stringVal(v.DockerContainerID), @@ -2653,10 +2650,10 @@ func (b *builder) buildTLSConfig(rt RuntimeConfig, t TLS) (tlsutil.Config, error return c, errors.New("verify_outgoing is not valid in the tls.grpc stanza") } - // Similarly, only the internal RPC and defaults configuration honor VerifyServerHostname + // Similarly, only the internal RPC configuration honors VerifyServerHostname // so we call it out here too. - if t.GRPC.VerifyServerHostname != nil || t.HTTPS.VerifyServerHostname != nil { - return c, errors.New("verify_server_hostname is only valid in the tls.defaults and tls.internal_rpc stanzas") + if t.Defaults.VerifyServerHostname != nil || t.GRPC.VerifyServerHostname != nil || t.HTTPS.VerifyServerHostname != nil { + return c, errors.New("verify_server_hostname is only valid in the tls.internal_rpc stanza") } // And UseAutoCert right now only applies to external gRPC interface. @@ -2706,11 +2703,8 @@ func (b *builder) buildTLSConfig(rt RuntimeConfig, t TLS) (tlsutil.Config, error } mapCommon("internal_rpc", t.InternalRPC, &c.InternalRPC) + c.InternalRPC.VerifyServerHostname = boolVal(t.InternalRPC.VerifyServerHostname) - c.InternalRPC.VerifyServerHostname = boolVal(t.Defaults.VerifyServerHostname) - if t.InternalRPC.VerifyServerHostname != nil { - c.InternalRPC.VerifyServerHostname = boolVal(t.InternalRPC.VerifyServerHostname) - } // Setting only verify_server_hostname is documented to imply verify_outgoing. // If it doesn't then we risk sending communication over plain TCP when we // documented it as forcing TLS for RPCs. Enforce this here rather than in diff --git a/agent/config/builder_ce.go b/agent/config/builder_ce.go index ab7e1ece5a870..dae1e275c96a6 100644 --- a/agent/config/builder_ce.go +++ b/agent/config/builder_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/config/builder_ce_test.go b/agent/config/builder_ce_test.go index 3b3a220278c7e..100f905859da6 100644 --- a/agent/config/builder_ce_test.go +++ b/agent/config/builder_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/config/builder_test.go b/agent/config/builder_test.go index 2cc3e3148c37a..3eb81fdee4de6 100644 --- a/agent/config/builder_test.go +++ b/agent/config/builder_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/config.go b/agent/config/config.go index baaa1805191a9..911b1c3513210 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config @@ -423,6 +423,7 @@ type CheckDefinition struct { DisableRedirects *bool `mapstructure:"disable_redirects"` OutputMaxSize *int `mapstructure:"output_max_size"` TCP *string `mapstructure:"tcp"` + TCPUseTLS *bool `mapstructure:"tcp_use_tls"` UDP *string `mapstructure:"udp"` Interval *string `mapstructure:"interval"` DockerContainerID *string `mapstructure:"docker_container_id" alias:"dockercontainerid"` diff --git a/agent/config/config_ce.go b/agent/config/config_ce.go index aaf743919b97a..2fc8da58e6da8 100644 --- a/agent/config/config_ce.go +++ b/agent/config/config_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/config/default.go b/agent/config/default.go index f5ef349b752bf..536ac7ac33407 100644 --- a/agent/config/default.go +++ b/agent/config/default.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config @@ -209,7 +209,9 @@ func DevSource() Source { ports = { grpc = 8502 } - experiments = [] + experiments = [ + "resource-apis" + ] `, } } diff --git a/agent/config/default_ce.go b/agent/config/default_ce.go index 4f5adf0de724f..f91bb9c7d3600 100644 --- a/agent/config/default_ce.go +++ b/agent/config/default_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/config/deprecated.go b/agent/config/deprecated.go index 921e3329ffa6b..597095f8e2642 100644 --- a/agent/config/deprecated.go +++ b/agent/config/deprecated.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/deprecated_test.go b/agent/config/deprecated_test.go index 8d03e431f7afb..785c9555084f2 100644 --- a/agent/config/deprecated_test.go +++ b/agent/config/deprecated_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/doc.go b/agent/config/doc.go index 5bfc77d902528..4cbc2c41cfdcb 100644 --- a/agent/config/doc.go +++ b/agent/config/doc.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package config contains the command line and config file code for the // consul agent. diff --git a/agent/config/file_watcher.go b/agent/config/file_watcher.go index 2afe19b1a659a..c91bb1dd50cc7 100644 --- a/agent/config/file_watcher.go +++ b/agent/config/file_watcher.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/file_watcher_test.go b/agent/config/file_watcher_test.go index f937d1401195a..02b1cd14117be 100644 --- a/agent/config/file_watcher_test.go +++ b/agent/config/file_watcher_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/flags.go b/agent/config/flags.go index b56a162287c0c..21e1ac612a530 100644 --- a/agent/config/flags.go +++ b/agent/config/flags.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/flags_test.go b/agent/config/flags_test.go index a6c9ee23bd4aa..10df0d6d7f005 100644 --- a/agent/config/flags_test.go +++ b/agent/config/flags_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/flagset.go b/agent/config/flagset.go index af1b06d70ce9a..3b2abe6fdf9a2 100644 --- a/agent/config/flagset.go +++ b/agent/config/flagset.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/golden_test.go b/agent/config/golden_test.go index a9ce20d7bd1af..fb4401efbf4d7 100644 --- a/agent/config/golden_test.go +++ b/agent/config/golden_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/limits.go b/agent/config/limits.go index 46b6d45a1e52f..6b5d466ab639a 100644 --- a/agent/config/limits.go +++ b/agent/config/limits.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !windows // +build !windows diff --git a/agent/config/limits_windows.go b/agent/config/limits_windows.go index 538d84721f4f9..d9d3499397b56 100644 --- a/agent/config/limits_windows.go +++ b/agent/config/limits_windows.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build windows // +build windows diff --git a/agent/config/merge.go b/agent/config/merge.go index 64c7c1e974964..f40efdaa87793 100644 --- a/agent/config/merge.go +++ b/agent/config/merge.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/merge_test.go b/agent/config/merge_test.go index 9c2e2a1a07363..13e3cbb186ece 100644 --- a/agent/config/merge_test.go +++ b/agent/config/merge_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/ratelimited_file_watcher.go b/agent/config/ratelimited_file_watcher.go index 41f894837035f..33de08cf2b62e 100644 --- a/agent/config/ratelimited_file_watcher.go +++ b/agent/config/ratelimited_file_watcher.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/ratelimited_file_watcher_test.go b/agent/config/ratelimited_file_watcher_test.go index 8e4415aaa8712..d6a43b6be82be 100644 --- a/agent/config/ratelimited_file_watcher_test.go +++ b/agent/config/ratelimited_file_watcher_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/runtime.go b/agent/config/runtime.go index 18278b08b1ac8..1a8dc13794d3e 100644 --- a/agent/config/runtime.go +++ b/agent/config/runtime.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/config/runtime_ce.go b/agent/config/runtime_ce.go index ccc139a86b042..94a6b7fa6a62c 100644 --- a/agent/config/runtime_ce.go +++ b/agent/config/runtime_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/config/runtime_ce_test.go b/agent/config/runtime_ce_test.go index bab33fca55c82..99a2f6789e134 100644 --- a/agent/config/runtime_ce_test.go +++ b/agent/config/runtime_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index e39557b3d41b5..76366b6a0c4c7 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config @@ -324,7 +324,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { rt.DevMode = true rt.DisableAnonymousSignature = true rt.DisableKeyringFile = true - rt.Experiments = nil + rt.Experiments = []string{"resource-apis"} rt.EnableDebug = true rt.UIConfig.Enabled = true rt.LeaveOnTerm = false @@ -1038,13 +1038,6 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { }, }, }) - run(t, testCase{ - desc: "locality invalid", - args: []string{`-data-dir=` + dataDir}, - json: []string{`{"locality": {"zone": "us-west-1a"}}`}, - hcl: []string{`locality { zone = "us-west-1a" }`}, - expectedErr: "locality is invalid: zone cannot be set without region", - }) run(t, testCase{ desc: "client addr and ports == 0", args: []string{`-data-dir=` + dataDir}, @@ -2357,12 +2350,12 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { }, json: []string{`{ "cloud": { - "resource_id": "file-id" + "resource_id": "file-id" } }`}, hcl: []string{` cloud = { - resource_id = "file-id" + resource_id = "file-id" } `}, expected: func(rt *RuntimeConfig) { @@ -2529,6 +2522,60 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { rt.DataDir = dataDir }, }) + run(t, testCase{ + desc: "tcp check with tcp_use_tls set", + args: []string{ + `-data-dir=` + dataDir, + }, + json: []string{ + `{ "check": { "name": "a", "tcp": "localhost:55555", "tcp_use_tls": true, "interval": "5s" } }`, + }, + hcl: []string{ + `check = { name = "a" tcp = "localhost:55555" tcp_use_tls = true interval = "5s" }`, + }, + expected: func(rt *RuntimeConfig) { + rt.Checks = []*structs.CheckDefinition{ + {Name: "a", TCP: "localhost:55555", TCPUseTLS: true, OutputMaxSize: checks.DefaultBufSize, Interval: 5 * time.Second}, + } + rt.DataDir = dataDir + }, + }) + run(t, testCase{ + desc: "tcp check with tcp_use_tls set to false", + args: []string{ + `-data-dir=` + dataDir, + }, + json: []string{ + `{ "check": { "name": "a", "tcp": "localhost:55555", "tcp_use_tls": false, "interval": "5s" } }`, + }, + hcl: []string{ + `check = { name = "a" tcp = "localhost:55555" tcp_use_tls = false interval = "5s" }`, + }, + expected: func(rt *RuntimeConfig) { + rt.Checks = []*structs.CheckDefinition{ + {Name: "a", TCP: "localhost:55555", TCPUseTLS: false, OutputMaxSize: checks.DefaultBufSize, Interval: 5 * time.Second}, + } + rt.DataDir = dataDir + }, + }) + run(t, testCase{ + desc: "tcp check with tcp_use_tls not set", + args: []string{ + `-data-dir=` + dataDir, + }, + json: []string{ + `{ "check": { "name": "a", "tcp": "localhost:55555", "interval": "5s" } }`, + }, + hcl: []string{ + `check = { name = "a" tcp = "localhost:55555" interval = "5s" }`, + }, + expected: func(rt *RuntimeConfig) { + rt.Checks = []*structs.CheckDefinition{ + {Name: "a", TCP: "localhost:55555", TCPUseTLS: false, OutputMaxSize: checks.DefaultBufSize, Interval: 5 * time.Second}, + } + rt.DataDir = dataDir + }, + }) run(t, testCase{ desc: "h2ping check without h2ping_use_tls set", args: []string{ @@ -2736,44 +2783,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { } } `}, - expected: func(rt *RuntimeConfig) { - rt.DataDir = dataDir - rt.TLS.InternalRPC.VerifyServerHostname = true - rt.TLS.InternalRPC.VerifyOutgoing = true - }, - }) - run(t, testCase{ - desc: "verify_server_hostname in the defaults stanza and internal_rpc", - args: []string{ - `-data-dir=` + dataDir, - }, - hcl: []string{` - tls { - defaults { - verify_server_hostname = false - }, - internal_rpc { - verify_server_hostname = true - } - } - `}, - json: []string{` - { - "tls": { - "defaults": { - "verify_server_hostname": false - }, - "internal_rpc": { - "verify_server_hostname": true - } - } - } - `}, - expected: func(rt *RuntimeConfig) { - rt.DataDir = dataDir - rt.TLS.InternalRPC.VerifyServerHostname = true - rt.TLS.InternalRPC.VerifyOutgoing = true - }, + expectedErr: "verify_server_hostname is only valid in the tls.internal_rpc stanza", }) run(t, testCase{ desc: "verify_server_hostname in the grpc stanza", @@ -2796,7 +2806,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { } } `}, - expectedErr: "verify_server_hostname is only valid in the tls.defaults and tls.internal_rpc stanza", + expectedErr: "verify_server_hostname is only valid in the tls.internal_rpc stanza", }) run(t, testCase{ desc: "verify_server_hostname in the https stanza", @@ -2819,7 +2829,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { } } `}, - expectedErr: "verify_server_hostname is only valid in the tls.defaults and tls.internal_rpc stanza", + expectedErr: "verify_server_hostname is only valid in the tls.internal_rpc stanza", }) run(t, testCase{ desc: "translated keys", @@ -5760,74 +5770,6 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { rt.TLS.InternalRPC.VerifyOutgoing = true }, }) - run(t, testCase{ - desc: "tls.defaults.verify_server_hostname implies tls.internal_rpc.verify_outgoing", - args: []string{ - `-data-dir=` + dataDir, - }, - json: []string{` - { - "tls": { - "defaults": { - "verify_server_hostname": true - } - } - } - `}, - hcl: []string{` - tls { - defaults { - verify_server_hostname = true - } - } - `}, - expected: func(rt *RuntimeConfig) { - rt.DataDir = dataDir - - rt.TLS.Domain = "consul." - rt.TLS.NodeName = "thehostname" - - rt.TLS.InternalRPC.VerifyServerHostname = true - rt.TLS.InternalRPC.VerifyOutgoing = true - }, - }) - run(t, testCase{ - desc: "tls.internal_rpc.verify_server_hostname overwrites tls.defaults.verify_server_hostname", - args: []string{ - `-data-dir=` + dataDir, - }, - json: []string{` - { - "tls": { - "defaults": { - "verify_server_hostname": false - }, - "internal_rpc": { - "verify_server_hostname": true - } - } - } - `}, - hcl: []string{` - tls { - defaults { - verify_server_hostname = false - }, - internal_rpc { - verify_server_hostname = true - } - } - `}, - expected: func(rt *RuntimeConfig) { - rt.DataDir = dataDir - - rt.TLS.Domain = "consul." - rt.TLS.NodeName = "thehostname" - - rt.TLS.InternalRPC.VerifyServerHostname = true - rt.TLS.InternalRPC.VerifyOutgoing = true - }, - }) run(t, testCase{ desc: "tls.grpc.use_auto_cert defaults to false", args: []string{ @@ -6287,6 +6229,7 @@ func TestLoad_FullConfig(t *testing.T) { Body: "wSjTy7dg", DisableRedirects: true, TCP: "RJQND605", + TCPUseTLS: false, H2PING: "9N1cSb5B", H2PingUseTLS: false, OSService: "aAjE6m9Z", @@ -6317,6 +6260,7 @@ func TestLoad_FullConfig(t *testing.T) { DisableRedirects: false, OutputMaxSize: checks.DefaultBufSize, TCP: "4jG5casb", + TCPUseTLS: false, H2PING: "HCHU7gEb", H2PingUseTLS: false, OSService: "aqq95BhP", @@ -6346,6 +6290,7 @@ func TestLoad_FullConfig(t *testing.T) { DisableRedirects: true, OutputMaxSize: checks.DefaultBufSize, TCP: "JY6fTTcw", + TCPUseTLS: false, H2PING: "rQ8eyCSF", H2PingUseTLS: false, OSService: "aZaCAXww", diff --git a/agent/config/segment_ce.go b/agent/config/segment_ce.go index 3baee7076b142..5f8e8cff7d8fc 100644 --- a/agent/config/segment_ce.go +++ b/agent/config/segment_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/config/segment_ce_test.go b/agent/config/segment_ce_test.go index 20e6564778258..1fbaf3c2ae0bb 100644 --- a/agent/config/segment_ce_test.go +++ b/agent/config/segment_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden index 6bb08ff95feda..e339923dc95f8 100644 --- a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden +++ b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden @@ -117,6 +117,7 @@ "Status": "", "SuccessBeforePassing": 0, "TCP": "", + "TCPUseTLS": false, "TLSServerName": "", "TLSSkipVerify": false, "TTL": "0s", @@ -368,6 +369,7 @@ "Status": "", "SuccessBeforePassing": 0, "TCP": "", + "TCPUseTLS": false, "TLSServerName": "", "TLSSkipVerify": false, "TTL": "0s", diff --git a/agent/config/testdata/full-config.hcl b/agent/config/testdata/full-config.hcl index 1c1fb0158aa5c..6029d2ea2e6bb 100644 --- a/agent/config/testdata/full-config.hcl +++ b/agent/config/testdata/full-config.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 acl_agent_master_token = "furuQD0b" acl_agent_token = "cOshLOQ2" diff --git a/agent/config_endpoint.go b/agent/config_endpoint.go index e1b3f0eeef415..396215d78d990 100644 --- a/agent/config_endpoint.go +++ b/agent/config_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/config_endpoint_test.go b/agent/config_endpoint_test.go index 141e1e8f4d0d7..f8c0c01e329a1 100644 --- a/agent/config_endpoint_test.go +++ b/agent/config_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/configentry/compare.go b/agent/configentry/compare.go index 3bf761dba828d..f28d5c9b03d94 100644 --- a/agent/configentry/compare.go +++ b/agent/configentry/compare.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package configentry import ( diff --git a/agent/configentry/compare_test.go b/agent/configentry/compare_test.go index eeeec32f853b4..fcb63d0fa86e7 100644 --- a/agent/configentry/compare_test.go +++ b/agent/configentry/compare_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package configentry import ( diff --git a/agent/configentry/config_entry.go b/agent/configentry/config_entry.go index b10989aa95d79..a4ebb254e0407 100644 --- a/agent/configentry/config_entry.go +++ b/agent/configentry/config_entry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package configentry diff --git a/agent/configentry/discoverychain.go b/agent/configentry/discoverychain.go index 58bdb81fc20ca..d66b6590e0a42 100644 --- a/agent/configentry/discoverychain.go +++ b/agent/configentry/discoverychain.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package configentry diff --git a/agent/configentry/doc.go b/agent/configentry/doc.go index 7dff4a06621b5..18fd1405ab18c 100644 --- a/agent/configentry/doc.go +++ b/agent/configentry/doc.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package configentry contains structs and logic related to the Configuration // Entry subsystem. Currently this is restricted to structs used during diff --git a/agent/configentry/merge_service_config.go b/agent/configentry/merge_service_config.go index 1bbe24a3ebc4e..cc692e789b372 100644 --- a/agent/configentry/merge_service_config.go +++ b/agent/configentry/merge_service_config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package configentry @@ -7,7 +7,7 @@ import ( "fmt" "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-memdb" + memdb "github.com/hashicorp/go-memdb" "github.com/imdario/mergo" "github.com/mitchellh/copystructure" @@ -141,10 +141,6 @@ func MergeServiceConfig(defaults *structs.ServiceConfigResponse, service *struct ns.Proxy.EnvoyExtensions = nsExtensions } - if ratelimit := defaults.RateLimits.ToEnvoyExtension(); ratelimit != nil { - ns.Proxy.EnvoyExtensions = append(ns.Proxy.EnvoyExtensions, *ratelimit) - } - if ns.Proxy.MeshGateway.Mode == structs.MeshGatewayModeDefault { ns.Proxy.MeshGateway.Mode = defaults.MeshGateway.Mode } diff --git a/agent/configentry/merge_service_config_test.go b/agent/configentry/merge_service_config_test.go index e9f051d0026af..4f6dbb55488a2 100644 --- a/agent/configentry/merge_service_config_test.go +++ b/agent/configentry/merge_service_config_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package configentry @@ -972,111 +972,3 @@ func Test_MergeServiceConfig_UpstreamOverrides(t *testing.T) { }) } } - -// Tests that RateLimit config is a no-op in non-enterprise. -// In practice, the ratelimit config would have been validated -// on write. -func Test_MergeServiceConfig_RateLimit(t *testing.T) { - rl := structs.RateLimits{ - InstanceLevel: structs.InstanceLevelRateLimits{ - RequestsPerSecond: 1234, - RequestsMaxBurst: 2345, - Routes: []structs.InstanceLevelRouteRateLimits{ - { - PathExact: "/admin", - RequestsPerSecond: 3333, - RequestsMaxBurst: 4444, - }, - }, - }, - } - tests := []struct { - name string - defaults *structs.ServiceConfigResponse - service *structs.NodeService - want *structs.NodeService - }{ - { - name: "injects ratelimit extension", - defaults: &structs.ServiceConfigResponse{ - RateLimits: rl, - }, - service: &structs.NodeService{ - ID: "foo-proxy", - Service: "foo-proxy", - Proxy: structs.ConnectProxyConfig{ - DestinationServiceName: "foo", - DestinationServiceID: "foo", - }, - }, - want: &structs.NodeService{ - ID: "foo-proxy", - Service: "foo-proxy", - Proxy: structs.ConnectProxyConfig{ - DestinationServiceName: "foo", - DestinationServiceID: "foo", - EnvoyExtensions: func() []structs.EnvoyExtension { - if ext := rl.ToEnvoyExtension(); ext != nil { - return []structs.EnvoyExtension{*ext} - } - return nil - }(), - }, - }, - }, - { - name: "injects ratelimit extension at the end", - defaults: &structs.ServiceConfigResponse{ - RateLimits: rl, - EnvoyExtensions: []structs.EnvoyExtension{ - { - Name: "existing-ext", - Required: true, - Arguments: map[string]interface{}{ - "arg1": "val1", - }, - }, - }, - }, - service: &structs.NodeService{ - ID: "foo-proxy", - Service: "foo-proxy", - Proxy: structs.ConnectProxyConfig{ - DestinationServiceName: "foo", - DestinationServiceID: "foo", - }, - }, - - want: &structs.NodeService{ - ID: "foo-proxy", - Service: "foo-proxy", - Proxy: structs.ConnectProxyConfig{ - DestinationServiceName: "foo", - DestinationServiceID: "foo", - EnvoyExtensions: func() []structs.EnvoyExtension { - existing := []structs.EnvoyExtension{ - { - Name: "existing-ext", - Required: true, - Arguments: map[string]interface{}{ - "arg1": "val1", - }, - }, - } - if ext := rl.ToEnvoyExtension(); ext != nil { - existing = append(existing, *ext) - } - return existing - }(), - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := MergeServiceConfig(tt.defaults, tt.service) - require.NoError(t, err) - assert.Equal(t, tt.want, got) - }) - } -} diff --git a/agent/configentry/resolve.go b/agent/configentry/resolve.go index 82efc3b8bd759..882f1d16b5489 100644 --- a/agent/configentry/resolve.go +++ b/agent/configentry/resolve.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package configentry @@ -117,9 +117,6 @@ func ComputeResolvedServiceConfig( if serviceConf.Destination != nil { thisReply.Destination = *serviceConf.Destination } - if serviceConf.RateLimits != nil { - thisReply.RateLimits = *serviceConf.RateLimits - } // Populate values for the proxy config map proxyConf := thisReply.ProxyConfig diff --git a/agent/configentry/resolve_test.go b/agent/configentry/resolve_test.go index f93649df8ae7b..f0457730eaa06 100644 --- a/agent/configentry/resolve_test.go +++ b/agent/configentry/resolve_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package configentry diff --git a/agent/configentry/service_config.go b/agent/configentry/service_config.go index 83e24e27c390b..4b7e5e2a27c1d 100644 --- a/agent/configentry/service_config.go +++ b/agent/configentry/service_config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package configentry diff --git a/agent/connect/authz.go b/agent/connect/authz.go index cc14dd0cb61d1..74b306354faf1 100644 --- a/agent/connect/authz.go +++ b/agent/connect/authz.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/authz_test.go b/agent/connect/authz_test.go index 1cbf17517d819..6428acfc4722e 100644 --- a/agent/connect/authz_test.go +++ b/agent/connect/authz_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/ca/common.go b/agent/connect/ca/common.go index f52b030ed977e..b83a196a8a235 100644 --- a/agent/connect/ca/common.go +++ b/agent/connect/ca/common.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider.go b/agent/connect/ca/provider.go index 898da46af7290..2ef34228bc483 100644 --- a/agent/connect/ca/provider.go +++ b/agent/connect/ca/provider.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca @@ -152,7 +152,7 @@ type PrimaryProvider interface { SignIntermediate(*x509.CertificateRequest) (string, error) // CrossSignCA must accept a CA certificate from another CA provider and cross - // sign it exactly as it is such that it forms a chain back the + // sign it exactly as it is such that it forms a chain back the the // CAProvider's current root. Specifically, the Distinguished Name, Subject // Alternative Name, SubjectKeyID and other relevant extensions must be kept. // The resulting certificate must have a distinct Serial Number and the diff --git a/agent/connect/ca/provider_aws.go b/agent/connect/ca/provider_aws.go index 1ce5a5eba57d8..d45f3295a8e74 100644 --- a/agent/connect/ca/provider_aws.go +++ b/agent/connect/ca/provider_aws.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_aws_test.go b/agent/connect/ca/provider_aws_test.go index d46221af1fce9..cba2897fa26a4 100644 --- a/agent/connect/ca/provider_aws_test.go +++ b/agent/connect/ca/provider_aws_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_consul.go b/agent/connect/ca/provider_consul.go index a4aba91942bf4..01c4987e07d81 100644 --- a/agent/connect/ca/provider_consul.go +++ b/agent/connect/ca/provider_consul.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_consul_config.go b/agent/connect/ca/provider_consul_config.go index c7e8b0346cdb9..b0998a0aa11b6 100644 --- a/agent/connect/ca/provider_consul_config.go +++ b/agent/connect/ca/provider_consul_config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_consul_test.go b/agent/connect/ca/provider_consul_test.go index 658a97d39bd97..0c6959c7f5d41 100644 --- a/agent/connect/ca/provider_consul_test.go +++ b/agent/connect/ca/provider_consul_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_test.go b/agent/connect/ca/provider_test.go index 85deedbf4cb57..b7ed9e29b412d 100644 --- a/agent/connect/ca/provider_test.go +++ b/agent/connect/ca/provider_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca @@ -113,7 +113,7 @@ func TestStructs_CAConfiguration_MsgpackEncodeDecode(t *testing.T) { TLSSkipVerify: true, }, parseFunc: func(t *testing.T, raw map[string]interface{}) interface{} { - config, err := ParseVaultCAConfig(raw, true) + config, err := ParseVaultCAConfig(raw) require.NoError(t, err) return config }, diff --git a/agent/connect/ca/provider_vault.go b/agent/connect/ca/provider_vault.go index 8c77f032e83dc..d48a38ce320cb 100644 --- a/agent/connect/ca/provider_vault.go +++ b/agent/connect/ca/provider_vault.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca @@ -101,7 +101,7 @@ func vaultTLSConfig(config *structs.VaultCAProviderConfig) *vaultapi.TLSConfig { // Configure sets up the provider using the given configuration. // Configure supports being called multiple times to re-configure the provider. func (v *VaultProvider) Configure(cfg ProviderConfig) error { - config, err := ParseVaultCAConfig(cfg.RawConfig, v.isPrimary) + config, err := ParseVaultCAConfig(cfg.RawConfig) if err != nil { return err } @@ -192,11 +192,11 @@ func (v *VaultProvider) Configure(cfg ProviderConfig) error { } func (v *VaultProvider) ValidateConfigUpdate(prevRaw, nextRaw map[string]interface{}) error { - prev, err := ParseVaultCAConfig(prevRaw, v.isPrimary) + prev, err := ParseVaultCAConfig(prevRaw) if err != nil { return fmt.Errorf("failed to parse existing CA config: %w", err) } - next, err := ParseVaultCAConfig(nextRaw, v.isPrimary) + next, err := ParseVaultCAConfig(nextRaw) if err != nil { return fmt.Errorf("failed to parse new CA config: %w", err) } @@ -789,7 +789,7 @@ func (v *VaultProvider) Cleanup(providerTypeChange bool, otherConfig map[string] v.Stop() if !providerTypeChange { - newConfig, err := ParseVaultCAConfig(otherConfig, v.isPrimary) + newConfig, err := ParseVaultCAConfig(otherConfig) if err != nil { return err } @@ -889,7 +889,7 @@ func (v *VaultProvider) autotidyIssuers(path string) (bool, string) { return tidySet, errStr } -func ParseVaultCAConfig(raw map[string]interface{}, isPrimary bool) (*structs.VaultCAProviderConfig, error) { +func ParseVaultCAConfig(raw map[string]interface{}) (*structs.VaultCAProviderConfig, error) { config := structs.VaultCAProviderConfig{ CommonCAProviderConfig: defaultCommonConfig(), } @@ -920,10 +920,10 @@ func ParseVaultCAConfig(raw map[string]interface{}, isPrimary bool) (*structs.Va return nil, fmt.Errorf("only one of Vault token or Vault auth method can be provided, but not both") } - if isPrimary && config.RootPKIPath == "" { + if config.RootPKIPath == "" { return nil, fmt.Errorf("must provide a valid path to a root PKI backend") } - if config.RootPKIPath != "" && !strings.HasSuffix(config.RootPKIPath, "/") { + if !strings.HasSuffix(config.RootPKIPath, "/") { config.RootPKIPath += "/" } diff --git a/agent/connect/ca/provider_vault_auth.go b/agent/connect/ca/provider_vault_auth.go index 70176cc3c328a..ddfbde34070c7 100644 --- a/agent/connect/ca/provider_vault_auth.go +++ b/agent/connect/ca/provider_vault_auth.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_vault_auth_alicloud.go b/agent/connect/ca/provider_vault_auth_alicloud.go index d6ae5b185ed38..1c30583179254 100644 --- a/agent/connect/ca/provider_vault_auth_alicloud.go +++ b/agent/connect/ca/provider_vault_auth_alicloud.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_vault_auth_approle.go b/agent/connect/ca/provider_vault_auth_approle.go index c3d7d8f9c8ac8..150c463aea9aa 100644 --- a/agent/connect/ca/provider_vault_auth_approle.go +++ b/agent/connect/ca/provider_vault_auth_approle.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_vault_auth_aws.go b/agent/connect/ca/provider_vault_auth_aws.go index 61762b36fd618..02abf39824cb5 100644 --- a/agent/connect/ca/provider_vault_auth_aws.go +++ b/agent/connect/ca/provider_vault_auth_aws.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_vault_auth_azure.go b/agent/connect/ca/provider_vault_auth_azure.go index ac8d326b32790..8025977007f4d 100644 --- a/agent/connect/ca/provider_vault_auth_azure.go +++ b/agent/connect/ca/provider_vault_auth_azure.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_vault_auth_gcp.go b/agent/connect/ca/provider_vault_auth_gcp.go index 10dfbf4b294a7..5eefc7143663f 100644 --- a/agent/connect/ca/provider_vault_auth_gcp.go +++ b/agent/connect/ca/provider_vault_auth_gcp.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_vault_auth_jwt.go b/agent/connect/ca/provider_vault_auth_jwt.go index e80751cd59c3d..2560f856d82af 100644 --- a/agent/connect/ca/provider_vault_auth_jwt.go +++ b/agent/connect/ca/provider_vault_auth_jwt.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_vault_auth_k8s.go b/agent/connect/ca/provider_vault_auth_k8s.go index acd6f68bc5ddc..c3a69c6ccd44b 100644 --- a/agent/connect/ca/provider_vault_auth_k8s.go +++ b/agent/connect/ca/provider_vault_auth_k8s.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_vault_auth_test.go b/agent/connect/ca/provider_vault_auth_test.go index 361d89400e22c..74507acb39e7b 100644 --- a/agent/connect/ca/provider_vault_auth_test.go +++ b/agent/connect/ca/provider_vault_auth_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/ca/provider_vault_test.go b/agent/connect/ca/provider_vault_test.go index c76ea1c28a6c4..e75d02984262f 100644 --- a/agent/connect/ca/provider_vault_test.go +++ b/agent/connect/ca/provider_vault_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca @@ -60,7 +60,6 @@ func TestVaultCAProvider_ParseVaultCAConfig(t *testing.T) { cases := map[string]struct { rawConfig map[string]interface{} expConfig *structs.VaultCAProviderConfig - isPrimary bool expError string }{ "no token and no auth method provided": { @@ -71,26 +70,15 @@ func TestVaultCAProvider_ParseVaultCAConfig(t *testing.T) { rawConfig: map[string]interface{}{"Token": "test", "AuthMethod": map[string]interface{}{"Type": "test"}}, expError: "only one of Vault token or Vault auth method can be provided, but not both", }, - "primary no root PKI path": { - rawConfig: map[string]interface{}{"Token": "test", "IntermediatePKIPath": "test"}, - isPrimary: true, + "no root PKI path": { + rawConfig: map[string]interface{}{"Token": "test"}, expError: "must provide a valid path to a root PKI backend", }, - "secondary no root PKI path": { - rawConfig: map[string]interface{}{"Token": "test", "IntermediatePKIPath": "test"}, - isPrimary: false, - expConfig: &structs.VaultCAProviderConfig{ - CommonCAProviderConfig: defaultCommonConfig(), - Token: "test", - IntermediatePKIPath: "test/", - }, - }, "no root intermediate path": { rawConfig: map[string]interface{}{"Token": "test", "RootPKIPath": "test"}, expError: "must provide a valid path for the intermediate PKI backend", }, "adds a slash to RootPKIPath and IntermediatePKIPath": { - isPrimary: true, rawConfig: map[string]interface{}{"Token": "test", "RootPKIPath": "test", "IntermediatePKIPath": "test"}, expConfig: &structs.VaultCAProviderConfig{ CommonCAProviderConfig: defaultCommonConfig(), @@ -103,7 +91,7 @@ func TestVaultCAProvider_ParseVaultCAConfig(t *testing.T) { for name, c := range cases { t.Run(name, func(t *testing.T) { - config, err := ParseVaultCAConfig(c.rawConfig, c.isPrimary) + config, err := ParseVaultCAConfig(c.rawConfig) if c.expError != "" { require.EqualError(t, err, c.expError) } else { diff --git a/agent/connect/ca/testing.go b/agent/connect/ca/testing.go index 28d077e34e5ad..d7458bcda8d62 100644 --- a/agent/connect/ca/testing.go +++ b/agent/connect/ca/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/agent/connect/common_names.go b/agent/connect/common_names.go index c52df9f10fb49..3c4c30633d533 100644 --- a/agent/connect/common_names.go +++ b/agent/connect/common_names.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/csr.go b/agent/connect/csr.go index 0a491b0b65522..9cf0d884dea7b 100644 --- a/agent/connect/csr.go +++ b/agent/connect/csr.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/csr_test.go b/agent/connect/csr_test.go index 1833b78a77985..6aef985f006fe 100644 --- a/agent/connect/csr_test.go +++ b/agent/connect/csr_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/generate.go b/agent/connect/generate.go index 84c91a246846b..819428d147a9c 100644 --- a/agent/connect/generate.go +++ b/agent/connect/generate.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/generate_test.go b/agent/connect/generate_test.go index ca956b702f165..67be6081fe08c 100644 --- a/agent/connect/generate_test.go +++ b/agent/connect/generate_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/parsing.go b/agent/connect/parsing.go index f1e89fe0255bc..a89544532fbb1 100644 --- a/agent/connect/parsing.go +++ b/agent/connect/parsing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect @@ -148,7 +148,7 @@ func ParseSigner(pemValue string) (crypto.Signer, error) { } // ParseCSR parses a CSR from a PEM-encoded value. The certificate request -// must be the first block in the PEM value. +// must be the the first block in the PEM value. func ParseCSR(pemValue string) (*x509.CertificateRequest, error) { // The _ result below is not an error but the remaining PEM bytes. block, _ := pem.Decode([]byte(pemValue)) diff --git a/agent/connect/sni.go b/agent/connect/sni.go index f7d14800a922f..339116b64c038 100644 --- a/agent/connect/sni.go +++ b/agent/connect/sni.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/sni_test.go b/agent/connect/sni_test.go index ed0bd07280417..acbfd49ce028e 100644 --- a/agent/connect/sni_test.go +++ b/agent/connect/sni_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/testing_ca.go b/agent/connect/testing_ca.go index a852d9130c87b..7b30d85176478 100644 --- a/agent/connect/testing_ca.go +++ b/agent/connect/testing_ca.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/testing_ca_test.go b/agent/connect/testing_ca_test.go index 9b62a2baee54b..492ca9e32d93b 100644 --- a/agent/connect/testing_ca_test.go +++ b/agent/connect/testing_ca_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/testing_spiffe.go b/agent/connect/testing_spiffe.go index fdbff5eda67d7..f48222c443f9c 100644 --- a/agent/connect/testing_spiffe.go +++ b/agent/connect/testing_spiffe.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/uri.go b/agent/connect/uri.go index d9d5aa037d8ae..ce44967432f61 100644 --- a/agent/connect/uri.go +++ b/agent/connect/uri.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/uri_agent.go b/agent/connect/uri_agent.go index 1babf99873809..c3d3a86bf115c 100644 --- a/agent/connect/uri_agent.go +++ b/agent/connect/uri_agent.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/uri_agent_ce.go b/agent/connect/uri_agent_ce.go index 5cfad14a7d973..2a87d108432fb 100644 --- a/agent/connect/uri_agent_ce.go +++ b/agent/connect/uri_agent_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/connect/uri_agent_ce_test.go b/agent/connect/uri_agent_ce_test.go index 241d804841d5e..57f1286fd1e1a 100644 --- a/agent/connect/uri_agent_ce_test.go +++ b/agent/connect/uri_agent_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/connect/uri_mesh_gateway.go b/agent/connect/uri_mesh_gateway.go index d5cf155bf8d7c..ec474efa40851 100644 --- a/agent/connect/uri_mesh_gateway.go +++ b/agent/connect/uri_mesh_gateway.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/uri_mesh_gateway_ce.go b/agent/connect/uri_mesh_gateway_ce.go index a0c0cdba0541a..876e05101b6b6 100644 --- a/agent/connect/uri_mesh_gateway_ce.go +++ b/agent/connect/uri_mesh_gateway_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/connect/uri_mesh_gateway_ce_test.go b/agent/connect/uri_mesh_gateway_ce_test.go index 4a8e8ada3701b..593de8ef31053 100644 --- a/agent/connect/uri_mesh_gateway_ce_test.go +++ b/agent/connect/uri_mesh_gateway_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/connect/uri_server.go b/agent/connect/uri_server.go index 5a2b9c2429283..894ad63784bfe 100644 --- a/agent/connect/uri_server.go +++ b/agent/connect/uri_server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/uri_service.go b/agent/connect/uri_service.go index 3be7cf4797a33..31bd3e5df62ba 100644 --- a/agent/connect/uri_service.go +++ b/agent/connect/uri_service.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/uri_service_ce.go b/agent/connect/uri_service_ce.go index a1e1dd43c3f26..4106fc811b38c 100644 --- a/agent/connect/uri_service_ce.go +++ b/agent/connect/uri_service_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/connect/uri_service_ce_test.go b/agent/connect/uri_service_ce_test.go index 774632063e94b..7d73151edc032 100644 --- a/agent/connect/uri_service_ce_test.go +++ b/agent/connect/uri_service_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/connect/uri_signing.go b/agent/connect/uri_signing.go index 4c4dd6ef67e82..24330a3d70b12 100644 --- a/agent/connect/uri_signing.go +++ b/agent/connect/uri_signing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/uri_signing_test.go b/agent/connect/uri_signing_test.go index edd3d468931ba..ba426173160ea 100644 --- a/agent/connect/uri_signing_test.go +++ b/agent/connect/uri_signing_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/uri_test.go b/agent/connect/uri_test.go index fcbcf42ab3a28..2ea439f53668c 100644 --- a/agent/connect/uri_test.go +++ b/agent/connect/uri_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/x509_patch.go b/agent/connect/x509_patch.go index 54a33ce07834f..f448154f8d9f0 100644 --- a/agent/connect/x509_patch.go +++ b/agent/connect/x509_patch.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect/x509_patch_test.go b/agent/connect/x509_patch_test.go index bdcb99045b578..1447802a5b879 100644 --- a/agent/connect/x509_patch_test.go +++ b/agent/connect/x509_patch_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/agent/connect_auth.go b/agent/connect_auth.go index 3b07013d3919b..7060d10b599f5 100644 --- a/agent/connect_auth.go +++ b/agent/connect_auth.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/connect_ca_endpoint.go b/agent/connect_ca_endpoint.go index 0a60f37662473..913836f8c8757 100644 --- a/agent/connect_ca_endpoint.go +++ b/agent/connect_ca_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/connect_ca_endpoint_test.go b/agent/connect_ca_endpoint_test.go index f83d7328863c9..575250de4cadc 100644 --- a/agent/connect_ca_endpoint_test.go +++ b/agent/connect_ca_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/consul/acl.go b/agent/consul/acl.go index 84646912a5fd4..c0107a6aa5a2c 100644 --- a/agent/consul/acl.go +++ b/agent/consul/acl.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/acl_authmethod.go b/agent/consul/acl_authmethod.go index 217007f2b5ee4..42f5b6e2404df 100644 --- a/agent/consul/acl_authmethod.go +++ b/agent/consul/acl_authmethod.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/acl_authmethod_ce.go b/agent/consul/acl_authmethod_ce.go index 0587d0dc2a633..94bf78bd25693 100644 --- a/agent/consul/acl_authmethod_ce.go +++ b/agent/consul/acl_authmethod_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/acl_ce.go b/agent/consul/acl_ce.go index 7e55a90ca9509..aafe26a13ef91 100644 --- a/agent/consul/acl_ce.go +++ b/agent/consul/acl_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/acl_ce_test.go b/agent/consul/acl_ce_test.go index 27f55a0efc05d..69660f9da8044 100644 --- a/agent/consul/acl_ce_test.go +++ b/agent/consul/acl_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/acl_client.go b/agent/consul/acl_client.go index e6ff70720cfc8..d133807604bf3 100644 --- a/agent/consul/acl_client.go +++ b/agent/consul/acl_client.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/acl_endpoint.go b/agent/consul/acl_endpoint.go index 97189bb45d27d..0dac4fdd9436a 100644 --- a/agent/consul/acl_endpoint.go +++ b/agent/consul/acl_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul @@ -680,8 +680,18 @@ func (a *ACL) TokenList(args *structs.ACLTokenListRequest, reply *structs.ACLTok } return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, - func(ws memdb.WatchSet, state *state.Store) error { - index, tokens, err := state.ACLTokenList(ws, args.IncludeLocal, args.IncludeGlobal, args.Policy, args.Role, args.AuthMethod, methodMeta, &args.EnterpriseMeta) + func(ws memdb.WatchSet, s *state.Store) error { + index, tokens, err := s.ACLTokenListWithParameters(ws, state.ACLTokenListParameters{ + Local: args.IncludeLocal, + Global: args.IncludeGlobal, + Policy: args.Policy, + Role: args.Role, + MethodName: args.AuthMethod, + ServiceName: args.ServiceName, + MethodMeta: methodMeta, + EnterpriseMeta: &args.EnterpriseMeta, + }) + if err != nil { return err } diff --git a/agent/consul/acl_endpoint_ce.go b/agent/consul/acl_endpoint_ce.go index 75a6c84ed36e4..9d45f0fd7d890 100644 --- a/agent/consul/acl_endpoint_ce.go +++ b/agent/consul/acl_endpoint_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/acl_endpoint_test.go b/agent/consul/acl_endpoint_test.go index 73f7f6230d679..20deb56aa4b00 100644 --- a/agent/consul/acl_endpoint_test.go +++ b/agent/consul/acl_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/acl_replication.go b/agent/consul/acl_replication.go index 79e4e5d7a7d89..849e81adf697a 100644 --- a/agent/consul/acl_replication.go +++ b/agent/consul/acl_replication.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/acl_replication_test.go b/agent/consul/acl_replication_test.go index 7a8e8efa12cb5..2b50f142bf303 100644 --- a/agent/consul/acl_replication_test.go +++ b/agent/consul/acl_replication_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul @@ -378,8 +378,10 @@ func TestACLReplication_Tokens(t *testing.T) { checkSame := func(t *retry.R) { // only account for global tokens - local tokens shouldn't be replicated + // nolint:staticcheck index, remote, err := s1.fsm.State().ACLTokenList(nil, false, true, "", "", "", nil, nil) require.NoError(t, err) + // nolint:staticcheck _, local, err := s2.fsm.State().ACLTokenList(nil, false, true, "", "", "", nil, nil) require.NoError(t, err) @@ -483,6 +485,7 @@ func TestACLReplication_Tokens(t *testing.T) { }) // verify dc2 local tokens didn't get blown away + // nolint:staticcheck _, local, err := s2.fsm.State().ACLTokenList(nil, true, false, "", "", "", nil, nil) require.NoError(t, err) require.Len(t, local, 50) @@ -821,9 +824,11 @@ func TestACLReplication_AllTypes(t *testing.T) { checkSameTokens := func(t *retry.R) { // only account for global tokens - local tokens shouldn't be replicated + // nolint:staticcheck index, remote, err := s1.fsm.State().ACLTokenList(nil, false, true, "", "", "", nil, nil) require.NoError(t, err) // Query for all of them, so that we can prove that no globals snuck in. + // nolint:staticcheck _, local, err := s2.fsm.State().ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) diff --git a/agent/consul/acl_replication_types.go b/agent/consul/acl_replication_types.go index de9e8cf763a0f..6d6b68690682b 100644 --- a/agent/consul/acl_replication_types.go +++ b/agent/consul/acl_replication_types.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul @@ -38,6 +38,7 @@ func (r *aclTokenReplicator) FetchRemote(srv *Server, lastRemoteIndex uint64) (i func (r *aclTokenReplicator) FetchLocal(srv *Server) (int, uint64, error) { r.local = nil + // nolint:staticcheck idx, local, err := srv.fsm.State().ACLTokenList(nil, false, true, "", "", "", nil, srv.replicationEnterpriseMeta()) if err != nil { return 0, 0, err diff --git a/agent/consul/acl_server.go b/agent/consul/acl_server.go index 8fe1f45fd0984..f91cb77620238 100644 --- a/agent/consul/acl_server.go +++ b/agent/consul/acl_server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/acl_server_ce.go b/agent/consul/acl_server_ce.go index bd7f34e776fc3..f2de1486a28af 100644 --- a/agent/consul/acl_server_ce.go +++ b/agent/consul/acl_server_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/acl_test.go b/agent/consul/acl_test.go index 275316786bbf9..386c60e38e39f 100644 --- a/agent/consul/acl_test.go +++ b/agent/consul/acl_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/acl_token_exp.go b/agent/consul/acl_token_exp.go index 06559ce71d566..7f5de395c7a9d 100644 --- a/agent/consul/acl_token_exp.go +++ b/agent/consul/acl_token_exp.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/acl_token_exp_test.go b/agent/consul/acl_token_exp_test.go index 031c150dabb0c..949d54510ba54 100644 --- a/agent/consul/acl_token_exp_test.go +++ b/agent/consul/acl_token_exp_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/auth/binder.go b/agent/consul/auth/binder.go index aed1e0f371ac6..354fedc8f1854 100644 --- a/agent/consul/auth/binder.go +++ b/agent/consul/auth/binder.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package auth diff --git a/agent/consul/auth/binder_ce.go b/agent/consul/auth/binder_ce.go index 19528ffedb172..f6fa5e5e841c1 100644 --- a/agent/consul/auth/binder_ce.go +++ b/agent/consul/auth/binder_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/auth/binder_test.go b/agent/consul/auth/binder_test.go index 7eedc89afcd81..b86d4526dd006 100644 --- a/agent/consul/auth/binder_test.go +++ b/agent/consul/auth/binder_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package auth diff --git a/agent/consul/auth/login.go b/agent/consul/auth/login.go index 7ca1f70d3431b..9592e5a841d6f 100644 --- a/agent/consul/auth/login.go +++ b/agent/consul/auth/login.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package auth diff --git a/agent/consul/auth/token_writer.go b/agent/consul/auth/token_writer.go index 8321b78610225..857a2e3d13213 100644 --- a/agent/consul/auth/token_writer.go +++ b/agent/consul/auth/token_writer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package auth diff --git a/agent/consul/auth/token_writer_ce.go b/agent/consul/auth/token_writer_ce.go index 224eee669ad85..b0ad9e833bb0e 100644 --- a/agent/consul/auth/token_writer_ce.go +++ b/agent/consul/auth/token_writer_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/auth/token_writer_test.go b/agent/consul/auth/token_writer_test.go index 45cd4c99ce8d5..51a2b3cc45a83 100644 --- a/agent/consul/auth/token_writer_test.go +++ b/agent/consul/auth/token_writer_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package auth diff --git a/agent/consul/authmethod/authmethods.go b/agent/consul/authmethod/authmethods.go index d03e2b410cb4f..946fce927e697 100644 --- a/agent/consul/authmethod/authmethods.go +++ b/agent/consul/authmethod/authmethods.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethod diff --git a/agent/consul/authmethod/authmethods_ce.go b/agent/consul/authmethod/authmethods_ce.go index 8eb430401a3ea..0839b4aba5a74 100644 --- a/agent/consul/authmethod/authmethods_ce.go +++ b/agent/consul/authmethod/authmethods_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/authmethod/awsauth/aws.go b/agent/consul/authmethod/awsauth/aws.go index 3381a893fa5da..d2cd73482cde5 100644 --- a/agent/consul/authmethod/awsauth/aws.go +++ b/agent/consul/authmethod/awsauth/aws.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package awsauth diff --git a/agent/consul/authmethod/awsauth/aws_test.go b/agent/consul/authmethod/awsauth/aws_test.go index 279e4b3e46d48..7a894cc217878 100644 --- a/agent/consul/authmethod/awsauth/aws_test.go +++ b/agent/consul/authmethod/awsauth/aws_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package awsauth diff --git a/agent/consul/authmethod/kubeauth/k8s.go b/agent/consul/authmethod/kubeauth/k8s.go index 274dd2ec9d03a..f71157cbeccb7 100644 --- a/agent/consul/authmethod/kubeauth/k8s.go +++ b/agent/consul/authmethod/kubeauth/k8s.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package kubeauth diff --git a/agent/consul/authmethod/kubeauth/k8s_ce.go b/agent/consul/authmethod/kubeauth/k8s_ce.go index e8ad4485069d8..b2b7e8a2d8715 100644 --- a/agent/consul/authmethod/kubeauth/k8s_ce.go +++ b/agent/consul/authmethod/kubeauth/k8s_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/authmethod/kubeauth/k8s_test.go b/agent/consul/authmethod/kubeauth/k8s_test.go index 48ef6e61c4839..95decce11597c 100644 --- a/agent/consul/authmethod/kubeauth/k8s_test.go +++ b/agent/consul/authmethod/kubeauth/k8s_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package kubeauth diff --git a/agent/consul/authmethod/kubeauth/testing.go b/agent/consul/authmethod/kubeauth/testing.go index 38b7d9c330a3f..e5538bb90998f 100644 --- a/agent/consul/authmethod/kubeauth/testing.go +++ b/agent/consul/authmethod/kubeauth/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package kubeauth diff --git a/agent/consul/authmethod/ssoauth/sso.go b/agent/consul/authmethod/ssoauth/sso.go index 398f5689799b3..6215c0eafe719 100644 --- a/agent/consul/authmethod/ssoauth/sso.go +++ b/agent/consul/authmethod/ssoauth/sso.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ssoauth diff --git a/agent/consul/authmethod/ssoauth/sso_ce.go b/agent/consul/authmethod/ssoauth/sso_ce.go index c8f760049f3de..74e3be3082ccb 100644 --- a/agent/consul/authmethod/ssoauth/sso_ce.go +++ b/agent/consul/authmethod/ssoauth/sso_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/authmethod/ssoauth/sso_test.go b/agent/consul/authmethod/ssoauth/sso_test.go index 357612fad6894..840e37b86fd46 100644 --- a/agent/consul/authmethod/ssoauth/sso_test.go +++ b/agent/consul/authmethod/ssoauth/sso_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ssoauth diff --git a/agent/consul/authmethod/testauth/testing.go b/agent/consul/authmethod/testauth/testing.go index ead9ae081a7ea..9f6c85ae23d5e 100644 --- a/agent/consul/authmethod/testauth/testing.go +++ b/agent/consul/authmethod/testauth/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package testauth diff --git a/agent/consul/authmethod/testauth/testing_ce.go b/agent/consul/authmethod/testauth/testing_ce.go index 6f38c0250298b..f4b909b4b8127 100644 --- a/agent/consul/authmethod/testauth/testing_ce.go +++ b/agent/consul/authmethod/testauth/testing_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/authmethod/testing.go b/agent/consul/authmethod/testing.go index 0f43e5e5201fc..933082a5b4295 100644 --- a/agent/consul/authmethod/testing.go +++ b/agent/consul/authmethod/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethod diff --git a/agent/consul/auto_config_backend.go b/agent/consul/auto_config_backend.go index 0aaccfa35d99b..78413fe0121c1 100644 --- a/agent/consul/auto_config_backend.go +++ b/agent/consul/auto_config_backend.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul @@ -34,7 +34,7 @@ func (b autoConfigBackend) GetCARoots() (*structs.IndexedCARoots, error) { } // DatacenterJoinAddresses will return all the strings suitable for usage in -// retry join operations to connect to the LAN or LAN segment gossip pool. +// retry join operations to connect to the the LAN or LAN segment gossip pool. func (b autoConfigBackend) DatacenterJoinAddresses(partition, segment string) ([]string, error) { members, err := b.Server.LANMembers(LANMemberFilter{ Segment: segment, diff --git a/agent/consul/auto_config_backend_test.go b/agent/consul/auto_config_backend_test.go index 00c0dc10d80d7..6a4a202fceb8e 100644 --- a/agent/consul/auto_config_backend_test.go +++ b/agent/consul/auto_config_backend_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/auto_config_endpoint.go b/agent/consul/auto_config_endpoint.go index f491bcbad832a..808aa63304dcd 100644 --- a/agent/consul/auto_config_endpoint.go +++ b/agent/consul/auto_config_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/auto_config_endpoint_test.go b/agent/consul/auto_config_endpoint_test.go index 39c4f3a7a5efa..a3f485ee60c2a 100644 --- a/agent/consul/auto_config_endpoint_test.go +++ b/agent/consul/auto_config_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/auto_encrypt_endpoint.go b/agent/consul/auto_encrypt_endpoint.go index dbd39355cfbf3..b893e783215ad 100644 --- a/agent/consul/auto_encrypt_endpoint.go +++ b/agent/consul/auto_encrypt_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/auto_encrypt_endpoint_test.go b/agent/consul/auto_encrypt_endpoint_test.go index f3b2320116340..d8124f9fb3623 100644 --- a/agent/consul/auto_encrypt_endpoint_test.go +++ b/agent/consul/auto_encrypt_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/autopilot.go b/agent/consul/autopilot.go index 70391f6b99107..f682ffed6f164 100644 --- a/agent/consul/autopilot.go +++ b/agent/consul/autopilot.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/autopilot_ce.go b/agent/consul/autopilot_ce.go index e20b31a626f38..92f9b4ccae41d 100644 --- a/agent/consul/autopilot_ce.go +++ b/agent/consul/autopilot_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/autopilot_test.go b/agent/consul/autopilot_test.go index 8d1d214b17104..4429340eda5a8 100644 --- a/agent/consul/autopilot_test.go +++ b/agent/consul/autopilot_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/autopilotevents/ready_servers_events.go b/agent/consul/autopilotevents/ready_servers_events.go index 16e064aa7905d..404276f3ec2d5 100644 --- a/agent/consul/autopilotevents/ready_servers_events.go +++ b/agent/consul/autopilotevents/ready_servers_events.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autopilotevents diff --git a/agent/consul/autopilotevents/ready_servers_events_test.go b/agent/consul/autopilotevents/ready_servers_events_test.go index 16d78b52e3b5f..994020c290c0d 100644 --- a/agent/consul/autopilotevents/ready_servers_events_test.go +++ b/agent/consul/autopilotevents/ready_servers_events_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autopilotevents diff --git a/agent/consul/catalog_endpoint.go b/agent/consul/catalog_endpoint.go index 0f1527c7e13de..446037a313109 100644 --- a/agent/consul/catalog_endpoint.go +++ b/agent/consul/catalog_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/catalog_endpoint_test.go b/agent/consul/catalog_endpoint_test.go index 628ad83ae4db0..192a3d6d7d275 100644 --- a/agent/consul/catalog_endpoint_test.go +++ b/agent/consul/catalog_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/client.go b/agent/consul/client.go index fa5f1239e134e..23e96be002875 100644 --- a/agent/consul/client.go +++ b/agent/consul/client.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul @@ -25,7 +25,6 @@ import ( "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/logging" - "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/tlsutil" "github.com/hashicorp/consul/types" ) @@ -94,9 +93,6 @@ type Client struct { EnterpriseClient tlsConfigurator *tlsutil.Configurator - - // resourceServiceClient is a client for the gRPC Resource Service. - resourceServiceClient pbresource.ResourceServiceClient } // NewClient creates and returns a Client @@ -155,13 +151,6 @@ func NewClient(config *Config, deps Deps) (*Client, error) { } c.router = deps.Router - conn, err := deps.GRPCConnPool.ClientConn(deps.ConnPool.Datacenter) - if err != nil { - c.Shutdown() - return nil, fmt.Errorf("Failed to get gRPC client connection: %w", err) - } - c.resourceServiceClient = pbresource.NewResourceServiceClient(conn) - // Start LAN event handlers after the router is complete since the event // handlers depend on the router and the router depends on Serf. go c.lanEventHandler() @@ -462,7 +451,3 @@ func (c *Client) AgentEnterpriseMeta() *acl.EnterpriseMeta { func (c *Client) agentSegmentName() string { return c.config.Segment } - -func (c *Client) ResourceServiceClient() pbresource.ResourceServiceClient { - return c.resourceServiceClient -} diff --git a/agent/consul/client_serf.go b/agent/consul/client_serf.go index c92fdd1726c30..7d68b50395e49 100644 --- a/agent/consul/client_serf.go +++ b/agent/consul/client_serf.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/client_test.go b/agent/consul/client_test.go index 9683d313041f0..4b8f5c433d8e7 100644 --- a/agent/consul/client_test.go +++ b/agent/consul/client_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul @@ -14,8 +14,6 @@ import ( "testing" "time" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/go-hclog" "github.com/hashicorp/serf/serf" "github.com/stretchr/testify/require" @@ -578,7 +576,6 @@ func newDefaultDeps(t *testing.T, c *Config) Deps { GetNetRPCInterceptorFunc: middleware.GetNetRPCInterceptor, EnterpriseDeps: newDefaultDepsEnterprise(t, logger, c), XDSStreamLimiter: limiter.NewSessionLimiter(), - Registry: resource.NewRegistry(), } } diff --git a/agent/consul/cluster_test.go b/agent/consul/cluster_test.go index 7cc266908198c..925d32a610692 100644 --- a/agent/consul/cluster_test.go +++ b/agent/consul/cluster_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/config.go b/agent/consul/config.go index cdda407c406c9..eef4bc4376f4e 100644 --- a/agent/consul/config.go +++ b/agent/consul/config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/config_ce.go b/agent/consul/config_ce.go index bed1211696bdf..e91d0981e86ee 100644 --- a/agent/consul/config_ce.go +++ b/agent/consul/config_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/config_cloud.go b/agent/consul/config_cloud.go index 5b62574c811b4..b0780052f668a 100644 --- a/agent/consul/config_cloud.go +++ b/agent/consul/config_cloud.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package consul type CloudConfig struct { diff --git a/agent/consul/config_endpoint.go b/agent/consul/config_endpoint.go index a78859c35058e..4108eb20b95c6 100644 --- a/agent/consul/config_endpoint.go +++ b/agent/consul/config_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/config_endpoint_test.go b/agent/consul/config_endpoint_test.go index 49a10dce21797..7dc7632fade71 100644 --- a/agent/consul/config_endpoint_test.go +++ b/agent/consul/config_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/config_replication.go b/agent/consul/config_replication.go index d9573ad58bf99..1b9ac0284939a 100644 --- a/agent/consul/config_replication.go +++ b/agent/consul/config_replication.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/config_replication_test.go b/agent/consul/config_replication_test.go index 41ccf53362d5d..a0eb8cf52a6e1 100644 --- a/agent/consul/config_replication_test.go +++ b/agent/consul/config_replication_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/config_test.go b/agent/consul/config_test.go index 8e61b8fe96806..e2706e00b4065 100644 --- a/agent/consul/config_test.go +++ b/agent/consul/config_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/connect_ca_endpoint.go b/agent/consul/connect_ca_endpoint.go index 180f7ccc47b61..771eae2464b95 100644 --- a/agent/consul/connect_ca_endpoint.go +++ b/agent/consul/connect_ca_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/connect_ca_endpoint_test.go b/agent/consul/connect_ca_endpoint_test.go index 587ed42b5a10e..3911db1923109 100644 --- a/agent/consul/connect_ca_endpoint_test.go +++ b/agent/consul/connect_ca_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/context.go b/agent/consul/context.go index d85124f74881a..7de4157d8f401 100644 --- a/agent/consul/context.go +++ b/agent/consul/context.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/context_test.go b/agent/consul/context_test.go index 42e6feb744868..264dcdd988611 100644 --- a/agent/consul/context_test.go +++ b/agent/consul/context_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/controller/controller.go b/agent/consul/controller/controller.go index 1eccb7e7aba04..f8d6a50c7f827 100644 --- a/agent/consul/controller/controller.go +++ b/agent/consul/controller/controller.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package controller diff --git a/agent/consul/controller/controller_test.go b/agent/consul/controller/controller_test.go index 1d1002e8abede..97d110222b3e3 100644 --- a/agent/consul/controller/controller_test.go +++ b/agent/consul/controller/controller_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package controller diff --git a/agent/consul/controller/doc.go b/agent/consul/controller/doc.go index ba30d95a546fd..638eb5c5d9a2e 100644 --- a/agent/consul/controller/doc.go +++ b/agent/consul/controller/doc.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package controller contains a re-implementation of the Kubernetes // [controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) diff --git a/agent/consul/controller/queue/defer.go b/agent/consul/controller/queue/defer.go index e9b8a9c3ad751..01666219c2919 100644 --- a/agent/consul/controller/queue/defer.go +++ b/agent/consul/controller/queue/defer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package queue diff --git a/agent/consul/controller/queue/queue.go b/agent/consul/controller/queue/queue.go index 92c624cc2a734..6d9f0a657125d 100644 --- a/agent/consul/controller/queue/queue.go +++ b/agent/consul/controller/queue/queue.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package queue diff --git a/agent/consul/controller/queue/rate.go b/agent/consul/controller/queue/rate.go index 615047fdeb39b..471601f85a270 100644 --- a/agent/consul/controller/queue/rate.go +++ b/agent/consul/controller/queue/rate.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package queue diff --git a/agent/consul/controller/queue/rate_test.go b/agent/consul/controller/queue/rate_test.go index 166111d5c7508..40dc540138e2a 100644 --- a/agent/consul/controller/queue/rate_test.go +++ b/agent/consul/controller/queue/rate_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package queue diff --git a/agent/consul/controller/queue_test.go b/agent/consul/controller/queue_test.go index cb6f609829100..11e1bc82b7626 100644 --- a/agent/consul/controller/queue_test.go +++ b/agent/consul/controller/queue_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package controller diff --git a/agent/consul/controller/reconciler.go b/agent/consul/controller/reconciler.go index fa948f81f6e62..dc4222508b57b 100644 --- a/agent/consul/controller/reconciler.go +++ b/agent/consul/controller/reconciler.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package controller diff --git a/agent/consul/controller/reconciler_test.go b/agent/consul/controller/reconciler_test.go index c3b8a450b18bb..56ae022ea263b 100644 --- a/agent/consul/controller/reconciler_test.go +++ b/agent/consul/controller/reconciler_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package controller diff --git a/agent/consul/coordinate_endpoint.go b/agent/consul/coordinate_endpoint.go index f0e69332ee686..28bf63b0bfd80 100644 --- a/agent/consul/coordinate_endpoint.go +++ b/agent/consul/coordinate_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/coordinate_endpoint_test.go b/agent/consul/coordinate_endpoint_test.go index 1c693ba83bbfe..fbb3e13aa76d6 100644 --- a/agent/consul/coordinate_endpoint_test.go +++ b/agent/consul/coordinate_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/discovery_chain_endpoint.go b/agent/consul/discovery_chain_endpoint.go index c70cebb094e68..4d1f9959c96e8 100644 --- a/agent/consul/discovery_chain_endpoint.go +++ b/agent/consul/discovery_chain_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/discovery_chain_endpoint_test.go b/agent/consul/discovery_chain_endpoint_test.go index 62d90e9020af6..b0197f00d493d 100644 --- a/agent/consul/discovery_chain_endpoint_test.go +++ b/agent/consul/discovery_chain_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/discoverychain/compile.go b/agent/consul/discoverychain/compile.go index 32a6408be5445..20227db3ef195 100644 --- a/agent/consul/discoverychain/compile.go +++ b/agent/consul/discoverychain/compile.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package discoverychain diff --git a/agent/consul/discoverychain/compile_ce.go b/agent/consul/discoverychain/compile_ce.go index 2c280120b5017..d980c71f38f05 100644 --- a/agent/consul/discoverychain/compile_ce.go +++ b/agent/consul/discoverychain/compile_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/discoverychain/compile_test.go b/agent/consul/discoverychain/compile_test.go index dda28780431d1..ca39aa236fc95 100644 --- a/agent/consul/discoverychain/compile_test.go +++ b/agent/consul/discoverychain/compile_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package discoverychain diff --git a/agent/consul/discoverychain/gateway.go b/agent/consul/discoverychain/gateway.go index 559d17844f7bb..e43e4b631f613 100644 --- a/agent/consul/discoverychain/gateway.go +++ b/agent/consul/discoverychain/gateway.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package discoverychain diff --git a/agent/consul/discoverychain/gateway_httproute.go b/agent/consul/discoverychain/gateway_httproute.go index 100fe980acdab..fcd2dc440259f 100644 --- a/agent/consul/discoverychain/gateway_httproute.go +++ b/agent/consul/discoverychain/gateway_httproute.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package discoverychain @@ -161,28 +161,6 @@ func httpRouteToDiscoveryChain(route structs.HTTPRouteConfigEntry) (*structs.Ser } } - if rule.Filters.RetryFilter != nil { - if rule.Filters.RetryFilter.NumRetries != nil { - destination.NumRetries = *rule.Filters.RetryFilter.NumRetries - } - if rule.Filters.RetryFilter.RetryOnConnectFailure != nil { - destination.RetryOnConnectFailure = *rule.Filters.RetryFilter.RetryOnConnectFailure - } - - if len(rule.Filters.RetryFilter.RetryOn) > 0 { - destination.RetryOn = rule.Filters.RetryFilter.RetryOn - } - - if len(rule.Filters.RetryFilter.RetryOnStatusCodes) > 0 { - destination.RetryOnStatusCodes = rule.Filters.RetryFilter.RetryOnStatusCodes - } - } - - if rule.Filters.TimeoutFilter != nil { - destination.IdleTimeout = rule.Filters.TimeoutFilter.IdleTimeout - destination.RequestTimeout = rule.Filters.TimeoutFilter.RequestTimeout - } - // for each match rule a ServiceRoute is created for the service-router // if there are no rules a single route with the destination is set if len(rule.Matches) == 0 { @@ -195,7 +173,6 @@ func httpRouteToDiscoveryChain(route structs.HTTPRouteConfigEntry) (*structs.Ser Destination: &destination, }) } - } return router, splitters, defaults diff --git a/agent/consul/discoverychain/gateway_tcproute.go b/agent/consul/discoverychain/gateway_tcproute.go index 910fd517551c0..21afef3ec1846 100644 --- a/agent/consul/discoverychain/gateway_tcproute.go +++ b/agent/consul/discoverychain/gateway_tcproute.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package discoverychain diff --git a/agent/consul/discoverychain/gateway_test.go b/agent/consul/discoverychain/gateway_test.go index 4e56a3925463a..42bbed65ebfb6 100644 --- a/agent/consul/discoverychain/gateway_test.go +++ b/agent/consul/discoverychain/gateway_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package discoverychain diff --git a/agent/consul/discoverychain/string_stack.go b/agent/consul/discoverychain/string_stack.go index d5f842f3dc615..e47743a3f3861 100644 --- a/agent/consul/discoverychain/string_stack.go +++ b/agent/consul/discoverychain/string_stack.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package discoverychain diff --git a/agent/consul/discoverychain/string_stack_test.go b/agent/consul/discoverychain/string_stack_test.go index 9867b91795206..84f58203d43b2 100644 --- a/agent/consul/discoverychain/string_stack_test.go +++ b/agent/consul/discoverychain/string_stack_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package discoverychain diff --git a/agent/consul/discoverychain/testing.go b/agent/consul/discoverychain/testing.go index 8992870f9c457..37a3bb4ec1162 100644 --- a/agent/consul/discoverychain/testing.go +++ b/agent/consul/discoverychain/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package discoverychain diff --git a/agent/consul/enterprise_client_ce.go b/agent/consul/enterprise_client_ce.go index b19705f65b7e4..3d432213bd848 100644 --- a/agent/consul/enterprise_client_ce.go +++ b/agent/consul/enterprise_client_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/enterprise_config_ce.go b/agent/consul/enterprise_config_ce.go index d057012af1511..15af4ea1603e7 100644 --- a/agent/consul/enterprise_config_ce.go +++ b/agent/consul/enterprise_config_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/enterprise_server_ce.go b/agent/consul/enterprise_server_ce.go index d14cb7bac33c5..8e56a8108cb35 100644 --- a/agent/consul/enterprise_server_ce.go +++ b/agent/consul/enterprise_server_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/enterprise_server_ce_test.go b/agent/consul/enterprise_server_ce_test.go index bd49bae1b10b9..9bd3eb8c0c9b0 100644 --- a/agent/consul/enterprise_server_ce_test.go +++ b/agent/consul/enterprise_server_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/federation_state_endpoint.go b/agent/consul/federation_state_endpoint.go index 4afa481a397b6..db842e666d65d 100644 --- a/agent/consul/federation_state_endpoint.go +++ b/agent/consul/federation_state_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/federation_state_endpoint_test.go b/agent/consul/federation_state_endpoint_test.go index 2ada2fc17a469..977de1c9c193c 100644 --- a/agent/consul/federation_state_endpoint_test.go +++ b/agent/consul/federation_state_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/federation_state_replication.go b/agent/consul/federation_state_replication.go index 2f5a6dd150f31..f56c3c6089c73 100644 --- a/agent/consul/federation_state_replication.go +++ b/agent/consul/federation_state_replication.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/federation_state_replication_test.go b/agent/consul/federation_state_replication_test.go index 97a34b8dc8c16..5100e45926a13 100644 --- a/agent/consul/federation_state_replication_test.go +++ b/agent/consul/federation_state_replication_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/filter.go b/agent/consul/filter.go index 920b8e843676f..18643463690ee 100644 --- a/agent/consul/filter.go +++ b/agent/consul/filter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/filter_test.go b/agent/consul/filter_test.go index 1ca34b0ed0726..d8f6ba54c3232 100644 --- a/agent/consul/filter_test.go +++ b/agent/consul/filter_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/flood.go b/agent/consul/flood.go index e01b5ed97eb83..ee7dfbc1dd5ec 100644 --- a/agent/consul/flood.go +++ b/agent/consul/flood.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/fsm/commands_ce.go b/agent/consul/fsm/commands_ce.go index c5e7fd968238b..e9f9f66e3361e 100644 --- a/agent/consul/fsm/commands_ce.go +++ b/agent/consul/fsm/commands_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package fsm diff --git a/agent/consul/fsm/commands_ce_test.go b/agent/consul/fsm/commands_ce_test.go index 445f4c0190760..cea6f05f54f3f 100644 --- a/agent/consul/fsm/commands_ce_test.go +++ b/agent/consul/fsm/commands_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package fsm diff --git a/agent/consul/fsm/fsm.go b/agent/consul/fsm/fsm.go index 92a3931b5b331..4357ad7c39e2b 100644 --- a/agent/consul/fsm/fsm.go +++ b/agent/consul/fsm/fsm.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package fsm diff --git a/agent/consul/fsm/fsm_test.go b/agent/consul/fsm/fsm_test.go index 839401014b52e..aa31615a5aa7a 100644 --- a/agent/consul/fsm/fsm_test.go +++ b/agent/consul/fsm/fsm_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package fsm diff --git a/agent/consul/fsm/log_verification_chunking_shim.go b/agent/consul/fsm/log_verification_chunking_shim.go index 4f40c1820b74d..a74b92b5684d3 100644 --- a/agent/consul/fsm/log_verification_chunking_shim.go +++ b/agent/consul/fsm/log_verification_chunking_shim.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package fsm diff --git a/agent/consul/fsm/snapshot.go b/agent/consul/fsm/snapshot.go index c01d2c9f2dd4b..c49cefd3a9937 100644 --- a/agent/consul/fsm/snapshot.go +++ b/agent/consul/fsm/snapshot.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package fsm diff --git a/agent/consul/fsm/snapshot_ce.go b/agent/consul/fsm/snapshot_ce.go index bbe5e0693eaa7..f563ba21a19f3 100644 --- a/agent/consul/fsm/snapshot_ce.go +++ b/agent/consul/fsm/snapshot_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package fsm diff --git a/agent/consul/fsm/snapshot_ce_test.go b/agent/consul/fsm/snapshot_ce_test.go index 5bc389dffa4ac..b08e75716f385 100644 --- a/agent/consul/fsm/snapshot_ce_test.go +++ b/agent/consul/fsm/snapshot_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/fsm/snapshot_test.go b/agent/consul/fsm/snapshot_test.go index ff975aaf9f034..3e16efb190728 100644 --- a/agent/consul/fsm/snapshot_test.go +++ b/agent/consul/fsm/snapshot_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package fsm diff --git a/agent/consul/gateway_locator.go b/agent/consul/gateway_locator.go index 6503ca0c979d5..8f8ca29fbb469 100644 --- a/agent/consul/gateway_locator.go +++ b/agent/consul/gateway_locator.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/gateway_locator_test.go b/agent/consul/gateway_locator_test.go index a3e9da3d69007..f9b1daf26d825 100644 --- a/agent/consul/gateway_locator_test.go +++ b/agent/consul/gateway_locator_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/gateways/controller_gateways.go b/agent/consul/gateways/controller_gateways.go index fe8ddbcedc6fc..cf4f25aa5d46d 100644 --- a/agent/consul/gateways/controller_gateways.go +++ b/agent/consul/gateways/controller_gateways.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package gateways diff --git a/agent/consul/gateways/controller_gateways_test.go b/agent/consul/gateways/controller_gateways_test.go index 7877ab357ed9a..07d85357acdc7 100644 --- a/agent/consul/gateways/controller_gateways_test.go +++ b/agent/consul/gateways/controller_gateways_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package gateways diff --git a/agent/consul/grpc_integration_test.go b/agent/consul/grpc_integration_test.go index 6ae49e09fa3aa..678403a450409 100644 --- a/agent/consul/grpc_integration_test.go +++ b/agent/consul/grpc_integration_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/health_endpoint.go b/agent/consul/health_endpoint.go index d26bbcd3b6f2f..c1286cce172fd 100644 --- a/agent/consul/health_endpoint.go +++ b/agent/consul/health_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/health_endpoint_test.go b/agent/consul/health_endpoint_test.go index b47159c229424..21a83ea90db2e 100644 --- a/agent/consul/health_endpoint_test.go +++ b/agent/consul/health_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/helper_test.go b/agent/consul/helper_test.go index d21523b8fecff..0619004c546e6 100644 --- a/agent/consul/helper_test.go +++ b/agent/consul/helper_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/intention_endpoint.go b/agent/consul/intention_endpoint.go index a3e4ad678b1d3..b00ebfbb46f0d 100644 --- a/agent/consul/intention_endpoint.go +++ b/agent/consul/intention_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/intention_endpoint_test.go b/agent/consul/intention_endpoint_test.go index d7e469b80326f..fb7dcaebf5737 100644 --- a/agent/consul/intention_endpoint_test.go +++ b/agent/consul/intention_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/internal_endpoint.go b/agent/consul/internal_endpoint.go index 1a8a0fca3028e..16dab8c22f87b 100644 --- a/agent/consul/internal_endpoint.go +++ b/agent/consul/internal_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/internal_endpoint_test.go b/agent/consul/internal_endpoint_test.go index 3f853df7ceb22..d7da66244336b 100644 --- a/agent/consul/internal_endpoint_test.go +++ b/agent/consul/internal_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/issue_test.go b/agent/consul/issue_test.go index 17624400fe3f1..14928a9db99d1 100644 --- a/agent/consul/issue_test.go +++ b/agent/consul/issue_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/kvs_endpoint.go b/agent/consul/kvs_endpoint.go index 65dc2cd56d40f..183f95f7f8bf0 100644 --- a/agent/consul/kvs_endpoint.go +++ b/agent/consul/kvs_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/kvs_endpoint_test.go b/agent/consul/kvs_endpoint_test.go index dc4272c4bd55d..ca9960f4b6e4e 100644 --- a/agent/consul/kvs_endpoint_test.go +++ b/agent/consul/kvs_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader.go b/agent/consul/leader.go index fcbf794541f3d..17408d4ef4419 100644 --- a/agent/consul/leader.go +++ b/agent/consul/leader.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader_ce_test.go b/agent/consul/leader_ce_test.go index 9e5e2d34ffdd8..7ff6f64ee193d 100644 --- a/agent/consul/leader_ce_test.go +++ b/agent/consul/leader_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/leader_connect.go b/agent/consul/leader_connect.go index 794820786f576..f872508bbcf90 100644 --- a/agent/consul/leader_connect.go +++ b/agent/consul/leader_connect.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader_connect_ca.go b/agent/consul/leader_connect_ca.go index 00b3712028429..717c9ff0b2544 100644 --- a/agent/consul/leader_connect_ca.go +++ b/agent/consul/leader_connect_ca.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader_connect_ca_test.go b/agent/consul/leader_connect_ca_test.go index b3e8fdc9d0edb..e1c2cf8506c29 100644 --- a/agent/consul/leader_connect_ca_test.go +++ b/agent/consul/leader_connect_ca_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul @@ -566,7 +566,7 @@ func TestCAManager_Initialize_Logging(t *testing.T) { deps := newDefaultDeps(t, conf1) deps.Logger = logger - s1, err := NewServer(conf1, deps, grpc.NewServer(), nil, logger, nil) + s1, err := NewServer(conf1, deps, grpc.NewServer(), nil, logger) require.NoError(t, err) defer s1.Shutdown() testrpc.WaitForLeader(t, s1.RPC, "dc1") diff --git a/agent/consul/leader_connect_test.go b/agent/consul/leader_connect_test.go index d9150c3a4545b..539226b297d3d 100644 --- a/agent/consul/leader_connect_test.go +++ b/agent/consul/leader_connect_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader_federation_state_ae.go b/agent/consul/leader_federation_state_ae.go index 870dc5460e2b0..fa46bea770b3a 100644 --- a/agent/consul/leader_federation_state_ae.go +++ b/agent/consul/leader_federation_state_ae.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader_federation_state_ae_test.go b/agent/consul/leader_federation_state_ae_test.go index ca5ac47b7a974..ef3333da31dac 100644 --- a/agent/consul/leader_federation_state_ae_test.go +++ b/agent/consul/leader_federation_state_ae_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader_intentions.go b/agent/consul/leader_intentions.go index 52736838aec81..cf0844d3ff5cd 100644 --- a/agent/consul/leader_intentions.go +++ b/agent/consul/leader_intentions.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader_intentions_ce.go b/agent/consul/leader_intentions_ce.go index 98acecf918fdd..83880d31de371 100644 --- a/agent/consul/leader_intentions_ce.go +++ b/agent/consul/leader_intentions_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/leader_intentions_ce_test.go b/agent/consul/leader_intentions_ce_test.go index 3e689d40a8067..7d144fb2e98e7 100644 --- a/agent/consul/leader_intentions_ce_test.go +++ b/agent/consul/leader_intentions_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/leader_intentions_test.go b/agent/consul/leader_intentions_test.go index fc868bc747fc1..2de1b97dd7e10 100644 --- a/agent/consul/leader_intentions_test.go +++ b/agent/consul/leader_intentions_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader_log_verification.go b/agent/consul/leader_log_verification.go index 32a23dd3f5c06..ef32ce17904ea 100644 --- a/agent/consul/leader_log_verification.go +++ b/agent/consul/leader_log_verification.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader_metrics.go b/agent/consul/leader_metrics.go index e210b2ffd9333..188e409e3bbd1 100644 --- a/agent/consul/leader_metrics.go +++ b/agent/consul/leader_metrics.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader_metrics_test.go b/agent/consul/leader_metrics_test.go index e3636e1bcf8c9..96e7a0d75d971 100644 --- a/agent/consul/leader_metrics_test.go +++ b/agent/consul/leader_metrics_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader_peering.go b/agent/consul/leader_peering.go index 0f58ed08f491e..32f220164b64c 100644 --- a/agent/consul/leader_peering.go +++ b/agent/consul/leader_peering.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader_peering_test.go b/agent/consul/leader_peering_test.go index 8db496273d281..0787115ca70ac 100644 --- a/agent/consul/leader_peering_test.go +++ b/agent/consul/leader_peering_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/leader_test.go b/agent/consul/leader_test.go index 7a4b63eb05ee9..8a5a158ce34a3 100644 --- a/agent/consul/leader_test.go +++ b/agent/consul/leader_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul @@ -1640,7 +1640,7 @@ func TestLeader_ConfigEntryBootstrap_Fail(t *testing.T) { deps := newDefaultDeps(t, config) deps.Logger = logger - srv, err := NewServer(config, deps, grpc.NewServer(), nil, logger, nil) + srv, err := NewServer(config, deps, grpc.NewServer(), nil, logger) require.NoError(t, err) defer srv.Shutdown() diff --git a/agent/consul/logging.go b/agent/consul/logging.go index cfafe62b0d31f..da07daa8febfa 100644 --- a/agent/consul/logging.go +++ b/agent/consul/logging.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/logging_test.go b/agent/consul/logging_test.go index 3b756c0bb6226..7f090992a7a26 100644 --- a/agent/consul/logging_test.go +++ b/agent/consul/logging_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/merge.go b/agent/consul/merge.go index f6771d110f0ce..21b59f1aa92d6 100644 --- a/agent/consul/merge.go +++ b/agent/consul/merge.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/merge_ce.go b/agent/consul/merge_ce.go index 83e8f5343d4ca..59704f6533203 100644 --- a/agent/consul/merge_ce.go +++ b/agent/consul/merge_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/merge_ce_test.go b/agent/consul/merge_ce_test.go index 5213907d1bcb8..8b0a7514ab264 100644 --- a/agent/consul/merge_ce_test.go +++ b/agent/consul/merge_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/merge_test.go b/agent/consul/merge_test.go index bc9d1f2cb4da8..f5f5c6d88ff1c 100644 --- a/agent/consul/merge_test.go +++ b/agent/consul/merge_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/multilimiter/multilimiter.go b/agent/consul/multilimiter/multilimiter.go index a0b9a6044f0df..f40e6c501abe6 100644 --- a/agent/consul/multilimiter/multilimiter.go +++ b/agent/consul/multilimiter/multilimiter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package multilimiter diff --git a/agent/consul/multilimiter/multilimiter_test.go b/agent/consul/multilimiter/multilimiter_test.go index e7cdab4e14824..b649bdb6c9c95 100644 --- a/agent/consul/multilimiter/multilimiter_test.go +++ b/agent/consul/multilimiter/multilimiter_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package multilimiter diff --git a/agent/consul/operator_autopilot_endpoint.go b/agent/consul/operator_autopilot_endpoint.go index 39bd5b648ddb8..b6ef7d38e6565 100644 --- a/agent/consul/operator_autopilot_endpoint.go +++ b/agent/consul/operator_autopilot_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/operator_autopilot_endpoint_test.go b/agent/consul/operator_autopilot_endpoint_test.go index 4cef3f0960d42..c9258e9aa2705 100644 --- a/agent/consul/operator_autopilot_endpoint_test.go +++ b/agent/consul/operator_autopilot_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/operator_backend.go b/agent/consul/operator_backend.go index 136baa1a22ab1..a72128735ab3c 100644 --- a/agent/consul/operator_backend.go +++ b/agent/consul/operator_backend.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/operator_backend_test.go b/agent/consul/operator_backend_test.go index 0a4650359ec1e..2189fe00630c7 100644 --- a/agent/consul/operator_backend_test.go +++ b/agent/consul/operator_backend_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/operator_endpoint.go b/agent/consul/operator_endpoint.go index 67259c9408a95..33e73e6ee1df9 100644 --- a/agent/consul/operator_endpoint.go +++ b/agent/consul/operator_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/operator_raft_endpoint.go b/agent/consul/operator_raft_endpoint.go index b8a16fc2c3ec9..7b0bcbc5cc035 100644 --- a/agent/consul/operator_raft_endpoint.go +++ b/agent/consul/operator_raft_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/operator_raft_endpoint_test.go b/agent/consul/operator_raft_endpoint_test.go index bb2dc88fc89e3..7242c40e6c45a 100644 --- a/agent/consul/operator_raft_endpoint_test.go +++ b/agent/consul/operator_raft_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/operator_usage_endpoint.go b/agent/consul/operator_usage_endpoint.go index 68f3137d0a61f..d23815b147c7d 100644 --- a/agent/consul/operator_usage_endpoint.go +++ b/agent/consul/operator_usage_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/options.go b/agent/consul/options.go index fa2781b83d095..26cb2471a89bc 100644 --- a/agent/consul/options.go +++ b/agent/consul/options.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul @@ -16,7 +16,6 @@ import ( "github.com/hashicorp/consul/agent/router" "github.com/hashicorp/consul/agent/rpc/middleware" "github.com/hashicorp/consul/agent/token" - "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/tlsutil" ) @@ -30,7 +29,6 @@ type Deps struct { GRPCConnPool GRPCClientConner LeaderForwarder LeaderForwarder XDSStreamLimiter *limiter.SessionLimiter - Registry resource.Registry // GetNetRPCInterceptorFunc, if not nil, sets the net/rpc rpc.ServerServiceCallInterceptor on // the server side to record metrics around the RPC requests. If nil, no interceptor is added to // the rpc server. diff --git a/agent/consul/options_ce.go b/agent/consul/options_ce.go index 0b4d04a66a74b..7604ddd87f925 100644 --- a/agent/consul/options_ce.go +++ b/agent/consul/options_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/peering_backend.go b/agent/consul/peering_backend.go index 5a27bc6442a1d..1771be10fbaac 100644 --- a/agent/consul/peering_backend.go +++ b/agent/consul/peering_backend.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/peering_backend_ce.go b/agent/consul/peering_backend_ce.go index 7b00e1907b695..81a133b3425a0 100644 --- a/agent/consul/peering_backend_ce.go +++ b/agent/consul/peering_backend_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/peering_backend_ce_test.go b/agent/consul/peering_backend_ce_test.go index a8eae8f067de7..410bf5f234273 100644 --- a/agent/consul/peering_backend_ce_test.go +++ b/agent/consul/peering_backend_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/peering_backend_test.go b/agent/consul/peering_backend_test.go index adfe6fe228f95..648052b7a15fe 100644 --- a/agent/consul/peering_backend_test.go +++ b/agent/consul/peering_backend_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/prepared_query/template.go b/agent/consul/prepared_query/template.go index 03cf9d2f58505..ef2e2abd4cae4 100644 --- a/agent/consul/prepared_query/template.go +++ b/agent/consul/prepared_query/template.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package prepared_query diff --git a/agent/consul/prepared_query/template_test.go b/agent/consul/prepared_query/template_test.go index 7c9b2f1a3af29..d4f78402140de 100644 --- a/agent/consul/prepared_query/template_test.go +++ b/agent/consul/prepared_query/template_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package prepared_query diff --git a/agent/consul/prepared_query/walk.go b/agent/consul/prepared_query/walk.go index 72296c0c7fe64..da53ce105b5f3 100644 --- a/agent/consul/prepared_query/walk.go +++ b/agent/consul/prepared_query/walk.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package prepared_query diff --git a/agent/consul/prepared_query/walk_ce_test.go b/agent/consul/prepared_query/walk_ce_test.go index 8d19b951c5bfe..dec84b241b0a3 100644 --- a/agent/consul/prepared_query/walk_ce_test.go +++ b/agent/consul/prepared_query/walk_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/prepared_query/walk_test.go b/agent/consul/prepared_query/walk_test.go index b788571e4af5f..9ff380248bd2b 100644 --- a/agent/consul/prepared_query/walk_test.go +++ b/agent/consul/prepared_query/walk_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package prepared_query diff --git a/agent/consul/prepared_query_endpoint.go b/agent/consul/prepared_query_endpoint.go index 139556bb1af8c..101839708ea2f 100644 --- a/agent/consul/prepared_query_endpoint.go +++ b/agent/consul/prepared_query_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/prepared_query_endpoint_ce.go b/agent/consul/prepared_query_endpoint_ce.go index 4f7087806cfe6..612b81b2e6880 100644 --- a/agent/consul/prepared_query_endpoint_ce.go +++ b/agent/consul/prepared_query_endpoint_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/prepared_query_endpoint_ce_test.go b/agent/consul/prepared_query_endpoint_ce_test.go index 3c30daf0a92cb..876f91d42cd5d 100644 --- a/agent/consul/prepared_query_endpoint_ce_test.go +++ b/agent/consul/prepared_query_endpoint_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/prepared_query_endpoint_test.go b/agent/consul/prepared_query_endpoint_test.go index f0d63dc277c18..af1fd65a876d1 100644 --- a/agent/consul/prepared_query_endpoint_test.go +++ b/agent/consul/prepared_query_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul @@ -2808,7 +2808,7 @@ func TestPreparedQuery_Wrapper(t *testing.T) { t.Fatalf("bad: %v", ret) } // Since we have no idea when the joinWAN operation completes - // we keep on querying until the join operation completes. + // we keep on querying until the the join operation completes. retry.Run(t, func(r *retry.R) { r.Check(s1.forwardDC("Status.Ping", "dc2", &struct{}{}, &struct{}{})) }) diff --git a/agent/consul/raft_handle.go b/agent/consul/raft_handle.go index 2906fe7115f19..bf38f0ee9e767 100644 --- a/agent/consul/raft_handle.go +++ b/agent/consul/raft_handle.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/raft_rpc.go b/agent/consul/raft_rpc.go index 1a0d6caa64d4a..7928ad31e2b9a 100644 --- a/agent/consul/raft_rpc.go +++ b/agent/consul/raft_rpc.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/rate/handler.go b/agent/consul/rate/handler.go index bb3aef63931dd..c18ec85eddc8d 100644 --- a/agent/consul/rate/handler.go +++ b/agent/consul/rate/handler.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package rate implements server-side RPC rate limiting. package rate diff --git a/agent/consul/rate/handler_ce.go b/agent/consul/rate/handler_ce.go index b9ec451869a3a..fc33a69487f88 100644 --- a/agent/consul/rate/handler_ce.go +++ b/agent/consul/rate/handler_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/rate/handler_test.go b/agent/consul/rate/handler_test.go index 268568ce9599c..54a8b86a4b989 100644 --- a/agent/consul/rate/handler_test.go +++ b/agent/consul/rate/handler_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package rate diff --git a/agent/consul/rate/metrics.go b/agent/consul/rate/metrics.go index ac69c14661776..cbf796fa935c6 100644 --- a/agent/consul/rate/metrics.go +++ b/agent/consul/rate/metrics.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package rate diff --git a/agent/consul/replication.go b/agent/consul/replication.go index 08b8811129bea..0d85d082653cb 100644 --- a/agent/consul/replication.go +++ b/agent/consul/replication.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/replication_test.go b/agent/consul/replication_test.go index 27000fc563b78..e37e19b1f2933 100644 --- a/agent/consul/replication_test.go +++ b/agent/consul/replication_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/reporting/reporting.go b/agent/consul/reporting/reporting.go index d6c480f6bace4..fec7050f695ba 100644 --- a/agent/consul/reporting/reporting.go +++ b/agent/consul/reporting/reporting.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package reporting diff --git a/agent/consul/reporting/reporting_ce.go b/agent/consul/reporting/reporting_ce.go index 669ca264afdc0..a1e95a177416c 100644 --- a/agent/consul/reporting/reporting_ce.go +++ b/agent/consul/reporting/reporting_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/rpc.go b/agent/consul/rpc.go index dbb781951e348..f97a5ff886746 100644 --- a/agent/consul/rpc.go +++ b/agent/consul/rpc.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/rpc_test.go b/agent/consul/rpc_test.go index 39351c98ca92a..f1b05fa528287 100644 --- a/agent/consul/rpc_test.go +++ b/agent/consul/rpc_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/rtt.go b/agent/consul/rtt.go index 1599301e158df..5db0a634b4352 100644 --- a/agent/consul/rtt.go +++ b/agent/consul/rtt.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/rtt_test.go b/agent/consul/rtt_test.go index aeed0b66f50d5..9420f36c83657 100644 --- a/agent/consul/rtt_test.go +++ b/agent/consul/rtt_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/segment_ce.go b/agent/consul/segment_ce.go index fd3fce459f49a..a3c0162d2a1e2 100644 --- a/agent/consul/segment_ce.go +++ b/agent/consul/segment_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/serf_filter.go b/agent/consul/serf_filter.go index 7b09c2b9e8020..fd6911bf0ab8a 100644 --- a/agent/consul/serf_filter.go +++ b/agent/consul/serf_filter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/serf_test.go b/agent/consul/serf_test.go index 4d4bc4926a46d..62cc6d0a0ba3f 100644 --- a/agent/consul/serf_test.go +++ b/agent/consul/serf_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/server.go b/agent/consul/server.go index ad6e5b23f8b88..6bb424c67535d 100644 --- a/agent/consul/server.go +++ b/agent/consul/server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul @@ -20,7 +20,6 @@ import ( "time" "github.com/armon/go-metrics" - "github.com/hashicorp/consul-net-rpc/net/rpc" "github.com/hashicorp/go-connlimit" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-memdb" @@ -35,7 +34,8 @@ import ( "golang.org/x/time/rate" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - "google.golang.org/grpc/reflection" + + "github.com/hashicorp/consul-net-rpc/net/rpc" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl/resolver" @@ -73,7 +73,6 @@ import ( "github.com/hashicorp/consul/internal/catalog" "github.com/hashicorp/consul/internal/controller" "github.com/hashicorp/consul/internal/mesh" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/internal/resource/reaper" @@ -82,7 +81,6 @@ import ( "github.com/hashicorp/consul/lib/routine" "github.com/hashicorp/consul/lib/stringslice" "github.com/hashicorp/consul/logging" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/proto/private/pbsubscribe" "github.com/hashicorp/consul/tlsutil" @@ -135,7 +133,7 @@ const ( LeaderTransferMinVersion = "1.6.0" - CatalogResourceExperimentName = "resource-apis" + catalogResourceExperimentName = "resource-apis" ) const ( @@ -244,7 +242,7 @@ type Server struct { // serf cluster that spans datacenters eventChWAN chan serf.Event - // wanMembershipNotifyCh is used to receive notifications that the + // wanMembershipNotifyCh is used to receive notifications that the the // serfWAN wan pool may have changed. // // If this is nil, notification is skipped. @@ -441,20 +439,13 @@ type Server struct { // run by the Server routineManager *routine.Manager - // resourceServiceServer implements the Resource Service. - resourceServiceServer *resourcegrpc.Server + // typeRegistry contains Consul's registered resource types. + typeRegistry resource.Registry - // insecureResourceServiceClient is a client that can be used to communicate - // with the Resource Service in-process (i.e. not via the network) *without* - // auth. It should only be used for purely-internal workloads, such as - // controllers. - insecureResourceServiceClient pbresource.ResourceServiceClient - - // secureResourceServiceClient is a client that can be used to communicate - // with the Resource Service in-process (i.e. not via the network) *with* auth. - // It can be used to make requests to the Resource Service on behalf of the user - // (e.g. from the HTTP API). - secureResourceServiceClient pbresource.ResourceServiceClient + // internalResourceServiceClient is a client that can be used to communicate + // with the Resource Service in-process (i.e. not via the network) without auth. + // It should only be used for purely-internal workloads, such as controllers. + internalResourceServiceClient pbresource.ResourceServiceClient // controllerManager schedules the execution of controllers. controllerManager *controller.Manager @@ -481,21 +472,9 @@ type connHandler interface { Shutdown() error } -// ProxyUpdater is an interface for ProxyTracker. -type ProxyUpdater interface { - // PushChange allows pushing a computed ProxyState to xds for xds resource generation to send to a proxy. - PushChange(id *pbresource.ID, snapshot proxysnapshot.ProxySnapshot) error - - // ProxyConnectedToServer returns whether this id is connected to this server. - ProxyConnectedToServer(id *pbresource.ID) bool - - EventChannel() chan controller.Event -} - // NewServer is used to construct a new Consul server from the configuration // and extra options, potentially returning an error. -func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, - incomingRPCLimiter rpcRate.RequestLimitsHandler, serverLogger hclog.InterceptLogger, proxyUpdater ProxyUpdater) (*Server, error) { +func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, incomingRPCLimiter rpcRate.RequestLimitsHandler, serverLogger hclog.InterceptLogger) (*Server, error) { logger := flat.Logger if err := config.CheckProtocolVersion(); err != nil { return nil, err @@ -547,6 +526,7 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, publisher: flat.EventPublisher, incomingRPCLimiter: incomingRPCLimiter, routineManager: routine.NewManager(logger.Named(logging.ConsulServer)), + typeRegistry: resource.NewRegistry(), } incomingRPCLimiter.Register(s) @@ -814,7 +794,7 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, go s.reportingManager.Run(&lib.StopChannelContext{StopCh: s.shutdownCh}) // Initialize external gRPC server - s.setupExternalGRPC(config, flat.Registry, logger) + s.setupExternalGRPC(config, logger) // Initialize internal gRPC server. // @@ -823,19 +803,14 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, s.grpcHandler = newGRPCHandlerFromConfig(flat, config, s) s.grpcLeaderForwarder = flat.LeaderForwarder - if err := s.setupSecureResourceServiceClient(); err != nil { - return nil, err - } - - if err := s.setupInsecureResourceServiceClient(flat.Registry, logger); err != nil { + if err := s.setupInternalResourceService(logger); err != nil { return nil, err } - s.controllerManager = controller.NewManager( - s.insecureResourceServiceClient, + s.internalResourceServiceClient, logger.Named(logging.ControllerRuntime), ) - s.registerControllers(flat, proxyUpdater) + s.registerResources(flat) go s.controllerManager.Run(&lib.StopChannelContext{StopCh: shutdownCh}) go s.trackLeaderChanges() @@ -886,29 +861,18 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, return s, nil } -func (s *Server) registerControllers(deps Deps, proxyUpdater ProxyUpdater) { - if stringslice.Contains(deps.Experiments, CatalogResourceExperimentName) { +func (s *Server) registerResources(deps Deps) { + if stringslice.Contains(deps.Experiments, catalogResourceExperimentName) { + catalog.RegisterTypes(s.typeRegistry) catalog.RegisterControllers(s.controllerManager, catalog.DefaultControllerDependencies()) - mesh.RegisterControllers(s.controllerManager, mesh.ControllerDependencies{ - TrustBundleFetcher: func() (*pbproxystate.TrustBundle, error) { - var bundle pbproxystate.TrustBundle - roots, err := s.getCARoots(nil, s.GetState()) - if err != nil { - return nil, err - } - bundle.TrustDomain = roots.TrustDomain - for _, root := range roots.Roots { - bundle.Roots = append(bundle.Roots, root.RootCert) - } - return &bundle, nil - }, - ProxyUpdater: proxyUpdater, - }) + + mesh.RegisterTypes(s.typeRegistry) } reaper.RegisterControllers(s.controllerManager) if s.config.DevMode { + demo.RegisterTypes(s.typeRegistry) demo.RegisterControllers(s.controllerManager) } } @@ -965,7 +929,6 @@ func newGRPCHandlerFromConfig(deps Deps, config *Config, s *Server) connHandler s.peerStreamServer.Register(srv) s.externalACLServer.Register(srv) s.externalConnectCAServer.Register(srv) - s.resourceServiceServer.Register(srv) } return agentgrpc.NewHandler(deps.Logger, config.RPCAddr, register, nil, s.incomingRPCLimiter) @@ -1306,7 +1269,7 @@ func (s *Server) setupRPC() error { } // Initialize and register services on external gRPC server. -func (s *Server) setupExternalGRPC(config *Config, typeRegistry resource.Registry, logger hclog.Logger) { +func (s *Server) setupExternalGRPC(config *Config, logger hclog.Logger) { s.externalACLServer = aclgrpc.NewServer(aclgrpc.Config{ ACLsEnabled: s.config.ACLsEnabled, ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { @@ -1371,54 +1334,23 @@ func (s *Server) setupExternalGRPC(config *Config, typeRegistry resource.Registr }) s.peerStreamServer.Register(s.externalGRPCServer) - s.resourceServiceServer = resourcegrpc.NewServer(resourcegrpc.Config{ - Registry: typeRegistry, - Backend: s.raftStorageBackend, - ACLResolver: s.ACLResolver, - Logger: logger.Named("grpc-api.resource"), - V1TenancyBridge: NewV1TenancyBridge(s), - }) - s.resourceServiceServer.Register(s.externalGRPCServer) - - reflection.Register(s.externalGRPCServer) -} - -func (s *Server) setupInsecureResourceServiceClient(typeRegistry resource.Registry, logger hclog.Logger) error { - server := resourcegrpc.NewServer(resourcegrpc.Config{ - Registry: typeRegistry, - Backend: s.raftStorageBackend, - ACLResolver: resolver.DANGER_NO_AUTH{}, - Logger: logger.Named("grpc-api.resource"), - V1TenancyBridge: NewV1TenancyBridge(s), - }) - - conn, err := s.runInProcessGRPCServer(server.Register) - if err != nil { - return err - } - s.insecureResourceServiceClient = pbresource.NewResourceServiceClient(conn) - - return nil -} - -func (s *Server) setupSecureResourceServiceClient() error { - conn, err := s.runInProcessGRPCServer(s.resourceServiceServer.Register) - if err != nil { - return err - } - s.secureResourceServiceClient = pbresource.NewResourceServiceClient(conn) - - return nil + resourcegrpc.NewServer(resourcegrpc.Config{ + Registry: s.typeRegistry, + Backend: s.raftStorageBackend, + ACLResolver: s.ACLResolver, + Logger: logger.Named("grpc-api.resource"), + }).Register(s.externalGRPCServer) } -// runInProcessGRPCServer runs a gRPC server that can only be accessed in the -// same process, rather than over the network, using a pipe listener. -func (s *Server) runInProcessGRPCServer(registerFn ...func(*grpc.Server)) (*grpc.ClientConn, error) { +func (s *Server) setupInternalResourceService(logger hclog.Logger) error { server := grpc.NewServer() - for _, fn := range registerFn { - fn(server) - } + resourcegrpc.NewServer(resourcegrpc.Config{ + Registry: s.typeRegistry, + Backend: s.raftStorageBackend, + ACLResolver: resolver.DANGER_NO_AUTH{}, + Logger: logger.Named("grpc-api.resource"), + }).Register(server) pipe := agentgrpc.NewPipeListener() go server.Serve(pipe) @@ -1435,14 +1367,15 @@ func (s *Server) runInProcessGRPCServer(registerFn ...func(*grpc.Server)) (*grpc ) if err != nil { server.Stop() - return nil, err + return err } go func() { <-s.shutdownCh conn.Close() }() + s.internalResourceServiceClient = pbresource.NewResourceServiceClient(conn) - return conn, nil + return nil } // Shutdown is used to shutdown the server @@ -2162,10 +2095,6 @@ func (s *Server) hcpServerStatus(deps Deps) hcp.StatusCallback { } } -func (s *Server) ResourceServiceClient() pbresource.ResourceServiceClient { - return s.secureResourceServiceClient -} - func fileExists(name string) (bool, error) { _, err := os.Stat(name) if err == nil { diff --git a/agent/consul/server_ce.go b/agent/consul/server_ce.go index ab586a0292c04..22660f490b7f2 100644 --- a/agent/consul/server_ce.go +++ b/agent/consul/server_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/server_ce_test.go b/agent/consul/server_ce_test.go index 472560f2b925d..c1760589a9e14 100644 --- a/agent/consul/server_ce_test.go +++ b/agent/consul/server_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/server_connect.go b/agent/consul/server_connect.go index d76e4fc8c425e..496d059cb4941 100644 --- a/agent/consul/server_connect.go +++ b/agent/consul/server_connect.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/server_log_verification.go b/agent/consul/server_log_verification.go index 2bde7dbc81b40..5646e78760989 100644 --- a/agent/consul/server_log_verification.go +++ b/agent/consul/server_log_verification.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/server_lookup.go b/agent/consul/server_lookup.go index 60b9c076bf148..e1952d671d07d 100644 --- a/agent/consul/server_lookup.go +++ b/agent/consul/server_lookup.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/server_lookup_test.go b/agent/consul/server_lookup_test.go index 52e3605de719b..5d3d3d4e0e42f 100644 --- a/agent/consul/server_lookup_test.go +++ b/agent/consul/server_lookup_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/server_metadata.go b/agent/consul/server_metadata.go index 03e4751a290c2..742391e0b6a1f 100644 --- a/agent/consul/server_metadata.go +++ b/agent/consul/server_metadata.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/server_metadata_test.go b/agent/consul/server_metadata_test.go index bf993bc1be57c..d091bfdf3630e 100644 --- a/agent/consul/server_metadata_test.go +++ b/agent/consul/server_metadata_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/server_overview.go b/agent/consul/server_overview.go index a94749d53498a..62bdb34406121 100644 --- a/agent/consul/server_overview.go +++ b/agent/consul/server_overview.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/server_overview_test.go b/agent/consul/server_overview_test.go index 7780b5ce83967..ebb930a1e2bf2 100644 --- a/agent/consul/server_overview_test.go +++ b/agent/consul/server_overview_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/server_register.go b/agent/consul/server_register.go index 90d95f061956f..61f1daefc7dfa 100644 --- a/agent/consul/server_register.go +++ b/agent/consul/server_register.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/server_serf.go b/agent/consul/server_serf.go index aea50aa6dd199..1dc6c25b1cce5 100644 --- a/agent/consul/server_serf.go +++ b/agent/consul/server_serf.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/server_test.go b/agent/consul/server_test.go index e8058a468a3f9..ebff789b14a5d 100644 --- a/agent/consul/server_test.go +++ b/agent/consul/server_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul @@ -336,7 +336,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()) - srv, err := NewServer(c, deps, grpcServer, nil, deps.Logger, nil) + srv, err := NewServer(c, deps, grpcServer, nil, deps.Logger) if err != nil { return nil, err } @@ -1243,7 +1243,7 @@ func TestServer_RPC_MetricsIntercept_Off(t *testing.T) { } } - s1, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger, nil) + s1, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger) if err != nil { t.Fatalf("err: %v", err) } @@ -1281,7 +1281,7 @@ func TestServer_RPC_MetricsIntercept_Off(t *testing.T) { return nil } - s2, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger, nil) + s2, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger) if err != nil { t.Fatalf("err: %v", err) } @@ -1315,7 +1315,7 @@ func TestServer_RPC_RequestRecorder(t *testing.T) { deps := newDefaultDeps(t, conf) deps.NewRequestRecorderFunc = nil - s1, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger, nil) + s1, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger) require.Error(t, err, "need err when provider func is nil") require.Equal(t, err.Error(), "cannot initialize server without an RPC request recorder provider") @@ -1334,7 +1334,7 @@ func TestServer_RPC_RequestRecorder(t *testing.T) { return nil } - s2, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger, nil) + s2, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger) require.Error(t, err, "need err when RequestRecorder is nil") require.Equal(t, err.Error(), "cannot initialize server with a nil RPC request recorder") diff --git a/agent/consul/servercert/manager.go b/agent/consul/servercert/manager.go index 664753439477d..75c2a4f276082 100644 --- a/agent/consul/servercert/manager.go +++ b/agent/consul/servercert/manager.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package servercert diff --git a/agent/consul/servercert/manager_test.go b/agent/consul/servercert/manager_test.go index e9cc0c81c58c1..dfadfe4b953fb 100644 --- a/agent/consul/servercert/manager_test.go +++ b/agent/consul/servercert/manager_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package servercert diff --git a/agent/consul/session_endpoint.go b/agent/consul/session_endpoint.go index f2f8ab7740234..6e41138f983c6 100644 --- a/agent/consul/session_endpoint.go +++ b/agent/consul/session_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/session_endpoint_test.go b/agent/consul/session_endpoint_test.go index 408cd7b058c59..ae04d2658f9a7 100644 --- a/agent/consul/session_endpoint_test.go +++ b/agent/consul/session_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/session_timers.go b/agent/consul/session_timers.go index f1c62b08a8196..b4c1b425cb267 100644 --- a/agent/consul/session_timers.go +++ b/agent/consul/session_timers.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/session_timers_test.go b/agent/consul/session_timers_test.go index f944cc76745d8..d44ed2b366fed 100644 --- a/agent/consul/session_timers_test.go +++ b/agent/consul/session_timers_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/session_ttl.go b/agent/consul/session_ttl.go index 8f5440e14dffa..7866ec8fed198 100644 --- a/agent/consul/session_ttl.go +++ b/agent/consul/session_ttl.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/session_ttl_test.go b/agent/consul/session_ttl_test.go index e552f0ff6cdff..5cd720f3f8933 100644 --- a/agent/consul/session_ttl_test.go +++ b/agent/consul/session_ttl_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/snapshot_endpoint.go b/agent/consul/snapshot_endpoint.go index c9a6e9ace47c8..7e5f21113aebd 100644 --- a/agent/consul/snapshot_endpoint.go +++ b/agent/consul/snapshot_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // The snapshot endpoint is a special non-RPC endpoint that supports streaming // for taking and restoring snapshots for disaster recovery. This gets wired diff --git a/agent/consul/snapshot_endpoint_test.go b/agent/consul/snapshot_endpoint_test.go index 40bede9149743..f401bb72e38d0 100644 --- a/agent/consul/snapshot_endpoint_test.go +++ b/agent/consul/snapshot_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/state/acl.go b/agent/consul/state/acl.go index f82b671b18b6a..f57c3387352de 100644 --- a/agent/consul/state/acl.go +++ b/agent/consul/state/acl.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state @@ -623,8 +623,35 @@ func aclTokenGetTxn(tx ReadTxn, ws memdb.WatchSet, value, index string, entMeta return nil, nil } +type ACLTokenListParameters struct { + Local bool + Global bool + Policy string + Role string + ServiceName string + MethodName string + MethodMeta *acl.EnterpriseMeta + EnterpriseMeta *acl.EnterpriseMeta +} + // ACLTokenList return a list of ACL Tokens that match the policy, role, and method. +// This function should be treated as deprecated, and ACLTokenListWithParameters should be preferred. +// +// Deprecated: use ACLTokenListWithParameters func (s *Store) ACLTokenList(ws memdb.WatchSet, local, global bool, policy, role, methodName string, methodMeta, entMeta *acl.EnterpriseMeta) (uint64, structs.ACLTokens, error) { + return s.ACLTokenListWithParameters(ws, ACLTokenListParameters{ + Local: local, + Global: global, + Policy: policy, + Role: role, + MethodName: methodName, + MethodMeta: methodMeta, + EnterpriseMeta: entMeta, + }) +} + +// ACLTokenListWithParameters returns a list of ACL Tokens that match the provided parameters. +func (s *Store) ACLTokenListWithParameters(ws memdb.WatchSet, params ACLTokenListParameters) (uint64, structs.ACLTokens, error) { tx := s.db.Txn(false) defer tx.Abort() @@ -637,43 +664,51 @@ func (s *Store) ACLTokenList(ws memdb.WatchSet, local, global bool, policy, role needLocalityFilter := false - if policy == "" && role == "" && methodName == "" { - if global == local { - iter, err = aclTokenListAll(tx, entMeta) + if params.Policy == "" && params.Role == "" && params.MethodName == "" && params.ServiceName == "" { + if params.Global == params.Local { + iter, err = aclTokenListAll(tx, params.EnterpriseMeta) } else { - iter, err = aclTokenList(tx, entMeta, local) + iter, err = aclTokenList(tx, params.EnterpriseMeta, params.Local) } - } else if policy != "" && role == "" && methodName == "" { - iter, err = aclTokenListByPolicy(tx, policy, entMeta) + } else if params.Policy != "" && params.Role == "" && params.MethodName == "" && params.ServiceName == "" { + // Find by policy + iter, err = aclTokenListByPolicy(tx, params.Policy, params.EnterpriseMeta) + needLocalityFilter = true + + } else if params.Policy == "" && params.Role != "" && params.MethodName == "" && params.ServiceName == "" { + // Find by role + iter, err = aclTokenListByRole(tx, params.Role, params.EnterpriseMeta) needLocalityFilter = true - } else if policy == "" && role != "" && methodName == "" { - iter, err = aclTokenListByRole(tx, role, entMeta) + } else if params.Policy == "" && params.Role == "" && params.MethodName != "" && params.ServiceName == "" { + // Find by methodName + iter, err = aclTokenListByAuthMethod(tx, params.MethodName, params.MethodMeta, params.EnterpriseMeta) needLocalityFilter = true - } else if policy == "" && role == "" && methodName != "" { - iter, err = aclTokenListByAuthMethod(tx, methodName, methodMeta, entMeta) + } else if params.Policy == "" && params.Role == "" && params.MethodName == "" && params.ServiceName != "" { + // Find by the service identity's serviceName + iter, err = aclTokenListByServiceName(tx, params.ServiceName, params.EnterpriseMeta) needLocalityFilter = true } else { - return 0, nil, fmt.Errorf("can only filter by one of policy, role, or methodName at a time") + return 0, nil, fmt.Errorf("can only filter by one of policy, role, serviceName, or methodName at a time") } if err != nil { return 0, nil, fmt.Errorf("failed acl token lookup: %v", err) } - if needLocalityFilter && global != local { + if needLocalityFilter && params.Global != params.Local { iter = memdb.NewFilterIterator(iter, func(raw interface{}) bool { token, ok := raw.(*structs.ACLToken) if !ok { return true } - if global && !token.Local { + if params.Global && !token.Local { return false - } else if local && token.Local { + } else if params.Local && token.Local { return false } @@ -698,7 +733,7 @@ func (s *Store) ACLTokenList(ws memdb.WatchSet, local, global bool, policy, role } // Get the table index. - idx := aclTokenMaxIndex(tx, nil, entMeta) + idx := aclTokenMaxIndex(tx, nil, params.EnterpriseMeta) return idx, result, nil } diff --git a/agent/consul/state/acl_ce.go b/agent/consul/state/acl_ce.go index ee0a8eb5ee64b..33b3b5986fcaa 100644 --- a/agent/consul/state/acl_ce.go +++ b/agent/consul/state/acl_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent @@ -76,6 +76,10 @@ func aclTokenListByAuthMethod(tx ReadTxn, authMethod string, _, _ *acl.Enterpris return tx.Get(tableACLTokens, indexAuthMethod, AuthMethodQuery{Value: authMethod}) } +func aclTokenListByServiceName(tx ReadTxn, serviceName string, entMeta *acl.EnterpriseMeta) (memdb.ResultIterator, error) { + return tx.Get(tableACLTokens, indexServiceName, Query{Value: serviceName}) +} + func aclTokenDeleteWithToken(tx WriteTxn, token *structs.ACLToken, idx uint64) error { // remove the token if err := tx.Delete(tableACLTokens, token); err != nil { diff --git a/agent/consul/state/acl_ce_test.go b/agent/consul/state/acl_ce_test.go index 38cf2ebcda1fa..4d3bcdcfc00b7 100644 --- a/agent/consul/state/acl_ce_test.go +++ b/agent/consul/state/acl_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/acl_events.go b/agent/consul/state/acl_events.go index d00062c23bac9..3767d2d2d1542 100644 --- a/agent/consul/state/acl_events.go +++ b/agent/consul/state/acl_events.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/acl_events_test.go b/agent/consul/state/acl_events_test.go index 3c6e3fdfab174..303d54a25be1b 100644 --- a/agent/consul/state/acl_events_test.go +++ b/agent/consul/state/acl_events_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/acl_schema.go b/agent/consul/state/acl_schema.go index cdee3ed9fff4e..75ca0f3a26893 100644 --- a/agent/consul/state/acl_schema.go +++ b/agent/consul/state/acl_schema.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state @@ -22,6 +22,7 @@ const ( indexAccessor = "accessor" indexPolicies = "policies" indexRoles = "roles" + indexServiceName = "service-name" indexAuthMethod = "authmethod" indexLocality = "locality" indexName = "name" @@ -106,6 +107,15 @@ func tokensTableSchema() *memdb.TableSchema { writeIndex: indexExpiresLocalFromACLToken, }, }, + indexServiceName: { + Name: indexServiceName, + AllowMissing: true, + Unique: false, + Indexer: indexerMulti[Query, *structs.ACLToken]{ + readIndex: indexFromQuery, + writeIndexMulti: indexServiceNameFromACLToken, + }, + }, }, } } @@ -398,6 +408,21 @@ func indexExpiresFromACLToken(t *structs.ACLToken, local bool) ([]byte, error) { return b.Bytes(), nil } +func indexServiceNameFromACLToken(token *structs.ACLToken) ([][]byte, error) { + vals := make([][]byte, 0, len(token.ServiceIdentities)) + for _, id := range token.ServiceIdentities { + if id != nil && id.ServiceName != "" { + var b indexBuilder + b.String(strings.ToLower(id.ServiceName)) + vals = append(vals, b.Bytes()) + } + } + if len(vals) == 0 { + return nil, errMissingValueForIndex + } + return vals, nil +} + func authMethodsTableSchema() *memdb.TableSchema { return &memdb.TableSchema{ Name: tableACLAuthMethods, diff --git a/agent/consul/state/acl_test.go b/agent/consul/state/acl_test.go index 330c0689aafc0..3c58cb2923184 100644 --- a/agent/consul/state/acl_test.go +++ b/agent/consul/state/acl_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state @@ -214,6 +214,7 @@ func TestStateStore_ACLBootstrap(t *testing.T) { require.Equal(t, uint64(3), index) // Make sure the ACLs are in an expected state. + // nolint:staticcheck _, tokens, err := s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) require.Len(t, tokens, 1) @@ -228,6 +229,7 @@ func TestStateStore_ACLBootstrap(t *testing.T) { err = s.ACLBootstrap(32, index, token2.Clone()) require.NoError(t, err) + // nolint:staticcheck _, tokens, err = s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) require.Len(t, tokens, 2) @@ -849,18 +851,36 @@ func TestStateStore_ACLToken_List(t *testing.T) { AuthMethod: "test", Local: true, }, + // the serviceName specific token + &structs.ACLToken{ + AccessorID: "80c900e1-2fc5-4685-ae29-1b2d17fc30e4", + SecretID: "9d229cfd-ec4b-4d31-a6fd-ecbcb2a41d41", + ServiceIdentities: []*structs.ACLServiceIdentity{ + {ServiceName: "sn1"}, + }, + }, + // the serviceName specific token and local + &structs.ACLToken{ + AccessorID: "a14fa45e-0afe-4b44-961d-a430030ccfe2", + SecretID: "17f696b9-448a-4bd3-936b-08c92c66530f", + ServiceIdentities: []*structs.ACLServiceIdentity{ + {ServiceName: "sn1"}, + }, + Local: true, + }, } require.NoError(t, s.ACLTokenBatchSet(2, tokens, ACLTokenSetOptions{})) type testCase struct { - name string - local bool - global bool - policy string - role string - methodName string - accessors []string + name string + local bool + global bool + policy string + role string + methodName string + serviceName string + accessors []string } cases := []testCase{ @@ -876,6 +896,7 @@ func TestStateStore_ACLToken_List(t *testing.T) { "47eea4da-bda1-48a6-901c-3e36d2d9262f", // policy + global "54866514-3cf2-4fec-8a8a-710583831834", // mgmt + global "74277ae1-6a9b-4035-b444-2370fe6a2cb5", // authMethod + global + "80c900e1-2fc5-4685-ae29-1b2d17fc30e4", // serviceName + global "a7715fde-8954-4c92-afbc-d84c6ecdc582", // role + global }, }, @@ -889,6 +910,7 @@ func TestStateStore_ACLToken_List(t *testing.T) { accessors: []string{ "211f0360-ef53-41d3-9d4d-db84396eb6c0", // authMethod + local "4915fc9d-3726-4171-b588-6c271f45eecd", // policy + local + "a14fa45e-0afe-4b44-961d-a430030ccfe2", // serviceName + local "cadb4f13-f62a-49ab-ab3f-5a7e01b925d9", // role + local "f1093997-b6c7-496d-bfb8-6b1b1895641b", // mgmt + local }, @@ -983,6 +1005,30 @@ func TestStateStore_ACLToken_List(t *testing.T) { "74277ae1-6a9b-4035-b444-2370fe6a2cb5", // authMethod + global }, }, + { + name: "ServiceName - Local", + local: true, + global: false, + policy: "", + role: "", + methodName: "", + serviceName: "sn1", + accessors: []string{ + "a14fa45e-0afe-4b44-961d-a430030ccfe2", // serviceName + local + }, + }, + { + name: "ServiceName - Global", + local: false, + global: true, + policy: "", + role: "", + methodName: "", + serviceName: "sn1", + accessors: []string{ + "80c900e1-2fc5-4685-ae29-1b2d17fc30e4", // serviceName + global + }, + }, { name: "All", local: true, @@ -997,6 +1043,8 @@ func TestStateStore_ACLToken_List(t *testing.T) { "4915fc9d-3726-4171-b588-6c271f45eecd", // policy + local "54866514-3cf2-4fec-8a8a-710583831834", // mgmt + global "74277ae1-6a9b-4035-b444-2370fe6a2cb5", // authMethod + global + "80c900e1-2fc5-4685-ae29-1b2d17fc30e4", // serviceName + global + "a14fa45e-0afe-4b44-961d-a430030ccfe2", // serviceName + local "a7715fde-8954-4c92-afbc-d84c6ecdc582", // role + global "cadb4f13-f62a-49ab-ab3f-5a7e01b925d9", // role + local "f1093997-b6c7-496d-bfb8-6b1b1895641b", // mgmt + local @@ -1004,14 +1052,27 @@ func TestStateStore_ACLToken_List(t *testing.T) { }, } - for _, tc := range []struct{ policy, role, methodName string }{ - {testPolicyID_A, testRoleID_A, "test"}, - {"", testRoleID_A, "test"}, - {testPolicyID_A, "", "test"}, - {testPolicyID_A, testRoleID_A, ""}, + for _, tc := range []struct{ policy, role, methodName, serviceName string }{ + {testPolicyID_A, testRoleID_A, "test", ""}, + {"", testRoleID_A, "test", ""}, + {testPolicyID_A, "", "test", ""}, + {testPolicyID_A, testRoleID_A, "", ""}, + {testPolicyID_A, "", "", "test"}, } { - t.Run(fmt.Sprintf("can't filter on more than one: %s/%s/%s", tc.policy, tc.role, tc.methodName), func(t *testing.T) { - _, _, err := s.ACLTokenList(nil, false, false, tc.policy, tc.role, tc.methodName, nil, nil) + t.Run(fmt.Sprintf("can't filter on more than one: %s/%s/%s/%s", tc.policy, tc.role, tc.methodName, tc.serviceName), func(t *testing.T) { + var err error + if tc.serviceName == "" { + // The legacy call can only be tested when the serviceName is not specified + // nolint:staticcheck + _, _, err = s.ACLTokenList(nil, false, false, tc.policy, tc.role, tc.methodName, nil, nil) + require.Error(t, err) + } + _, _, err = s.ACLTokenListWithParameters(nil, ACLTokenListParameters{ + Policy: tc.policy, + Role: tc.role, + MethodName: tc.methodName, + ServiceName: tc.serviceName, + }) require.Error(t, err) }) } @@ -1020,12 +1081,33 @@ func TestStateStore_ACLToken_List(t *testing.T) { tc := tc // capture range variable t.Run(tc.name, func(t *testing.T) { t.Parallel() - _, tokens, err := s.ACLTokenList(nil, tc.local, tc.global, tc.policy, tc.role, tc.methodName, nil, nil) - require.NoError(t, err) - require.Len(t, tokens, len(tc.accessors)) - tokens.Sort() - for i, token := range tokens { - require.Equal(t, tc.accessors[i], token.AccessorID) + // Test old function + if tc.serviceName == "" { + // nolint:staticcheck + _, tokens, err := s.ACLTokenList(nil, tc.local, tc.global, tc.policy, tc.role, tc.methodName, nil, nil) + require.NoError(t, err) + require.Len(t, tokens, len(tc.accessors)) + tokens.Sort() + for i, token := range tokens { + require.Equal(t, tc.accessors[i], token.AccessorID) + } + } + // Test new function + { + _, tokens, err := s.ACLTokenListWithParameters(nil, ACLTokenListParameters{ + Local: tc.local, + Global: tc.global, + Policy: tc.policy, + Role: tc.role, + ServiceName: tc.serviceName, + MethodName: tc.methodName, + }) + require.NoError(t, err) + require.Len(t, tokens, len(tc.accessors)) + tokens.Sort() + for i, token := range tokens { + require.Equal(t, tc.accessors[i], token.AccessorID) + } } }) } @@ -1080,6 +1162,7 @@ func TestStateStore_ACLToken_FixupPolicyLinks(t *testing.T) { require.Equal(t, "node-read-renamed", retrieved.Policies[0].Name) // list tokens without stale links + // nolint:staticcheck _, tokens, err := s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) @@ -1124,6 +1207,7 @@ func TestStateStore_ACLToken_FixupPolicyLinks(t *testing.T) { require.Len(t, retrieved.Policies, 0) // list tokens without stale links + // nolint:staticcheck _, tokens, err = s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) @@ -1209,6 +1293,7 @@ func TestStateStore_ACLToken_FixupRoleLinks(t *testing.T) { require.Equal(t, "node-read-role-renamed", retrieved.Roles[0].Name) // list tokens without stale links + // nolint:staticcheck _, tokens, err := s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) @@ -1253,6 +1338,7 @@ func TestStateStore_ACLToken_FixupRoleLinks(t *testing.T) { require.Len(t, retrieved.Roles, 0) // list tokens without stale links + // nolint:staticcheck _, tokens, err = s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) @@ -2688,16 +2774,19 @@ func TestStateStore_ACLAuthMethod_GlobalNameShadowing_TokenTest(t *testing.T) { } require.True(t, t.Run("list local only", func(t *testing.T) { + // nolint:staticcheck _, got, err := s.ACLTokenList(nil, true, false, "", "", "test", defaultEntMeta, defaultEntMeta) require.NoError(t, err) require.ElementsMatch(t, []string{methodDC2_tok1, methodDC2_tok2}, toList(got)) })) require.True(t, t.Run("list global only", func(t *testing.T) { + // nolint:staticcheck _, got, err := s.ACLTokenList(nil, false, true, "", "", "test", defaultEntMeta, defaultEntMeta) require.NoError(t, err) require.ElementsMatch(t, []string{methodDC1_tok1, methodDC1_tok2}, toList(got)) })) require.True(t, t.Run("list both", func(t *testing.T) { + // nolint:staticcheck _, got, err := s.ACLTokenList(nil, true, true, "", "", "test", defaultEntMeta, defaultEntMeta) require.NoError(t, err) require.ElementsMatch(t, []string{methodDC1_tok1, methodDC1_tok2, methodDC2_tok1, methodDC2_tok2}, toList(got)) @@ -2709,16 +2798,19 @@ func TestStateStore_ACLAuthMethod_GlobalNameShadowing_TokenTest(t *testing.T) { })) require.True(t, t.Run("list local only (after dc2 delete)", func(t *testing.T) { + // nolint:staticcheck _, got, err := s.ACLTokenList(nil, true, false, "", "", "test", defaultEntMeta, defaultEntMeta) require.NoError(t, err) require.Empty(t, got) })) require.True(t, t.Run("list global only (after dc2 delete)", func(t *testing.T) { + // nolint:staticcheck _, got, err := s.ACLTokenList(nil, false, true, "", "", "test", defaultEntMeta, defaultEntMeta) require.NoError(t, err) require.ElementsMatch(t, []string{methodDC1_tok1, methodDC1_tok2}, toList(got)) })) require.True(t, t.Run("list both (after dc2 delete)", func(t *testing.T) { + // nolint:staticcheck _, got, err := s.ACLTokenList(nil, true, true, "", "", "test", defaultEntMeta, defaultEntMeta) require.NoError(t, err) require.ElementsMatch(t, []string{methodDC1_tok1, methodDC1_tok2}, toList(got)) @@ -3509,6 +3601,7 @@ func TestStateStore_ACLTokens_Snapshot_Restore(t *testing.T) { require.NoError(t, s.ACLRoleBatchSet(2, roles, false)) // Read the restored ACLs back out and verify that they match. + // nolint:staticcheck idx, res, err := s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) require.Equal(t, uint64(4), idx) diff --git a/agent/consul/state/autopilot.go b/agent/consul/state/autopilot.go index 608f08f5215c2..472ce4bfc31c2 100644 --- a/agent/consul/state/autopilot.go +++ b/agent/consul/state/autopilot.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/autopilot_test.go b/agent/consul/state/autopilot_test.go index a2877e2df5ffa..f26163bc4ec1b 100644 --- a/agent/consul/state/autopilot_test.go +++ b/agent/consul/state/autopilot_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/catalog.go b/agent/consul/state/catalog.go index f5007a893fd6f..040a9608142ba 100644 --- a/agent/consul/state/catalog.go +++ b/agent/consul/state/catalog.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state @@ -3972,7 +3972,7 @@ func updateGatewayService(tx WriteTxn, idx uint64, mapping *structs.GatewayServi } // checkWildcardForGatewaysAndUpdate checks whether a service matches a -// wildcard definition in gateway config entries and if so adds it the +// wildcard definition in gateway config entries and if so adds it the the // gateway-services table. func checkGatewayWildcardsAndUpdate(tx WriteTxn, idx uint64, svc *structs.ServiceName, ns *structs.NodeService, kind structs.GatewayServiceKind) error { sn := structs.ServiceName{Name: structs.WildcardSpecifier, EnterpriseMeta: svc.EnterpriseMeta} @@ -4020,7 +4020,7 @@ func checkGatewayWildcardsAndUpdate(tx WriteTxn, idx uint64, svc *structs.Servic } // checkGatewayAndUpdate checks whether a service matches a -// wildcard definition in gateway config entries and if so adds it the +// wildcard definition in gateway config entries and if so adds it the the // gateway-services table. func checkGatewayAndUpdate(tx WriteTxn, idx uint64, svc *structs.ServiceName, kind structs.GatewayServiceKind) error { sn := structs.ServiceName{Name: svc.Name, EnterpriseMeta: svc.EnterpriseMeta} diff --git a/agent/consul/state/catalog_ce.go b/agent/consul/state/catalog_ce.go index 1c8062567d74f..bec9a6a619771 100644 --- a/agent/consul/state/catalog_ce.go +++ b/agent/consul/state/catalog_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/catalog_ce_test.go b/agent/consul/state/catalog_ce_test.go index f0ad6ffbc9289..e8c71812f860f 100644 --- a/agent/consul/state/catalog_ce_test.go +++ b/agent/consul/state/catalog_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/catalog_events.go b/agent/consul/state/catalog_events.go index 7b2057c6f43a0..0cd7258d5e806 100644 --- a/agent/consul/state/catalog_events.go +++ b/agent/consul/state/catalog_events.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state @@ -645,7 +645,7 @@ func getPayloadCheckServiceNode(payload stream.Payload) *structs.CheckServiceNod } // newServiceHealthEventsForNode returns health events for all services on the -// given node. This mirrors some of the logic in the oddly-named +// given node. This mirrors some of the the logic in the oddly-named // parseCheckServiceNodes but is more efficient since we know they are all on // the same node. func newServiceHealthEventsForNode(tx ReadTxn, idx uint64, node string, entMeta *acl.EnterpriseMeta, peerName string) ([]stream.Event, error) { diff --git a/agent/consul/state/catalog_events_ce.go b/agent/consul/state/catalog_events_ce.go index 25e9dc149b1a1..72e3993b5d56d 100644 --- a/agent/consul/state/catalog_events_ce.go +++ b/agent/consul/state/catalog_events_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/catalog_events_ce_test.go b/agent/consul/state/catalog_events_ce_test.go index 75f9a6ddeb234..0de8286c44c85 100644 --- a/agent/consul/state/catalog_events_ce_test.go +++ b/agent/consul/state/catalog_events_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/catalog_events_test.go b/agent/consul/state/catalog_events_test.go index 94406e34f9aee..46e0b269617fa 100644 --- a/agent/consul/state/catalog_events_test.go +++ b/agent/consul/state/catalog_events_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/catalog_schema.deepcopy.go b/agent/consul/state/catalog_schema.deepcopy.go index af4d430d2f971..406a7fdce796f 100644 --- a/agent/consul/state/catalog_schema.deepcopy.go +++ b/agent/consul/state/catalog_schema.deepcopy.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - // generated by deep-copy -pointer-receiver -o ./catalog_schema.deepcopy.go -type upstreamDownstream ./; DO NOT EDIT. package state diff --git a/agent/consul/state/catalog_schema.go b/agent/consul/state/catalog_schema.go index b8da7c0999361..8702cc2e0cf5f 100644 --- a/agent/consul/state/catalog_schema.go +++ b/agent/consul/state/catalog_schema.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/catalog_test.go b/agent/consul/state/catalog_test.go index 6fc79a5a7c0fa..e6b279580b030 100644 --- a/agent/consul/state/catalog_test.go +++ b/agent/consul/state/catalog_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/config_entry.go b/agent/consul/state/config_entry.go index b298b6122080d..9abaafc390d3a 100644 --- a/agent/consul/state/config_entry.go +++ b/agent/consul/state/config_entry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/config_entry_ce.go b/agent/consul/state/config_entry_ce.go index 091a5be157688..ec01e0c09aaea 100644 --- a/agent/consul/state/config_entry_ce.go +++ b/agent/consul/state/config_entry_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/config_entry_ce_test.go b/agent/consul/state/config_entry_ce_test.go index 736ede4e54fe8..02fb3be78a2c5 100644 --- a/agent/consul/state/config_entry_ce_test.go +++ b/agent/consul/state/config_entry_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/config_entry_events.go b/agent/consul/state/config_entry_events.go index c6c19fce3453e..5681362dbe16e 100644 --- a/agent/consul/state/config_entry_events.go +++ b/agent/consul/state/config_entry_events.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/config_entry_events_test.go b/agent/consul/state/config_entry_events_test.go index e8ceb10f65d85..1ee92770bc65b 100644 --- a/agent/consul/state/config_entry_events_test.go +++ b/agent/consul/state/config_entry_events_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/config_entry_exported_services.go b/agent/consul/state/config_entry_exported_services.go index 7534613ae137a..b758adc09eafb 100644 --- a/agent/consul/state/config_entry_exported_services.go +++ b/agent/consul/state/config_entry_exported_services.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/config_entry_exported_services_ce.go b/agent/consul/state/config_entry_exported_services_ce.go index 0dfbf95ecf058..9dfc4751d2d61 100644 --- a/agent/consul/state/config_entry_exported_services_ce.go +++ b/agent/consul/state/config_entry_exported_services_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/config_entry_intention.go b/agent/consul/state/config_entry_intention.go index 459d8c4276e6f..301baf9c09093 100644 --- a/agent/consul/state/config_entry_intention.go +++ b/agent/consul/state/config_entry_intention.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/config_entry_intention_ce.go b/agent/consul/state/config_entry_intention_ce.go index b0eb69b355f92..6d479f9ad6bfb 100644 --- a/agent/consul/state/config_entry_intention_ce.go +++ b/agent/consul/state/config_entry_intention_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/config_entry_sameness_group.go b/agent/consul/state/config_entry_sameness_group.go index d8308008dfbb4..7f02787b6553b 100644 --- a/agent/consul/state/config_entry_sameness_group.go +++ b/agent/consul/state/config_entry_sameness_group.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package state import ( diff --git a/agent/consul/state/config_entry_sameness_group_ce.go b/agent/consul/state/config_entry_sameness_group_ce.go index 76c285b5e33e0..16437cd8fd187 100644 --- a/agent/consul/state/config_entry_sameness_group_ce.go +++ b/agent/consul/state/config_entry_sameness_group_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/config_entry_sameness_group_ce_test.go b/agent/consul/state/config_entry_sameness_group_ce_test.go index 6397e90699d0b..ce4aeb8394f8b 100644 --- a/agent/consul/state/config_entry_sameness_group_ce_test.go +++ b/agent/consul/state/config_entry_sameness_group_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/config_entry_schema.go b/agent/consul/state/config_entry_schema.go index c662415252966..e420d657cae8a 100644 --- a/agent/consul/state/config_entry_schema.go +++ b/agent/consul/state/config_entry_schema.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/config_entry_test.go b/agent/consul/state/config_entry_test.go index af9dc0997156d..d72f12c876890 100644 --- a/agent/consul/state/config_entry_test.go +++ b/agent/consul/state/config_entry_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/connect_ca.go b/agent/consul/state/connect_ca.go index 4b1eeeab783d4..99e99637b6aa9 100644 --- a/agent/consul/state/connect_ca.go +++ b/agent/consul/state/connect_ca.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/connect_ca_events.go b/agent/consul/state/connect_ca_events.go index a285b9d07cb75..554a867dcd59c 100644 --- a/agent/consul/state/connect_ca_events.go +++ b/agent/consul/state/connect_ca_events.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/connect_ca_events_test.go b/agent/consul/state/connect_ca_events_test.go index 79df8df5be879..bf13eefcb9376 100644 --- a/agent/consul/state/connect_ca_events_test.go +++ b/agent/consul/state/connect_ca_events_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/connect_ca_test.go b/agent/consul/state/connect_ca_test.go index 2a49723d65cbc..124392cf1a432 100644 --- a/agent/consul/state/connect_ca_test.go +++ b/agent/consul/state/connect_ca_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/coordinate.go b/agent/consul/state/coordinate.go index bcd71e5a0f08d..f2eb7b30425e6 100644 --- a/agent/consul/state/coordinate.go +++ b/agent/consul/state/coordinate.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/coordinate_ce.go b/agent/consul/state/coordinate_ce.go index 05568e40b09d8..17956e964eee6 100644 --- a/agent/consul/state/coordinate_ce.go +++ b/agent/consul/state/coordinate_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/coordinate_ce_test.go b/agent/consul/state/coordinate_ce_test.go index 520f8b5d83f1e..a4608245060ea 100644 --- a/agent/consul/state/coordinate_ce_test.go +++ b/agent/consul/state/coordinate_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/coordinate_test.go b/agent/consul/state/coordinate_test.go index dad0ce3e32ec6..0fe582eab5aa9 100644 --- a/agent/consul/state/coordinate_test.go +++ b/agent/consul/state/coordinate_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/deep-copy.sh b/agent/consul/state/deep-copy.sh index 809e20432b624..d976d921f3c83 100755 --- a/agent/consul/state/deep-copy.sh +++ b/agent/consul/state/deep-copy.sh @@ -1,7 +1,4 @@ #!/usr/bin/env bash -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - readonly PACKAGE_DIR="$(dirname "${BASH_SOURCE[0]}")" cd $PACKAGE_DIR diff --git a/agent/consul/state/delay_ce.go b/agent/consul/state/delay_ce.go index ca55c465fd9f3..a2471ae636241 100644 --- a/agent/consul/state/delay_ce.go +++ b/agent/consul/state/delay_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/delay_test.go b/agent/consul/state/delay_test.go index 6a2d0fa80c2d6..40f1842efd679 100644 --- a/agent/consul/state/delay_test.go +++ b/agent/consul/state/delay_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/events.go b/agent/consul/state/events.go index 0d4f4eb4fe403..666dc60035d1e 100644 --- a/agent/consul/state/events.go +++ b/agent/consul/state/events.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/events_test.go b/agent/consul/state/events_test.go index c2a4ad399d641..3da9a26549b2a 100644 --- a/agent/consul/state/events_test.go +++ b/agent/consul/state/events_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/federation_state.go b/agent/consul/state/federation_state.go index a02a38ed3b532..556caa4b48549 100644 --- a/agent/consul/state/federation_state.go +++ b/agent/consul/state/federation_state.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/graveyard.go b/agent/consul/state/graveyard.go index 45398584356cf..5b6a95dafbaa2 100644 --- a/agent/consul/state/graveyard.go +++ b/agent/consul/state/graveyard.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/graveyard_ce.go b/agent/consul/state/graveyard_ce.go index b02659b74c3f3..963ed6632e5be 100644 --- a/agent/consul/state/graveyard_ce.go +++ b/agent/consul/state/graveyard_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/graveyard_test.go b/agent/consul/state/graveyard_test.go index 66aaaf92fb143..af50673e9e741 100644 --- a/agent/consul/state/graveyard_test.go +++ b/agent/consul/state/graveyard_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/index_connect_test.go b/agent/consul/state/index_connect_test.go index 7b5404b5b2a8e..a598fab68ac44 100644 --- a/agent/consul/state/index_connect_test.go +++ b/agent/consul/state/index_connect_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/indexer.go b/agent/consul/state/indexer.go index c752b3af55cfc..f360eb2befe97 100644 --- a/agent/consul/state/indexer.go +++ b/agent/consul/state/indexer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/intention.go b/agent/consul/state/intention.go index f360555228586..4341590e4ec20 100644 --- a/agent/consul/state/intention.go +++ b/agent/consul/state/intention.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/intention_ce.go b/agent/consul/state/intention_ce.go index 43b80a47ad454..e82177eb1a563 100644 --- a/agent/consul/state/intention_ce.go +++ b/agent/consul/state/intention_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/intention_test.go b/agent/consul/state/intention_test.go index 72455565d5821..3545527b790c2 100644 --- a/agent/consul/state/intention_test.go +++ b/agent/consul/state/intention_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/kvs.go b/agent/consul/state/kvs.go index b0b4f6c1e52dc..0d0a419ae5c29 100644 --- a/agent/consul/state/kvs.go +++ b/agent/consul/state/kvs.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/kvs_ce.go b/agent/consul/state/kvs_ce.go index 6243bbd71b061..10528e3be6dbb 100644 --- a/agent/consul/state/kvs_ce.go +++ b/agent/consul/state/kvs_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/kvs_ce_test.go b/agent/consul/state/kvs_ce_test.go index a7a1034c6a8d0..adf41fe7dbe86 100644 --- a/agent/consul/state/kvs_ce_test.go +++ b/agent/consul/state/kvs_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/kvs_test.go b/agent/consul/state/kvs_test.go index b85a08f98d181..4ced02586f0c0 100644 --- a/agent/consul/state/kvs_test.go +++ b/agent/consul/state/kvs_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/memdb.go b/agent/consul/state/memdb.go index 93707d0e0751d..0a3b66c6a6275 100644 --- a/agent/consul/state/memdb.go +++ b/agent/consul/state/memdb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/memdb_test.go b/agent/consul/state/memdb_test.go index e603fc5bb1691..7e893619be5de 100644 --- a/agent/consul/state/memdb_test.go +++ b/agent/consul/state/memdb_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/operations_ce.go b/agent/consul/state/operations_ce.go index acf1cd38b801c..08de08015b449 100644 --- a/agent/consul/state/operations_ce.go +++ b/agent/consul/state/operations_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/peering.go b/agent/consul/state/peering.go index 1763777cff838..90db748458847 100644 --- a/agent/consul/state/peering.go +++ b/agent/consul/state/peering.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/peering_ce.go b/agent/consul/state/peering_ce.go index 40e207729dfac..a54e2d37ddffb 100644 --- a/agent/consul/state/peering_ce.go +++ b/agent/consul/state/peering_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/peering_ce_test.go b/agent/consul/state/peering_ce_test.go index 927fa1c71db96..41d1bce452db0 100644 --- a/agent/consul/state/peering_ce_test.go +++ b/agent/consul/state/peering_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/peering_test.go b/agent/consul/state/peering_test.go index 764286bb77b8e..8125b96860aac 100644 --- a/agent/consul/state/peering_test.go +++ b/agent/consul/state/peering_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/prepared_query.go b/agent/consul/state/prepared_query.go index 62cf39588d17a..7638d925170f0 100644 --- a/agent/consul/state/prepared_query.go +++ b/agent/consul/state/prepared_query.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/prepared_query_index.go b/agent/consul/state/prepared_query_index.go index 83bb5dc738251..ac76846366699 100644 --- a/agent/consul/state/prepared_query_index.go +++ b/agent/consul/state/prepared_query_index.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/prepared_query_index_test.go b/agent/consul/state/prepared_query_index_test.go index aaaa62692f1cf..a486047f57e33 100644 --- a/agent/consul/state/prepared_query_index_test.go +++ b/agent/consul/state/prepared_query_index_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/prepared_query_test.go b/agent/consul/state/prepared_query_test.go index dc902de4ad309..f0b0cd95f4469 100644 --- a/agent/consul/state/prepared_query_test.go +++ b/agent/consul/state/prepared_query_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/query.go b/agent/consul/state/query.go index 288e715e83314..2256aab995fb0 100644 --- a/agent/consul/state/query.go +++ b/agent/consul/state/query.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/query_ce.go b/agent/consul/state/query_ce.go index 178dc60b77e1e..98108d6ff02b2 100644 --- a/agent/consul/state/query_ce.go +++ b/agent/consul/state/query_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/schema.go b/agent/consul/state/schema.go index 0934ca483e5eb..9e0e6db2fee42 100644 --- a/agent/consul/state/schema.go +++ b/agent/consul/state/schema.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/schema_ce.go b/agent/consul/state/schema_ce.go index 15a3ec44788ae..eecde09aab619 100644 --- a/agent/consul/state/schema_ce.go +++ b/agent/consul/state/schema_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/schema_ce_test.go b/agent/consul/state/schema_ce_test.go index eb8a1e079574e..55fc3ee54c194 100644 --- a/agent/consul/state/schema_ce_test.go +++ b/agent/consul/state/schema_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/schema_test.go b/agent/consul/state/schema_test.go index a0af2223e27ce..f67b18e8c3beb 100644 --- a/agent/consul/state/schema_test.go +++ b/agent/consul/state/schema_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/session.go b/agent/consul/state/session.go index d57b05947d396..5e666f80fd894 100644 --- a/agent/consul/state/session.go +++ b/agent/consul/state/session.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/session_ce.go b/agent/consul/state/session_ce.go index 6bd13c0132dc0..1854fb3e1448b 100644 --- a/agent/consul/state/session_ce.go +++ b/agent/consul/state/session_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/session_test.go b/agent/consul/state/session_test.go index 08f7ad09d0c1f..eab4299581637 100644 --- a/agent/consul/state/session_test.go +++ b/agent/consul/state/session_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/state_store.go b/agent/consul/state/state_store.go index dff3441535bb5..fce3b3c96155f 100644 --- a/agent/consul/state/state_store.go +++ b/agent/consul/state/state_store.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/state_store_ce_test.go b/agent/consul/state/state_store_ce_test.go index 81f25ed1e8b2c..5515b193f688c 100644 --- a/agent/consul/state/state_store_ce_test.go +++ b/agent/consul/state/state_store_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/state_store_test.go b/agent/consul/state/state_store_test.go index 751ecee779dee..587f15c03d948 100644 --- a/agent/consul/state/state_store_test.go +++ b/agent/consul/state/state_store_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/store_integration_test.go b/agent/consul/state/store_integration_test.go index 25a91c558646f..9395aa1cb1820 100644 --- a/agent/consul/state/store_integration_test.go +++ b/agent/consul/state/store_integration_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/system_metadata.go b/agent/consul/state/system_metadata.go index 06e2d3cc598b9..ed802efbd1cd8 100644 --- a/agent/consul/state/system_metadata.go +++ b/agent/consul/state/system_metadata.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/system_metadata_test.go b/agent/consul/state/system_metadata_test.go index c2ac97b390b8c..59f8bcd30c3eb 100644 --- a/agent/consul/state/system_metadata_test.go +++ b/agent/consul/state/system_metadata_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/tombstone_gc.go b/agent/consul/state/tombstone_gc.go index 6eab5b6b5ba91..3fc19c5cd9cc8 100644 --- a/agent/consul/state/tombstone_gc.go +++ b/agent/consul/state/tombstone_gc.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/tombstone_gc_test.go b/agent/consul/state/tombstone_gc_test.go index def4c9af19720..d0fd11fa7c5a6 100644 --- a/agent/consul/state/tombstone_gc_test.go +++ b/agent/consul/state/tombstone_gc_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/txn.go b/agent/consul/state/txn.go index 30189fc1ed602..81d8acd039291 100644 --- a/agent/consul/state/txn.go +++ b/agent/consul/state/txn.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/txn_test.go b/agent/consul/state/txn_test.go index bda004a63a3b6..a128badf42e52 100644 --- a/agent/consul/state/txn_test.go +++ b/agent/consul/state/txn_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/usage.go b/agent/consul/state/usage.go index 20515e2e7b0cd..0893d25288b68 100644 --- a/agent/consul/state/usage.go +++ b/agent/consul/state/usage.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/state/usage_ce.go b/agent/consul/state/usage_ce.go index 3daad8b986579..1824cf12399a5 100644 --- a/agent/consul/state/usage_ce.go +++ b/agent/consul/state/usage_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/state/usage_test.go b/agent/consul/state/usage_test.go index 4195779b8c037..68844ebc1140d 100644 --- a/agent/consul/state/usage_test.go +++ b/agent/consul/state/usage_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/agent/consul/stats_fetcher.go b/agent/consul/stats_fetcher.go index 94e122f2b4389..d52930e85add3 100644 --- a/agent/consul/stats_fetcher.go +++ b/agent/consul/stats_fetcher.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/stats_fetcher_test.go b/agent/consul/stats_fetcher_test.go index 8dc9ce9eb2880..783424393a79e 100644 --- a/agent/consul/stats_fetcher_test.go +++ b/agent/consul/stats_fetcher_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/status_endpoint.go b/agent/consul/status_endpoint.go index bca454e25eb0f..efa2fa2cf4fa6 100644 --- a/agent/consul/status_endpoint.go +++ b/agent/consul/status_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/status_endpoint_test.go b/agent/consul/status_endpoint_test.go index d4cf5cb7798b9..6d95d7f6fd48d 100644 --- a/agent/consul/status_endpoint_test.go +++ b/agent/consul/status_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/stream/event.go b/agent/consul/stream/event.go index df8160d2dd366..db6f3a6312f38 100644 --- a/agent/consul/stream/event.go +++ b/agent/consul/stream/event.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 /* Package stream provides a publish/subscribe system for events produced by changes diff --git a/agent/consul/stream/event_buffer.go b/agent/consul/stream/event_buffer.go index 08060306e8d64..1c7f8c2b956a5 100644 --- a/agent/consul/stream/event_buffer.go +++ b/agent/consul/stream/event_buffer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package stream diff --git a/agent/consul/stream/event_buffer_test.go b/agent/consul/stream/event_buffer_test.go index 892a14d733e1a..b6ec48e1775e1 100644 --- a/agent/consul/stream/event_buffer_test.go +++ b/agent/consul/stream/event_buffer_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package stream diff --git a/agent/consul/stream/event_publisher.go b/agent/consul/stream/event_publisher.go index bb6d87f8bacf2..f39ea22869a08 100644 --- a/agent/consul/stream/event_publisher.go +++ b/agent/consul/stream/event_publisher.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package stream diff --git a/agent/consul/stream/event_publisher_test.go b/agent/consul/stream/event_publisher_test.go index 4ae53ebcbf8f3..13efd0fb564ab 100644 --- a/agent/consul/stream/event_publisher_test.go +++ b/agent/consul/stream/event_publisher_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package stream diff --git a/agent/consul/stream/event_snapshot.go b/agent/consul/stream/event_snapshot.go index 40c9f3d007d50..6b4b693689b42 100644 --- a/agent/consul/stream/event_snapshot.go +++ b/agent/consul/stream/event_snapshot.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package stream diff --git a/agent/consul/stream/event_snapshot_test.go b/agent/consul/stream/event_snapshot_test.go index 8a6d4e27c6bf5..0888b90c39c9c 100644 --- a/agent/consul/stream/event_snapshot_test.go +++ b/agent/consul/stream/event_snapshot_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package stream diff --git a/agent/consul/stream/event_test.go b/agent/consul/stream/event_test.go index 22afe390de9c7..ff6f07c10ea83 100644 --- a/agent/consul/stream/event_test.go +++ b/agent/consul/stream/event_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package stream diff --git a/agent/consul/stream/noop.go b/agent/consul/stream/noop.go index 65fcbb3fb7770..1cd35ea922eb8 100644 --- a/agent/consul/stream/noop.go +++ b/agent/consul/stream/noop.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package stream diff --git a/agent/consul/stream/string_types.go b/agent/consul/stream/string_types.go index 2d0cb656777d3..6e6c4ef8e92fa 100644 --- a/agent/consul/stream/string_types.go +++ b/agent/consul/stream/string_types.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package stream diff --git a/agent/consul/stream/subscription.go b/agent/consul/stream/subscription.go index 23911eff2e657..40286768abe02 100644 --- a/agent/consul/stream/subscription.go +++ b/agent/consul/stream/subscription.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package stream diff --git a/agent/consul/stream/subscription_test.go b/agent/consul/stream/subscription_test.go index fd4af464ee532..9bf0b95b5d564 100644 --- a/agent/consul/stream/subscription_test.go +++ b/agent/consul/stream/subscription_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package stream diff --git a/agent/consul/subscribe_backend.go b/agent/consul/subscribe_backend.go index c73dea18136af..9afcd4fc567df 100644 --- a/agent/consul/subscribe_backend.go +++ b/agent/consul/subscribe_backend.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/subscribe_backend_test.go b/agent/consul/subscribe_backend_test.go index 8d0f7a501ca1e..833f049c9728a 100644 --- a/agent/consul/subscribe_backend_test.go +++ b/agent/consul/subscribe_backend_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/system_metadata.go b/agent/consul/system_metadata.go index f110255aa2e09..40185294b8d77 100644 --- a/agent/consul/system_metadata.go +++ b/agent/consul/system_metadata.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/system_metadata_test.go b/agent/consul/system_metadata_test.go index 75e69786b8dd5..7c4eb30e4732e 100644 --- a/agent/consul/system_metadata_test.go +++ b/agent/consul/system_metadata_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/tenancy_bridge.go b/agent/consul/tenancy_bridge.go deleted file mode 100644 index 4573db2feb060..0000000000000 --- a/agent/consul/tenancy_bridge.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package consul - -// V1TenancyBridge is used by the resource service to access V1 implementations of -// partitions and namespaces. This bridge will be removed when V2 implemenations -// of partitions and namespaces are available. -type V1TenancyBridge struct { - server *Server -} - -func NewV1TenancyBridge(server *Server) *V1TenancyBridge { - return &V1TenancyBridge{server: server} -} diff --git a/agent/consul/tenancy_bridge_ce.go b/agent/consul/tenancy_bridge_ce.go deleted file mode 100644 index 03f87378e7591..0000000000000 --- a/agent/consul/tenancy_bridge_ce.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package consul - -func (b *V1TenancyBridge) PartitionExists(partition string) (bool, error) { - if partition == "default" { - return true, nil - } - return false, nil -} - -func (b *V1TenancyBridge) IsPartitionMarkedForDeletion(partition string) (bool, error) { - return false, nil -} - -func (b *V1TenancyBridge) NamespaceExists(partition, namespace string) (bool, error) { - if partition == "default" && namespace == "default" { - return true, nil - } - return false, nil -} - -func (b *V1TenancyBridge) IsNamespaceMarkedForDeletion(partition, namespace string) (bool, error) { - return false, nil -} diff --git a/agent/consul/txn_endpoint.go b/agent/consul/txn_endpoint.go index f39cd502cb170..e7e5d870875e9 100644 --- a/agent/consul/txn_endpoint.go +++ b/agent/consul/txn_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/txn_endpoint_test.go b/agent/consul/txn_endpoint_test.go index ef2ecd13a3f85..f5654fdc001db 100644 --- a/agent/consul/txn_endpoint_test.go +++ b/agent/consul/txn_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/type_registry.go b/agent/consul/type_registry.go deleted file mode 100644 index 90bf76576fcf5..0000000000000 --- a/agent/consul/type_registry.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package consul - -import ( - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/mesh" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/demo" -) - -// NewTypeRegistry returns a registry populated with all supported resource -// types. -// -// Note: the registry includes resource types that may not be suitable for -// production use (e.g. experimental or development resource types) because -// it is used in the CLI, where feature flags and other runtime configuration -// may not be available. -func NewTypeRegistry() resource.Registry { - registry := resource.NewRegistry() - - demo.RegisterTypes(registry) - mesh.RegisterTypes(registry) - catalog.RegisterTypes(registry) - - return registry -} diff --git a/agent/consul/usagemetrics/usagemetrics.go b/agent/consul/usagemetrics/usagemetrics.go index 7bd21b7d265bd..169238c375e14 100644 --- a/agent/consul/usagemetrics/usagemetrics.go +++ b/agent/consul/usagemetrics/usagemetrics.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package usagemetrics diff --git a/agent/consul/usagemetrics/usagemetrics_ce.go b/agent/consul/usagemetrics/usagemetrics_ce.go index 7de677cc079c0..17853b4fcf6e3 100644 --- a/agent/consul/usagemetrics/usagemetrics_ce.go +++ b/agent/consul/usagemetrics/usagemetrics_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/usagemetrics/usagemetrics_ce_test.go b/agent/consul/usagemetrics/usagemetrics_ce_test.go index 621224fb98822..47834da9164a9 100644 --- a/agent/consul/usagemetrics/usagemetrics_ce_test.go +++ b/agent/consul/usagemetrics/usagemetrics_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/consul/usagemetrics/usagemetrics_test.go b/agent/consul/usagemetrics/usagemetrics_test.go index c97fb13be802f..7bdf396b25749 100644 --- a/agent/consul/usagemetrics/usagemetrics_test.go +++ b/agent/consul/usagemetrics/usagemetrics_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package usagemetrics diff --git a/agent/consul/util.go b/agent/consul/util.go index 0fd88e14c8eb9..6fd6c77da33b1 100644 --- a/agent/consul/util.go +++ b/agent/consul/util.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/util_test.go b/agent/consul/util_test.go index d0a4fcb6842f1..c41b7748919fa 100644 --- a/agent/consul/util_test.go +++ b/agent/consul/util_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package consul diff --git a/agent/consul/wanfed/pool.go b/agent/consul/wanfed/pool.go index 3d083019346d4..9320087b3f713 100644 --- a/agent/consul/wanfed/pool.go +++ b/agent/consul/wanfed/pool.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package wanfed diff --git a/agent/consul/wanfed/wanfed.go b/agent/consul/wanfed/wanfed.go index 7732e05ad39a4..e82eddcfa88ef 100644 --- a/agent/consul/wanfed/wanfed.go +++ b/agent/consul/wanfed/wanfed.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package wanfed diff --git a/agent/consul/wanfed/wanfed_test.go b/agent/consul/wanfed/wanfed_test.go index 8254e9434b367..ef45c197c179a 100644 --- a/agent/consul/wanfed/wanfed_test.go +++ b/agent/consul/wanfed/wanfed_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package wanfed diff --git a/agent/consul/watch/server_local.go b/agent/consul/watch/server_local.go index 2bb98fe349df9..5937ba1c6a10e 100644 --- a/agent/consul/watch/server_local.go +++ b/agent/consul/watch/server_local.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package watch diff --git a/agent/consul/watch/server_local_test.go b/agent/consul/watch/server_local_test.go index 84ab8de5739a2..1f96b1ec00d03 100644 --- a/agent/consul/watch/server_local_test.go +++ b/agent/consul/watch/server_local_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package watch diff --git a/agent/consul/xdscapacity/capacity.go b/agent/consul/xdscapacity/capacity.go index bf3cf4ced02a1..6396841d63fe8 100644 --- a/agent/consul/xdscapacity/capacity.go +++ b/agent/consul/xdscapacity/capacity.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xdscapacity diff --git a/agent/consul/xdscapacity/capacity_test.go b/agent/consul/xdscapacity/capacity_test.go index b3a3935a8806f..d26453feae607 100644 --- a/agent/consul/xdscapacity/capacity_test.go +++ b/agent/consul/xdscapacity/capacity_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xdscapacity diff --git a/agent/coordinate_endpoint.go b/agent/coordinate_endpoint.go index 60b69244afd5d..744498c055336 100644 --- a/agent/coordinate_endpoint.go +++ b/agent/coordinate_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/coordinate_endpoint_test.go b/agent/coordinate_endpoint_test.go index 508f308d13c7c..fe6deeef9567e 100644 --- a/agent/coordinate_endpoint_test.go +++ b/agent/coordinate_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/debug/host.go b/agent/debug/host.go index f863117e547b0..5116bf7499f7e 100644 --- a/agent/debug/host.go +++ b/agent/debug/host.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package debug diff --git a/agent/debug/host_test.go b/agent/debug/host_test.go index dce469b542f2a..1289e21b4f066 100644 --- a/agent/debug/host_test.go +++ b/agent/debug/host_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package debug diff --git a/agent/delegate_mock_test.go b/agent/delegate_mock_test.go index a75cf2d1e2624..9f91a6a0d919b 100644 --- a/agent/delegate_mock_test.go +++ b/agent/delegate_mock_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent @@ -15,7 +15,6 @@ import ( "github.com/hashicorp/consul/agent/consul" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/lib" - "github.com/hashicorp/consul/proto-public/pbresource" ) type delegateMock struct { @@ -77,7 +76,3 @@ func (m *delegateMock) Stats() map[string]map[string]string { func (m *delegateMock) ReloadConfig(config consul.ReloadableConfig) error { return m.Called(config).Error(0) } - -func (m *delegateMock) ResourceServiceClient() pbresource.ResourceServiceClient { - return nil -} diff --git a/agent/denylist.go b/agent/denylist.go index 5fdd8cc9f8721..b621465298146 100644 --- a/agent/denylist.go +++ b/agent/denylist.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/denylist_test.go b/agent/denylist_test.go index dd77e977d94d7..f9370723a7c30 100644 --- a/agent/denylist_test.go +++ b/agent/denylist_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/discovery_chain_endpoint.go b/agent/discovery_chain_endpoint.go index 69a5e668f46e1..a3aaa421f9387 100644 --- a/agent/discovery_chain_endpoint.go +++ b/agent/discovery_chain_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/discovery_chain_endpoint_test.go b/agent/discovery_chain_endpoint_test.go index 7e1e9a5524e4f..ed42ca0aede8a 100644 --- a/agent/discovery_chain_endpoint_test.go +++ b/agent/discovery_chain_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/dns.go b/agent/dns.go index 3ae9a18b673a4..5804dc97dd8ef 100644 --- a/agent/dns.go +++ b/agent/dns.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/dns/dns.go b/agent/dns/dns.go index 1942a1fdd8d23..9f8e785a390b6 100644 --- a/agent/dns/dns.go +++ b/agent/dns/dns.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dns diff --git a/agent/dns/dns_test.go b/agent/dns/dns_test.go index 3acd2260e0a78..91dc3ea72a919 100644 --- a/agent/dns/dns_test.go +++ b/agent/dns/dns_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dns diff --git a/agent/dns/validation.go b/agent/dns/validation.go index a88aaff2dbcba..cd66acf6fa8fe 100644 --- a/agent/dns/validation.go +++ b/agent/dns/validation.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dns diff --git a/agent/dns/validation_test.go b/agent/dns/validation_test.go index 8855e375c5f9c..bcb65adf14a23 100644 --- a/agent/dns/validation_test.go +++ b/agent/dns/validation_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dns_test diff --git a/agent/dns_ce.go b/agent/dns_ce.go index f82d1a31d2743..8c055776ed997 100644 --- a/agent/dns_ce.go +++ b/agent/dns_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/dns_ce_test.go b/agent/dns_ce_test.go index 50b100a989d2e..920568cd3b9bd 100644 --- a/agent/dns_ce_test.go +++ b/agent/dns_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/dns_test.go b/agent/dns_test.go index 399899527218e..ef5364964dd35 100644 --- a/agent/dns_test.go +++ b/agent/dns_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/enterprise_delegate_ce.go b/agent/enterprise_delegate_ce.go index 81d41ea8fa41b..39ae3db7c46d2 100644 --- a/agent/enterprise_delegate_ce.go +++ b/agent/enterprise_delegate_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/envoyextensions/builtin/aws-lambda/aws_lambda.go b/agent/envoyextensions/builtin/aws-lambda/aws_lambda.go index 978fc5cf5552b..fa36d6fa500d9 100644 --- a/agent/envoyextensions/builtin/aws-lambda/aws_lambda.go +++ b/agent/envoyextensions/builtin/aws-lambda/aws_lambda.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package awslambda diff --git a/agent/envoyextensions/builtin/aws-lambda/aws_lambda_test.go b/agent/envoyextensions/builtin/aws-lambda/aws_lambda_test.go index 3dda09e317a47..26f49eef4bd16 100644 --- a/agent/envoyextensions/builtin/aws-lambda/aws_lambda_test.go +++ b/agent/envoyextensions/builtin/aws-lambda/aws_lambda_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package awslambda diff --git a/agent/envoyextensions/builtin/ext-authz/ext_authz.go b/agent/envoyextensions/builtin/ext-authz/ext_authz.go index 00e1d47640c4a..7400aef13a04c 100644 --- a/agent/envoyextensions/builtin/ext-authz/ext_authz.go +++ b/agent/envoyextensions/builtin/ext-authz/ext_authz.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package extauthz @@ -23,8 +23,6 @@ type extAuthz struct { ProxyType api.ServiceKind // InsertOptions controls how the extension inserts the filter. InsertOptions ext_cmn.InsertOptions - // ListenerType controls which listener the extension applies to. It supports "inbound" or "outbound" listeners. - ListenerType string // Config holds the extension configuration. Config extAuthzConfig } @@ -63,14 +61,10 @@ func (a *extAuthz) PatchClusters(cfg *ext_cmn.RuntimeConfig, c ext_cmn.ClusterMa return c, nil } -func (a *extAuthz) matchesListenerDirection(isInboundListener bool) bool { - return (!isInboundListener && a.ListenerType == "outbound") || (isInboundListener && a.ListenerType == "inbound") -} - // PatchFilters inserts an ext-authz filter into the list of network filters or the filter chain of the HTTP connection manager. func (a *extAuthz) PatchFilters(cfg *ext_cmn.RuntimeConfig, filters []*envoy_listener_v3.Filter, isInboundListener bool) ([]*envoy_listener_v3.Filter, error) { // The ext_authz extension only patches filters for inbound listeners. - if !a.matchesListenerDirection(isInboundListener) { + if !isInboundListener { return filters, nil } @@ -135,11 +129,6 @@ func (a *extAuthz) normalize() { if a.ProxyType == "" { a.ProxyType = api.ServiceKindConnectProxy } - - if a.ListenerType == "" { - a.ListenerType = "inbound" - } - a.Config.normalize() } @@ -151,10 +140,6 @@ func (a *extAuthz) validate() error { api.ServiceKindConnectProxy)) } - if a.ListenerType != "inbound" && a.ListenerType != "outbound" { - resultErr = multierror.Append(resultErr, fmt.Errorf(`unexpected ListenerType %q, supported values are "inbound" or "outbound"`, a.ListenerType)) - } - if err := a.Config.validate(); err != nil { resultErr = multierror.Append(resultErr, err) } diff --git a/agent/envoyextensions/builtin/ext-authz/ext_authz_test.go b/agent/envoyextensions/builtin/ext-authz/ext_authz_test.go index 6db284476dd71..88e87d7e9a8f8 100644 --- a/agent/envoyextensions/builtin/ext-authz/ext_authz_test.go +++ b/agent/envoyextensions/builtin/ext-authz/ext_authz_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package extauthz diff --git a/agent/envoyextensions/builtin/ext-authz/structs.go b/agent/envoyextensions/builtin/ext-authz/structs.go index 0a7e7dcce43a7..a14cedd63a765 100644 --- a/agent/envoyextensions/builtin/ext-authz/structs.go +++ b/agent/envoyextensions/builtin/ext-authz/structs.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package extauthz diff --git a/agent/envoyextensions/builtin/lua/lua.go b/agent/envoyextensions/builtin/lua/lua.go index ba08d9d286c01..aefea37e6c496 100644 --- a/agent/envoyextensions/builtin/lua/lua.go +++ b/agent/envoyextensions/builtin/lua/lua.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lua diff --git a/agent/envoyextensions/builtin/lua/lua_test.go b/agent/envoyextensions/builtin/lua/lua_test.go index afe65d067f433..3ea2ba716c1de 100644 --- a/agent/envoyextensions/builtin/lua/lua_test.go +++ b/agent/envoyextensions/builtin/lua/lua_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lua diff --git a/agent/envoyextensions/builtin/otel-access-logging/otel_access_logging.go b/agent/envoyextensions/builtin/otel-access-logging/otel_access_logging.go deleted file mode 100644 index 2f003b5525826..0000000000000 --- a/agent/envoyextensions/builtin/otel-access-logging/otel_access_logging.go +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package otelaccesslogging - -import ( - "fmt" - - envoy_extensions_access_loggers_v3 "github.com/envoyproxy/go-control-plane/envoy/config/accesslog/v3" - envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" - envoy_extensions_access_loggers_otel_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/open_telemetry/v3" - "github.com/mitchellh/mapstructure" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/api" - ext_cmn "github.com/hashicorp/consul/envoyextensions/extensioncommon" - "github.com/hashicorp/go-multierror" - v1 "go.opentelemetry.io/proto/otlp/common/v1" -) - -type otelAccessLogging struct { - ext_cmn.BasicExtensionAdapter - - // ProxyType identifies the type of Envoy proxy that this extension applies to. - // The extension will only be configured for proxies that match this type and - // will be ignored for all other proxy types. - ProxyType api.ServiceKind - // ListenerType controls which listener the extension applies to. It supports "inbound" or "outbound" listeners. - ListenerType string - // Config holds the extension configuration. - Config AccessLog -} - -var _ ext_cmn.BasicExtension = (*otelAccessLogging)(nil) - -func Constructor(ext api.EnvoyExtension) (ext_cmn.EnvoyExtender, error) { - otel, err := newOTELAccessLogging(ext) - if err != nil { - return nil, err - } - return &ext_cmn.BasicEnvoyExtender{ - Extension: otel, - }, nil -} - -// CanApply indicates if the extension can be applied to the given extension runtime configuration. -func (a *otelAccessLogging) CanApply(config *ext_cmn.RuntimeConfig) bool { - return config.Kind == api.ServiceKindConnectProxy -} - -// PatchClusters modifies the cluster resources for the extension. -// -// If the extension is configured to target the OTEL service running on the local host network -// this func will insert a cluster for calling that service. It does nothing if the extension is -// configured to target an upstream service because the existing cluster for the upstream will be -// used directly by the filter. -func (a *otelAccessLogging) PatchClusters(cfg *ext_cmn.RuntimeConfig, c ext_cmn.ClusterMap) (ext_cmn.ClusterMap, error) { - cluster, err := a.Config.toEnvoyCluster(cfg) - if err != nil { - return c, err - } - if cluster != nil { - c[cluster.Name] = cluster - } - return c, nil -} - -func (a *otelAccessLogging) matchesListenerDirection(p ext_cmn.FilterPayload) bool { - isInboundListener := p.IsInbound() - return (!isInboundListener && a.ListenerType == "outbound") || (isInboundListener && a.ListenerType == "inbound") -} - -// PatchFilter adds the OTEL access log in the HTTP connection manager. -func (a *otelAccessLogging) PatchFilter(p ext_cmn.FilterPayload) (*envoy_listener_v3.Filter, bool, error) { - filter := p.Message - // Make sure filter matches extension config. - if !a.matchesListenerDirection(p) { - return filter, false, nil - } - - httpConnectionManager, _, err := ext_cmn.GetHTTPConnectionManager(filter) - if err != nil { - return filter, false, err - } - - accessLog, err := a.toEnvoyAccessLog(p.RuntimeConfig) - if err != nil { - return filter, false, err - } - - httpConnectionManager.AccessLog = append(httpConnectionManager.AccessLog, accessLog) - newHCM, err := ext_cmn.MakeFilter("envoy.filters.network.http_connection_manager", httpConnectionManager) - if err != nil { - return filter, false, err - } - - return newHCM, true, nil -} - -func newOTELAccessLogging(ext api.EnvoyExtension) (*otelAccessLogging, error) { - otel := &otelAccessLogging{} - if ext.Name != api.BuiltinOTELAccessLoggingExtension { - return otel, fmt.Errorf("expected extension name %q but got %q", api.BuiltinOTELAccessLoggingExtension, ext.Name) - } - if err := otel.fromArguments(ext.Arguments); err != nil { - return otel, err - } - - return otel, nil -} - -func (a *otelAccessLogging) fromArguments(args map[string]any) error { - if err := mapstructure.Decode(args, a); err != nil { - return err - } - a.normalize() - return a.validate() -} - -func (a *otelAccessLogging) toEnvoyAccessLog(cfg *ext_cmn.RuntimeConfig) (*envoy_extensions_access_loggers_v3.AccessLog, error) { - commonConfig, err := a.Config.toEnvoyCommonGrpcAccessLogConfig(cfg) - if err != nil { - return nil, err - } - - body, err := toEnvoyAnyValue(a.Config.Body) - if err != nil { - return nil, fmt.Errorf("failed to marshal Body: %w", err) - } - - attributes, err := toEnvoyKeyValueList(a.Config.Attributes) - if err != nil { - return nil, fmt.Errorf("failed to marshal Attributes: %w", err) - } - - resourceAttributes, err := toEnvoyKeyValueList(a.Config.ResourceAttributes) - if err != nil { - return nil, fmt.Errorf("failed to marshal ResourceAttributes: %w", err) - } - - otelAccessLogConfig := &envoy_extensions_access_loggers_otel_v3.OpenTelemetryAccessLogConfig{ - CommonConfig: commonConfig, - Body: body, - Attributes: attributes, - ResourceAttributes: resourceAttributes, - } - - // Marshal the struct to bytes. - otelAccessLogConfigBytes, err := proto.Marshal(otelAccessLogConfig) - if err != nil { - return nil, fmt.Errorf("failed to marshal OpenTelemetryAccessLogConfig: %w", err) - } - - return &envoy_extensions_access_loggers_v3.AccessLog{ - Name: "envoy.access_loggers.open_telemetry", - ConfigType: &envoy_extensions_access_loggers_v3.AccessLog_TypedConfig{ - TypedConfig: &anypb.Any{ - Value: otelAccessLogConfigBytes, - TypeUrl: "type.googleapis.com/envoy.extensions.access_loggers.open_telemetry.v3.OpenTelemetryAccessLogConfig", - }, - }, - }, nil -} - -func (a *otelAccessLogging) normalize() { - if a.ProxyType == "" { - a.ProxyType = api.ServiceKindConnectProxy - } - - if a.ListenerType == "" { - a.ListenerType = "inbound" - } - - if a.Config.LogName == "" { - a.Config.LogName = a.ListenerType - } - - a.Config.normalize() -} - -func (a *otelAccessLogging) validate() error { - var resultErr error - if a.ProxyType != api.ServiceKindConnectProxy { - resultErr = multierror.Append(resultErr, fmt.Errorf("unsupported ProxyType %q, only %q is supported", - a.ProxyType, - api.ServiceKindConnectProxy)) - } - - if a.ListenerType != "inbound" && a.ListenerType != "outbound" { - resultErr = multierror.Append(resultErr, fmt.Errorf(`unexpected ListenerType %q, supported values are "inbound" or "outbound"`, a.ListenerType)) - } - - if err := a.Config.validate(); err != nil { - resultErr = multierror.Append(resultErr, err) - } - - return resultErr -} - -func toEnvoyKeyValueList(attributes map[string]any) (*v1.KeyValueList, error) { - keyValueList := &v1.KeyValueList{} - for key, value := range attributes { - anyValue, err := toEnvoyAnyValue(value) - if err != nil { - return nil, err - } - keyValueList.Values = append(keyValueList.Values, &v1.KeyValue{ - Key: key, - Value: anyValue, - }) - } - - return keyValueList, nil -} - -func toEnvoyAnyValue(value interface{}) (*v1.AnyValue, error) { - if value == nil { - return nil, nil - } - - switch v := value.(type) { - case string: - return &v1.AnyValue{ - Value: &v1.AnyValue_StringValue{ - StringValue: v, - }, - }, nil - case int: - return &v1.AnyValue{ - Value: &v1.AnyValue_IntValue{ - IntValue: int64(v), - }, - }, nil - case int32: - return &v1.AnyValue{ - Value: &v1.AnyValue_IntValue{ - IntValue: int64(v), - }, - }, nil - case int64: - return &v1.AnyValue{ - Value: &v1.AnyValue_IntValue{ - IntValue: v, - }, - }, nil - case float32: - return &v1.AnyValue{ - Value: &v1.AnyValue_DoubleValue{ - DoubleValue: float64(v), - }, - }, nil - case float64: - return &v1.AnyValue{ - Value: &v1.AnyValue_DoubleValue{ - DoubleValue: v, - }, - }, nil - case bool: - return &v1.AnyValue{ - Value: &v1.AnyValue_BoolValue{ - BoolValue: v, - }, - }, nil - case []byte: - return &v1.AnyValue{ - Value: &v1.AnyValue_BytesValue{ - BytesValue: v, - }, - }, nil - default: - return nil, fmt.Errorf("unsupported type %T", v) - } -} diff --git a/agent/envoyextensions/builtin/otel-access-logging/otel_access_logging_test.go b/agent/envoyextensions/builtin/otel-access-logging/otel_access_logging_test.go deleted file mode 100644 index 5c6b9ffa6636c..0000000000000 --- a/agent/envoyextensions/builtin/otel-access-logging/otel_access_logging_test.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package otelaccesslogging - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/envoyextensions/extensioncommon" -) - -func TestConstructor(t *testing.T) { - makeArguments := func(overrides map[string]interface{}) map[string]interface{} { - m := map[string]interface{}{ - "ProxyType": "connect-proxy", - "ListenerType": "inbound", - "Config": AccessLog{ - LogName: "access.log", - GrpcService: &GrpcService{ - Target: &Target{ - Service: api.CompoundServiceName{ - Name: "otel-collector", - Namespace: "default", - Partition: "default", - }, - }, - }, - }, - } - - for k, v := range overrides { - m[k] = v - } - - return m - } - - cases := map[string]struct { - extensionName string - arguments map[string]interface{} - expected otelAccessLogging - ok bool - }{ - "with no arguments": { - arguments: nil, - ok: false, - }, - "with an invalid name": { - arguments: makeArguments(map[string]interface{}{}), - extensionName: "bad", - ok: false, - }, - "invalid proxy type": { - arguments: makeArguments(map[string]interface{}{"ProxyType": "terminating-gateway"}), - ok: false, - }, - "invalid listener": { - arguments: makeArguments(map[string]interface{}{"ListenerType": "invalid"}), - ok: false, - }, - "default proxy type": { - arguments: makeArguments(map[string]interface{}{"ProxyType": ""}), - expected: otelAccessLogging{ - ProxyType: "connect-proxy", - ListenerType: "inbound", - Config: AccessLog{ - LogName: "access.log", - GrpcService: &GrpcService{ - Target: &Target{ - Service: api.CompoundServiceName{ - Name: "otel-collector", - Namespace: "default", - Partition: "default", - }, - }, - }, - }, - }, - ok: true, - }, - } - - for n, tc := range cases { - t.Run(n, func(t *testing.T) { - - extensionName := api.BuiltinOTELAccessLoggingExtension - if tc.extensionName != "" { - extensionName = tc.extensionName - } - - svc := api.CompoundServiceName{Name: "svc"} - ext := extensioncommon.RuntimeConfig{ - ServiceName: svc, - EnvoyExtension: api.EnvoyExtension{ - Name: extensionName, - Arguments: tc.arguments, - }, - } - - e, err := Constructor(ext.EnvoyExtension) - - if tc.ok { - require.NoError(t, err) - require.Equal(t, &extensioncommon.BasicEnvoyExtender{Extension: &tc.expected}, e) - } else { - require.Error(t, err) - } - }) - } -} diff --git a/agent/envoyextensions/builtin/otel-access-logging/structs.go b/agent/envoyextensions/builtin/otel-access-logging/structs.go deleted file mode 100644 index 5d23a0e4032c7..0000000000000 --- a/agent/envoyextensions/builtin/otel-access-logging/structs.go +++ /dev/null @@ -1,424 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package otelaccesslogging - -import ( - "fmt" - "strconv" - "strings" - "time" - - envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" - envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" - envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" - envoy_extensions_access_loggers_grpc_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/grpc/v3" - envoy_upstreams_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/v3" - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/api" - cmn "github.com/hashicorp/consul/envoyextensions/extensioncommon" - "github.com/hashicorp/go-multierror" - "google.golang.org/protobuf/types/known/anypb" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/wrapperspb" -) - -const ( - LocalAccessLogClusterName = "local_access_log" - - localhost = "localhost" - localhostIPv4 = "127.0.0.1" - localhostIPv6 = "::1" -) - -type AccessLog struct { - LogName string - GrpcService *GrpcService - BufferFlushInterval *time.Duration - BufferSizeBytes uint32 - FilterStateObjectsToLog []string - RetryPolicy *RetryPolicy - Body interface{} - Attributes map[string]interface{} - ResourceAttributes map[string]interface{} -} - -func (a *AccessLog) normalize() { - if a.GrpcService != nil { - a.GrpcService.normalize() - } - - if a.RetryPolicy != nil { - a.RetryPolicy.normalize() - } -} - -func (a *AccessLog) validate() error { - a.normalize() - - if a.GrpcService == nil { - return fmt.Errorf("missing GrpcService") - } - - var resultErr error - - var field string - var validate func() error - field = "GrpcService" - validate = a.GrpcService.validate - - if err := validate(); err != nil { - resultErr = multierror.Append(resultErr, fmt.Errorf("failed to validate Config.%s: %w", field, err)) - } - - return resultErr -} - -func (a *AccessLog) envoyGrpcService(cfg *cmn.RuntimeConfig) (*envoy_core_v3.GrpcService, error) { - target := a.GrpcService.Target - clusterName, err := a.getClusterName(cfg, target) - if err != nil { - return nil, err - } - - var initialMetadata []*envoy_core_v3.HeaderValue - for _, meta := range a.GrpcService.InitialMetadata { - initialMetadata = append(initialMetadata, meta.toEnvoy()) - } - - return &envoy_core_v3.GrpcService{ - TargetSpecifier: &envoy_core_v3.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_core_v3.GrpcService_EnvoyGrpc{ - ClusterName: clusterName, - Authority: a.GrpcService.Authority, - }, - }, - Timeout: target.timeoutDurationPB(), - InitialMetadata: initialMetadata, - }, nil -} - -// getClusterName returns the name of the cluster for the OpenTelemetry access logging service. -// If the extension is configured with an upstream OpenTelemetry access logging service then the name of the cluster for -// that upstream is returned. If the extension is configured with a URI, the only allowed host is `localhost` -// and the extension will insert a new cluster with the name "local_access_log", so we use that name. -func (a *AccessLog) getClusterName(cfg *cmn.RuntimeConfig, target *Target) (string, error) { - var err error - clusterName := LocalAccessLogClusterName - if target.isService() { - if clusterName, err = target.clusterName(cfg); err != nil { - return "", err - } - } - return clusterName, nil -} - -// toEnvoyCluster returns an Envoy cluster for connecting to the OpenTelemetry access logging service. -// If the extension is configured with the OpenTelemetry access logging service locally via the URI set to localhost, -// this func will return a new cluster definition that will allow the proxy to connect to the OpenTelemetry access logging -// service running on localhost on the configured port. -// -// If the extension is configured with the OpenTelemetry access logging service as an upstream there is no need to insert -// a new cluster so this method returns nil. -func (a *AccessLog) toEnvoyCluster(_ *cmn.RuntimeConfig) (*envoy_cluster_v3.Cluster, error) { - target := a.GrpcService.Target - - // If the target is an upstream we do not need to create a cluster. We will use the cluster of the upstream. - if target.isService() { - return nil, nil - } - - host, port, err := target.addr() - if err != nil { - return nil, err - } - - clusterType := &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_STATIC} - if host == localhost { - // If the host is "localhost" use a STRICT_DNS cluster type to perform DNS lookup. - clusterType = &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_STRICT_DNS} - } - - var typedExtProtoOpts map[string]*anypb.Any - - httpProtoOpts := &envoy_upstreams_http_v3.HttpProtocolOptions{ - UpstreamProtocolOptions: &envoy_upstreams_http_v3.HttpProtocolOptions_ExplicitHttpConfig_{ - ExplicitHttpConfig: &envoy_upstreams_http_v3.HttpProtocolOptions_ExplicitHttpConfig{ - ProtocolConfig: &envoy_upstreams_http_v3.HttpProtocolOptions_ExplicitHttpConfig_Http2ProtocolOptions{}, - }, - }, - } - httpProtoOptsAny, err := anypb.New(httpProtoOpts) - if err != nil { - return nil, err - } - typedExtProtoOpts = make(map[string]*anypb.Any) - typedExtProtoOpts["envoy.extensions.upstreams.http.v3.HttpProtocolOptions"] = httpProtoOptsAny - - return &envoy_cluster_v3.Cluster{ - Name: LocalAccessLogClusterName, - ClusterDiscoveryType: clusterType, - ConnectTimeout: target.timeoutDurationPB(), - LoadAssignment: &envoy_endpoint_v3.ClusterLoadAssignment{ - ClusterName: LocalAccessLogClusterName, - Endpoints: []*envoy_endpoint_v3.LocalityLbEndpoints{ - { - LbEndpoints: []*envoy_endpoint_v3.LbEndpoint{{ - HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ - Endpoint: &envoy_endpoint_v3.Endpoint{ - Address: &envoy_core_v3.Address{ - Address: &envoy_core_v3.Address_SocketAddress{ - SocketAddress: &envoy_core_v3.SocketAddress{ - Address: host, - PortSpecifier: &envoy_core_v3.SocketAddress_PortValue{ - PortValue: uint32(port), - }, - }, - }, - }, - }, - }, - }}, - }, - }, - }, - TypedExtensionProtocolOptions: typedExtProtoOpts, - }, nil -} - -func (a *AccessLog) toEnvoyCommonGrpcAccessLogConfig(cfg *cmn.RuntimeConfig) (*envoy_extensions_access_loggers_grpc_v3.CommonGrpcAccessLogConfig, error) { - config := &envoy_extensions_access_loggers_grpc_v3.CommonGrpcAccessLogConfig{ - LogName: a.LogName, - BufferSizeBytes: wrapperspb.UInt32(a.BufferSizeBytes), - FilterStateObjectsToLog: a.FilterStateObjectsToLog, - TransportApiVersion: envoy_core_v3.ApiVersion_V3, - } - - if a.BufferFlushInterval != nil { - config.BufferFlushInterval = durationpb.New(*a.BufferFlushInterval) - } - - if a.RetryPolicy != nil { - config.GrpcStreamRetryPolicy = a.RetryPolicy.toEnvoy() - } - - grpcSvc, err := a.envoyGrpcService(cfg) - if err != nil { - return nil, err - } - config.GrpcService = grpcSvc - - return config, nil -} - -type GrpcService struct { - Target *Target - Authority string - InitialMetadata []*HeaderValue -} - -func (v *GrpcService) normalize() { - if v == nil { - return - } - v.Target.normalize() -} - -func (v *GrpcService) validate() error { - var resultErr error - if v == nil { - return resultErr - } - - if v.Target == nil { - resultErr = multierror.Append(resultErr, fmt.Errorf("GrpcService.Target must be set")) - } - if err := v.Target.validate(); err != nil { - resultErr = multierror.Append(resultErr, err) - } - return resultErr -} - -type HeaderValue struct { - Key string - Value string -} - -func (h *HeaderValue) toEnvoy() *envoy_core_v3.HeaderValue { - if h == nil { - return nil - } - return &envoy_core_v3.HeaderValue{Key: h.Key, Value: h.Value} -} - -type Target struct { - Service api.CompoundServiceName - URI string - Timeout string - - timeout *time.Duration - host string - port int -} - -// addr returns the host and port for the target when the target is a URI. -// It returns a non-nil error if the target is not a URI. -func (t Target) addr() (string, int, error) { - if !t.isURI() { - return "", 0, fmt.Errorf("target is not configured with a URI, set Target.URI") - } - return t.host, t.port, nil -} - -// clusterName returns the cluster name for the target when the target is an upstream service. -// It searches through the upstreams in the provided runtime configuration and returns the name -// of the cluster for the first upstream service that matches the target service. -// It returns a non-nil error if a matching cluster is not found or if the target is not an -// upstream service. -func (t Target) clusterName(cfg *cmn.RuntimeConfig) (string, error) { - if !t.isService() { - return "", fmt.Errorf("target is not configured with an upstream service, set Target.Service") - } - - for service, upstream := range cfg.Upstreams { - if service == t.Service { - for sni := range upstream.SNIs { - return sni, nil - } - } - } - return "", fmt.Errorf("no upstream definition found for service %q", t.Service.Name) -} - -func (t Target) isService() bool { - return t.Service.Name != "" -} - -func (t Target) isURI() bool { - return t.URI != "" -} - -func (t *Target) normalize() { - if t == nil { - return - } - t.Service.Namespace = acl.NamespaceOrDefault(t.Service.Namespace) - t.Service.Partition = acl.PartitionOrDefault(t.Service.Partition) -} - -// timeoutDurationPB returns the target's timeout as a *durationpb.Duration. -// It returns nil if the timeout has not been explicitly set. -func (t *Target) timeoutDurationPB() *durationpb.Duration { - if t == nil || t.timeout == nil { - return nil - } - return durationpb.New(*t.timeout) -} - -func (t *Target) validate() error { - var err, resultErr error - if t == nil { - return resultErr - } - - if t.isURI() == t.isService() { - resultErr = multierror.Append(resultErr, fmt.Errorf("exactly one of Target.Service or Target.URI must be set")) - } - - if t.isURI() { - t.host, t.port, err = parseAddr(t.URI) - if err == nil { - switch t.host { - case localhost, localhostIPv4, localhostIPv6: - default: - resultErr = multierror.Append(resultErr, - fmt.Errorf("invalid host for Target.URI %q: expected %q, %q, or %q", t.URI, localhost, localhostIPv4, localhostIPv6)) - } - } else { - resultErr = multierror.Append(resultErr, fmt.Errorf("invalid format for Target.URI %q: expected host:port", t.URI)) - } - } - - if t.Timeout != "" { - if d, err := time.ParseDuration(t.Timeout); err == nil { - t.timeout = &d - } else { - resultErr = multierror.Append(resultErr, fmt.Errorf("failed to parse Target.Timeout %q as a duration: %w", t.Timeout, err)) - } - } - return resultErr -} - -type RetryPolicy struct { - RetryBackOff *RetryBackOff - NumRetries uint32 -} - -func (r *RetryPolicy) normalize() { - if r == nil { - return - } - r.RetryBackOff.normalize() -} - -func (r *RetryPolicy) toEnvoy() *envoy_core_v3.RetryPolicy { - if r == nil { - return nil - } - - return &envoy_core_v3.RetryPolicy{ - RetryBackOff: r.RetryBackOff.toEnvoy(), - NumRetries: wrapperspb.UInt32(r.NumRetries), - } -} - -type RetryBackOff struct { - BaseInterval *time.Duration - MaxInterval *time.Duration -} - -func (v *RetryBackOff) normalize() { - if v == nil { - return - } - - if v.BaseInterval == nil { - v.BaseInterval = new(time.Duration) - *v.BaseInterval = time.Second - } - - if v.MaxInterval == nil { - v.MaxInterval = new(time.Duration) - *v.MaxInterval = time.Second * 30 - } -} - -func (r *RetryBackOff) toEnvoy() *envoy_core_v3.BackoffStrategy { - if r == nil { - return nil - } - - return &envoy_core_v3.BackoffStrategy{ - BaseInterval: durationpb.New(*r.BaseInterval), - MaxInterval: durationpb.New(*r.MaxInterval), - } -} - -func parseAddr(s string) (host string, port int, err error) { - // Strip the protocol if one was provided - if _, addr, hasProto := strings.Cut(s, "://"); hasProto { - s = addr - } - idx := strings.LastIndex(s, ":") - switch idx { - case -1, len(s) - 1: - err = fmt.Errorf("invalid input format %q: expected host:port", s) - case 0: - host = localhost - port, err = strconv.Atoi(s[idx+1:]) - default: - host = s[:idx] - port, err = strconv.Atoi(s[idx+1:]) - } - return -} diff --git a/agent/envoyextensions/builtin/property-override/property_override.go b/agent/envoyextensions/builtin/property-override/property_override.go index 70577a56e3d40..41e98074b7a23 100644 --- a/agent/envoyextensions/builtin/property-override/property_override.go +++ b/agent/envoyextensions/builtin/property-override/property_override.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package propertyoverride import ( diff --git a/agent/envoyextensions/builtin/property-override/property_override_test.go b/agent/envoyextensions/builtin/property-override/property_override_test.go index 20febc21074db..0e4317f9ddb72 100644 --- a/agent/envoyextensions/builtin/property-override/property_override_test.go +++ b/agent/envoyextensions/builtin/property-override/property_override_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package propertyoverride import ( diff --git a/agent/envoyextensions/builtin/property-override/structpatcher.go b/agent/envoyextensions/builtin/property-override/structpatcher.go index 76fe3be1a8570..91de4cf7f86d1 100644 --- a/agent/envoyextensions/builtin/property-override/structpatcher.go +++ b/agent/envoyextensions/builtin/property-override/structpatcher.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package propertyoverride import ( diff --git a/agent/envoyextensions/builtin/property-override/structpatcher_test.go b/agent/envoyextensions/builtin/property-override/structpatcher_test.go index 4916f0c505c7d..ac7379f9f1868 100644 --- a/agent/envoyextensions/builtin/property-override/structpatcher_test.go +++ b/agent/envoyextensions/builtin/property-override/structpatcher_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package propertyoverride import ( diff --git a/agent/envoyextensions/builtin/wasm/structs.go b/agent/envoyextensions/builtin/wasm/structs.go index 67540fee56c94..012099ab62036 100644 --- a/agent/envoyextensions/builtin/wasm/structs.go +++ b/agent/envoyextensions/builtin/wasm/structs.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package wasm diff --git a/agent/envoyextensions/builtin/wasm/wasm.go b/agent/envoyextensions/builtin/wasm/wasm.go index da1e0a7ceaa95..c16ac4da81c0e 100644 --- a/agent/envoyextensions/builtin/wasm/wasm.go +++ b/agent/envoyextensions/builtin/wasm/wasm.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package wasm diff --git a/agent/envoyextensions/builtin/wasm/wasm_test.go b/agent/envoyextensions/builtin/wasm/wasm_test.go index 41769beecdc9f..93f3a4b5e0aff 100644 --- a/agent/envoyextensions/builtin/wasm/wasm_test.go +++ b/agent/envoyextensions/builtin/wasm/wasm_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package wasm diff --git a/agent/envoyextensions/registered_extensions.go b/agent/envoyextensions/registered_extensions.go index b2bb2aeeaaa9e..7b0f2ae61da14 100644 --- a/agent/envoyextensions/registered_extensions.go +++ b/agent/envoyextensions/registered_extensions.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package envoyextensions @@ -12,7 +12,6 @@ import ( awslambda "github.com/hashicorp/consul/agent/envoyextensions/builtin/aws-lambda" extauthz "github.com/hashicorp/consul/agent/envoyextensions/builtin/ext-authz" "github.com/hashicorp/consul/agent/envoyextensions/builtin/lua" - otelaccesslogging "github.com/hashicorp/consul/agent/envoyextensions/builtin/otel-access-logging" propertyoverride "github.com/hashicorp/consul/agent/envoyextensions/builtin/property-override" "github.com/hashicorp/consul/agent/envoyextensions/builtin/wasm" "github.com/hashicorp/consul/api" @@ -22,25 +21,22 @@ import ( type extensionConstructor func(api.EnvoyExtension) (extensioncommon.EnvoyExtender, error) var extensionConstructors = map[string]extensionConstructor{ - api.BuiltinOTELAccessLoggingExtension: otelaccesslogging.Constructor, - api.BuiltinLuaExtension: lua.Constructor, - api.BuiltinAWSLambdaExtension: awslambda.Constructor, - api.BuiltinPropertyOverrideExtension: propertyoverride.Constructor, - api.BuiltinWasmExtension: wasm.Constructor, - api.BuiltinExtAuthzExtension: extauthz.Constructor, + api.BuiltinLuaExtension: lua.Constructor, + api.BuiltinAWSLambdaExtension: awslambda.Constructor, + api.BuiltinPropertyOverrideExtension: propertyoverride.Constructor, + api.BuiltinWasmExtension: wasm.Constructor, + api.BuiltinExtAuthzExtension: extauthz.Constructor, } // ConstructExtension attempts to lookup and build an extension from the registry with the // given config. Returns an error if the extension does not exist, or if the extension fails // to be constructed properly. func ConstructExtension(ext api.EnvoyExtension) (extensioncommon.EnvoyExtender, error) { - if constructor, ok := extensionConstructors[ext.Name]; ok { - return constructor(ext) + constructor, ok := extensionConstructors[ext.Name] + if !ok { + return nil, fmt.Errorf("name %q is not a built-in extension", ext.Name) } - if constructor, ok := enterpriseExtensionConstructors[ext.Name]; ok { - return constructor(ext) - } - return nil, fmt.Errorf("name %q is not a built-in extension", ext.Name) + return constructor(ext) } // ValidateExtensions will attempt to construct each instance of the given envoy extension configurations diff --git a/agent/envoyextensions/registered_extensions_ce.go b/agent/envoyextensions/registered_extensions_ce.go deleted file mode 100644 index 4b9e07e50ba46..0000000000000 --- a/agent/envoyextensions/registered_extensions_ce.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent - -package envoyextensions - -var enterpriseExtensionConstructors = map[string]extensionConstructor{} diff --git a/agent/envoyextensions/registered_extensions_test.go b/agent/envoyextensions/registered_extensions_test.go index 818db87fafea8..7f3cb6bbac7dc 100644 --- a/agent/envoyextensions/registered_extensions_test.go +++ b/agent/envoyextensions/registered_extensions_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package envoyextensions diff --git a/agent/event_endpoint.go b/agent/event_endpoint.go index da589632c75af..034dec305619b 100644 --- a/agent/event_endpoint.go +++ b/agent/event_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/event_endpoint_test.go b/agent/event_endpoint_test.go index a041088c448c7..4be21a6914b91 100644 --- a/agent/event_endpoint_test.go +++ b/agent/event_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/exec/exec.go b/agent/exec/exec.go index 408dc6bb8110d..d4b4bfafd1fed 100644 --- a/agent/exec/exec.go +++ b/agent/exec/exec.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package exec diff --git a/agent/exec/exec_unix.go b/agent/exec/exec_unix.go index b31e593163a0a..32ff23249e3b0 100644 --- a/agent/exec/exec_unix.go +++ b/agent/exec/exec_unix.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !windows // +build !windows diff --git a/agent/exec/exec_windows.go b/agent/exec/exec_windows.go index aeb9b6a847819..1a0cb4c82c806 100644 --- a/agent/exec/exec_windows.go +++ b/agent/exec/exec_windows.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build windows // +build windows diff --git a/agent/federation_state_endpoint.go b/agent/federation_state_endpoint.go index 40a3df1ff1cd9..0bec145ae60cd 100644 --- a/agent/federation_state_endpoint.go +++ b/agent/federation_state_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/grpc-external/forward.go b/agent/grpc-external/forward.go index 395fb6aa479d0..c0ed064ac808c 100644 --- a/agent/grpc-external/forward.go +++ b/agent/grpc-external/forward.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package external diff --git a/agent/grpc-external/limiter/limiter.go b/agent/grpc-external/limiter/limiter.go index 44aaac616f99f..f995f963049be 100644 --- a/agent/grpc-external/limiter/limiter.go +++ b/agent/grpc-external/limiter/limiter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // package limiter provides primatives for limiting the number of concurrent // operations in-flight. diff --git a/agent/grpc-external/limiter/limiter_test.go b/agent/grpc-external/limiter/limiter_test.go index 3cfa3ad263273..fa165a66706bb 100644 --- a/agent/grpc-external/limiter/limiter_test.go +++ b/agent/grpc-external/limiter/limiter_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package limiter diff --git a/agent/grpc-external/options.go b/agent/grpc-external/options.go index 04e5c10efb513..a25a4482990f6 100644 --- a/agent/grpc-external/options.go +++ b/agent/grpc-external/options.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package external diff --git a/agent/grpc-external/options_test.go b/agent/grpc-external/options_test.go index ccc0ad12fd697..b2edb8fbf1f50 100644 --- a/agent/grpc-external/options_test.go +++ b/agent/grpc-external/options_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package external diff --git a/agent/grpc-external/querymeta.go b/agent/grpc-external/querymeta.go index 0f4dd52adb867..55b960255fffa 100644 --- a/agent/grpc-external/querymeta.go +++ b/agent/grpc-external/querymeta.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package external import ( diff --git a/agent/grpc-external/querymeta_test.go b/agent/grpc-external/querymeta_test.go index 4406929648179..66c7136a3dd48 100644 --- a/agent/grpc-external/querymeta_test.go +++ b/agent/grpc-external/querymeta_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package external import ( diff --git a/agent/grpc-external/server.go b/agent/grpc-external/server.go index 6090a8f31a155..0513d22e223c9 100644 --- a/agent/grpc-external/server.go +++ b/agent/grpc-external/server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package external diff --git a/agent/grpc-external/services/acl/login.go b/agent/grpc-external/services/acl/login.go index 1e44acf8a1712..c8c399d108be3 100644 --- a/agent/grpc-external/services/acl/login.go +++ b/agent/grpc-external/services/acl/login.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/agent/grpc-external/services/acl/login_test.go b/agent/grpc-external/services/acl/login_test.go index 3b956d7c8c71e..e858618a906b4 100644 --- a/agent/grpc-external/services/acl/login_test.go +++ b/agent/grpc-external/services/acl/login_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/agent/grpc-external/services/acl/logout.go b/agent/grpc-external/services/acl/logout.go index 691ac7b888949..bd3bb5e3e42a2 100644 --- a/agent/grpc-external/services/acl/logout.go +++ b/agent/grpc-external/services/acl/logout.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/agent/grpc-external/services/acl/logout_test.go b/agent/grpc-external/services/acl/logout_test.go index df5c39628297c..69491db5e3b0a 100644 --- a/agent/grpc-external/services/acl/logout_test.go +++ b/agent/grpc-external/services/acl/logout_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/agent/grpc-external/services/acl/server.go b/agent/grpc-external/services/acl/server.go index 2393f11aa1068..5513950e02ec8 100644 --- a/agent/grpc-external/services/acl/server.go +++ b/agent/grpc-external/services/acl/server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/agent/grpc-external/services/acl/server_test.go b/agent/grpc-external/services/acl/server_test.go index 1b6cd066001ef..89c49bf226a13 100644 --- a/agent/grpc-external/services/acl/server_test.go +++ b/agent/grpc-external/services/acl/server_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/agent/grpc-external/services/connectca/server.go b/agent/grpc-external/services/connectca/server.go index 4ef91705f7a14..c90962e180c84 100644 --- a/agent/grpc-external/services/connectca/server.go +++ b/agent/grpc-external/services/connectca/server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connectca diff --git a/agent/grpc-external/services/connectca/server_test.go b/agent/grpc-external/services/connectca/server_test.go index 27c8d17c0c9dc..84636e9e75886 100644 --- a/agent/grpc-external/services/connectca/server_test.go +++ b/agent/grpc-external/services/connectca/server_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connectca diff --git a/agent/grpc-external/services/connectca/sign.go b/agent/grpc-external/services/connectca/sign.go index 148bf675b0570..59c1a6f28354a 100644 --- a/agent/grpc-external/services/connectca/sign.go +++ b/agent/grpc-external/services/connectca/sign.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connectca diff --git a/agent/grpc-external/services/connectca/sign_test.go b/agent/grpc-external/services/connectca/sign_test.go index 07be304081ebb..e43978e0b906d 100644 --- a/agent/grpc-external/services/connectca/sign_test.go +++ b/agent/grpc-external/services/connectca/sign_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connectca diff --git a/agent/grpc-external/services/connectca/watch_roots.go b/agent/grpc-external/services/connectca/watch_roots.go index ddd02ca56e0f9..14927e2188a18 100644 --- a/agent/grpc-external/services/connectca/watch_roots.go +++ b/agent/grpc-external/services/connectca/watch_roots.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connectca diff --git a/agent/grpc-external/services/connectca/watch_roots_test.go b/agent/grpc-external/services/connectca/watch_roots_test.go index 171e00324643c..bfdb76f33bdd8 100644 --- a/agent/grpc-external/services/connectca/watch_roots_test.go +++ b/agent/grpc-external/services/connectca/watch_roots_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connectca diff --git a/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params.go b/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params.go index 147f84d302e28..13bbd1c9f94b9 100644 --- a/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params.go +++ b/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dataplane diff --git a/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params_test.go b/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params_test.go index 03e968ba42219..322d2f6527459 100644 --- a/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params_test.go +++ b/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dataplane diff --git a/agent/grpc-external/services/dataplane/get_supported_features.go b/agent/grpc-external/services/dataplane/get_supported_features.go index 214f0e249f30e..ea638715338a3 100644 --- a/agent/grpc-external/services/dataplane/get_supported_features.go +++ b/agent/grpc-external/services/dataplane/get_supported_features.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dataplane diff --git a/agent/grpc-external/services/dataplane/get_supported_features_test.go b/agent/grpc-external/services/dataplane/get_supported_features_test.go index 4761ccb3cb38a..329b5df0f68f1 100644 --- a/agent/grpc-external/services/dataplane/get_supported_features_test.go +++ b/agent/grpc-external/services/dataplane/get_supported_features_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dataplane diff --git a/agent/grpc-external/services/dataplane/server.go b/agent/grpc-external/services/dataplane/server.go index 88b586f459a4c..8772893863840 100644 --- a/agent/grpc-external/services/dataplane/server.go +++ b/agent/grpc-external/services/dataplane/server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dataplane diff --git a/agent/grpc-external/services/dataplane/server_test.go b/agent/grpc-external/services/dataplane/server_test.go index ec57396bcb791..15ac272871e85 100644 --- a/agent/grpc-external/services/dataplane/server_test.go +++ b/agent/grpc-external/services/dataplane/server_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dataplane diff --git a/agent/grpc-external/services/dns/server.go b/agent/grpc-external/services/dns/server.go index a6f2249733c11..a9733c40666be 100644 --- a/agent/grpc-external/services/dns/server.go +++ b/agent/grpc-external/services/dns/server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dns diff --git a/agent/grpc-external/services/dns/server_test.go b/agent/grpc-external/services/dns/server_test.go index a6576b51adcfd..0144eccc0cd1f 100644 --- a/agent/grpc-external/services/dns/server_test.go +++ b/agent/grpc-external/services/dns/server_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dns diff --git a/agent/grpc-external/services/peerstream/health_snapshot.go b/agent/grpc-external/services/peerstream/health_snapshot.go index efd60a7f1039e..dd9a10c67469b 100644 --- a/agent/grpc-external/services/peerstream/health_snapshot.go +++ b/agent/grpc-external/services/peerstream/health_snapshot.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/health_snapshot_test.go b/agent/grpc-external/services/peerstream/health_snapshot_test.go index 6759db252d2cc..7ea404f3854c3 100644 --- a/agent/grpc-external/services/peerstream/health_snapshot_test.go +++ b/agent/grpc-external/services/peerstream/health_snapshot_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/replication.go b/agent/grpc-external/services/peerstream/replication.go index 692a475235be0..a0c1e4387f1c6 100644 --- a/agent/grpc-external/services/peerstream/replication.go +++ b/agent/grpc-external/services/peerstream/replication.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/server.go b/agent/grpc-external/services/peerstream/server.go index 4127312fe72cd..58e436bd1f5cd 100644 --- a/agent/grpc-external/services/peerstream/server.go +++ b/agent/grpc-external/services/peerstream/server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/server_test.go b/agent/grpc-external/services/peerstream/server_test.go index 836b09d89b2b1..cb7c60e3cf0a2 100644 --- a/agent/grpc-external/services/peerstream/server_test.go +++ b/agent/grpc-external/services/peerstream/server_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/stream_resources.go b/agent/grpc-external/services/peerstream/stream_resources.go index 9f2d9cf896f3d..61c98d3f07894 100644 --- a/agent/grpc-external/services/peerstream/stream_resources.go +++ b/agent/grpc-external/services/peerstream/stream_resources.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/stream_test.go b/agent/grpc-external/services/peerstream/stream_test.go index 8c1e0783bd7ba..2d8f6f3e16677 100644 --- a/agent/grpc-external/services/peerstream/stream_test.go +++ b/agent/grpc-external/services/peerstream/stream_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/stream_tracker.go b/agent/grpc-external/services/peerstream/stream_tracker.go index c74a1b284f09e..abb5a003a3992 100644 --- a/agent/grpc-external/services/peerstream/stream_tracker.go +++ b/agent/grpc-external/services/peerstream/stream_tracker.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/stream_tracker_test.go b/agent/grpc-external/services/peerstream/stream_tracker_test.go index 33ea536469d8a..d676587a2520e 100644 --- a/agent/grpc-external/services/peerstream/stream_tracker_test.go +++ b/agent/grpc-external/services/peerstream/stream_tracker_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/subscription_blocking.go b/agent/grpc-external/services/peerstream/subscription_blocking.go index a1257d3d33819..7fa8bc1eff59f 100644 --- a/agent/grpc-external/services/peerstream/subscription_blocking.go +++ b/agent/grpc-external/services/peerstream/subscription_blocking.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/subscription_manager.go b/agent/grpc-external/services/peerstream/subscription_manager.go index bd2d36ffd942c..4fcd27635b81d 100644 --- a/agent/grpc-external/services/peerstream/subscription_manager.go +++ b/agent/grpc-external/services/peerstream/subscription_manager.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/subscription_manager_test.go b/agent/grpc-external/services/peerstream/subscription_manager_test.go index cc2afee0d54cd..4ed912368e89b 100644 --- a/agent/grpc-external/services/peerstream/subscription_manager_test.go +++ b/agent/grpc-external/services/peerstream/subscription_manager_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/subscription_state.go b/agent/grpc-external/services/peerstream/subscription_state.go index a1a370a3ec4c6..dba315370de7f 100644 --- a/agent/grpc-external/services/peerstream/subscription_state.go +++ b/agent/grpc-external/services/peerstream/subscription_state.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/subscription_state_test.go b/agent/grpc-external/services/peerstream/subscription_state_test.go index cc3e49ab4c9cb..3cba66c9c2be4 100644 --- a/agent/grpc-external/services/peerstream/subscription_state_test.go +++ b/agent/grpc-external/services/peerstream/subscription_state_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/subscription_view.go b/agent/grpc-external/services/peerstream/subscription_view.go index 575729bc71df9..c85c82b15e5c8 100644 --- a/agent/grpc-external/services/peerstream/subscription_view.go +++ b/agent/grpc-external/services/peerstream/subscription_view.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/subscription_view_test.go b/agent/grpc-external/services/peerstream/subscription_view_test.go index cd2f61e60feb7..a51ca57e2902c 100644 --- a/agent/grpc-external/services/peerstream/subscription_view_test.go +++ b/agent/grpc-external/services/peerstream/subscription_view_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/peerstream/testing.go b/agent/grpc-external/services/peerstream/testing.go index 47cc8d1dbec64..2208249dc6fc8 100644 --- a/agent/grpc-external/services/peerstream/testing.go +++ b/agent/grpc-external/services/peerstream/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peerstream diff --git a/agent/grpc-external/services/resource/delete.go b/agent/grpc-external/services/resource/delete.go index 123ffac35b389..b3045b3d6d294 100644 --- a/agent/grpc-external/services/resource/delete.go +++ b/agent/grpc-external/services/resource/delete.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -27,38 +27,21 @@ import ( // - Errors with Aborted if the requested Version does not match the stored Version. // - Errors with PermissionDenied if ACL check fails func (s *Server) Delete(ctx context.Context, req *pbresource.DeleteRequest) (*pbresource.DeleteResponse, error) { - reg, err := s.validateDeleteRequest(req) - if err != nil { + if err := validateDeleteRequest(req); err != nil { return nil, err } - entMeta := v2TenancyToV1EntMeta(req.Id.Tenancy) - authz, authzContext, err := s.getAuthorizer(tokenFromContext(ctx), entMeta) + reg, err := s.resolveType(req.Id.Type) if err != nil { return nil, err } - // Retrieve resource since ACL hook requires it. Furthermore, we'll need the - // read to be strongly consistent if the passed in Version or Uid are empty. - consistency := storage.EventualConsistency - if req.Version == "" || req.Id.Uid == "" { - consistency = storage.StrongConsistency - } - - // Apply defaults when tenancy units empty. - v1EntMetaToV2Tenancy(reg, entMeta, req.Id.Tenancy) - - existing, err := s.Backend.Read(ctx, consistency, req.Id) - switch { - case errors.Is(err, storage.ErrNotFound): - // Deletes are idempotent so no-op when not found - return &pbresource.DeleteResponse{}, nil - case err != nil: - return nil, status.Errorf(codes.Internal, "failed read: %v", err) + authz, err := s.getAuthorizer(tokenFromContext(ctx)) + if err != nil { + return nil, err } - // Check ACLs - err = reg.ACLs.Write(authz, authzContext, existing) + err = reg.ACLs.Write(authz, req.Id) switch { case acl.IsErrPermissionDenied(err): return nil, status.Error(codes.PermissionDenied, err.Error()) @@ -66,11 +49,27 @@ func (s *Server) Delete(ctx context.Context, req *pbresource.DeleteRequest) (*pb return nil, status.Errorf(codes.Internal, "failed write acl: %v", err) } + // The storage backend requires a Version and Uid to delete a resource based + // on CAS semantics. When either are not provided, the resource must be read + // with a strongly consistent read to retrieve either or both. + // + // n.b.: There is a chance DeleteCAS may fail with a storage.ErrCASFailure + // if an update occurs between the Read and DeleteCAS. Consider refactoring + // to use retryCAS() similar to the Write endpoint to close this gap. deleteVersion := req.Version deleteId := req.Id if deleteVersion == "" || deleteId.Uid == "" { - deleteVersion = existing.Version - deleteId = existing.Id + existing, err := s.Backend.Read(ctx, storage.StrongConsistency, req.Id) + switch { + case err == nil: + deleteVersion = existing.Version + deleteId = existing.Id + case errors.Is(err, storage.ErrNotFound): + // Deletes are idempotent so no-op when not found + return &pbresource.DeleteResponse{}, nil + default: + return nil, status.Errorf(codes.Internal, "failed read: %v", err) + } } if err := s.maybeCreateTombstone(ctx, deleteId); err != nil { @@ -144,31 +143,15 @@ func (s *Server) maybeCreateTombstone(ctx context.Context, deleteId *pbresource. } } -func (s *Server) validateDeleteRequest(req *pbresource.DeleteRequest) (*resource.Registration, error) { +func validateDeleteRequest(req *pbresource.DeleteRequest) error { if req.Id == nil { - return nil, status.Errorf(codes.InvalidArgument, "id is required") + return status.Errorf(codes.InvalidArgument, "id is required") } if err := validateId(req.Id, "id"); err != nil { - return nil, err - } - - reg, err := s.resolveType(req.Id.Type) - if err != nil { - return nil, err + return err } - - // Check scope - if reg.Scope == resource.ScopePartition && req.Id.Tenancy.Namespace != "" { - return nil, status.Errorf( - codes.InvalidArgument, - "partition scoped resource %s cannot have a namespace. got: %s", - resource.ToGVK(req.Id.Type), - req.Id.Tenancy.Namespace, - ) - } - - return reg, nil + return nil } // Maintains a deterministic mapping between a resource and it's tombstone's diff --git a/agent/grpc-external/services/resource/delete_test.go b/agent/grpc-external/services/resource/delete_test.go index 3b8a8099021df..0e98d3fd57a7a 100644 --- a/agent/grpc-external/services/resource/delete_test.go +++ b/agent/grpc-external/services/resource/delete_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -11,7 +11,6 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" "github.com/hashicorp/consul/acl/resolver" "github.com/hashicorp/consul/internal/resource" @@ -26,36 +25,32 @@ func TestDelete_InputValidation(t *testing.T) { demo.RegisterTypes(server.Registry) - testCases := map[string]func(artistId, recordLabelId *pbresource.ID) *pbresource.ID{ - "no id": func(artistId, recordLabelId *pbresource.ID) *pbresource.ID { - return nil + testCases := map[string]func(*pbresource.DeleteRequest){ + "no id": func(req *pbresource.DeleteRequest) { req.Id = nil }, + "no type": func(req *pbresource.DeleteRequest) { req.Id.Type = nil }, + "no tenancy": func(req *pbresource.DeleteRequest) { req.Id.Tenancy = nil }, + "no name": func(req *pbresource.DeleteRequest) { req.Id.Name = "" }, + // clone necessary to not pollute DefaultTenancy + "tenancy partition not default": func(req *pbresource.DeleteRequest) { + req.Id.Tenancy = clone(req.Id.Tenancy) + req.Id.Tenancy.Partition = "" }, - "no type": func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Type = nil - return artistId + "tenancy namespace not default": func(req *pbresource.DeleteRequest) { + req.Id.Tenancy = clone(req.Id.Tenancy) + req.Id.Tenancy.Namespace = "" }, - "no tenancy": func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy = nil - return artistId - }, - "no name": func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Name = "" - return artistId - }, - "partition scoped resource with namespace": func(_, recordLabelId *pbresource.ID) *pbresource.ID { - recordLabelId.Tenancy.Namespace = "ishouldnothaveanamespace" - return recordLabelId + "tenancy peername not local": func(req *pbresource.DeleteRequest) { + req.Id.Tenancy = clone(req.Id.Tenancy) + req.Id.Tenancy.PeerName = "" }, } for desc, modFn := range testCases { t.Run(desc, func(t *testing.T) { - recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") - require.NoError(t, err) - - artist, err := demo.GenerateV2Artist() + res, err := demo.GenerateV2Artist() require.NoError(t, err) - req := &pbresource.DeleteRequest{Id: modFn(artist.Id, recordLabel.Id), Version: ""} + req := &pbresource.DeleteRequest{Id: res.Id, Version: ""} + modFn(req) _, err = client.Delete(testContext(t), req) require.Error(t, err) @@ -127,48 +122,34 @@ func TestDelete_Success(t *testing.T) { for desc, tc := range deleteTestCases() { t.Run(desc, func(t *testing.T) { - for tenancyDesc, modFn := range tenancyCases() { - t.Run(tenancyDesc, func(t *testing.T) { - server, client, ctx := testDeps(t) - demo.RegisterTypes(server.Registry) - - recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") - require.NoError(t, err) - recordLabel, err = server.Backend.WriteCAS(ctx, recordLabel) - require.NoError(t, err) - - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - artist, err = server.Backend.WriteCAS(ctx, artist) - require.NoError(t, err) - - // Pick the resource to be deleted based on type's scope - deleteId := modFn(artist.Id, recordLabel.Id) - deleteReq := tc.deleteReqFn(recordLabel) - if proto.Equal(deleteId.Type, demo.TypeV2Artist) { - deleteReq = tc.deleteReqFn(artist) - } - - // Delete - _, err = client.Delete(ctx, deleteReq) - require.NoError(t, err) - - // Verify deleted - _, err = server.Backend.Read(ctx, storage.StrongConsistency, deleteId) - require.Error(t, err) - require.ErrorIs(t, err, storage.ErrNotFound) - - // Verify tombstone created - _, err = client.Read(ctx, &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Name: tombstoneName(deleteReq.Id), - Type: resource.TypeV1Tombstone, - Tenancy: deleteReq.Id.Tenancy, - }, - }) - require.NoError(t, err, "expected tombstome to be found") - }) - } + server, client, ctx := testDeps(t) + demo.RegisterTypes(server.Registry) + artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + + rsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: artist}) + require.NoError(t, err) + artistId := clone(rsp.Resource.Id) + artist = rsp.Resource + + // delete + _, err = client.Delete(ctx, tc.deleteReqFn(artist)) + require.NoError(t, err) + + // verify deleted + _, err = server.Backend.Read(ctx, storage.StrongConsistency, artistId) + require.Error(t, err) + require.ErrorIs(t, err, storage.ErrNotFound) + + // verify tombstone created + _, err = client.Read(ctx, &pbresource.ReadRequest{ + Id: &pbresource.ID{ + Name: tombstoneName(artistId), + Type: resource.TypeV1Tombstone, + Tenancy: artist.Id.Tenancy, + }, + }) + require.NoError(t, err) }) } } diff --git a/agent/grpc-external/services/resource/list.go b/agent/grpc-external/services/resource/list.go index cc2b19026a11b..77269e74688ff 100644 --- a/agent/grpc-external/services/resource/list.go +++ b/agent/grpc-external/services/resource/list.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -10,27 +10,28 @@ import ( "google.golang.org/grpc/status" "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/storage" "github.com/hashicorp/consul/proto-public/pbresource" ) func (s *Server) List(ctx context.Context, req *pbresource.ListRequest) (*pbresource.ListResponse, error) { - reg, err := s.validateListRequest(req) + if err := validateListRequest(req); err != nil { + return nil, err + } + + // check type + reg, err := s.resolveType(req.Type) if err != nil { return nil, err } - // v1 ACL subsystem is "wildcard" aware so just pass on through. - entMeta := v2TenancyToV1EntMeta(req.Tenancy) - token := tokenFromContext(ctx) - authz, authzContext, err := s.getAuthorizer(token, entMeta) + authz, err := s.getAuthorizer(tokenFromContext(ctx)) if err != nil { return nil, err } - // Check ACLs. - err = reg.ACLs.List(authz, authzContext) + // check acls + err = reg.ACLs.List(authz, req.Tenancy) switch { case acl.IsErrPermissionDenied(err): return nil, status.Error(codes.PermissionDenied, err.Error()) @@ -38,9 +39,6 @@ func (s *Server) List(ctx context.Context, req *pbresource.ListRequest) (*pbreso return nil, status.Errorf(codes.Internal, "failed list acl: %v", err) } - // Ensure we're defaulting correctly when request tenancy units are empty. - v1EntMetaToV2Tenancy(reg, entMeta, req.Tenancy) - resources, err := s.Backend.List( ctx, readConsistencyFrom(ctx), @@ -54,22 +52,13 @@ func (s *Server) List(ctx context.Context, req *pbresource.ListRequest) (*pbreso result := make([]*pbresource.Resource, 0) for _, resource := range resources { - // Filter out non-matching GroupVersion. + // filter out non-matching GroupVersion if resource.Id.Type.GroupVersion != req.Type.GroupVersion { continue } - // Need to rebuild authorizer per resource since wildcard inputs may - // result in different tenancies. Consider caching per tenancy if this - // is deemed expensive. - entMeta = v2TenancyToV1EntMeta(resource.Id.Tenancy) - authz, authzContext, err = s.getAuthorizer(token, entMeta) - if err != nil { - return nil, err - } - - // Filter out items that don't pass read ACLs. - err = reg.ACLs.Read(authz, authzContext, resource.Id) + // filter out items that don't pass read ACLs + err = reg.ACLs.Read(authz, resource.Id) switch { case acl.IsErrPermissionDenied(err): continue @@ -81,37 +70,15 @@ func (s *Server) List(ctx context.Context, req *pbresource.ListRequest) (*pbreso return &pbresource.ListResponse{Resources: result}, nil } -func (s *Server) validateListRequest(req *pbresource.ListRequest) (*resource.Registration, error) { +func validateListRequest(req *pbresource.ListRequest) error { var field string switch { case req.Type == nil: field = "type" case req.Tenancy == nil: field = "tenancy" + default: + return nil } - - if field != "" { - return nil, status.Errorf(codes.InvalidArgument, "%s is required", field) - } - - // Check type exists. - reg, err := s.resolveType(req.Type) - if 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 != "" { - return nil, status.Errorf( - codes.InvalidArgument, - "partition scoped type %s cannot have a namespace. got: %s", - resource.ToGVK(req.Type), - req.Tenancy.Namespace, - ) - } - - return reg, nil + return status.Errorf(codes.InvalidArgument, "%s is required", field) } diff --git a/agent/grpc-external/services/resource/list_by_owner.go b/agent/grpc-external/services/resource/list_by_owner.go index 3c0ccbda65e8b..2cc203e72c30b 100644 --- a/agent/grpc-external/services/resource/list_by_owner.go +++ b/agent/grpc-external/services/resource/list_by_owner.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -10,71 +10,38 @@ import ( "google.golang.org/grpc/status" "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/proto-public/pbresource" ) func (s *Server) ListByOwner(ctx context.Context, req *pbresource.ListByOwnerRequest) (*pbresource.ListByOwnerResponse, error) { - reg, err := s.validateListByOwnerRequest(req) - if err != nil { + if err := validateListByOwnerRequest(req); err != nil { return nil, err } - // Convert v2 request tenancy to v1 for ACL subsystem. - entMeta := v2TenancyToV1EntMeta(req.Owner.Tenancy) - token := tokenFromContext(ctx) - - // Fill entMeta with token tenancy when empty. - authz, authzContext, err := s.getAuthorizer(token, entMeta) + _, err := s.resolveType(req.Owner.Type) if err != nil { return nil, err } - // Handle defaulting empty tenancy units from request. - v1EntMetaToV2Tenancy(reg, entMeta, req.Owner.Tenancy) - - // Check list ACL before verifying tenancy exists to not leak tenancy existence. - err = reg.ACLs.List(authz, authzContext) - switch { - case acl.IsErrPermissionDenied(err): - return nil, status.Error(codes.PermissionDenied, err.Error()) - case err != nil: - return nil, status.Errorf(codes.Internal, "failed list acl: %v", err) - } - - // Check v1 tenancy exists for the v2 resource. - if err = v1TenancyExists(reg, s.V1TenancyBridge, req.Owner.Tenancy, codes.InvalidArgument); err != nil { - return nil, err - } - - // Get owned resources. children, err := s.Backend.ListByOwner(ctx, req.Owner) if err != nil { return nil, status.Errorf(codes.Internal, "failed list by owner: %v", err) } + authz, err := s.getAuthorizer(tokenFromContext(ctx)) + if err != nil { + return nil, err + } + result := make([]*pbresource.Resource, 0) for _, child := range children { - // Retrieve child type's registration to access read ACL hook. - childReg, err := s.resolveType(child.Id.Type) + reg, err := s.resolveType(child.Id.Type) if err != nil { return nil, err } - // Rebuild authorizer if tenancy not identical between owner and child (child scope - // may be narrower). - childAuthz := authz - childAuthzContext := authzContext - if !resource.EqualTenancy(req.Owner.Tenancy, child.Id.Tenancy) { - childEntMeta := v2TenancyToV1EntMeta(child.Id.Tenancy) - childAuthz, childAuthzContext, err = s.getAuthorizer(token, childEntMeta) - if err != nil { - return nil, err - } - } - - // Filter out children that fail real ACL. - err = childReg.ACLs.Read(childAuthz, childAuthzContext, child.Id) + // ACL filter + err = reg.ACLs.Read(authz, child.Id) switch { case acl.IsErrPermissionDenied(err): continue @@ -87,36 +54,17 @@ func (s *Server) ListByOwner(ctx context.Context, req *pbresource.ListByOwnerReq return &pbresource.ListByOwnerResponse{Resources: result}, nil } -func (s *Server) validateListByOwnerRequest(req *pbresource.ListByOwnerRequest) (*resource.Registration, error) { +func validateListByOwnerRequest(req *pbresource.ListByOwnerRequest) error { if req.Owner == nil { - return nil, status.Errorf(codes.InvalidArgument, "owner is required") + return status.Errorf(codes.InvalidArgument, "owner is required") } if err := validateId(req.Owner, "owner"); err != nil { - return nil, err + return err } if req.Owner.Uid == "" { - return nil, status.Errorf(codes.InvalidArgument, "owner uid is required") + return status.Errorf(codes.InvalidArgument, "owner uid is required") } - - reg, err := s.resolveType(req.Owner.Type) - if 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 != "" { - return nil, status.Errorf( - codes.InvalidArgument, - "partition scoped type %s cannot have a namespace. got: %s", - resource.ToGVK(req.Owner.Type), - req.Owner.Tenancy.Namespace, - ) - } - - return reg, nil + return nil } 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 4a60e3ac9460c..218971a050daa 100644 --- a/agent/grpc-external/services/resource/list_by_owner_test.go +++ b/agent/grpc-external/services/resource/list_by_owner_test.go @@ -1,5 +1,5 @@ // // Copyright (c) HashiCorp, Inc. -// // SPDX-License-Identifier: BUSL-1.1 +// // SPDX-License-Identifier: MPL-2.0 package resource @@ -9,7 +9,6 @@ import ( "testing" "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/proto/private/prototest" @@ -18,49 +17,41 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" ) func TestListByOwner_InputValidation(t *testing.T) { server := testServer(t) client := testClient(t, server) + demo.RegisterTypes(server.Registry) - testCases := map[string]func(artistId, recordlabelId *pbresource.ID) *pbresource.ID{ - "no owner": func(artistId, recordLabelId *pbresource.ID) *pbresource.ID { - return nil - }, - "no type": func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Type = nil - return artistId - }, - "no tenancy": func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy = nil - return artistId + testCases := map[string]func(*pbresource.ListByOwnerRequest){ + "no owner": func(req *pbresource.ListByOwnerRequest) { req.Owner = nil }, + "no type": func(req *pbresource.ListByOwnerRequest) { req.Owner.Type = nil }, + "no tenancy": func(req *pbresource.ListByOwnerRequest) { req.Owner.Tenancy = nil }, + "no name": func(req *pbresource.ListByOwnerRequest) { req.Owner.Name = "" }, + "no uid": func(req *pbresource.ListByOwnerRequest) { req.Owner.Uid = "" }, + // clone necessary to not pollute DefaultTenancy + "tenancy partition not default": func(req *pbresource.ListByOwnerRequest) { + req.Owner.Tenancy = clone(req.Owner.Tenancy) + req.Owner.Tenancy.Partition = "" }, - "no name": func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Name = "" - return artistId + "tenancy namespace not default": func(req *pbresource.ListByOwnerRequest) { + req.Owner.Tenancy = clone(req.Owner.Tenancy) + req.Owner.Tenancy.Namespace = "" }, - "no uid": func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Uid = "" - return artistId - }, - "partition scope with non-empty namespace": func(_, recordLabelId *pbresource.ID) *pbresource.ID { - recordLabelId.Tenancy.Namespace = "ishouldnothaveanamespace" - return recordLabelId + "tenancy peername not local": func(req *pbresource.ListByOwnerRequest) { + req.Owner.Tenancy = clone(req.Owner.Tenancy) + req.Owner.Tenancy.PeerName = "" }, } for desc, modFn := range testCases { t.Run(desc, func(t *testing.T) { - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - - recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") + res, err := demo.GenerateV2Artist() require.NoError(t, err) - // Each test case picks which resource to use based on the resource type's scope. - req := &pbresource.ListByOwnerRequest{Owner: modFn(artist.Id, recordLabel.Id)} + req := &pbresource.ListByOwnerRequest{Owner: res.Id} + modFn(req) _, err = client.ListByOwner(testContext(t), req) require.Error(t, err) @@ -76,7 +67,7 @@ func TestListByOwner_TypeNotRegistered(t *testing.T) { _, err := client.ListByOwner(context.Background(), &pbresource.ListByOwnerRequest{ Owner: &pbresource.ID{ Type: demo.TypeV2Artist, - Tenancy: resource.DefaultNamespacedTenancy(), + Tenancy: demo.TenancyDefault, Uid: "bogus", Name: "bogus", }, @@ -134,108 +125,8 @@ func TestListByOwner_Many(t *testing.T) { prototest.AssertElementsMatch(t, albums, rsp3.Resources) } -func TestListByOwner_OwnerTenancyDoesNotExist(t *testing.T) { - 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": func(artistId, _ *pbresource.ID) *pbresource.ID { - id := clone(artistId) - id.Uid = "doesnotmatter" - id.Tenancy.Namespace = "bogusnamespace" - return id - }, - "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, 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("LoonyTunes") - require.NoError(t, err) - recordLabel, err = server.Backend.WriteCAS(testContext(t), recordLabel) - require.NoError(t, err) - - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - artist, err = server.Backend.WriteCAS(testContext(t), artist) - require.NoError(t, err) - - // 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.Contains(t, err.Error(), "resource not found") - }) - } -} - -func TestListByOwner_Tenancy_Defaults_And_Normalization(t *testing.T) { - for tenancyDesc, modFn := range tenancyCases() { - t.Run(tenancyDesc, func(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) - - // Create partition scoped recordLabel. - recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") - require.NoError(t, err) - rsp1, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: recordLabel}) - require.NoError(t, err) - recordLabel = rsp1.Resource - - // Create namespace scoped artist. - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - rsp2, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: artist}) - require.NoError(t, err) - artist = rsp2.Resource - - // Owner will be either partition scoped (recordLabel) or namespace scoped (artist) based on testcase. - moddedOwnerId := modFn(artist.Id, recordLabel.Id) - var ownerId *pbresource.ID - - // Avoid using the modded id when linking owner to child. - switch { - case proto.Equal(moddedOwnerId.Type, demo.TypeV2Artist): - ownerId = artist.Id - case proto.Equal(moddedOwnerId.Type, demo.TypeV1RecordLabel): - ownerId = recordLabel.Id - default: - require.Fail(t, "unexpected resource type") - } - - // Link owner to child. - album, err := demo.GenerateV2Album(ownerId) - require.NoError(t, err) - rsp3, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: album}) - require.NoError(t, err) - album = rsp3.Resource - - // Test - listRsp, err := client.ListByOwner(testContext(t), &pbresource.ListByOwnerRequest{ - Owner: moddedOwnerId, - }) - require.NoError(t, err) - - // Verify child album always returned. - prototest.AssertDeepEqual(t, album, listRsp.Resources[0]) - }) - } -} - func TestListByOwner_ACL_PerTypeDenied(t *testing.T) { - authz := AuthorizerFrom(t, `key_prefix "resource/demo.v2.Album/" { policy = "deny" }`, demo.ArtistV2ListPolicy) + authz := AuthorizerFrom(t, `key_prefix "resource/demo.v2.Album/" { policy = "deny" }`) _, rsp, err := roundTripListByOwner(t, authz) // verify resource filtered out, hence no results @@ -244,7 +135,7 @@ func TestListByOwner_ACL_PerTypeDenied(t *testing.T) { } func TestListByOwner_ACL_PerTypeAllowed(t *testing.T) { - authz := AuthorizerFrom(t, `key_prefix "resource/demo.v2.Album/" { policy = "read" }`, demo.ArtistV2ListPolicy) + authz := AuthorizerFrom(t, `key_prefix "resource/demo.v2.Album/" { policy = "read" }`) album, rsp, err := roundTripListByOwner(t, authz) // verify resource not filtered out diff --git a/agent/grpc-external/services/resource/list_test.go b/agent/grpc-external/services/resource/list_test.go index 64026b7d34e59..4d6b50951b758 100644 --- a/agent/grpc-external/services/resource/list_test.go +++ b/agent/grpc-external/services/resource/list_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -10,7 +10,6 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/grpc-external/testutils" - "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/internal/storage" "github.com/hashicorp/consul/proto-public/pbresource" @@ -32,16 +31,12 @@ func TestList_InputValidation(t *testing.T) { 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, modFn := range testCases { t.Run(desc, func(t *testing.T) { req := &pbresource.ListRequest{ Type: demo.TypeV2Album, - Tenancy: resource.DefaultNamespacedTenancy(), + Tenancy: demo.TenancyDefault, } modFn(req) @@ -58,7 +53,7 @@ func TestList_TypeNotFound(t *testing.T) { _, err := client.List(context.Background(), &pbresource.ListRequest{ Type: demo.TypeV2Artist, - Tenancy: resource.DefaultNamespacedTenancy(), + Tenancy: demo.TenancyDefault, NamePrefix: "", }) require.Error(t, err) @@ -75,7 +70,7 @@ func TestList_Empty(t *testing.T) { rsp, err := client.List(tc.ctx, &pbresource.ListRequest{ Type: demo.TypeV1Artist, - Tenancy: resource.DefaultNamespacedTenancy(), + Tenancy: demo.TenancyDefault, NamePrefix: "", }) require.NoError(t, err) @@ -107,7 +102,7 @@ func TestList_Many(t *testing.T) { rsp, err := client.List(tc.ctx, &pbresource.ListRequest{ Type: demo.TypeV2Artist, - Tenancy: resource.DefaultNamespacedTenancy(), + Tenancy: demo.TenancyDefault, NamePrefix: "", }) require.NoError(t, err) @@ -116,44 +111,6 @@ func TestList_Many(t *testing.T) { } } -func TestList_Tenancy_Defaults_And_Normalization(t *testing.T) { - // Test units of tenancy get defaulted correctly when empty. - ctx := context.Background() - for desc, tc := range wildcardTenancyCases() { - t.Run(desc, func(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) - - // Write partition scoped record label - recordLabel, err := demo.GenerateV1RecordLabel("LooneyTunes") - require.NoError(t, err) - recordLabelRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: recordLabel}) - require.NoError(t, err) - - // Write namespace scoped artist - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - artistRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: artist}) - require.NoError(t, err) - - // List and verify correct resource returned for empty tenancy units. - listRsp, err := client.List(ctx, &pbresource.ListRequest{ - Type: tc.typ, - Tenancy: tc.tenancy, - }) - require.NoError(t, err) - require.Len(t, listRsp.Resources, 1) - if tc.typ == demo.TypeV1RecordLabel { - prototest.AssertDeepEqual(t, recordLabelRsp.Resource, listRsp.Resources[0]) - } else { - prototest.AssertDeepEqual(t, artistRsp.Resource, listRsp.Resources[0]) - } - }) - - } -} - func TestList_GroupVersionMismatch(t *testing.T) { for desc, tc := range listTestCases() { t.Run(desc, func(t *testing.T) { diff --git a/agent/grpc-external/services/resource/mock_TenancyBridge.go b/agent/grpc-external/services/resource/mock_TenancyBridge.go deleted file mode 100644 index 662b4004b99f7..0000000000000 --- a/agent/grpc-external/services/resource/mock_TenancyBridge.go +++ /dev/null @@ -1,121 +0,0 @@ -// Code generated by mockery v2.20.0. DO NOT EDIT. - -package resource - -import mock "github.com/stretchr/testify/mock" - -// MockTenancyBridge is an autogenerated mock type for the TenancyBridge type -type MockTenancyBridge struct { - mock.Mock -} - -// IsNamespaceMarkedForDeletion provides a mock function with given fields: partition, namespace -func (_m *MockTenancyBridge) IsNamespaceMarkedForDeletion(partition string, namespace string) (bool, error) { - ret := _m.Called(partition, namespace) - - var r0 bool - var r1 error - if rf, ok := ret.Get(0).(func(string, string) (bool, error)); ok { - return rf(partition, namespace) - } - if rf, ok := ret.Get(0).(func(string, string) bool); ok { - r0 = rf(partition, namespace) - } else { - r0 = ret.Get(0).(bool) - } - - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(partition, namespace) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// IsPartitionMarkedForDeletion provides a mock function with given fields: partition -func (_m *MockTenancyBridge) IsPartitionMarkedForDeletion(partition string) (bool, error) { - ret := _m.Called(partition) - - var r0 bool - var r1 error - if rf, ok := ret.Get(0).(func(string) (bool, error)); ok { - return rf(partition) - } - if rf, ok := ret.Get(0).(func(string) bool); ok { - r0 = rf(partition) - } else { - r0 = ret.Get(0).(bool) - } - - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(partition) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NamespaceExists provides a mock function with given fields: partition, namespace -func (_m *MockTenancyBridge) NamespaceExists(partition string, namespace string) (bool, error) { - ret := _m.Called(partition, namespace) - - var r0 bool - var r1 error - if rf, ok := ret.Get(0).(func(string, string) (bool, error)); ok { - return rf(partition, namespace) - } - if rf, ok := ret.Get(0).(func(string, string) bool); ok { - r0 = rf(partition, namespace) - } else { - r0 = ret.Get(0).(bool) - } - - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(partition, namespace) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PartitionExists provides a mock function with given fields: partition -func (_m *MockTenancyBridge) PartitionExists(partition string) (bool, error) { - ret := _m.Called(partition) - - var r0 bool - var r1 error - if rf, ok := ret.Get(0).(func(string) (bool, error)); ok { - return rf(partition) - } - if rf, ok := ret.Get(0).(func(string) bool); ok { - r0 = rf(partition) - } else { - r0 = ret.Get(0).(bool) - } - - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(partition) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -type mockConstructorTestingTNewMockTenancyBridge interface { - mock.TestingT - Cleanup(func()) -} - -// NewMockTenancyBridge creates a new instance of MockTenancyBridge. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewMockTenancyBridge(t mockConstructorTestingTNewMockTenancyBridge) *MockTenancyBridge { - mock := &MockTenancyBridge{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/agent/grpc-external/services/resource/read.go b/agent/grpc-external/services/resource/read.go index febfcb69f0faa..c75779183cb8d 100644 --- a/agent/grpc-external/services/resource/read.go +++ b/agent/grpc-external/services/resource/read.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -11,41 +11,28 @@ import ( "google.golang.org/grpc/status" "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/storage" "github.com/hashicorp/consul/proto-public/pbresource" ) func (s *Server) Read(ctx context.Context, req *pbresource.ReadRequest) (*pbresource.ReadResponse, error) { - // Light first pass validation based on what user passed in and not much more. - reg, err := s.validateReadRequest(req) - if err != nil { + if err := validateReadRequest(req); err != nil { return nil, err } - // acl.EnterpriseMeta acl.AuthorizerContext follow rules for V1 resources since they integrate with the V1 acl subsystem. - // pbresource.Tenacy follows rules for V2 resources and the Resource service. - // Example: - // - // A CE namespace scoped resource: - // V1: EnterpriseMeta{} - // V2: Tenancy {Partition: "default", Namespace: "default"} - // - // An ENT namespace scoped resource: - // V1: EnterpriseMeta{Partition: "default", Namespace: "default"} - // V2: Tenancy {Partition: "default", Namespace: "default"} - // - // It is necessary to convert back and forth depending on which component supports which version, V1 or V2. - entMeta := v2TenancyToV1EntMeta(req.Id.Tenancy) - authz, authzContext, err := s.getAuthorizer(tokenFromContext(ctx), entMeta) + // check type exists + reg, err := s.resolveType(req.Id.Type) if err != nil { return nil, err } - v1EntMetaToV2Tenancy(reg, entMeta, req.Id.Tenancy) + authz, err := s.getAuthorizer(tokenFromContext(ctx)) + if err != nil { + return nil, err + } - // ACL check comes before tenancy existence checks to not leak tenancy "existence". - err = reg.ACLs.Read(authz, authzContext, req.Id) + // check acls + err = reg.ACLs.Read(authz, req.Id) switch { case acl.IsErrPermissionDenied(err): return nil, status.Error(codes.PermissionDenied, err.Error()) @@ -53,11 +40,6 @@ func (s *Server) Read(ctx context.Context, req *pbresource.ReadRequest) (*pbreso return nil, status.Errorf(codes.Internal, "failed read acl: %v", err) } - // Check V1 tenancy exists for the V2 resource. - if err = v1TenancyExists(reg, s.V1TenancyBridge, req.Id.Tenancy, codes.NotFound); err != nil { - return nil, err - } - resource, err := s.Backend.Read(ctx, readConsistencyFrom(ctx), req.Id) switch { case err == nil: @@ -71,30 +53,13 @@ func (s *Server) Read(ctx context.Context, req *pbresource.ReadRequest) (*pbreso } } -func (s *Server) validateReadRequest(req *pbresource.ReadRequest) (*resource.Registration, error) { +func validateReadRequest(req *pbresource.ReadRequest) error { if req.Id == nil { - return nil, status.Errorf(codes.InvalidArgument, "id is required") + return status.Errorf(codes.InvalidArgument, "id is required") } if err := validateId(req.Id, "id"); err != nil { - return nil, err + return err } - - // Check type exists. - reg, err := s.resolveType(req.Id.Type) - if err != nil { - return nil, err - } - - // Check scope - if reg.Scope == resource.ScopePartition && req.Id.Tenancy.Namespace != "" { - return nil, status.Errorf( - codes.InvalidArgument, - "partition scoped resource %s cannot have a namespace. got: %s", - resource.ToGVK(req.Id.Type), - req.Id.Tenancy.Namespace, - ) - } - - return reg, nil + return nil } diff --git a/agent/grpc-external/services/resource/read_test.go b/agent/grpc-external/services/resource/read_test.go index ff312c82ca005..cca911ec15b5b 100644 --- a/agent/grpc-external/services/resource/read_test.go +++ b/agent/grpc-external/services/resource/read_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -12,7 +12,6 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" "github.com/hashicorp/consul/acl/resolver" "github.com/hashicorp/consul/internal/resource" @@ -25,37 +24,35 @@ import ( func TestRead_InputValidation(t *testing.T) { server := testServer(t) client := testClient(t, server) + demo.RegisterTypes(server.Registry) - testCases := map[string]func(artistId, recordlabelId *pbresource.ID) *pbresource.ID{ - "no id": func(artistId, recordLabelId *pbresource.ID) *pbresource.ID { return nil }, - "no type": func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Type = nil - return artistId - }, - "no tenancy": func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Tenancy = nil - return artistId + testCases := map[string]func(*pbresource.ReadRequest){ + "no id": func(req *pbresource.ReadRequest) { req.Id = nil }, + "no type": func(req *pbresource.ReadRequest) { req.Id.Type = nil }, + "no tenancy": func(req *pbresource.ReadRequest) { req.Id.Tenancy = nil }, + "no name": func(req *pbresource.ReadRequest) { req.Id.Name = "" }, + // clone necessary to not pollute DefaultTenancy + "tenancy partition not default": func(req *pbresource.ReadRequest) { + req.Id.Tenancy = clone(req.Id.Tenancy) + req.Id.Tenancy.Partition = "" }, - "no name": func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Name = "" - return artistId + "tenancy namespace not default": func(req *pbresource.ReadRequest) { + req.Id.Tenancy = clone(req.Id.Tenancy) + req.Id.Tenancy.Namespace = "" }, - "partition scope with non-empty namespace": func(_, recordLabelId *pbresource.ID) *pbresource.ID { - recordLabelId.Tenancy.Namespace = "ishouldnothaveanamespace" - return recordLabelId + "tenancy peername not local": func(req *pbresource.ReadRequest) { + req.Id.Tenancy = clone(req.Id.Tenancy) + req.Id.Tenancy.PeerName = "" }, } for desc, modFn := range testCases { t.Run(desc, func(t *testing.T) { - artist, err := demo.GenerateV2Artist() + res, err := demo.GenerateV2Artist() require.NoError(t, err) - 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.ReadRequest{Id: modFn(artist.Id, recordLabel.Id)} + req := &pbresource.ReadRequest{Id: res.Id} + modFn(req) _, err = client.Read(testContext(t), req) require.Error(t, err) @@ -80,50 +77,18 @@ func TestRead_TypeNotFound(t *testing.T) { func TestRead_ResourceNotFound(t *testing.T) { for desc, tc := range readTestCases() { t.Run(desc, func(t *testing.T) { - 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": func(artistId, _ *pbresource.ID) *pbresource.ID { - id := clone(artistId) - id.Tenancy.Partition = "boguspartition" - return id - }, - "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": func(_, recordLabelId *pbresource.ID) *pbresource.ID { - id := clone(recordLabelId) - id.Tenancy.Partition = "boguspartition" - return id - }, - } - 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("LoonyTunes") - require.NoError(t, err) - recordLabel, err = server.Backend.WriteCAS(tc.ctx, recordLabel) - require.NoError(t, err) - - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - artist, err = server.Backend.WriteCAS(tc.ctx, artist) - 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: modFn(artist.Id, recordLabel.Id)}) - require.Error(t, err) - require.Equal(t, codes.NotFound.String(), status.Code(err).String()) - require.Contains(t, err.Error(), "resource not found") - }) - } + server := testServer(t) + + demo.RegisterTypes(server.Registry) + client := testClient(t, server) + + artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + + _, err = client.Read(tc.ctx, &pbresource.ReadRequest{Id: artist.Id}) + require.Error(t, err) + require.Equal(t, codes.NotFound.String(), status.Code(err).String()) + require.Contains(t, err.Error(), "resource not found") }) } } @@ -156,37 +121,20 @@ func TestRead_GroupVersionMismatch(t *testing.T) { func TestRead_Success(t *testing.T) { for desc, tc := range readTestCases() { t.Run(desc, func(t *testing.T) { - 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("LoonyTunes") - require.NoError(t, err) - recordLabel, err = server.Backend.WriteCAS(tc.ctx, recordLabel) - require.NoError(t, err) - - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - artist, err = server.Backend.WriteCAS(tc.ctx, artist) - require.NoError(t, err) - - // Each tenancy test case picks which resource to use based on the resource type's scope. - req := &pbresource.ReadRequest{Id: modFn(artist.Id, recordLabel.Id)} - rsp, err := client.Read(tc.ctx, req) - require.NoError(t, err) - - switch { - case proto.Equal(rsp.Resource.Id.Type, demo.TypeV2Artist): - prototest.AssertDeepEqual(t, artist, rsp.Resource) - case proto.Equal(rsp.Resource.Id.Type, demo.TypeV1RecordLabel): - prototest.AssertDeepEqual(t, recordLabel, rsp.Resource) - default: - require.Fail(t, "unexpected resource type") - } - }) - } + server := testServer(t) + + demo.RegisterTypes(server.Registry) + client := testClient(t, server) + + artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + + resource1, err := server.Backend.WriteCAS(tc.ctx, artist) + require.NoError(t, err) + + rsp, err := client.Read(tc.ctx, &pbresource.ReadRequest{Id: artist.Id}) + require.NoError(t, err) + prototest.AssertDeepEqual(t, resource1, rsp.Resource) }) } } diff --git a/agent/grpc-external/services/resource/server.go b/agent/grpc-external/services/resource/server.go index 29b18bd964c8b..51bb4610d527f 100644 --- a/agent/grpc-external/services/resource/server.go +++ b/agent/grpc-external/services/resource/server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -31,9 +31,6 @@ type Config struct { // Backend is the storage backend that will be used for resource persistence. Backend Backend ACLResolver ACLResolver - // V1TenancyBridge temporarily allows us to use V1 implementations of - // partitions and namespaces until V2 implementations are available. - V1TenancyBridge TenancyBridge } //go:generate mockery --name Registry --inpackage @@ -51,14 +48,6 @@ type ACLResolver interface { ResolveTokenAndDefaultMeta(string, *acl.EnterpriseMeta, *acl.AuthorizerContext) (resolver.Result, error) } -//go:generate mockery --name TenancyBridge --inpackage -type TenancyBridge interface { - PartitionExists(partition string) (bool, error) - IsPartitionMarkedForDeletion(partition string) (bool, error) - NamespaceExists(partition, namespace string) (bool, error) - IsNamespaceMarkedForDeletion(partition, namespace string) (bool, error) -} - func NewServer(cfg Config) *Server { return &Server{cfg} } @@ -111,13 +100,12 @@ func readConsistencyFrom(ctx context.Context) storage.ReadConsistency { return storage.EventualConsistency } -func (s *Server) getAuthorizer(token string, entMeta *acl.EnterpriseMeta) (acl.Authorizer, *acl.AuthorizerContext, error) { - authzContext := &acl.AuthorizerContext{} - authz, err := s.ACLResolver.ResolveTokenAndDefaultMeta(token, entMeta, authzContext) +func (s *Server) getAuthorizer(token string) (acl.Authorizer, error) { + authz, err := s.ACLResolver.ResolveTokenAndDefaultMeta(token, nil, nil) if err != nil { - return nil, nil, status.Errorf(codes.Internal, "failed getting authorizer: %v", err) + return nil, status.Errorf(codes.Internal, "failed getting authorizer: %v", err) } - return authz, authzContext, nil + return authz, nil } func isGRPCStatusError(err error) bool { @@ -142,55 +130,20 @@ func validateId(id *pbresource.ID, errorPrefix string) error { if field != "" { return status.Errorf(codes.InvalidArgument, "%s.%s is required", errorPrefix, field) } - resource.Normalize(id.Tenancy) - - return nil -} - -// 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 := v1Bridge.PartitionExists(tenancy.Partition) - switch { - case err != nil: - return err - case !exists: - return status.Errorf(errCode, "partition resource not found: %v", tenancy.Partition) - } - } - if reg.Scope == resource.ScopeNamespace { - exists, err := v1Bridge.NamespaceExists(tenancy.Partition, tenancy.Namespace) - switch { - case err != nil: - return err - case !exists: - return status.Errorf(errCode, "namespace resource not found: %v", tenancy.Namespace) - } - } - return nil -} - -// 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 := v1Bridge.IsPartitionMarkedForDeletion(tenancy.Partition) - switch { - case err != nil: - return err - case marked: - return status.Errorf(codes.InvalidArgument, "partition marked for deletion: %v", tenancy.Partition) - } + // Revisit defaulting and non-namespaced resources post-1.16 + var expected string + switch { + case id.Tenancy.Partition != "default": + field, expected = "partition", "default" + case id.Tenancy.Namespace != "default": + field, expected = "namespace", "default" + case id.Tenancy.PeerName != "local": + field, expected = "peername", "local" } - if reg.Scope == resource.ScopeNamespace { - marked, err := v1Bridge.IsNamespaceMarkedForDeletion(tenancy.Partition, tenancy.Namespace) - switch { - case err != nil: - return err - case marked: - return status.Errorf(codes.InvalidArgument, "namespace marked for deletion: %v", tenancy.Namespace) - } + if field != "" { + return status.Errorf(codes.InvalidArgument, "%s.tenancy.%s must be %s", errorPrefix, field, expected) } return nil } diff --git a/agent/grpc-external/services/resource/server_ce.go b/agent/grpc-external/services/resource/server_ce.go deleted file mode 100644 index 562af973200ff..0000000000000 --- a/agent/grpc-external/services/resource/server_ce.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package resource - -import ( - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func v2TenancyToV1EntMeta(tenancy *pbresource.Tenancy) *acl.EnterpriseMeta { - return acl.DefaultEnterpriseMeta() -} - -func v1EntMetaToV2Tenancy(reg *resource.Registration, entMeta *acl.EnterpriseMeta, tenancy *pbresource.Tenancy) { - if (reg.Scope == resource.ScopeNamespace || reg.Scope == resource.ScopePartition) && tenancy.Partition == "" { - tenancy.Partition = entMeta.PartitionOrDefault() - } - - if reg.Scope == resource.ScopeNamespace && tenancy.Namespace == "" { - tenancy.Namespace = entMeta.NamespaceOrDefault() - } -} diff --git a/agent/grpc-external/services/resource/server_ce_test.go b/agent/grpc-external/services/resource/server_ce_test.go deleted file mode 100644 index 9e155019ca01e..0000000000000 --- a/agent/grpc-external/services/resource/server_ce_test.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package resource - -import "github.com/hashicorp/consul/acl" - -func fillEntMeta(entMeta *acl.EnterpriseMeta) { - return -} - -func fillAuthorizerContext(authzContext *acl.AuthorizerContext) { - return -} diff --git a/agent/grpc-external/services/resource/server_test.go b/agent/grpc-external/services/resource/server_test.go index 7f745952e5e5c..a92fff38a3266 100644 --- a/agent/grpc-external/services/resource/server_test.go +++ b/agent/grpc-external/services/resource/server_test.go @@ -1,12 +1,11 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource import ( "context" "fmt" - "strings" "testing" "github.com/stretchr/testify/mock" @@ -21,7 +20,6 @@ import ( "github.com/hashicorp/consul/agent/grpc-external/testutils" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/internal/storage/inmem" "github.com/hashicorp/consul/proto-public/pbresource" pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2" @@ -59,38 +57,16 @@ func testServer(t *testing.T) *Server { require.NoError(t, err) go backend.Run(testContext(t)) - // Mock the ACL Resolver to "allow all" for testing. + // Mock the ACL Resolver to allow everything for testing mockACLResolver := &MockACLResolver{} mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). - Return(testutils.ACLsDisabled(t), nil). - Run(func(args mock.Arguments) { - // Caller expecting passed in tokenEntMeta and authorizerContext to be filled in. - tokenEntMeta := args.Get(1).(*acl.EnterpriseMeta) - if tokenEntMeta != nil { - fillEntMeta(tokenEntMeta) - } - - authzContext := args.Get(2).(*acl.AuthorizerContext) - if authzContext != nil { - fillAuthorizerContext(authzContext) - } - }) - - // 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) - mockTenancyBridge.On("PartitionExists", mock.Anything).Return(false, nil) - mockTenancyBridge.On("NamespaceExists", mock.Anything, mock.Anything).Return(false, nil) - mockTenancyBridge.On("IsPartitionMarkedForDeletion", resource.DefaultPartitionName).Return(false, nil) - mockTenancyBridge.On("IsNamespaceMarkedForDeletion", resource.DefaultPartitionName, resource.DefaultNamespaceName).Return(false, nil) + Return(testutils.ACLsDisabled(t), nil) return NewServer(Config{ - Logger: testutil.Logger(t), - Registry: resource.NewRegistry(), - Backend: backend, - ACLResolver: mockACLResolver, - V1TenancyBridge: mockTenancyBridge, + Logger: testutil.Logger(t), + Registry: resource.NewRegistry(), + Backend: backend, + ACLResolver: mockACLResolver, }) } @@ -131,134 +107,3 @@ func modifyArtist(t *testing.T, res *pbresource.Resource) *pbresource.Resource { res.Data = data return res } - -// wildcardTenancyCases returns permutations of tenancy and type scope used as input -// to endpoints that accept wildcards for tenancy. -func wildcardTenancyCases() map[string]struct { - typ *pbresource.Type - tenancy *pbresource.Tenancy -} { - return map[string]struct { - typ *pbresource.Type - tenancy *pbresource.Tenancy - }{ - "namespaced type with empty partition": { - typ: demo.TypeV2Artist, - tenancy: &pbresource.Tenancy{ - Partition: "", - Namespace: resource.DefaultNamespaceName, - PeerName: "local", - }, - }, - "namespaced type with empty namespace": { - typ: demo.TypeV2Artist, - tenancy: &pbresource.Tenancy{ - Partition: resource.DefaultPartitionName, - Namespace: "", - PeerName: "local", - }, - }, - "namespaced type with empty partition and namespace": { - typ: demo.TypeV2Artist, - tenancy: &pbresource.Tenancy{ - Partition: "", - Namespace: "", - PeerName: "local", - }, - }, - "namespaced type with uppercase partition and namespace": { - typ: demo.TypeV2Artist, - tenancy: &pbresource.Tenancy{ - Partition: "DEFAULT", - Namespace: "DEFAULT", - PeerName: "local", - }, - }, - "namespaced type with wildcard partition and empty namespace": { - typ: demo.TypeV2Artist, - tenancy: &pbresource.Tenancy{ - Partition: "*", - Namespace: "", - PeerName: "local", - }, - }, - "namespaced type with empty partition and wildcard namespace": { - typ: demo.TypeV2Artist, - tenancy: &pbresource.Tenancy{ - Partition: "", - Namespace: "*", - PeerName: "local", - }, - }, - "partitioned type with empty partition": { - typ: demo.TypeV1RecordLabel, - tenancy: &pbresource.Tenancy{ - Partition: "", - Namespace: "", - 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{ - Partition: "*", - PeerName: "local", - }, - }, - } -} - -// tenancyCases returns permutations of valid tenancy structs in a resource id to use as inputs. -// - the id is for a recordLabel when the resource is partition scoped -// - the id is for an artist when the resource is namespace scoped -func tenancyCases() map[string]func(artistId, recordlabelId *pbresource.ID) *pbresource.ID { - tenancyCases := map[string]func(artistId, recordlabelId *pbresource.ID) *pbresource.ID{ - "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 = "" - return id - }, - "namespaced resource inherits tokens namespace when empty": func(artistId, _ *pbresource.ID) *pbresource.ID { - id := clone(artistId) - id.Tenancy.Namespace = "" - return id - }, - "namespaced resource inherits tokens partition and namespace when empty": func(artistId, _ *pbresource.ID) *pbresource.ID { - id := clone(artistId) - id.Tenancy.Partition = "" - id.Tenancy.Namespace = "" - return id - }, - "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 = "" - return id - }, - } - return tenancyCases -} diff --git a/agent/grpc-external/services/resource/testing/testing.go b/agent/grpc-external/services/resource/testing/testing.go index 403263404fe27..5bcbc148e7bb6 100644 --- a/agent/grpc-external/services/resource/testing/testing.go +++ b/agent/grpc-external/services/resource/testing/testing.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package testing import ( @@ -11,51 +8,18 @@ import ( "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" internal "github.com/hashicorp/consul/agent/grpc-internal" - "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/storage/inmem" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/sdk/testutil" ) -func randomACLIdentity(t *testing.T) structs.ACLIdentity { - id, err := uuid.GenerateUUID() - require.NoError(t, err) - - return &structs.ACLToken{AccessorID: id} -} - -func AuthorizerFrom(t *testing.T, policyStrs ...string) resolver.Result { - policies := []*acl.Policy{} - for _, policyStr := range policyStrs { - policy, err := acl.NewPolicyFromSource(policyStr, nil, nil) - require.NoError(t, err) - policies = append(policies, policy) - } - - authz, err := acl.NewPolicyAuthorizerWithDefaults(acl.DenyAll(), policies, nil) - require.NoError(t, err) - - return resolver.Result{ - Authorizer: authz, - ACLIdentity: randomACLIdentity(t), - } -} - // RunResourceService runs a Resource Service for the duration of the test and -// returns a client to interact with it. ACLs will be disabled and only the -// default partition and namespace are available. +// returns a client to interact with it. ACLs will be disabled. func RunResourceService(t *testing.T, registerFns ...func(resource.Registry)) pbresource.ResourceServiceClient { - return RunResourceServiceWithACL(t, resolver.DANGER_NO_AUTH{}, registerFns...) -} - -func RunResourceServiceWithACL(t *testing.T, aclResolver svc.ACLResolver, registerFns ...func(resource.Registry)) pbresource.ResourceServiceClient { t.Helper() backend, err := inmem.NewBackend() @@ -72,18 +36,11 @@ func RunResourceServiceWithACL(t *testing.T, aclResolver svc.ACLResolver, regist server := grpc.NewServer() - mockTenancyBridge := &svc.MockTenancyBridge{} - mockTenancyBridge.On("PartitionExists", resource.DefaultPartitionName).Return(true, nil) - mockTenancyBridge.On("NamespaceExists", resource.DefaultPartitionName, resource.DefaultNamespaceName).Return(true, nil) - mockTenancyBridge.On("IsPartitionMarkedForDeletion", resource.DefaultPartitionName).Return(false, nil) - mockTenancyBridge.On("IsNamespaceMarkedForDeletion", resource.DefaultPartitionName, resource.DefaultNamespaceName).Return(false, nil) - svc.NewServer(svc.Config{ - Backend: backend, - Registry: registry, - Logger: testutil.Logger(t), - ACLResolver: aclResolver, - V1TenancyBridge: mockTenancyBridge, + Backend: backend, + Registry: registry, + Logger: testutil.Logger(t), + ACLResolver: resolver.DANGER_NO_AUTH{}, }).Register(server) pipe := internal.NewPipeListener() diff --git a/agent/grpc-external/services/resource/watch.go b/agent/grpc-external/services/resource/watch.go index 6039613b8fed5..35ec14513ac37 100644 --- a/agent/grpc-external/services/resource/watch.go +++ b/agent/grpc-external/services/resource/watch.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -10,27 +10,28 @@ import ( "google.golang.org/grpc/status" "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/storage" "github.com/hashicorp/consul/proto-public/pbresource" ) func (s *Server) WatchList(req *pbresource.WatchListRequest, stream pbresource.ResourceService_WatchListServer) error { - reg, err := s.validateWatchListRequest(req) + if err := validateWatchListRequest(req); err != nil { + return err + } + + // check type exists + reg, err := s.resolveType(req.Type) if err != nil { return err } - // v1 ACL subsystem is "wildcard" aware so just pass on through. - entMeta := v2TenancyToV1EntMeta(req.Tenancy) - token := tokenFromContext(stream.Context()) - authz, authzContext, err := s.getAuthorizer(token, entMeta) + authz, err := s.getAuthorizer(tokenFromContext(stream.Context())) if err != nil { return err } - // Check list ACL. - err = reg.ACLs.List(authz, authzContext) + // check acls + err = reg.ACLs.List(authz, req.Tenancy) switch { case acl.IsErrPermissionDenied(err): return status.Error(codes.PermissionDenied, err.Error()) @@ -38,9 +39,6 @@ func (s *Server) WatchList(req *pbresource.WatchListRequest, stream pbresource.R return status.Errorf(codes.Internal, "failed list acl: %v", err) } - // Ensure we're defaulting correctly when request tenancy units are empty. - v1EntMetaToV2Tenancy(reg, entMeta, req.Tenancy) - unversionedType := storage.UnversionedTypeFrom(req.Type) watch, err := s.Backend.WatchList( stream.Context(), @@ -67,17 +65,8 @@ func (s *Server) WatchList(req *pbresource.WatchListRequest, stream pbresource.R continue } - // Need to rebuild authorizer per resource since wildcard inputs may - // result in different tenancies. Consider caching per tenancy if this - // is deemed expensive. - entMeta = v2TenancyToV1EntMeta(event.Resource.Id.Tenancy) - authz, authzContext, err = s.getAuthorizer(token, entMeta) - if err != nil { - return err - } - // filter out items that don't pass read ACLs - err = reg.ACLs.Read(authz, authzContext, event.Resource.Id) + err = reg.ACLs.Read(authz, event.Resource.Id) switch { case acl.IsErrPermissionDenied(err): continue @@ -91,37 +80,15 @@ func (s *Server) WatchList(req *pbresource.WatchListRequest, stream pbresource.R } } -func (s *Server) validateWatchListRequest(req *pbresource.WatchListRequest) (*resource.Registration, error) { +func validateWatchListRequest(req *pbresource.WatchListRequest) error { var field string switch { case req.Type == nil: field = "type" case req.Tenancy == nil: field = "tenancy" + default: + return nil } - - if field != "" { - return nil, status.Errorf(codes.InvalidArgument, "%s is required", field) - } - - // Check type exists. - reg, err := s.resolveType(req.Type) - if 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 != "" { - return nil, status.Errorf( - codes.InvalidArgument, - "partition scoped type %s cannot have a namespace. got: %s", - resource.ToGVK(req.Type), - req.Tenancy.Namespace, - ) - } - - return reg, nil + return status.Errorf(codes.InvalidArgument, "%s is required", field) } diff --git a/agent/grpc-external/services/resource/watch_test.go b/agent/grpc-external/services/resource/watch_test.go index 051264441bbc8..95695f295ebd4 100644 --- a/agent/grpc-external/services/resource/watch_test.go +++ b/agent/grpc-external/services/resource/watch_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -12,7 +12,6 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/grpc-external/testutils" - "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/proto/private/prototest" @@ -21,7 +20,6 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" ) func TestWatchList_InputValidation(t *testing.T) { @@ -33,16 +31,12 @@ func TestWatchList_InputValidation(t *testing.T) { 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, modFn := range testCases { t.Run(desc, func(t *testing.T) { req := &pbresource.WatchListRequest{ Type: demo.TypeV2Album, - Tenancy: resource.DefaultNamespacedTenancy(), + Tenancy: demo.TenancyDefault, } modFn(req) @@ -64,7 +58,7 @@ func TestWatchList_TypeNotFound(t *testing.T) { stream, err := client.WatchList(context.Background(), &pbresource.WatchListRequest{ Type: demo.TypeV2Artist, - Tenancy: resource.DefaultNamespacedTenancy(), + Tenancy: demo.TenancyDefault, NamePrefix: "", }) require.NoError(t, err) @@ -86,7 +80,7 @@ func TestWatchList_GroupVersionMatches(t *testing.T) { // create a watch stream, err := client.WatchList(ctx, &pbresource.WatchListRequest{ Type: demo.TypeV2Artist, - Tenancy: resource.DefaultNamespacedTenancy(), + Tenancy: demo.TenancyDefault, NamePrefix: "", }) require.NoError(t, err) @@ -117,54 +111,6 @@ func TestWatchList_GroupVersionMatches(t *testing.T) { require.Equal(t, pbresource.WatchEvent_OPERATION_DELETE, rsp.Operation) } -func TestWatchList_Tenancy_Defaults_And_Normalization(t *testing.T) { - // Test units of tenancy get lowercased and defaulted correctly when empty. - for desc, tc := range wildcardTenancyCases() { - t.Run(desc, func(t *testing.T) { - ctx := context.Background() - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) - - // Create a watch. - stream, err := client.WatchList(ctx, &pbresource.WatchListRequest{ - Type: tc.typ, - Tenancy: tc.tenancy, - NamePrefix: "", - }) - require.NoError(t, err) - rspCh := handleResourceStream(t, stream) - - // Testcase will pick one of recordLabel or artist based on scope of type. - recordLabel, err := demo.GenerateV1RecordLabel("LooneyTunes") - require.NoError(t, err) - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - - // Create and verify upsert event received. - recordLabel, err = server.Backend.WriteCAS(ctx, recordLabel) - require.NoError(t, err) - artist, err = server.Backend.WriteCAS(ctx, artist) - require.NoError(t, err) - - var expected *pbresource.Resource - switch { - case proto.Equal(tc.typ, demo.TypeV1RecordLabel): - expected = recordLabel - case proto.Equal(tc.typ, demo.TypeV2Artist): - expected = artist - default: - require.Fail(t, "unsupported type", tc.typ) - } - - rsp := mustGetResource(t, rspCh) - require.Equal(t, pbresource.WatchEvent_OPERATION_UPSERT, rsp.Operation) - prototest.AssertDeepEqual(t, expected, rsp.Resource) - }) - - } -} - func TestWatchList_GroupVersionMismatch(t *testing.T) { // Given a watch on TypeArtistV1 that only differs from TypeArtistV2 by GroupVersion // When a resource of TypeArtistV2 is created/updated/deleted @@ -179,7 +125,7 @@ func TestWatchList_GroupVersionMismatch(t *testing.T) { // create a watch for TypeArtistV1 stream, err := client.WatchList(ctx, &pbresource.WatchListRequest{ Type: demo.TypeV1Artist, - Tenancy: resource.DefaultNamespacedTenancy(), + Tenancy: demo.TenancyDefault, NamePrefix: "", }) require.NoError(t, err) diff --git a/agent/grpc-external/services/resource/write.go b/agent/grpc-external/services/resource/write.go index ec39f3a12a85d..34799ae8d82ec 100644 --- a/agent/grpc-external/services/resource/write.go +++ b/agent/grpc-external/services/resource/write.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -37,20 +37,22 @@ import ( var errUseWriteStatus = status.Error(codes.InvalidArgument, "resource.status can only be set using the WriteStatus endpoint") func (s *Server) Write(ctx context.Context, req *pbresource.WriteRequest) (*pbresource.WriteResponse, error) { - reg, err := s.validateWriteRequest(req) + if err := validateWriteRequest(req); err != nil { + return nil, err + } + + reg, err := s.resolveType(req.Resource.Id.Type) if err != nil { return nil, err } - v1EntMeta := v2TenancyToV1EntMeta(req.Resource.Id.Tenancy) - authz, authzContext, err := s.getAuthorizer(tokenFromContext(ctx), v1EntMeta) + authz, err := s.getAuthorizer(tokenFromContext(ctx)) if err != nil { return nil, err } - v1EntMetaToV2Tenancy(reg, v1EntMeta, req.Resource.Id.Tenancy) - // ACL check comes before tenancy existence checks to not leak tenancy "existence". - err = reg.ACLs.Write(authz, authzContext, req.Resource) + // check acls + err = reg.ACLs.Write(authz, req.Resource.Id) switch { case acl.IsErrPermissionDenied(err): return nil, status.Error(codes.PermissionDenied, err.Error()) @@ -70,24 +72,14 @@ func (s *Server) Write(ctx context.Context, req *pbresource.WriteRequest) (*pbre ) } - // Check V1 tenancy exists for the V2 resource - if err = v1TenancyExists(reg, s.V1TenancyBridge, req.Resource.Id.Tenancy, codes.InvalidArgument); err != nil { - return nil, err - } - - // Check V1 tenancy not marked for deletion. - if err = v1TenancyMarkedForDeletion(reg, s.V1TenancyBridge, req.Resource.Id.Tenancy); err != nil { - return nil, err + if err = reg.Validate(req.Resource); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) } if err = reg.Mutate(req.Resource); err != nil { return nil, status.Errorf(codes.Internal, "failed mutate hook: %v", err.Error()) } - if err = reg.Validate(req.Resource); err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) - } - // At the storage backend layer, all writes are CAS operations. // // This makes it possible to *safely* do things like keeping the Uid stable @@ -265,7 +257,7 @@ func (s *Server) retryCAS(ctx context.Context, vsn string, cas func() error) err return err } -func (s *Server) validateWriteRequest(req *pbresource.WriteRequest) (*resource.Registration, error) { +func validateWriteRequest(req *pbresource.WriteRequest) error { var field string switch { case req.Resource == nil: @@ -277,34 +269,17 @@ func (s *Server) validateWriteRequest(req *pbresource.WriteRequest) (*resource.R } if field != "" { - return nil, status.Errorf(codes.InvalidArgument, "%s is required", field) + return status.Errorf(codes.InvalidArgument, "%s is required", field) } if err := validateId(req.Resource.Id, "resource.id"); err != nil { - return nil, err + return err } if req.Resource.Owner != nil { if err := validateId(req.Resource.Owner, "resource.owner"); err != nil { - return nil, err + return err } } - - // Check type exists. - reg, err := s.resolveType(req.Resource.Id.Type) - if err != nil { - return nil, err - } - - // Check scope - if reg.Scope == resource.ScopePartition && req.Resource.Id.Tenancy.Namespace != "" { - return nil, status.Errorf( - codes.InvalidArgument, - "partition scoped resource %s cannot have a namespace. got: %s", - resource.ToGVK(req.Resource.Id.Type), - req.Resource.Id.Tenancy.Namespace, - ) - } - - return reg, nil + return nil } diff --git a/agent/grpc-external/services/resource/write_status.go b/agent/grpc-external/services/resource/write_status.go index 263814237eb3a..205918e1dc2b7 100644 --- a/agent/grpc-external/services/resource/write_status.go +++ b/agent/grpc-external/services/resource/write_status.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -8,49 +8,25 @@ import ( "errors" "fmt" - "github.com/oklog/ulid/v2" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/oklog/ulid/v2" + "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/storage" "github.com/hashicorp/consul/proto-public/pbresource" ) func (s *Server) WriteStatus(ctx context.Context, req *pbresource.WriteStatusRequest) (*pbresource.WriteStatusResponse, error) { - reg, err := s.validateWriteStatusRequest(req) - if err != nil { - return nil, err - } - - entMeta := v2TenancyToV1EntMeta(req.Id.Tenancy) - authz, authzContext, err := s.getAuthorizer(tokenFromContext(ctx), entMeta) + authz, err := s.getAuthorizer(tokenFromContext(ctx)) if err != nil { return nil, err } - // Apply defaults when tenancy units empty. - v1EntMetaToV2Tenancy(reg, entMeta, req.Id.Tenancy) - - // Check V1 tenancy exists for the V2 resource. Ignore "marked for deletion" since status updates - // should still work regardless. - if err = v1TenancyExists(reg, s.V1TenancyBridge, req.Id.Tenancy, codes.InvalidArgument); err != nil { - return nil, err - } - - // Retrieve resource since ACL hook requires it. - existing, err := s.Backend.Read(ctx, storage.EventualConsistency, req.Id) - switch { - case errors.Is(err, storage.ErrNotFound): - return nil, status.Errorf(codes.NotFound, err.Error()) - case err != nil: - return nil, status.Errorf(codes.Internal, "failed read: %v", err) - } - - // Check write ACL. - err = reg.ACLs.Write(authz, authzContext, existing) + // check acls + err = authz.ToAllowAuthorizer().OperatorWriteAllowed(&acl.AuthorizerContext{}) switch { case acl.IsErrPermissionDenied(err): return nil, status.Error(codes.PermissionDenied, err.Error()) @@ -58,6 +34,15 @@ func (s *Server) WriteStatus(ctx context.Context, req *pbresource.WriteStatusReq return nil, status.Errorf(codes.Internal, "failed operator:write allowed acl: %v", err) } + if err := validateWriteStatusRequest(req); err != nil { + return nil, err + } + + _, err = s.resolveType(req.Id.Type) + if err != nil { + return nil, err + } + // At the storage backend layer, all writes are CAS operations. // // See comment in write.go for more information. @@ -113,7 +98,7 @@ func (s *Server) WriteStatus(ctx context.Context, req *pbresource.WriteStatusReq return &pbresource.WriteStatusResponse{Resource: result}, nil } -func (s *Server) validateWriteStatusRequest(req *pbresource.WriteStatusRequest) (*resource.Registration, error) { +func validateWriteStatusRequest(req *pbresource.WriteStatusRequest) error { var field string switch { case req.Id == nil: @@ -158,35 +143,16 @@ func (s *Server) validateWriteStatusRequest(req *pbresource.WriteStatusRequest) } } if field != "" { - return nil, status.Errorf(codes.InvalidArgument, "%s is required", field) + return status.Errorf(codes.InvalidArgument, "%s is required", field) } if req.Status.UpdatedAt != nil { - return nil, status.Error(codes.InvalidArgument, "status.updated_at is automatically set and cannot be provided") + return status.Error(codes.InvalidArgument, "status.updated_at is automatically set and cannot be provided") } if _, err := ulid.ParseStrict(req.Status.ObservedGeneration); err != nil { - return nil, status.Error(codes.InvalidArgument, "status.observed_generation is not valid") - } - - // Lowercase - resource.Normalize(req.Id.Tenancy) - - // Check type exists. - reg, err := s.resolveType(req.Id.Type) - if err != nil { - return nil, err - } - - // Check scope. - if reg.Scope == resource.ScopePartition && req.Id.Tenancy.Namespace != "" { - return nil, status.Errorf( - codes.InvalidArgument, - "partition scoped resource %s cannot have a namespace. got: %s", - resource.ToGVK(req.Id.Type), - req.Id.Tenancy.Namespace, - ) + return status.Error(codes.InvalidArgument, "status.observed_generation is not valid") } - return reg, nil + return nil } diff --git a/agent/grpc-external/services/resource/write_status_test.go b/agent/grpc-external/services/resource/write_status_test.go index 622cbcccc746f..aa26330176df7 100644 --- a/agent/grpc-external/services/resource/write_status_test.go +++ b/agent/grpc-external/services/resource/write_status_test.go @@ -1,11 +1,10 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource import ( "fmt" - "strings" "testing" "github.com/oklog/ulid/v2" @@ -28,7 +27,7 @@ func TestWriteStatus_ACL(t *testing.T) { } testcases := map[string]testCase{ "denied": { - authz: AuthorizerFrom(t, demo.ArtistV2ReadPolicy), + authz: AuthorizerFrom(t, demo.ArtistV2WritePolicy), assertErrFn: func(err error) { require.Error(t, err) require.Equal(t, codes.PermissionDenied.String(), status.Code(err).String()) @@ -46,6 +45,11 @@ func TestWriteStatus_ACL(t *testing.T) { t.Run(desc, func(t *testing.T) { server := testServer(t) client := testClient(t, server) + + mockACLResolver := &MockACLResolver{} + mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). + Return(tc.authz, nil) + server.ACLResolver = mockACLResolver demo.RegisterTypes(server.Registry) artist, err := demo.GenerateV2Artist() @@ -55,12 +59,6 @@ func TestWriteStatus_ACL(t *testing.T) { require.NoError(t, err) artist = rsp.Resource - // Defer mocking out authz since above write is necessary to set up the test resource. - mockACLResolver := &MockACLResolver{} - mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). - Return(tc.authz, nil) - server.ACLResolver = mockACLResolver - // exercise ACL _, err = client.WriteStatus(testContext(t), validWriteStatusRequest(t, artist)) tc.assertErrFn(err) @@ -71,92 +69,35 @@ func TestWriteStatus_ACL(t *testing.T) { func TestWriteStatus_InputValidation(t *testing.T) { server := testServer(t) client := testClient(t, server) + demo.RegisterTypes(server.Registry) - testCases := map[string]struct { - typ *pbresource.Type - modFn func(req *pbresource.WriteStatusRequest) - }{ - "no id": { - 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 }, - }, - "no tenancy": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy = nil }, - }, - "no name": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Name = "" }, - }, - "no uid": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Uid = "" }, - }, - "no key": { - typ: demo.TypeV2Artist, - modFn: func(req *pbresource.WriteStatusRequest) { req.Key = "" }, - }, - "no status": { - 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 = "" }, - }, - "bad observed generation": { - 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 = "" }, - }, - "no reference type": { - 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 }, - }, - "no reference name": { - 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() }, - }, - "partition scoped type provides namespace in tenancy": { - typ: demo.TypeV1RecordLabel, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Namespace = "bad" }, - }, + testCases := map[string]func(*pbresource.WriteStatusRequest){ + "no id": func(req *pbresource.WriteStatusRequest) { req.Id = nil }, + "no type": func(req *pbresource.WriteStatusRequest) { req.Id.Type = nil }, + "no tenancy": func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy = nil }, + "no name": func(req *pbresource.WriteStatusRequest) { req.Id.Name = "" }, + "no uid": func(req *pbresource.WriteStatusRequest) { req.Id.Uid = "" }, + "no key": func(req *pbresource.WriteStatusRequest) { req.Key = "" }, + "no status": func(req *pbresource.WriteStatusRequest) { req.Status = nil }, + "no observed generation": func(req *pbresource.WriteStatusRequest) { req.Status.ObservedGeneration = "" }, + "bad observed generation": func(req *pbresource.WriteStatusRequest) { req.Status.ObservedGeneration = "bogus" }, + "no condition type": func(req *pbresource.WriteStatusRequest) { req.Status.Conditions[0].Type = "" }, + "no reference type": func(req *pbresource.WriteStatusRequest) { req.Status.Conditions[0].Resource.Type = nil }, + "no reference tenancy": func(req *pbresource.WriteStatusRequest) { req.Status.Conditions[0].Resource.Tenancy = nil }, + "no reference name": func(req *pbresource.WriteStatusRequest) { req.Status.Conditions[0].Resource.Name = "" }, + "updated at provided": func(req *pbresource.WriteStatusRequest) { req.Status.UpdatedAt = timestamppb.Now() }, } - for desc, tc := range testCases { + for desc, modFn := range testCases { t.Run(desc, func(t *testing.T) { - var res *pbresource.Resource - var err error - switch { - case resource.EqualType(demo.TypeV2Artist, tc.typ): - res, err = demo.GenerateV2Artist() - case resource.EqualType(demo.TypeV1RecordLabel, tc.typ): - res, err = demo.GenerateV1RecordLabel("Looney Tunes") - default: - t.Fatal("unsupported type", tc.typ) - } + res, err := demo.GenerateV2Artist() require.NoError(t, err) res.Id.Uid = ulid.Make().String() res.Generation = ulid.Make().String() req := validWriteStatusRequest(t, res) - tc.modFn(req) + modFn(req) _, err = client.WriteStatus(testContext(t), req) require.Error(t, err) @@ -173,6 +114,7 @@ func TestWriteStatus_Success(t *testing.T) { t.Run(desc, func(t *testing.T) { server := testServer(t) client := testClient(t, server) + demo.RegisterTypes(server.Registry) res, err := demo.GenerateV2Artist() @@ -205,149 +147,6 @@ func TestWriteStatus_Success(t *testing.T) { } } -func TestWriteStatus_Tenancy_Defaults(t *testing.T) { - for desc, tc := range map[string]struct { - scope resource.Scope - modFn func(req *pbresource.WriteStatusRequest) - }{ - "namespaced resource provides nonempty partition and namespace": { - 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 = "" }, - }, - "namespaced resource inherits tokens namespace when empty": { - scope: resource.ScopeNamespace, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Namespace = "" }, - }, - "namespaced resource inherits tokens partition and namespace when empty": { - scope: resource.ScopeNamespace, - modFn: func(req *pbresource.WriteStatusRequest) { - req.Id.Tenancy.Partition = "" - req.Id.Tenancy.Namespace = "" - }, - }, - "partitioned resource provides nonempty partition": { - 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 = "" }, - }, - } { - t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) - - // Pick resource based on scope of type in testcase. - var res *pbresource.Resource - var err error - switch tc.scope { - case resource.ScopeNamespace: - res, err = demo.GenerateV2Artist() - case resource.ScopePartition: - res, err = demo.GenerateV1RecordLabel("Looney Tunes") - } - require.NoError(t, err) - - // Write resource so we can update status later. - writeRsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - res = writeRsp.Resource - require.Nil(t, res.Status) - - // Write status with tenancy modded by testcase. - req := validWriteStatusRequest(t, res) - tc.modFn(req) - rsp, err := client.WriteStatus(testContext(t), req) - require.NoError(t, err) - res = rsp.Resource - - // 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 - require.NotNil(t, res.Status) - }) - } -} - -func TestWriteStatus_Tenancy_NotFound(t *testing.T) { - for desc, tc := range map[string]struct { - scope resource.Scope - modFn func(req *pbresource.WriteStatusRequest) - errCode codes.Code - errContains string - }{ - "namespaced resource provides nonexistant partition": { - scope: resource.ScopeNamespace, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Partition = "bad" }, - errCode: codes.InvalidArgument, - errContains: "partition", - }, - "namespaced resource provides nonexistant namespace": { - scope: resource.ScopeNamespace, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Namespace = "bad" }, - errCode: codes.InvalidArgument, - errContains: "namespace", - }, - "partitioned resource provides nonexistant partition": { - scope: resource.ScopePartition, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Partition = "bad" }, - errCode: codes.InvalidArgument, - errContains: "partition", - }, - } { - t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) - - // Pick resource based on scope of type in testcase. - var res *pbresource.Resource - var err error - switch tc.scope { - case resource.ScopeNamespace: - res, err = demo.GenerateV2Artist() - case resource.ScopePartition: - res, err = demo.GenerateV1RecordLabel("Looney Tunes") - } - require.NoError(t, err) - - // Fill in required fields so validation continues until tenancy is checked - req := validWriteStatusRequest(t, res) - req.Id.Uid = ulid.Make().String() - req.Status.ObservedGeneration = ulid.Make().String() - - // Write status with tenancy modded by testcase. - tc.modFn(req) - _, err = client.WriteStatus(testContext(t), req) - - // Verify non-existant tenancy field is the cause of the error. - require.Error(t, err) - require.Equal(t, tc.errCode.String(), status.Code(err).String()) - require.Contains(t, err.Error(), tc.errContains) - }) - } -} - func TestWriteStatus_CASFailure(t *testing.T) { server := testServer(t) client := testClient(t, server) @@ -469,49 +268,24 @@ func TestWriteStatus_NonCASUpdate_Retry(t *testing.T) { func validWriteStatusRequest(t *testing.T, res *pbresource.Resource) *pbresource.WriteStatusRequest { t.Helper() - switch { - case resource.EqualType(res.Id.Type, demo.TypeV2Artist): - album, err := demo.GenerateV2Album(res.Id) - require.NoError(t, err) - return &pbresource.WriteStatusRequest{ - Id: res.Id, - Version: res.Version, - Key: "consul.io/artist-controller", - Status: &pbresource.Status{ - ObservedGeneration: res.Generation, - Conditions: []*pbresource.Condition{ - { - Type: "AlbumCreated", - State: pbresource.Condition_STATE_TRUE, - Reason: "AlbumCreated", - Message: fmt.Sprintf("Album '%s' created", album.Id.Name), - Resource: resource.Reference(album.Id, ""), - }, - }, - }, - } - case resource.EqualType(res.Id.Type, demo.TypeV1RecordLabel): - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - return &pbresource.WriteStatusRequest{ - Id: res.Id, - Version: res.Version, - Key: "consul.io/recordlabel-controller", - Status: &pbresource.Status{ - ObservedGeneration: res.Generation, - Conditions: []*pbresource.Condition{ - { - Type: "ArtistCreated", - State: pbresource.Condition_STATE_TRUE, - Reason: "ArtistCreated", - Message: fmt.Sprintf("Artist '%s' created", artist.Id.Name), - Resource: resource.Reference(artist.Id, ""), - }, + album, err := demo.GenerateV2Album(res.Id) + require.NoError(t, err) + + return &pbresource.WriteStatusRequest{ + Id: res.Id, + Version: res.Version, + Key: "consul.io/artist-controller", + Status: &pbresource.Status{ + ObservedGeneration: res.Generation, + Conditions: []*pbresource.Condition{ + { + Type: "AlbumCreated", + State: pbresource.Condition_STATE_TRUE, + Reason: "AlbumCreated", + Message: fmt.Sprintf("Album '%s' created", album.Id.Name), + Resource: resource.Reference(album.Id, ""), }, }, - } - default: - t.Fatal("unsupported type", res.Id.Type) + }, } - return nil } diff --git a/agent/grpc-external/services/resource/write_test.go b/agent/grpc-external/services/resource/write_test.go index d472a6ec7414c..4ec25ee26c0c7 100644 --- a/agent/grpc-external/services/resource/write_test.go +++ b/agent/grpc-external/services/resource/write_test.go @@ -1,11 +1,10 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource import ( "context" - "strings" "sync/atomic" "testing" @@ -17,13 +16,11 @@ import ( "google.golang.org/protobuf/types/known/anypb" "github.com/hashicorp/consul/acl/resolver" - "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/internal/storage" "github.com/hashicorp/consul/proto-public/pbresource" pbdemov1 "github.com/hashicorp/consul/proto/private/pbdemo/v1" pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2" - "github.com/hashicorp/consul/proto/private/prototest" ) func TestWrite_InputValidation(t *testing.T) { @@ -32,56 +29,46 @@ func TestWrite_InputValidation(t *testing.T) { demo.RegisterTypes(server.Registry) - 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 + testCases := map[string]func(*pbresource.WriteRequest){ + "no resource": func(req *pbresource.WriteRequest) { req.Resource = nil }, + "no id": func(req *pbresource.WriteRequest) { req.Resource.Id = nil }, + "no type": func(req *pbresource.WriteRequest) { req.Resource.Id.Type = nil }, + "no tenancy": func(req *pbresource.WriteRequest) { req.Resource.Id.Tenancy = nil }, + "no name": func(req *pbresource.WriteRequest) { req.Resource.Id.Name = "" }, + "no data": func(req *pbresource.WriteRequest) { req.Resource.Data = nil }, + // clone necessary to not pollute DefaultTenancy + "tenancy partition not default": func(req *pbresource.WriteRequest) { + req.Resource.Id.Tenancy = clone(req.Resource.Id.Tenancy) + req.Resource.Id.Tenancy.Partition = "" }, - "no type": func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Type = nil - return artist + "tenancy namespace not default": func(req *pbresource.WriteRequest) { + req.Resource.Id.Tenancy = clone(req.Resource.Id.Tenancy) + req.Resource.Id.Tenancy.Namespace = "" }, - "no tenancy": func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy = nil - return artist + "tenancy peername not local": func(req *pbresource.WriteRequest) { + req.Resource.Id.Tenancy = clone(req.Resource.Id.Tenancy) + req.Resource.Id.Tenancy.PeerName = "" }, - "no name": func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Name = "" - return artist - }, - "no data": func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Data = nil - return artist - }, - "wrong data type": func(artist, _ *pbresource.Resource) *pbresource.Resource { + "wrong data type": func(req *pbresource.WriteRequest) { var err error - artist.Data, err = anypb.New(&pbdemov2.Album{}) + req.Resource.Data, err = anypb.New(&pbdemov2.Album{}) require.NoError(t, err) - return artist - }, - "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": func(_, recordLabel *pbresource.Resource) *pbresource.Resource { - recordLabel.Id.Tenancy.Namespace = "bogus" - return recordLabel + "fail validation hook": func(req *pbresource.WriteRequest) { + artist := &pbdemov2.Artist{} + require.NoError(t, req.Resource.Data.UnmarshalTo(artist)) + artist.Name = "" // name cannot be empty + require.NoError(t, req.Resource.Data.MarshalFrom(artist)) }, - // TODO(spatel): add cluster scope tests when we have an actual cluster scoped resource (e.g. partition) } for desc, modFn := range testCases { t.Run(desc, func(t *testing.T) { - artist, err := demo.GenerateV2Artist() + res, err := demo.GenerateV2Artist() require.NoError(t, err) - recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") - require.NoError(t, err) + req := &pbresource.WriteRequest{Resource: res} + modFn(req) - 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()) @@ -112,6 +99,28 @@ func TestWrite_OwnerValidation(t *testing.T) { modReqFn: func(req *pbresource.WriteRequest) { req.Resource.Owner.Name = "" }, errorContains: "resource.owner.name", }, + // clone necessary to not pollute DefaultTenancy + "owner tenancy partition not default": { + modReqFn: func(req *pbresource.WriteRequest) { + req.Resource.Owner.Tenancy = clone(req.Resource.Owner.Tenancy) + req.Resource.Owner.Tenancy.Partition = "" + }, + errorContains: "resource.owner.tenancy.partition", + }, + "owner tenancy namespace not default": { + modReqFn: func(req *pbresource.WriteRequest) { + req.Resource.Owner.Tenancy = clone(req.Resource.Owner.Tenancy) + req.Resource.Owner.Tenancy.Namespace = "" + }, + errorContains: "resource.owner.tenancy.namespace", + }, + "owner tenancy peername not local": { + modReqFn: func(req *pbresource.WriteRequest) { + req.Resource.Owner.Tenancy = clone(req.Resource.Owner.Tenancy) + req.Resource.Owner.Tenancy.PeerName = "" + }, + errorContains: "resource.owner.tenancy.peername", + }, } for desc, tc := range testCases { t.Run(desc, func(t *testing.T) { @@ -212,196 +221,20 @@ func TestWrite_Mutate(t *testing.T) { require.Equal(t, pbdemov2.Genre_GENRE_DISCO, artistData.Genre) } -func TestWrite_Create_Success(t *testing.T) { - testCases := map[string]struct { - modFn func(artist, recordLabel *pbresource.Resource) *pbresource.Resource - expectedTenancy *pbresource.Tenancy - }{ - "namespaced resource provides nonempty partition and namespace": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - return artist - }, - 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 = "" - return artist - }, - expectedTenancy: resource.DefaultNamespacedTenancy(), - }, - "namespaced resource inherits tokens namespace when empty": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Namespace = "" - return artist - }, - expectedTenancy: resource.DefaultNamespacedTenancy(), - }, - "namespaced resource inherits tokens partition and namespace when empty": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Partition = "" - artist.Id.Tenancy.Namespace = "" - return artist - }, - expectedTenancy: resource.DefaultNamespacedTenancy(), - }, - "partitioned resource provides nonempty partition": { - modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { - return recordLabel - }, - 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 = "" - return recordLabel - }, - expectedTenancy: resource.DefaultPartitionedTenancy(), - }, - // TODO(spatel): Add cluster scope tests when we have an actual cluster scoped resource (e.g. partition) - } - for desc, tc := range testCases { - t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) - - recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") - require.NoError(t, err) - - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - - rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: tc.modFn(artist, recordLabel)}) - require.NoError(t, err) - require.NotEmpty(t, rsp.Resource.Version, "resource should have version") - require.NotEmpty(t, rsp.Resource.Id.Uid, "resource id should have uid") - require.NotEmpty(t, rsp.Resource.Generation, "resource should have generation") - prototest.AssertDeepEqual(t, tc.expectedTenancy, rsp.Resource.Id.Tenancy) - }) - } -} - -func TestWrite_Create_Tenancy_NotFound(t *testing.T) { - testCases := map[string]struct { - modFn func(artist, recordLabel *pbresource.Resource) *pbresource.Resource - errCode codes.Code - errContains string - }{ - "namespaced resource provides nonexistant partition": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Partition = "boguspartition" - return artist - }, - errCode: codes.InvalidArgument, - errContains: "partition", - }, - "namespaced resource provides nonexistant namespace": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Namespace = "bogusnamespace" - return artist - }, - errCode: codes.InvalidArgument, - errContains: "namespace", - }, - "partitioned resource provides nonexistant partition": { - modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { - recordLabel.Id.Tenancy.Partition = "boguspartition" - return recordLabel - }, - errCode: codes.InvalidArgument, - errContains: "partition", - }, - } - for desc, tc := range testCases { - t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) - - recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") - require.NoError(t, err) - - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - - _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: tc.modFn(artist, recordLabel)}) - require.Error(t, err) - require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) - require.Contains(t, err.Error(), tc.errContains) - }) - } -} - -func TestWrite_Tenancy_MarkedForDeletion(t *testing.T) { - // Verify resource write fails when its partition or namespace is marked for deletion. - testCases := map[string]struct { - modFn func(artist, recordLabel *pbresource.Resource, mockTenancyBridge *MockTenancyBridge) *pbresource.Resource - errContains string - }{ - "namespaced resources partition marked for deletion": { - modFn: func(artist, _ *pbresource.Resource, mockTenancyBridge *MockTenancyBridge) *pbresource.Resource { - 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", "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", "part1").Return(true, nil) - return recordLabel - }, - errContains: "partition marked for deletion", - }, - } - for desc, tc := range testCases { - t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) - recordLabel, err := demo.GenerateV1RecordLabel("LoonyTunes") - require.NoError(t, err) - recordLabel.Id.Tenancy.Partition = "part1" +func TestWrite_ResourceCreation_Success(t *testing.T) { + server := testServer(t) + client := testClient(t, server) - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - artist.Id.Tenancy.Partition = "part1" - artist.Id.Tenancy.Namespace = "ns1" + demo.RegisterTypes(server.Registry) - mockTenancyBridge := &MockTenancyBridge{} - mockTenancyBridge.On("PartitionExists", "part1").Return(true, nil) - mockTenancyBridge.On("NamespaceExists", "part1", "ns1").Return(true, nil) - server.V1TenancyBridge = mockTenancyBridge + res, err := demo.GenerateV2Artist() + require.NoError(t, err) - _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: tc.modFn(artist, recordLabel, mockTenancyBridge)}) - require.Error(t, err) - require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) - require.Contains(t, err.Error(), tc.errContains) - }) - } + rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + require.NotEmpty(t, rsp.Resource.Version, "resource should have version") + require.NotEmpty(t, rsp.Resource.Id.Uid, "resource id should have uid") + require.NotEmpty(t, rsp.Resource.Generation, "resource should have generation") } func TestWrite_CASUpdate_Success(t *testing.T) { diff --git a/agent/grpc-external/services/serverdiscovery/server.go b/agent/grpc-external/services/serverdiscovery/server.go index 99011c6d076ff..477617122120c 100644 --- a/agent/grpc-external/services/serverdiscovery/server.go +++ b/agent/grpc-external/services/serverdiscovery/server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package serverdiscovery diff --git a/agent/grpc-external/services/serverdiscovery/server_test.go b/agent/grpc-external/services/serverdiscovery/server_test.go index a9fd65b7cbdce..cac32bd31ee30 100644 --- a/agent/grpc-external/services/serverdiscovery/server_test.go +++ b/agent/grpc-external/services/serverdiscovery/server_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package serverdiscovery diff --git a/agent/grpc-external/services/serverdiscovery/watch_servers.go b/agent/grpc-external/services/serverdiscovery/watch_servers.go index 94ed7ac58aef6..31a2cb92c8370 100644 --- a/agent/grpc-external/services/serverdiscovery/watch_servers.go +++ b/agent/grpc-external/services/serverdiscovery/watch_servers.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package serverdiscovery diff --git a/agent/grpc-external/services/serverdiscovery/watch_servers_test.go b/agent/grpc-external/services/serverdiscovery/watch_servers_test.go index 0df48f3bb35c4..d58d0be407c3f 100644 --- a/agent/grpc-external/services/serverdiscovery/watch_servers_test.go +++ b/agent/grpc-external/services/serverdiscovery/watch_servers_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package serverdiscovery diff --git a/agent/grpc-external/stats_test.go b/agent/grpc-external/stats_test.go index 798c900148ba0..eed834064e085 100644 --- a/agent/grpc-external/stats_test.go +++ b/agent/grpc-external/stats_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package external diff --git a/agent/grpc-external/testutils/acl.go b/agent/grpc-external/testutils/acl.go index caa5c7ae81f5e..440a837682817 100644 --- a/agent/grpc-external/testutils/acl.go +++ b/agent/grpc-external/testutils/acl.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package testutils diff --git a/agent/grpc-external/testutils/fsm.go b/agent/grpc-external/testutils/fsm.go index fdec1b109ed36..0e7b645a65ec5 100644 --- a/agent/grpc-external/testutils/fsm.go +++ b/agent/grpc-external/testutils/fsm.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package testutils diff --git a/agent/grpc-external/testutils/server.go b/agent/grpc-external/testutils/server.go index 13cbb985e564e..eecb10bb954f3 100644 --- a/agent/grpc-external/testutils/server.go +++ b/agent/grpc-external/testutils/server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package testutils diff --git a/agent/grpc-external/utils.go b/agent/grpc-external/utils.go index 13c84c75c1ce4..b3a3d3d20264a 100644 --- a/agent/grpc-external/utils.go +++ b/agent/grpc-external/utils.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package external diff --git a/agent/grpc-internal/balancer/balancer.go b/agent/grpc-internal/balancer/balancer.go index 884c2a1dec3dc..4941a80873188 100644 --- a/agent/grpc-internal/balancer/balancer.go +++ b/agent/grpc-internal/balancer/balancer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // package balancer implements a custom gRPC load balancer. // diff --git a/agent/grpc-internal/balancer/balancer_test.go b/agent/grpc-internal/balancer/balancer_test.go index f0c6db9f53296..35912aab269a1 100644 --- a/agent/grpc-internal/balancer/balancer_test.go +++ b/agent/grpc-internal/balancer/balancer_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package balancer diff --git a/agent/grpc-internal/balancer/registry.go b/agent/grpc-internal/balancer/registry.go index 53b2e6555ac30..f11ea6c8cebeb 100644 --- a/agent/grpc-internal/balancer/registry.go +++ b/agent/grpc-internal/balancer/registry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package balancer diff --git a/agent/grpc-internal/client.go b/agent/grpc-internal/client.go index 1d49bc23cdd31..98a6f1fd81c5d 100644 --- a/agent/grpc-internal/client.go +++ b/agent/grpc-internal/client.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package internal diff --git a/agent/grpc-internal/client_test.go b/agent/grpc-internal/client_test.go index 134a62aa4aae3..a3b99e78ad1b7 100644 --- a/agent/grpc-internal/client_test.go +++ b/agent/grpc-internal/client_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package internal diff --git a/agent/grpc-internal/handler.go b/agent/grpc-internal/handler.go index b0eeaa8a4f0c2..3278d744436f9 100644 --- a/agent/grpc-internal/handler.go +++ b/agent/grpc-internal/handler.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package internal diff --git a/agent/grpc-internal/handler_test.go b/agent/grpc-internal/handler_test.go index 2027c055866de..80c026113d1f5 100644 --- a/agent/grpc-internal/handler_test.go +++ b/agent/grpc-internal/handler_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package internal diff --git a/agent/grpc-internal/listener.go b/agent/grpc-internal/listener.go index a1c226613778c..bcbf121c733e8 100644 --- a/agent/grpc-internal/listener.go +++ b/agent/grpc-internal/listener.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package internal diff --git a/agent/grpc-internal/pipe.go b/agent/grpc-internal/pipe.go index 555f6d2162aa3..188defd085ed9 100644 --- a/agent/grpc-internal/pipe.go +++ b/agent/grpc-internal/pipe.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package internal diff --git a/agent/grpc-internal/pipe_test.go b/agent/grpc-internal/pipe_test.go index f51d1581292b2..e6ce286d1f867 100644 --- a/agent/grpc-internal/pipe_test.go +++ b/agent/grpc-internal/pipe_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package internal diff --git a/agent/grpc-internal/resolver/registry.go b/agent/grpc-internal/resolver/registry.go index aab369c501314..5151cfd46ce0f 100644 --- a/agent/grpc-internal/resolver/registry.go +++ b/agent/grpc-internal/resolver/registry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resolver diff --git a/agent/grpc-internal/resolver/resolver.go b/agent/grpc-internal/resolver/resolver.go index 8d1436bf7aff2..d04f1e657e61f 100644 --- a/agent/grpc-internal/resolver/resolver.go +++ b/agent/grpc-internal/resolver/resolver.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resolver diff --git a/agent/grpc-internal/resolver/resolver_test.go b/agent/grpc-internal/resolver/resolver_test.go index 0914eba147bae..2bd3f24f9936b 100644 --- a/agent/grpc-internal/resolver/resolver_test.go +++ b/agent/grpc-internal/resolver/resolver_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package resolver import ( diff --git a/agent/grpc-internal/server_test.go b/agent/grpc-internal/server_test.go index 12f420979b6ee..83774c712fc6a 100644 --- a/agent/grpc-internal/server_test.go +++ b/agent/grpc-internal/server_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package internal diff --git a/agent/grpc-internal/services/subscribe/logger.go b/agent/grpc-internal/services/subscribe/logger.go index 11c18f6adfa48..faaa63ff84270 100644 --- a/agent/grpc-internal/services/subscribe/logger.go +++ b/agent/grpc-internal/services/subscribe/logger.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package subscribe diff --git a/agent/grpc-internal/services/subscribe/subscribe.go b/agent/grpc-internal/services/subscribe/subscribe.go index a728b0164c977..08c501b6dd032 100644 --- a/agent/grpc-internal/services/subscribe/subscribe.go +++ b/agent/grpc-internal/services/subscribe/subscribe.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package subscribe diff --git a/agent/grpc-internal/services/subscribe/subscribe_test.go b/agent/grpc-internal/services/subscribe/subscribe_test.go index 910862d4cfbd4..54a267f7c40d1 100644 --- a/agent/grpc-internal/services/subscribe/subscribe_test.go +++ b/agent/grpc-internal/services/subscribe/subscribe_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package subscribe diff --git a/agent/grpc-internal/stats_test.go b/agent/grpc-internal/stats_test.go index d14c4c46bc451..5da26f512ccbe 100644 --- a/agent/grpc-internal/stats_test.go +++ b/agent/grpc-internal/stats_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package internal diff --git a/agent/grpc-internal/tracker.go b/agent/grpc-internal/tracker.go index 251fe48f95399..a313f88e53501 100644 --- a/agent/grpc-internal/tracker.go +++ b/agent/grpc-internal/tracker.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package internal diff --git a/agent/grpc-middleware/auth_interceptor.go b/agent/grpc-middleware/auth_interceptor.go index af85e5c6f94c2..0472b71f00ece 100644 --- a/agent/grpc-middleware/auth_interceptor.go +++ b/agent/grpc-middleware/auth_interceptor.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package middleware diff --git a/agent/grpc-middleware/auth_interceptor_test.go b/agent/grpc-middleware/auth_interceptor_test.go index 0c447499bcb2f..18f9334cc9b80 100644 --- a/agent/grpc-middleware/auth_interceptor_test.go +++ b/agent/grpc-middleware/auth_interceptor_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package middleware diff --git a/agent/grpc-middleware/handshake.go b/agent/grpc-middleware/handshake.go index 893421e0e7f1b..82b352bb5ac30 100644 --- a/agent/grpc-middleware/handshake.go +++ b/agent/grpc-middleware/handshake.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package middleware diff --git a/agent/grpc-middleware/handshake_test.go b/agent/grpc-middleware/handshake_test.go index 178451a31464c..f987a6689af22 100644 --- a/agent/grpc-middleware/handshake_test.go +++ b/agent/grpc-middleware/handshake_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package middleware diff --git a/agent/grpc-middleware/rate.go b/agent/grpc-middleware/rate.go index bdb63cd244a97..6f84fd36c16e6 100644 --- a/agent/grpc-middleware/rate.go +++ b/agent/grpc-middleware/rate.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package middleware diff --git a/agent/grpc-middleware/rate_test.go b/agent/grpc-middleware/rate_test.go index 16c84734a9edd..0a71d232465cf 100644 --- a/agent/grpc-middleware/rate_test.go +++ b/agent/grpc-middleware/rate_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package middleware diff --git a/agent/grpc-middleware/recovery.go b/agent/grpc-middleware/recovery.go index 04b918ee9b3a2..cf1cbabe4e085 100644 --- a/agent/grpc-middleware/recovery.go +++ b/agent/grpc-middleware/recovery.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package middleware diff --git a/agent/grpc-middleware/stats.go b/agent/grpc-middleware/stats.go index a6bf1d2c59bec..564d14a844b95 100644 --- a/agent/grpc-middleware/stats.go +++ b/agent/grpc-middleware/stats.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package middleware diff --git a/agent/grpc-middleware/testutil/fake_sink.go b/agent/grpc-middleware/testutil/fake_sink.go index be7623c774a2c..c121481ee24fb 100644 --- a/agent/grpc-middleware/testutil/fake_sink.go +++ b/agent/grpc-middleware/testutil/fake_sink.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package testutil diff --git a/agent/grpc-middleware/testutil/testservice/buf.gen.yaml b/agent/grpc-middleware/testutil/testservice/buf.gen.yaml index 8d8a6c7dbfc09..b8ba317a333a9 100644 --- a/agent/grpc-middleware/testutil/testservice/buf.gen.yaml +++ b/agent/grpc-middleware/testutil/testservice/buf.gen.yaml @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 version: v1 managed: diff --git a/agent/grpc-middleware/testutil/testservice/fake_service.go b/agent/grpc-middleware/testutil/testservice/fake_service.go index ca21d286f0b35..4428e173740bb 100644 --- a/agent/grpc-middleware/testutil/testservice/fake_service.go +++ b/agent/grpc-middleware/testutil/testservice/fake_service.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package testservice diff --git a/agent/grpc-middleware/testutil/testservice/simple.pb.go b/agent/grpc-middleware/testutil/testservice/simple.pb.go index b4f664bf1ca73..18022b3dad3d1 100644 --- a/agent/grpc-middleware/testutil/testservice/simple.pb.go +++ b/agent/grpc-middleware/testutil/testservice/simple.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: diff --git a/agent/grpc-middleware/testutil/testservice/simple.proto b/agent/grpc-middleware/testutil/testservice/simple.proto index d005a45aa1138..c8ce3d58118d3 100644 --- a/agent/grpc-middleware/testutil/testservice/simple.proto +++ b/agent/grpc-middleware/testutil/testservice/simple.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; diff --git a/agent/hcp/bootstrap/bootstrap.go b/agent/hcp/bootstrap/bootstrap.go index 8e544bdec3128..191859ea002b4 100644 --- a/agent/hcp/bootstrap/bootstrap.go +++ b/agent/hcp/bootstrap/bootstrap.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package bootstrap handles bootstrapping an agent's config from HCP. It must be a // separate package from other HCP components because it has a dependency on diff --git a/agent/hcp/bootstrap/bootstrap_test.go b/agent/hcp/bootstrap/bootstrap_test.go index b475223ff8cf3..74b57e5f50abd 100644 --- a/agent/hcp/bootstrap/bootstrap_test.go +++ b/agent/hcp/bootstrap/bootstrap_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package bootstrap import ( diff --git a/agent/hcp/bootstrap/testing.go b/agent/hcp/bootstrap/testing.go index f073d17183444..a10a5d2bc8add 100644 --- a/agent/hcp/bootstrap/testing.go +++ b/agent/hcp/bootstrap/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bootstrap diff --git a/agent/hcp/client/client.go b/agent/hcp/client/client.go index c0526c0e4acf0..f04767e983c7b 100644 --- a/agent/hcp/client/client.go +++ b/agent/hcp/client/client.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package client diff --git a/agent/hcp/client/client_test.go b/agent/hcp/client/client_test.go index 5571630ad45a3..d4bae2ae4cb52 100644 --- a/agent/hcp/client/client_test.go +++ b/agent/hcp/client/client_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package client import ( diff --git a/agent/hcp/client/metrics_client.go b/agent/hcp/client/metrics_client.go index b3c1c6a6b3dc8..3c5b5c4fb9d69 100644 --- a/agent/hcp/client/metrics_client.go +++ b/agent/hcp/client/metrics_client.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package client import ( diff --git a/agent/hcp/client/metrics_client_test.go b/agent/hcp/client/metrics_client_test.go index 20a5f010ec4cd..4119e326e9dc0 100644 --- a/agent/hcp/client/metrics_client_test.go +++ b/agent/hcp/client/metrics_client_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package client import ( diff --git a/agent/hcp/client/mock_CloudConfig.go b/agent/hcp/client/mock_CloudConfig.go index 574f83e55fd59..5f2ef50046d70 100644 --- a/agent/hcp/client/mock_CloudConfig.go +++ b/agent/hcp/client/mock_CloudConfig.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package client import ( diff --git a/agent/hcp/client/telemetry_config.go b/agent/hcp/client/telemetry_config.go index 0745f1b7c6197..55c2264380306 100644 --- a/agent/hcp/client/telemetry_config.go +++ b/agent/hcp/client/telemetry_config.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package client import ( @@ -20,7 +17,7 @@ import ( var ( // defaultMetricFilters is a regex that matches all metric names. - DefaultMetricFilters = regexp.MustCompile(".+") + defaultMetricFilters = regexp.MustCompile(".+") // Validation errors for AgentTelemetryConfigOK response. errMissingPayload = errors.New("missing payload") @@ -29,7 +26,6 @@ var ( errMissingMetricsConfig = errors.New("missing metrics config") errInvalidRefreshInterval = errors.New("invalid refresh interval") errInvalidEndpoint = errors.New("invalid metrics endpoint") - errEmptyEndpoint = errors.New("empty metrics endpoint") ) // TelemetryConfig contains configuration for telemetry data forwarded by Consul servers @@ -44,7 +40,6 @@ type MetricsConfig struct { Labels map[string]string Filters *regexp.Regexp Endpoint *url.URL - Disabled bool } // RefreshConfig contains configuration for the periodic fetch of configuration from HCP. @@ -52,6 +47,11 @@ type RefreshConfig struct { RefreshInterval time.Duration } +// MetricsEnabled returns true if metrics export is enabled, i.e. a valid metrics endpoint exists. +func (t *TelemetryConfig) MetricsEnabled() bool { + return t.MetricsConfig.Endpoint != nil +} + // validateAgentTelemetryConfigPayload ensures the returned payload from HCP is valid. func validateAgentTelemetryConfigPayload(resp *hcptelemetry.AgentTelemetryConfigOK) error { if resp.Payload == nil { @@ -83,7 +83,7 @@ func convertAgentTelemetryResponse(ctx context.Context, resp *hcptelemetry.Agent telemetryConfig := resp.Payload.TelemetryConfig metricsEndpoint, err := convertMetricEndpoint(telemetryConfig.Endpoint, telemetryConfig.Metrics.Endpoint) if err != nil { - return nil, err + return nil, errInvalidEndpoint } metricsFilters := convertMetricFilters(ctx, telemetryConfig.Metrics.IncludeList) @@ -94,7 +94,6 @@ func convertAgentTelemetryResponse(ctx context.Context, resp *hcptelemetry.Agent Endpoint: metricsEndpoint, Labels: metricLabels, Filters: metricsFilters, - Disabled: telemetryConfig.Metrics.Disabled, }, RefreshConfig: &RefreshConfig{ RefreshInterval: refreshInterval, @@ -112,8 +111,9 @@ func convertMetricEndpoint(telemetryEndpoint string, metricsEndpoint string) (*u endpoint = metricsEndpoint } + // If endpoint is empty, server not registered with CCM, no error returned. if endpoint == "" { - return nil, errEmptyEndpoint + return nil, nil } // Endpoint from CTW has no metrics path, so it must be added. @@ -142,7 +142,7 @@ func convertMetricFilters(ctx context.Context, payloadFilters []string) *regexp. if len(validFilters) == 0 { logger.Error("no valid filters") - return DefaultMetricFilters + return defaultMetricFilters } // Combine the valid regex strings with OR. @@ -150,7 +150,7 @@ func convertMetricFilters(ctx context.Context, payloadFilters []string) *regexp. composedRegex, err := regexp.Compile(finalRegex) if err != nil { logger.Error("failed to compile final regex", "error", err) - return DefaultMetricFilters + return defaultMetricFilters } return composedRegex diff --git a/agent/hcp/client/telemetry_config_test.go b/agent/hcp/client/telemetry_config_test.go index d43024400779a..42d3ee649802a 100644 --- a/agent/hcp/client/telemetry_config_test.go +++ b/agent/hcp/client/telemetry_config_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package client import ( @@ -88,6 +85,7 @@ func TestConvertAgentTelemetryResponse(t *testing.T) { resp *consul_telemetry_service.AgentTelemetryConfigOK expectedTelemetryCfg *TelemetryConfig wantErr error + expectedEnabled bool }{ "success": { resp: &consul_telemetry_service.AgentTelemetryConfigOK{ @@ -114,6 +112,34 @@ func TestConvertAgentTelemetryResponse(t *testing.T) { RefreshInterval: 2 * time.Second, }, }, + expectedEnabled: true, + }, + "successNoEndpoint": { + resp: &consul_telemetry_service.AgentTelemetryConfigOK{ + Payload: &models.HashicorpCloudConsulTelemetry20230414AgentTelemetryConfigResponse{ + TelemetryConfig: &models.HashicorpCloudConsulTelemetry20230414TelemetryConfig{ + Endpoint: "", + Labels: map[string]string{"test": "test"}, + Metrics: &models.HashicorpCloudConsulTelemetry20230414TelemetryMetricsConfig{ + IncludeList: []string{"test", "consul"}, + }, + }, + RefreshConfig: &models.HashicorpCloudConsulTelemetry20230414RefreshConfig{ + RefreshInterval: "2s", + }, + }, + }, + expectedTelemetryCfg: &TelemetryConfig{ + MetricsConfig: &MetricsConfig{ + Endpoint: nil, + Labels: map[string]string{"test": "test"}, + Filters: validTestFilters, + }, + RefreshConfig: &RefreshConfig{ + RefreshInterval: 2 * time.Second, + }, + }, + expectedEnabled: false, }, "successBadFilters": { resp: &consul_telemetry_service.AgentTelemetryConfigOK{ @@ -134,12 +160,13 @@ func TestConvertAgentTelemetryResponse(t *testing.T) { MetricsConfig: &MetricsConfig{ Endpoint: validTestURL, Labels: map[string]string{"test": "test"}, - Filters: DefaultMetricFilters, + Filters: defaultMetricFilters, }, RefreshConfig: &RefreshConfig{ RefreshInterval: 2 * time.Second, }, }, + expectedEnabled: true, }, "errorsWithInvalidRefreshInterval": { resp: &consul_telemetry_service.AgentTelemetryConfigOK{ @@ -179,6 +206,7 @@ func TestConvertAgentTelemetryResponse(t *testing.T) { } require.NoError(t, err) require.Equal(t, tc.expectedTelemetryCfg, telemetryCfg) + require.Equal(t, tc.expectedEnabled, telemetryCfg.MetricsEnabled()) }) } } @@ -200,10 +228,10 @@ func TestConvertMetricEndpoint(t *testing.T) { override: "https://override.com", expected: "https://override.com/v1/metrics", }, - "errorWithEmptyEndpoints": { + "noErrorWithEmptyEndpoints": { endpoint: "", override: "", - wantErr: errEmptyEndpoint, + expected: "", }, "errorWithInvalidURL": { endpoint: " ", @@ -221,6 +249,12 @@ func TestConvertMetricEndpoint(t *testing.T) { return } + if tc.expected == "" { + require.Nil(t, u) + require.NoError(t, err) + return + } + require.NotNil(t, u) require.NoError(t, err) require.Equal(t, tc.expected, u.String()) @@ -240,13 +274,13 @@ func TestConvertMetricFilters(t *testing.T) { }{ "badFilterRegex": { filters: []string{"(*LF)"}, - expectedRegexString: DefaultMetricFilters.String(), + expectedRegexString: defaultMetricFilters.String(), matches: []string{"consul.raft.peers", "consul.mem.heap_size"}, wantMatch: true, }, "emptyRegex": { filters: []string{}, - expectedRegexString: DefaultMetricFilters.String(), + expectedRegexString: defaultMetricFilters.String(), matches: []string{"consul.raft.peers", "consul.mem.heap_size"}, wantMatch: true, }, diff --git a/agent/hcp/config/config.go b/agent/hcp/config/config.go index 59977ef46f37d..319c39e40e94c 100644 --- a/agent/hcp/config/config.go +++ b/agent/hcp/config/config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/agent/hcp/deps.go b/agent/hcp/deps.go index 7bf384747dbd3..ab8288e344d11 100644 --- a/agent/hcp/deps.go +++ b/agent/hcp/deps.go @@ -1,24 +1,24 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package hcp import ( "context" "fmt" + "time" "github.com/armon/go-metrics" - "github.com/hashicorp/go-hclog" - - "github.com/hashicorp/consul/agent/hcp/client" + hcpclient "github.com/hashicorp/consul/agent/hcp/client" "github.com/hashicorp/consul/agent/hcp/config" "github.com/hashicorp/consul/agent/hcp/scada" "github.com/hashicorp/consul/agent/hcp/telemetry" + "github.com/hashicorp/go-hclog" ) // Deps contains the interfaces that the rest of Consul core depends on for HCP integration. type Deps struct { - Client client.Client + Client hcpclient.Client Provider scada.Provider Sink metrics.MetricSink } @@ -27,7 +27,7 @@ func NewDeps(cfg config.CloudConfig, logger hclog.Logger) (Deps, error) { ctx := context.Background() ctx = hclog.WithContext(ctx, logger) - hcpClient, err := client.NewClient(cfg) + client, err := hcpclient.NewClient(cfg) if err != nil { return Deps{}, fmt.Errorf("failed to init client: %w", err) } @@ -37,33 +37,50 @@ func NewDeps(cfg config.CloudConfig, logger hclog.Logger) (Deps, error) { return Deps{}, fmt.Errorf("failed to init scada: %w", err) } - metricsClient, err := client.NewMetricsClient(ctx, &cfg) + metricsClient, err := hcpclient.NewMetricsClient(ctx, &cfg) if err != nil { logger.Error("failed to init metrics client", "error", err) return Deps{}, fmt.Errorf("failed to init metrics client: %w", err) } - sink, err := sink(ctx, metricsClient, NewHCPProvider(ctx, hcpClient)) + sink, err := sink(ctx, client, metricsClient) if err != nil { // Do not prevent server start if sink init fails, only log error. logger.Error("failed to init sink", "error", err) } return Deps{ - Client: hcpClient, + Client: client, Provider: provider, Sink: sink, }, nil } // sink initializes an OTELSink which forwards Consul metrics to HCP. +// The sink is only initialized if the server is registered with the management plane (CCM). // This step should not block server initialization, errors are returned, only to be logged. func sink( ctx context.Context, + hcpClient hcpclient.Client, metricsClient telemetry.MetricsClient, - cfgProvider *hcpProviderImpl, ) (metrics.MetricSink, error) { - logger := hclog.FromContext(ctx) + logger := hclog.FromContext(ctx).Named("sink") + reqCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + telemetryCfg, err := hcpClient.FetchTelemetryConfig(reqCtx) + if err != nil { + return nil, fmt.Errorf("failed to fetch telemetry config: %w", err) + } + + if !telemetryCfg.MetricsEnabled() { + return nil, nil + } + + cfgProvider, err := NewHCPProvider(ctx, hcpClient, telemetryCfg) + if err != nil { + return nil, fmt.Errorf("failed to init config provider: %w", err) + } reader := telemetry.NewOTELReader(metricsClient, cfgProvider) sinkOpts := &telemetry.OTELSinkOpts{ @@ -73,7 +90,7 @@ func sink( sink, err := telemetry.NewOTELSink(ctx, sinkOpts) if err != nil { - return nil, fmt.Errorf("failed to create OTELSink: %w", err) + return nil, fmt.Errorf("failed create OTELSink: %w", err) } logger.Debug("initialized HCP metrics sink") diff --git a/agent/hcp/deps_test.go b/agent/hcp/deps_test.go index 7375dad68cb76..8bab66bac3f3c 100644 --- a/agent/hcp/deps_test.go +++ b/agent/hcp/deps_test.go @@ -1,14 +1,17 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package hcp import ( "context" + "fmt" + "net/url" + "regexp" "testing" + "time" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/agent/hcp/client" "github.com/hashicorp/consul/agent/hcp/telemetry" ) @@ -18,11 +21,79 @@ type mockMetricsClient struct { func TestSink(t *testing.T) { t.Parallel() + for name, test := range map[string]struct { + expect func(*client.MockClient) + wantErr string + expectedSink bool + }{ + "success": { + expect: func(mockClient *client.MockClient) { + u, _ := url.Parse("https://test.com/v1/metrics") + filters, _ := regexp.Compile("test") + mt := mockTelemetryConfig(1*time.Second, u, filters) + mockClient.EXPECT().FetchTelemetryConfig(mock.Anything).Return(mt, nil) + }, + expectedSink: true, + }, + "noSinkWhenFetchTelemetryConfigFails": { + expect: func(mockClient *client.MockClient) { + mockClient.EXPECT().FetchTelemetryConfig(mock.Anything).Return(nil, fmt.Errorf("fetch failed")) + }, + wantErr: "failed to fetch telemetry config", + }, + "noSinkWhenServerNotRegisteredWithCCM": { + expect: func(mockClient *client.MockClient) { + mt := mockTelemetryConfig(1*time.Second, nil, nil) + mockClient.EXPECT().FetchTelemetryConfig(mock.Anything).Return(mt, nil) + }, + }, + "noSinkWhenTelemetryConfigProviderInitFails": { + expect: func(mockClient *client.MockClient) { + u, _ := url.Parse("https://test.com/v1/metrics") + // Bad refresh interval forces ConfigProvider creation failure. + mt := mockTelemetryConfig(0*time.Second, u, nil) + mockClient.EXPECT().FetchTelemetryConfig(mock.Anything).Return(mt, nil) + }, + wantErr: "failed to init config provider", + }, + } { + test := test + t.Run(name, func(t *testing.T) { + t.Parallel() + c := client.NewMockClient(t) + mc := mockMetricsClient{} + + test.expect(c) + ctx := context.Background() + + s, err := sink(ctx, c, mc) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - s, err := sink(ctx, mockMetricsClient{}, &hcpProviderImpl{}) + if test.wantErr != "" { + require.NotNil(t, err) + require.Contains(t, err.Error(), test.wantErr) + require.Nil(t, s) + return + } + + if !test.expectedSink { + require.Nil(t, s) + require.Nil(t, err) + return + } + + require.NotNil(t, s) + }) + } +} - require.NotNil(t, s) - require.NoError(t, err) +func mockTelemetryConfig(refreshInterval time.Duration, metricsEndpoint *url.URL, filters *regexp.Regexp) *client.TelemetryConfig { + return &client.TelemetryConfig{ + MetricsConfig: &client.MetricsConfig{ + Endpoint: metricsEndpoint, + Filters: filters, + }, + RefreshConfig: &client.RefreshConfig{ + RefreshInterval: refreshInterval, + }, + } } diff --git a/agent/hcp/discover/discover.go b/agent/hcp/discover/discover.go index 981400c38b478..12024b7dd6a0b 100644 --- a/agent/hcp/discover/discover.go +++ b/agent/hcp/discover/discover.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package discover diff --git a/agent/hcp/manager.go b/agent/hcp/manager.go index a3664b0608dfe..0dc9db95da295 100644 --- a/agent/hcp/manager.go +++ b/agent/hcp/manager.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package hcp diff --git a/agent/hcp/manager_test.go b/agent/hcp/manager_test.go index 8432e63ed5288..48ace166618bf 100644 --- a/agent/hcp/manager_test.go +++ b/agent/hcp/manager_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package hcp diff --git a/agent/hcp/scada/capabilities.go b/agent/hcp/scada/capabilities.go index bbb6ea6266dc3..c18192ae6e94a 100644 --- a/agent/hcp/scada/capabilities.go +++ b/agent/hcp/scada/capabilities.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package scada diff --git a/agent/hcp/scada/scada.go b/agent/hcp/scada/scada.go index 151e1b6862efa..5aba819bda499 100644 --- a/agent/hcp/scada/scada.go +++ b/agent/hcp/scada/scada.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package scada diff --git a/agent/hcp/telemetry/custom_metrics.go b/agent/hcp/telemetry/custom_metrics.go index 39df765b9204b..d691dccde2078 100644 --- a/agent/hcp/telemetry/custom_metrics.go +++ b/agent/hcp/telemetry/custom_metrics.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package telemetry // Keys for custom Go Metrics metrics emitted only for the OTEL diff --git a/agent/hcp/telemetry/doc.go b/agent/hcp/telemetry/doc.go index d982a37c0f3e5..4ef18f39bd309 100644 --- a/agent/hcp/telemetry/doc.go +++ b/agent/hcp/telemetry/doc.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - // Package telemetry implements functionality to collect, aggregate, convert and export // telemetry data in OpenTelemetry Protocol (OTLP) format. // diff --git a/agent/hcp/telemetry/gauge_store.go b/agent/hcp/telemetry/gauge_store.go index bb7030dae852b..76dfb78066683 100644 --- a/agent/hcp/telemetry/gauge_store.go +++ b/agent/hcp/telemetry/gauge_store.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package telemetry import ( diff --git a/agent/hcp/telemetry/gauge_store_test.go b/agent/hcp/telemetry/gauge_store_test.go index 4ccac624dbd99..1171ee379c325 100644 --- a/agent/hcp/telemetry/gauge_store_test.go +++ b/agent/hcp/telemetry/gauge_store_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package telemetry import ( diff --git a/agent/hcp/telemetry/otel_exporter.go b/agent/hcp/telemetry/otel_exporter.go index 050d5660668d2..ba92d4419157a 100644 --- a/agent/hcp/telemetry/otel_exporter.go +++ b/agent/hcp/telemetry/otel_exporter.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package telemetry import ( @@ -23,9 +20,7 @@ type MetricsClient interface { // EndpointProvider provides the endpoint where metrics are exported to by the OTELExporter. // EndpointProvider exposes the GetEndpoint() interface method to fetch the endpoint. // This abstraction layer offers flexibility, in particular for dynamic configuration or changes to the endpoint. -// The OTELExporter calls the Disabled interface to verify that it should actually export metrics. type EndpointProvider interface { - Disabled GetEndpoint() *url.URL } @@ -70,10 +65,6 @@ func (e *otelExporter) Aggregation(kind metric.InstrumentKind) aggregation.Aggre // Export serializes and transmits metric data to a receiver. func (e *otelExporter) Export(ctx context.Context, metrics *metricdata.ResourceMetrics) error { - if e.endpointProvider.IsDisabled() { - return nil - } - endpoint := e.endpointProvider.GetEndpoint() if endpoint == nil { return nil diff --git a/agent/hcp/telemetry/otel_exporter_test.go b/agent/hcp/telemetry/otel_exporter_test.go index ebe6486abca85..704817f6407d2 100644 --- a/agent/hcp/telemetry/otel_exporter_test.go +++ b/agent/hcp/telemetry/otel_exporter_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package telemetry import ( @@ -34,11 +31,9 @@ func (m *mockMetricsClient) ExportMetrics(ctx context.Context, protoMetrics *met type mockEndpointProvider struct { endpoint *url.URL - disabled bool } func (m *mockEndpointProvider) GetEndpoint() *url.URL { return m.endpoint } -func (m *mockEndpointProvider) IsDisabled() bool { return m.disabled } func TestTemporality(t *testing.T) { t.Parallel() @@ -82,20 +77,13 @@ func TestExport(t *testing.T) { client MetricsClient provider EndpointProvider }{ - "earlyReturnDisabledProvider": { - client: &mockMetricsClient{}, - provider: &mockEndpointProvider{ - disabled: true, - }, - }, "earlyReturnWithoutEndpoint": { client: &mockMetricsClient{}, provider: &mockEndpointProvider{}, }, "earlyReturnWithoutScopeMetrics": { - client: &mockMetricsClient{}, - metrics: mutateMetrics(nil), - provider: &mockEndpointProvider{}, + client: &mockMetricsClient{}, + metrics: mutateMetrics(nil), }, "earlyReturnWithoutMetrics": { client: &mockMetricsClient{}, @@ -103,7 +91,6 @@ func TestExport(t *testing.T) { {Metrics: []metricdata.Metrics{}}, }, ), - provider: &mockEndpointProvider{}, }, "errorWithExportFailure": { client: &mockMetricsClient{ @@ -120,9 +107,6 @@ func TestExport(t *testing.T) { }, }, ), - provider: &mockEndpointProvider{ - endpoint: &url.URL{}, - }, wantErr: "failed to export metrics", }, } { diff --git a/agent/hcp/telemetry/otel_sink.go b/agent/hcp/telemetry/otel_sink.go index 12aae982016c2..a35b1827d60c7 100644 --- a/agent/hcp/telemetry/otel_sink.go +++ b/agent/hcp/telemetry/otel_sink.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package telemetry import ( @@ -36,15 +33,8 @@ const ( defaultExportTimeout = 30 * time.Second ) -// Disabled should be implemented to turn on/off metrics processing -type Disabled interface { - // IsDisabled() can return true disallow the sink from accepting metrics. - IsDisabled() bool -} - // ConfigProvider is required to provide custom metrics processing. type ConfigProvider interface { - Disabled // GetLabels should return a set of OTEL attributes added by default all metrics. GetLabels() map[string]string @@ -154,11 +144,8 @@ func (o *OTELSink) IncrCounter(key []string, val float32) { // AddSampleWithLabels emits a Consul gauge metric that gets // registed by an OpenTelemetry Histogram instrument. func (o *OTELSink) SetGaugeWithLabels(key []string, val float32, labels []gometrics.Label) { - if o.cfgProvider.IsDisabled() { - return - } - k := o.flattenKey(key) + if !o.allowedMetric(k) { return } @@ -185,11 +172,8 @@ func (o *OTELSink) SetGaugeWithLabels(key []string, val float32, labels []gometr // AddSampleWithLabels emits a Consul sample metric that gets registed by an OpenTelemetry Histogram instrument. func (o *OTELSink) AddSampleWithLabels(key []string, val float32, labels []gometrics.Label) { - if o.cfgProvider.IsDisabled() { - return - } - k := o.flattenKey(key) + if !o.allowedMetric(k) { return } @@ -214,11 +198,8 @@ func (o *OTELSink) AddSampleWithLabels(key []string, val float32, labels []gomet // IncrCounterWithLabels emits a Consul counter metric that gets registed by an OpenTelemetry Histogram instrument. func (o *OTELSink) IncrCounterWithLabels(key []string, val float32, labels []gometrics.Label) { - if o.cfgProvider.IsDisabled() { - return - } - k := o.flattenKey(key) + if !o.allowedMetric(k) { return } diff --git a/agent/hcp/telemetry/otel_sink_test.go b/agent/hcp/telemetry/otel_sink_test.go index 30bbeee519b7f..509dde299d627 100644 --- a/agent/hcp/telemetry/otel_sink_test.go +++ b/agent/hcp/telemetry/otel_sink_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package telemetry import ( @@ -21,9 +18,8 @@ import ( ) type mockConfigProvider struct { - filter *regexp.Regexp - labels map[string]string - disabled bool + filter *regexp.Regexp + labels map[string]string } func (m *mockConfigProvider) GetLabels() map[string]string { @@ -34,10 +30,6 @@ func (m *mockConfigProvider) GetFilters() *regexp.Regexp { return m.filter } -func (m *mockConfigProvider) IsDisabled() bool { - return m.disabled -} - var ( expectedResource = resource.NewSchemaless() @@ -228,29 +220,6 @@ func TestOTELSink(t *testing.T) { isSame(t, expectedSinkMetrics, collected) } -func TestOTELSinkDisabled(t *testing.T) { - reader := metric.NewManualReader() - ctx := context.Background() - - sink, err := NewOTELSink(ctx, &OTELSinkOpts{ - ConfigProvider: &mockConfigProvider{ - filter: regexp.MustCompile("raft"), - disabled: true, - }, - Reader: reader, - }) - require.NoError(t, err) - - sink.SetGauge([]string{"consul", "raft", "gauge"}, 1) - sink.IncrCounter([]string{"consul", "raft", "counter"}, 1) - sink.AddSample([]string{"consul", "raft", "sample"}, 1) - - var collected metricdata.ResourceMetrics - err = reader.Collect(ctx, &collected) - require.NoError(t, err) - require.Empty(t, collected.ScopeMetrics) -} - func TestLabelsToAttributes(t *testing.T) { for name, test := range map[string]struct { providerLabels map[string]string diff --git a/agent/hcp/telemetry/otlp_transform.go b/agent/hcp/telemetry/otlp_transform.go index 907e7922ad98d..76e20552a0d4e 100644 --- a/agent/hcp/telemetry/otlp_transform.go +++ b/agent/hcp/telemetry/otlp_transform.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package telemetry import ( @@ -16,8 +13,8 @@ import ( ) var ( - errAggregaton = errors.New("unsupported aggregation") - errTemporality = errors.New("unsupported temporality") + aggregationErr = errors.New("unsupported aggregation") + temporalityErr = errors.New("unsupported temporality") ) // isEmpty verifies if the given OTLP protobuf metrics contains metric data. @@ -99,7 +96,7 @@ func metricTypeToPB(m metricdata.Metrics) (*mpb.Metric, error) { } case metricdata.Sum[float64]: if a.Temporality != metricdata.CumulativeTemporality { - return out, fmt.Errorf("failed to convert metric to otel format: %w: %T", errTemporality, a) + return out, fmt.Errorf("error: %w: %T", temporalityErr, a) } out.Data = &mpb.Metric_Sum{ Sum: &mpb.Sum{ @@ -110,7 +107,7 @@ func metricTypeToPB(m metricdata.Metrics) (*mpb.Metric, error) { } case metricdata.Histogram[float64]: if a.Temporality != metricdata.CumulativeTemporality { - return out, fmt.Errorf("failed to convert metric to otel format: %w: %T", errTemporality, a) + return out, fmt.Errorf("error: %w: %T", temporalityErr, a) } out.Data = &mpb.Metric_Histogram{ Histogram: &mpb.Histogram{ @@ -119,7 +116,7 @@ func metricTypeToPB(m metricdata.Metrics) (*mpb.Metric, error) { }, } default: - return out, fmt.Errorf("failed to convert metric to otel format: %w: %T", errAggregaton, a) + return out, fmt.Errorf("error: %w: %T", aggregationErr, a) } return out, nil } diff --git a/agent/hcp/telemetry/otlp_transform_test.go b/agent/hcp/telemetry/otlp_transform_test.go index d67df73d83433..8f6beb7d489db 100644 --- a/agent/hcp/telemetry/otlp_transform_test.go +++ b/agent/hcp/telemetry/otlp_transform_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package telemetry import ( @@ -260,15 +257,15 @@ func TestTransformOTLP(t *testing.T) { // MetricType Error Test Cases _, err := metricTypeToPB(invalidHistTemporality) require.Error(t, err) - require.ErrorIs(t, err, errTemporality) + require.ErrorIs(t, err, temporalityErr) _, err = metricTypeToPB(invalidSumTemporality) require.Error(t, err) - require.ErrorIs(t, err, errTemporality) + require.ErrorIs(t, err, temporalityErr) _, err = metricTypeToPB(invalidSumAgg) require.Error(t, err) - require.ErrorIs(t, err, errAggregaton) + require.ErrorIs(t, err, aggregationErr) // Metrics Test Case m := metricsToPB(inputMetrics) diff --git a/agent/hcp/telemetry_provider.go b/agent/hcp/telemetry_provider.go index 22bb0f2f00b81..eb0f23e804f3c 100644 --- a/agent/hcp/telemetry_provider.go +++ b/agent/hcp/telemetry_provider.go @@ -1,17 +1,14 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package hcp import ( "context" + "fmt" "net/url" "regexp" "sync" "time" "github.com/armon/go-metrics" - "github.com/go-openapi/runtime" "github.com/hashicorp/go-hclog" "github.com/hashicorp/consul/agent/hcp/client" @@ -23,8 +20,6 @@ var ( internalMetricRefreshFailure []string = []string{"hcp", "telemetry_config_provider", "refresh", "failure"} // internalMetricRefreshSuccess is a metric to monitor refresh successes. internalMetricRefreshSuccess []string = []string{"hcp", "telemetry_config_provider", "refresh", "success"} - // defaultTelemetryConfigRefreshInterval is a default fallback in case the first HCP fetch fails. - defaultTelemetryConfigRefreshInterval = 1 * time.Minute ) // Ensure hcpProviderImpl implements telemetry provider interfaces. @@ -48,50 +43,47 @@ type hcpProviderImpl struct { // dynamicConfig is a set of configurable settings for metrics collection, processing and export. // fields MUST be exported to compute hash for equals method. type dynamicConfig struct { - disabled bool - endpoint *url.URL - labels map[string]string - filters *regexp.Regexp + Endpoint *url.URL + Labels map[string]string + Filters *regexp.Regexp // refreshInterval controls the interval at which configuration is fetched from HCP to refresh config. - refreshInterval time.Duration + RefreshInterval time.Duration } -// defaultDisabledCfg disables metric collection and contains default config values. -func defaultDisabledCfg() *dynamicConfig { - return &dynamicConfig{ - labels: map[string]string{}, - filters: client.DefaultMetricFilters, - refreshInterval: defaultTelemetryConfigRefreshInterval, - endpoint: nil, - disabled: true, +// NewHCPProvider initializes and starts a HCP Telemetry provider with provided params. +func NewHCPProvider(ctx context.Context, hcpClient client.Client, telemetryCfg *client.TelemetryConfig) (*hcpProviderImpl, error) { + refreshInterval := telemetryCfg.RefreshConfig.RefreshInterval + // refreshInterval must be greater than 0, otherwise time.Ticker panics. + if refreshInterval <= 0 { + return nil, fmt.Errorf("invalid refresh interval: %d", refreshInterval) + } + + cfg := &dynamicConfig{ + Endpoint: telemetryCfg.MetricsConfig.Endpoint, + Labels: telemetryCfg.MetricsConfig.Labels, + Filters: telemetryCfg.MetricsConfig.Filters, + RefreshInterval: refreshInterval, } -} -// NewHCPProvider initializes and starts a HCP Telemetry provider. -func NewHCPProvider(ctx context.Context, hcpClient client.Client) *hcpProviderImpl { - h := &hcpProviderImpl{ - // Initialize with default config values. - cfg: defaultDisabledCfg(), + t := &hcpProviderImpl{ + cfg: cfg, hcpClient: hcpClient, } - go h.run(ctx) + go t.run(ctx, refreshInterval) - return h + return t, nil } // run continously checks for updates to the telemetry configuration by making a request to HCP. -func (h *hcpProviderImpl) run(ctx context.Context) { - // Try to initialize config once before starting periodic fetch. - h.updateConfig(ctx) - - ticker := time.NewTicker(h.cfg.refreshInterval) +func (h *hcpProviderImpl) run(ctx context.Context, refreshInterval time.Duration) { + ticker := time.NewTicker(refreshInterval) defer ticker.Stop() for { select { case <-ticker.C: - if newRefreshInterval := h.updateConfig(ctx); newRefreshInterval > 0 { - ticker.Reset(newRefreshInterval) + if newCfg := h.getUpdate(ctx); newCfg != nil { + ticker.Reset(newCfg.RefreshInterval) } case <-ctx.Done(): return @@ -99,8 +91,9 @@ func (h *hcpProviderImpl) run(ctx context.Context) { } } -// updateConfig makes a HTTP request to HCP to update metrics configuration held in the provider. -func (h *hcpProviderImpl) updateConfig(ctx context.Context) time.Duration { +// getUpdate makes a HTTP request to HCP to return a new metrics configuration +// and updates the hcpProviderImpl. +func (h *hcpProviderImpl) getUpdate(ctx context.Context) *dynamicConfig { logger := hclog.FromContext(ctx).Named("telemetry_config_provider") ctx, cancel := context.WithTimeout(ctx, 5*time.Second) @@ -108,18 +101,9 @@ func (h *hcpProviderImpl) updateConfig(ctx context.Context) time.Duration { telemetryCfg, err := h.hcpClient.FetchTelemetryConfig(ctx) if err != nil { - // Only disable metrics on 404 or 401 to handle the case of an unlinked cluster. - // For other errors such as 5XX ones, we continue metrics collection, as these are potentially transient server-side errors. - apiErr, ok := err.(*runtime.APIError) - if ok && apiErr.IsClientError() { - disabledMetricsCfg := defaultDisabledCfg() - h.modifyDynamicCfg(disabledMetricsCfg) - return disabledMetricsCfg.refreshInterval - } - logger.Error("failed to fetch telemetry config from HCP", "error", err) metrics.IncrCounter(internalMetricRefreshFailure, 1) - return 0 + return nil } // newRefreshInterval of 0 or less can cause ticker Reset() panic. @@ -127,29 +111,24 @@ func (h *hcpProviderImpl) updateConfig(ctx context.Context) time.Duration { if newRefreshInterval <= 0 { logger.Error("invalid refresh interval duration", "refreshInterval", newRefreshInterval) metrics.IncrCounter(internalMetricRefreshFailure, 1) - return 0 + return nil } - newCfg := &dynamicConfig{ - filters: telemetryCfg.MetricsConfig.Filters, - endpoint: telemetryCfg.MetricsConfig.Endpoint, - labels: telemetryCfg.MetricsConfig.Labels, - refreshInterval: telemetryCfg.RefreshConfig.RefreshInterval, - disabled: telemetryCfg.MetricsConfig.Disabled, + newDynamicConfig := &dynamicConfig{ + Filters: telemetryCfg.MetricsConfig.Filters, + Endpoint: telemetryCfg.MetricsConfig.Endpoint, + Labels: telemetryCfg.MetricsConfig.Labels, + RefreshInterval: newRefreshInterval, } - h.modifyDynamicCfg(newCfg) - - return newCfg.refreshInterval -} - -// modifyDynamicCfg acquires a write lock to update new configuration and emits a success metric. -func (h *hcpProviderImpl) modifyDynamicCfg(newCfg *dynamicConfig) { + // Acquire write lock to update new configuration. h.rw.Lock() - h.cfg = newCfg + h.cfg = newDynamicConfig h.rw.Unlock() metrics.IncrCounter(internalMetricRefreshSuccess, 1) + + return newDynamicConfig } // GetEndpoint acquires a read lock to return endpoint configuration for consumers. @@ -157,7 +136,7 @@ func (h *hcpProviderImpl) GetEndpoint() *url.URL { h.rw.RLock() defer h.rw.RUnlock() - return h.cfg.endpoint + return h.cfg.Endpoint } // GetFilters acquires a read lock to return filters configuration for consumers. @@ -165,7 +144,7 @@ func (h *hcpProviderImpl) GetFilters() *regexp.Regexp { h.rw.RLock() defer h.rw.RUnlock() - return h.cfg.filters + return h.cfg.Filters } // GetLabels acquires a read lock to return labels configuration for consumers. @@ -173,13 +152,5 @@ func (h *hcpProviderImpl) GetLabels() map[string]string { h.rw.RLock() defer h.rw.RUnlock() - return h.cfg.labels -} - -// IsDisabled acquires a read lock and return true if metrics are enabled. -func (h *hcpProviderImpl) IsDisabled() bool { - h.rw.RLock() - defer h.rw.RUnlock() - - return h.cfg.disabled + return h.cfg.Labels } diff --git a/agent/hcp/telemetry_provider_test.go b/agent/hcp/telemetry_provider_test.go index 9e6405a516d36..684593b4f38b0 100644 --- a/agent/hcp/telemetry_provider_test.go +++ b/agent/hcp/telemetry_provider_test.go @@ -1,11 +1,7 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package hcp import ( "context" - "errors" "fmt" "net/url" "regexp" @@ -15,7 +11,6 @@ import ( "time" "github.com/armon/go-metrics" - "github.com/go-openapi/runtime" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -41,49 +36,64 @@ type testConfig struct { endpoint string labels map[string]string refreshInterval time.Duration - disabled bool } -func TestNewTelemetryConfigProvider_DefaultConfig(t *testing.T) { +func TestNewTelemetryConfigProvider(t *testing.T) { t.Parallel() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + for name, tc := range map[string]struct { + testInputs *testConfig + wantErr string + }{ + "success": { + testInputs: &testConfig{ + refreshInterval: 1 * time.Second, + }, + }, + "failsWithInvalidRefreshInterval": { + testInputs: &testConfig{ + refreshInterval: 0 * time.Second, + }, + wantErr: "invalid refresh interval", + }, + } { + tc := tc + t.Run(name, func(t *testing.T) { + t.Parallel() - // Initialize new provider, but fail all HCP fetches. - mc := client.NewMockClient(t) - mc.EXPECT().FetchTelemetryConfig(mock.Anything).Return(nil, errors.New("failed to fetch config")) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() - provider := NewHCPProvider(ctx, mc) - provider.updateConfig(ctx) + testCfg, err := testTelemetryCfg(tc.testInputs) + require.NoError(t, err) - // Assert provider has default configuration and metrics processing is disabled. - defaultCfg := &dynamicConfig{ - labels: map[string]string{}, - filters: client.DefaultMetricFilters, - refreshInterval: defaultTelemetryConfigRefreshInterval, - endpoint: nil, - disabled: true, + cfgProvider, err := NewHCPProvider(ctx, client.NewMockClient(t), testCfg) + if tc.wantErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tc.wantErr) + require.Nil(t, cfgProvider) + return + } + require.NotNil(t, cfgProvider) + }) } - require.Equal(t, defaultCfg, provider.cfg) } -func TestTelemetryConfigProvider_UpdateConfig(t *testing.T) { +func TestTelemetryConfigProviderGetUpdate(t *testing.T) { for name, tc := range map[string]struct { - mockExpect func(*client.MockClient) - metricKey string - initCfg *dynamicConfig - expected *dynamicConfig - expectedInterval time.Duration + mockExpect func(*client.MockClient) + metricKey string + optsInputs *testConfig + expected *testConfig }{ "noChanges": { - initCfg: testDynamicCfg(&testConfig{ + optsInputs: &testConfig{ endpoint: "http://test.com/v1/metrics", filters: "test", labels: map[string]string{ "test_label": "123", }, refreshInterval: testRefreshInterval, - }), + }, mockExpect: func(m *client.MockClient) { mockCfg, _ := testTelemetryCfg(&testConfig{ endpoint: "http://test.com/v1/metrics", @@ -95,26 +105,25 @@ func TestTelemetryConfigProvider_UpdateConfig(t *testing.T) { }) m.EXPECT().FetchTelemetryConfig(mock.Anything).Return(mockCfg, nil) }, - expected: testDynamicCfg(&testConfig{ + expected: &testConfig{ endpoint: "http://test.com/v1/metrics", labels: map[string]string{ "test_label": "123", }, filters: "test", refreshInterval: testRefreshInterval, - }), - metricKey: testMetricKeySuccess, - expectedInterval: testRefreshInterval, + }, + metricKey: testMetricKeySuccess, }, "newConfig": { - initCfg: testDynamicCfg(&testConfig{ + optsInputs: &testConfig{ endpoint: "http://test.com/v1/metrics", filters: "test", labels: map[string]string{ "test_label": "123", }, refreshInterval: 2 * time.Second, - }), + }, mockExpect: func(m *client.MockClient) { mockCfg, _ := testTelemetryCfg(&testConfig{ endpoint: "http://newendpoint/v1/metrics", @@ -126,136 +135,83 @@ func TestTelemetryConfigProvider_UpdateConfig(t *testing.T) { }) m.EXPECT().FetchTelemetryConfig(mock.Anything).Return(mockCfg, nil) }, - expected: testDynamicCfg(&testConfig{ + expected: &testConfig{ endpoint: "http://newendpoint/v1/metrics", filters: "consul", labels: map[string]string{ "new_label": "1234", }, refreshInterval: 2 * time.Second, - }), - expectedInterval: 2 * time.Second, - metricKey: testMetricKeySuccess, - }, - "newConfigMetricsDisabled": { - initCfg: testDynamicCfg(&testConfig{ - endpoint: "http://test.com/v1/metrics", - filters: "test", - labels: map[string]string{ - "test_label": "123", - }, - refreshInterval: 2 * time.Second, - }), - mockExpect: func(m *client.MockClient) { - mockCfg, _ := testTelemetryCfg(&testConfig{ - endpoint: "", - filters: "consul", - labels: map[string]string{ - "new_label": "1234", - }, - refreshInterval: 2 * time.Second, - disabled: true, - }) - m.EXPECT().FetchTelemetryConfig(mock.Anything).Return(mockCfg, nil) }, - expected: testDynamicCfg(&testConfig{ - endpoint: "", - filters: "consul", - labels: map[string]string{ - "new_label": "1234", - }, - refreshInterval: 2 * time.Second, - disabled: true, - }), - metricKey: testMetricKeySuccess, - expectedInterval: 2 * time.Second, + metricKey: testMetricKeySuccess, }, "sameConfigInvalidRefreshInterval": { - initCfg: testDynamicCfg(&testConfig{ + optsInputs: &testConfig{ endpoint: "http://test.com/v1/metrics", filters: "test", labels: map[string]string{ "test_label": "123", }, refreshInterval: testRefreshInterval, - }), + }, mockExpect: func(m *client.MockClient) { mockCfg, _ := testTelemetryCfg(&testConfig{ refreshInterval: 0 * time.Second, }) m.EXPECT().FetchTelemetryConfig(mock.Anything).Return(mockCfg, nil) }, - expected: testDynamicCfg(&testConfig{ + expected: &testConfig{ endpoint: "http://test.com/v1/metrics", labels: map[string]string{ "test_label": "123", }, filters: "test", refreshInterval: testRefreshInterval, - }), - metricKey: testMetricKeyFailure, - expectedInterval: 0, + }, + metricKey: testMetricKeyFailure, }, "sameConfigHCPClientFailure": { - initCfg: testDynamicCfg(&testConfig{ + optsInputs: &testConfig{ endpoint: "http://test.com/v1/metrics", filters: "test", labels: map[string]string{ "test_label": "123", }, refreshInterval: testRefreshInterval, - }), + }, mockExpect: func(m *client.MockClient) { m.EXPECT().FetchTelemetryConfig(mock.Anything).Return(nil, fmt.Errorf("failure")) }, - expected: testDynamicCfg(&testConfig{ - endpoint: "http://test.com/v1/metrics", - filters: "test", - labels: map[string]string{ - "test_label": "123", - }, - refreshInterval: testRefreshInterval, - }), - metricKey: testMetricKeyFailure, - expectedInterval: 0, - }, - "disableMetrics404": { - initCfg: testDynamicCfg(&testConfig{ + expected: &testConfig{ endpoint: "http://test.com/v1/metrics", filters: "test", labels: map[string]string{ "test_label": "123", }, refreshInterval: testRefreshInterval, - }), - mockExpect: func(m *client.MockClient) { - err := runtime.NewAPIError("404 failure", nil, 404) - m.EXPECT().FetchTelemetryConfig(mock.Anything).Return(nil, err) }, - expected: defaultDisabledCfg(), - metricKey: testMetricKeySuccess, - expectedInterval: defaultTelemetryConfigRefreshInterval, + metricKey: testMetricKeyFailure, }, } { - tc := tc t.Run(name, func(t *testing.T) { sink := initGlobalSink() mockClient := client.NewMockClient(t) tc.mockExpect(mockClient) + dynamicCfg, err := testDynamicCfg(tc.optsInputs) + require.NoError(t, err) + provider := &hcpProviderImpl{ hcpClient: mockClient, - cfg: tc.initCfg, + cfg: dynamicCfg, } - newInterval := provider.updateConfig(context.Background()) - require.Equal(t, tc.expectedInterval, newInterval) + provider.getUpdate(context.Background()) // Verify endpoint provider returns correct config values. - require.Equal(t, tc.expected.endpoint, provider.GetEndpoint()) - require.Equal(t, tc.expected.filters, provider.GetFilters()) + require.Equal(t, tc.expected.endpoint, provider.GetEndpoint().String()) + require.Equal(t, tc.expected.filters, provider.GetFilters().String()) require.Equal(t, tc.expected.labels, provider.GetLabels()) - require.Equal(t, tc.expected.disabled, provider.IsDisabled()) // Verify count for transform success metric. interval := sink.Data()[0] @@ -333,7 +289,8 @@ func TestTelemetryConfigProvider_Race(t *testing.T) { } // Start the provider goroutine, which fetches client TelemetryConfig every RefreshInterval. - provider := NewHCPProvider(ctx, m) + provider, err := NewHCPProvider(ctx, m, m.cfg) + require.NoError(t, err) for count := 0; count < testRaceWriteSampleCount; count++ { // Force a TelemetryConfig value change in the mockRaceClient. @@ -341,7 +298,7 @@ func TestTelemetryConfigProvider_Race(t *testing.T) { require.NoError(t, err) // Force provider to obtain new client TelemetryConfig immediately. // This call is necessary to guarantee TelemetryConfig changes to assert on expected values below. - provider.updateConfig(context.Background()) + provider.getUpdate(context.Background()) // Start goroutines to access label configuration. wg := &sync.WaitGroup{} @@ -385,20 +342,22 @@ func initGlobalSink() *metrics.InmemSink { } // testDynamicCfg converts testConfig inputs to a dynamicConfig to be used in tests. -func testDynamicCfg(testCfg *testConfig) *dynamicConfig { - filters, _ := regexp.Compile(testCfg.filters) +func testDynamicCfg(testCfg *testConfig) (*dynamicConfig, error) { + filters, err := regexp.Compile(testCfg.filters) + if err != nil { + return nil, err + } - var endpoint *url.URL - if testCfg.endpoint != "" { - endpoint, _ = url.Parse(testCfg.endpoint) + endpoint, err := url.Parse(testCfg.endpoint) + if err != nil { + return nil, err } return &dynamicConfig{ - endpoint: endpoint, - filters: filters, - labels: testCfg.labels, - refreshInterval: testCfg.refreshInterval, - disabled: testCfg.disabled, - } + Endpoint: endpoint, + Filters: filters, + Labels: testCfg.labels, + RefreshInterval: testCfg.refreshInterval, + }, nil } // testTelemetryCfg converts testConfig inputs to a TelemetryConfig to be used in tests. @@ -408,21 +367,15 @@ func testTelemetryCfg(testCfg *testConfig) (*client.TelemetryConfig, error) { return nil, err } - var endpoint *url.URL - if testCfg.endpoint != "" { - u, err := url.Parse(testCfg.endpoint) - if err != nil { - return nil, err - } - endpoint = u + endpoint, err := url.Parse(testCfg.endpoint) + if err != nil { + return nil, err } - return &client.TelemetryConfig{ MetricsConfig: &client.MetricsConfig{ Endpoint: endpoint, Filters: filters, Labels: testCfg.labels, - Disabled: testCfg.disabled, }, RefreshConfig: &client.RefreshConfig{ RefreshInterval: testCfg.refreshInterval, diff --git a/agent/hcp/testing.go b/agent/hcp/testing.go index 30f7ba7bcdeb3..94f3122c33d2d 100644 --- a/agent/hcp/testing.go +++ b/agent/hcp/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package hcp diff --git a/agent/hcp/testserver/main.go b/agent/hcp/testserver/main.go index e0db7670ef99f..ffdd4cac51afa 100644 --- a/agent/hcp/testserver/main.go +++ b/agent/hcp/testserver/main.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package main diff --git a/agent/health_endpoint.go b/agent/health_endpoint.go index 3b888988d2730..ea3d315f6b8b5 100644 --- a/agent/health_endpoint.go +++ b/agent/health_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/health_endpoint_test.go b/agent/health_endpoint_test.go index 021a269b8a093..3a589be0d78bd 100644 --- a/agent/health_endpoint_test.go +++ b/agent/health_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/http.go b/agent/http.go index 982e784c76b7c..32010c343a6c5 100644 --- a/agent/http.go +++ b/agent/http.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent @@ -36,7 +36,6 @@ import ( "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/uiserver" "github.com/hashicorp/consul/api" - resourcehttp "github.com/hashicorp/consul/internal/resource/http" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/proto/private/pbcommon" @@ -260,17 +259,6 @@ func (s *HTTPHandlers) handler() http.Handler { handlePProf("/debug/pprof/symbol", pprof.Symbol) handlePProf("/debug/pprof/trace", pprof.Trace) - mux.Handle("/api/", - http.StripPrefix("/api", - resourcehttp.NewHandler( - s.agent.delegate.ResourceServiceClient(), - s.agent.baseDeps.Registry, - s.parseToken, - s.agent.logger.Named(logging.HTTP), - ), - ), - ) - if s.IsUIEnabled() { // Note that we _don't_ support reloading ui_config.{enabled, content_dir, // content_path} since this only runs at initial startup. @@ -616,9 +604,7 @@ func (s *HTTPHandlers) marshalJSON(req *http.Request, obj interface{}) ([]byte, if err != nil { return nil, err } - if ok { - buf = append(buf, "\n"...) - } + buf = append(buf, "\n"...) return buf, nil } diff --git a/agent/http_ce.go b/agent/http_ce.go index 09a03c706246e..d9c233226c491 100644 --- a/agent/http_ce.go +++ b/agent/http_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/http_ce_test.go b/agent/http_ce_test.go index ea1d2af61d7a4..bf085ca8c29c7 100644 --- a/agent/http_ce_test.go +++ b/agent/http_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/http_decode_test.go b/agent/http_decode_test.go index 6aece784c0b2d..03d1b9191fa74 100644 --- a/agent/http_decode_test.go +++ b/agent/http_decode_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/http_register.go b/agent/http_register.go index bc2551ec000d0..b3f0dfea3f3a6 100644 --- a/agent/http_register.go +++ b/agent/http_register.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/http_test.go b/agent/http_test.go index 83510d9c06e08..99100c5fbc8e8 100644 --- a/agent/http_test.go +++ b/agent/http_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/intentions_endpoint.go b/agent/intentions_endpoint.go index 4f0b188a0cc43..2353c5bdac2ee 100644 --- a/agent/intentions_endpoint.go +++ b/agent/intentions_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/intentions_endpoint_ce_test.go b/agent/intentions_endpoint_ce_test.go index 6b5314de099fa..fb6a47f5e53d4 100644 --- a/agent/intentions_endpoint_ce_test.go +++ b/agent/intentions_endpoint_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/intentions_endpoint_test.go b/agent/intentions_endpoint_test.go index b1309feb9d2cd..161b8b5139d54 100644 --- a/agent/intentions_endpoint_test.go +++ b/agent/intentions_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/keyring.go b/agent/keyring.go index f30680774b340..3d96880f03aaa 100644 --- a/agent/keyring.go +++ b/agent/keyring.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/keyring_test.go b/agent/keyring_test.go index 1a9332a8a7393..7ce5d2cd4b93b 100644 --- a/agent/keyring_test.go +++ b/agent/keyring_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/kvs_endpoint.go b/agent/kvs_endpoint.go index e60567cd5b807..d5ad8cabc3de8 100644 --- a/agent/kvs_endpoint.go +++ b/agent/kvs_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/kvs_endpoint_test.go b/agent/kvs_endpoint_test.go index 2b3563000815b..6ea5efced20d2 100644 --- a/agent/kvs_endpoint_test.go +++ b/agent/kvs_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/leafcert/cached_roots.go b/agent/leafcert/cached_roots.go index aaf768a2fb8e0..b973b6dc660ca 100644 --- a/agent/leafcert/cached_roots.go +++ b/agent/leafcert/cached_roots.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package leafcert import ( diff --git a/agent/leafcert/cert.go b/agent/leafcert/cert.go index b6236a4a14ac1..0230685737756 100644 --- a/agent/leafcert/cert.go +++ b/agent/leafcert/cert.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package leafcert import ( diff --git a/agent/leafcert/generate.go b/agent/leafcert/generate.go index 9551e760b1fc2..0e397cdc2d52f 100644 --- a/agent/leafcert/generate.go +++ b/agent/leafcert/generate.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package leafcert import ( diff --git a/agent/leafcert/leafcert.go b/agent/leafcert/leafcert.go index 5b1cd6b9be3bd..9cd0c08db13d0 100644 --- a/agent/leafcert/leafcert.go +++ b/agent/leafcert/leafcert.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package leafcert import ( diff --git a/agent/leafcert/leafcert_test.go b/agent/leafcert/leafcert_test.go index 0b523523e4736..0db683a816e1a 100644 --- a/agent/leafcert/leafcert_test.go +++ b/agent/leafcert/leafcert_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package leafcert import ( diff --git a/agent/leafcert/roots.go b/agent/leafcert/roots.go index 161b0d0a041c2..7f95e0578dccb 100644 --- a/agent/leafcert/roots.go +++ b/agent/leafcert/roots.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package leafcert import ( diff --git a/agent/leafcert/signer_netrpc.go b/agent/leafcert/signer_netrpc.go index 0e1a7a7487f88..2d6b490a9ea8c 100644 --- a/agent/leafcert/signer_netrpc.go +++ b/agent/leafcert/signer_netrpc.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package leafcert import ( diff --git a/agent/leafcert/signer_test.go b/agent/leafcert/signer_test.go index ad385f8c72a1c..21e3388f5a1c4 100644 --- a/agent/leafcert/signer_test.go +++ b/agent/leafcert/signer_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package leafcert import ( diff --git a/agent/leafcert/structs.go b/agent/leafcert/structs.go index 7ad11a0869a52..531d35c897e68 100644 --- a/agent/leafcert/structs.go +++ b/agent/leafcert/structs.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package leafcert import ( diff --git a/agent/leafcert/structs_test.go b/agent/leafcert/structs_test.go index 6a8e034700313..bb131f10ed7c6 100644 --- a/agent/leafcert/structs_test.go +++ b/agent/leafcert/structs_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package leafcert import ( diff --git a/agent/leafcert/util.go b/agent/leafcert/util.go index 795aa62ac11c8..a7453df37b4f9 100644 --- a/agent/leafcert/util.go +++ b/agent/leafcert/util.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package leafcert import ( diff --git a/agent/leafcert/util_test.go b/agent/leafcert/util_test.go index 0716a9af88f24..be89ad5936c19 100644 --- a/agent/leafcert/util_test.go +++ b/agent/leafcert/util_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package leafcert import ( diff --git a/agent/leafcert/watch.go b/agent/leafcert/watch.go index fe745f916d14b..62a7260c42875 100644 --- a/agent/leafcert/watch.go +++ b/agent/leafcert/watch.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package leafcert import ( diff --git a/agent/local/state.go b/agent/local/state.go index 67e72aece0b4d..6cd5b0c82a584 100644 --- a/agent/local/state.go +++ b/agent/local/state.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package local diff --git a/agent/local/state_internal_test.go b/agent/local/state_internal_test.go index 61fc2c0273a80..ba68e20f287a6 100644 --- a/agent/local/state_internal_test.go +++ b/agent/local/state_internal_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package local diff --git a/agent/local/state_test.go b/agent/local/state_test.go index ced73201e72bd..4751352ec1c8f 100644 --- a/agent/local/state_test.go +++ b/agent/local/state_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package local_test diff --git a/agent/local/testing.go b/agent/local/testing.go index 5e9ae15ac3763..5303cb6b0c4ac 100644 --- a/agent/local/testing.go +++ b/agent/local/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package local diff --git a/agent/log-drop/log-drop.go b/agent/log-drop/log-drop.go index ea08f88d890b0..54bc09c5a8c3b 100644 --- a/agent/log-drop/log-drop.go +++ b/agent/log-drop/log-drop.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logdrop diff --git a/agent/log-drop/log-drop_test.go b/agent/log-drop/log-drop_test.go index c050a734be4a8..fdb61a059e525 100644 --- a/agent/log-drop/log-drop_test.go +++ b/agent/log-drop/log-drop_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logdrop diff --git a/agent/metadata/build.go b/agent/metadata/build.go index 76a432d9a380b..b50fa96acc7af 100644 --- a/agent/metadata/build.go +++ b/agent/metadata/build.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package metadata diff --git a/agent/metadata/build_test.go b/agent/metadata/build_test.go index 888b9b0210c4b..4688db2e1850f 100644 --- a/agent/metadata/build_test.go +++ b/agent/metadata/build_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package metadata diff --git a/agent/metadata/server.go b/agent/metadata/server.go index 2e626787bdff7..64c9936909892 100644 --- a/agent/metadata/server.go +++ b/agent/metadata/server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package metadata diff --git a/agent/metadata/server_internal_test.go b/agent/metadata/server_internal_test.go index bb0561ab2d193..5f3d47724ee91 100644 --- a/agent/metadata/server_internal_test.go +++ b/agent/metadata/server_internal_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package metadata diff --git a/agent/metadata/server_test.go b/agent/metadata/server_test.go index 78b16f2599b2f..8ee63fa3b413f 100644 --- a/agent/metadata/server_test.go +++ b/agent/metadata/server_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package metadata_test diff --git a/agent/metrics.go b/agent/metrics.go index 58f9e3c829e10..d9294eb25cb95 100644 --- a/agent/metrics.go +++ b/agent/metrics.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/metrics/testing.go b/agent/metrics/testing.go index 3663d6834c16d..0fc3455ab5e70 100644 --- a/agent/metrics/testing.go +++ b/agent/metrics/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package metrics diff --git a/agent/metrics_test.go b/agent/metrics_test.go index 41013b3c7069a..76da0e55f292f 100644 --- a/agent/metrics_test.go +++ b/agent/metrics_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/mock/notify.go b/agent/mock/notify.go index 00dc9a3864a7b..1aa700b31d2d3 100644 --- a/agent/mock/notify.go +++ b/agent/mock/notify.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package mock diff --git a/agent/nodeid.go b/agent/nodeid.go index c2192fac9123c..1e5823aef7c6c 100644 --- a/agent/nodeid.go +++ b/agent/nodeid.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/nodeid_test.go b/agent/nodeid_test.go index 73ce601249db3..d48889bf6d8df 100644 --- a/agent/nodeid_test.go +++ b/agent/nodeid_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/notify.go b/agent/notify.go index 80a150b19413a..eec501f098ada 100644 --- a/agent/notify.go +++ b/agent/notify.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/notify_test.go b/agent/notify_test.go index f256ee319ce7d..fe08800ae2ec8 100644 --- a/agent/notify_test.go +++ b/agent/notify_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/operator_endpoint.go b/agent/operator_endpoint.go index f669c13bd5caa..099f3dcfe4b08 100644 --- a/agent/operator_endpoint.go +++ b/agent/operator_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/operator_endpoint_ce.go b/agent/operator_endpoint_ce.go index d97e6422616fe..cf2ba2a2027d9 100644 --- a/agent/operator_endpoint_ce.go +++ b/agent/operator_endpoint_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/operator_endpoint_ce_test.go b/agent/operator_endpoint_ce_test.go index 0086a56065ca3..f4de46f9050c9 100644 --- a/agent/operator_endpoint_ce_test.go +++ b/agent/operator_endpoint_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/operator_endpoint_test.go b/agent/operator_endpoint_test.go index ffe5c1a53abe6..4d90dbb2249ef 100644 --- a/agent/operator_endpoint_test.go +++ b/agent/operator_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/peering_endpoint.go b/agent/peering_endpoint.go index 2d5cab92be2e7..a1fbd009acc60 100644 --- a/agent/peering_endpoint.go +++ b/agent/peering_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/peering_endpoint_ce_test.go b/agent/peering_endpoint_ce_test.go index f435ca3310522..b0395ea968398 100644 --- a/agent/peering_endpoint_ce_test.go +++ b/agent/peering_endpoint_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/peering_endpoint_test.go b/agent/peering_endpoint_test.go index ba3b704b8b5ad..7ec63c1cd73eb 100644 --- a/agent/peering_endpoint_test.go +++ b/agent/peering_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/pool/conn.go b/agent/pool/conn.go index 24d4c2cba4dc9..45a2c09486177 100644 --- a/agent/pool/conn.go +++ b/agent/pool/conn.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pool diff --git a/agent/pool/peek.go b/agent/pool/peek.go index b631134341d9a..d6557bb23db8c 100644 --- a/agent/pool/peek.go +++ b/agent/pool/peek.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pool diff --git a/agent/pool/peek_test.go b/agent/pool/peek_test.go index 29fbe9d4ab72e..cb53c421f9c2e 100644 --- a/agent/pool/peek_test.go +++ b/agent/pool/peek_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pool diff --git a/agent/pool/pool.go b/agent/pool/pool.go index 899cefe2e9740..cadb0e4af4ec6 100644 --- a/agent/pool/pool.go +++ b/agent/pool/pool.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pool diff --git a/agent/prepared_query_endpoint.go b/agent/prepared_query_endpoint.go index 15ab1005e48b5..8d5f9fdc5313f 100644 --- a/agent/prepared_query_endpoint.go +++ b/agent/prepared_query_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/prepared_query_endpoint_test.go b/agent/prepared_query_endpoint_test.go index 07e4b8e68c70e..f96c43ad8b904 100644 --- a/agent/prepared_query_endpoint_test.go +++ b/agent/prepared_query_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/proxycfg-glue/config_entry.go b/agent/proxycfg-glue/config_entry.go index 3a79e228277d7..cd86d91e1e91f 100644 --- a/agent/proxycfg-glue/config_entry.go +++ b/agent/proxycfg-glue/config_entry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/discovery_chain.go b/agent/proxycfg-glue/discovery_chain.go index 518467492d7cc..3b322e6b334f9 100644 --- a/agent/proxycfg-glue/discovery_chain.go +++ b/agent/proxycfg-glue/discovery_chain.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/discovery_chain_test.go b/agent/proxycfg-glue/discovery_chain_test.go index e4156667d36b7..60d48537c684b 100644 --- a/agent/proxycfg-glue/discovery_chain_test.go +++ b/agent/proxycfg-glue/discovery_chain_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/exported_peered_services.go b/agent/proxycfg-glue/exported_peered_services.go index 1b92600451710..8637891f1556b 100644 --- a/agent/proxycfg-glue/exported_peered_services.go +++ b/agent/proxycfg-glue/exported_peered_services.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/exported_peered_services_test.go b/agent/proxycfg-glue/exported_peered_services_test.go index 91b42323fab8a..a2b99d4d25b5f 100644 --- a/agent/proxycfg-glue/exported_peered_services_test.go +++ b/agent/proxycfg-glue/exported_peered_services_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/federation_state_list_mesh_gateways.go b/agent/proxycfg-glue/federation_state_list_mesh_gateways.go index c34303552c0a2..f5f32f1c01cba 100644 --- a/agent/proxycfg-glue/federation_state_list_mesh_gateways.go +++ b/agent/proxycfg-glue/federation_state_list_mesh_gateways.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/federation_state_list_mesh_gateways_test.go b/agent/proxycfg-glue/federation_state_list_mesh_gateways_test.go index baf477f4340b2..fd73e19aaf698 100644 --- a/agent/proxycfg-glue/federation_state_list_mesh_gateways_test.go +++ b/agent/proxycfg-glue/federation_state_list_mesh_gateways_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/gateway_services.go b/agent/proxycfg-glue/gateway_services.go index 555b1d5385359..24f4087eea817 100644 --- a/agent/proxycfg-glue/gateway_services.go +++ b/agent/proxycfg-glue/gateway_services.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/gateway_services_test.go b/agent/proxycfg-glue/gateway_services_test.go index ff89a62c92e45..eb853bd7b49e9 100644 --- a/agent/proxycfg-glue/gateway_services_test.go +++ b/agent/proxycfg-glue/gateway_services_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/glue.go b/agent/proxycfg-glue/glue.go index 8f23bf458ea77..817e151b9500b 100644 --- a/agent/proxycfg-glue/glue.go +++ b/agent/proxycfg-glue/glue.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue @@ -52,6 +52,9 @@ type Store interface { PeeringTrustBundleList(ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.PeeringTrustBundle, error) TrustBundleListByService(ws memdb.WatchSet, service, dc string, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.PeeringTrustBundle, error) VirtualIPsForAllImportedServices(ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (uint64, []state.ServiceVirtualIP, error) + CheckConnectServiceNodes(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) + CheckIngressServiceNodes(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta) (uint64, structs.CheckServiceNodes, error) + CheckServiceNodes(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) } // CacheCARoots satisfies the proxycfg.CARoots interface by sourcing data from diff --git a/agent/proxycfg-glue/health.go b/agent/proxycfg-glue/health.go index 6acf5b7023026..f0808da978ce9 100644 --- a/agent/proxycfg-glue/health.go +++ b/agent/proxycfg-glue/health.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/health_blocking.go b/agent/proxycfg-glue/health_blocking.go index 181605298aa8a..3504e050aa707 100644 --- a/agent/proxycfg-glue/health_blocking.go +++ b/agent/proxycfg-glue/health_blocking.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue @@ -12,7 +12,6 @@ import ( "github.com/hashicorp/go-memdb" "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/watch" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" @@ -39,14 +38,13 @@ import ( // because proxycfg has a `req.Source.Node != ""` which prevents the `streamingEnabled` check from passing. // This means that while agents should technically have this same issue, they don't experience it with mesh health // watches. -func ServerHealthBlocking(deps ServerDataSourceDeps, remoteSource proxycfg.Health, state *state.Store) *serverHealthBlocking { - return &serverHealthBlocking{deps, remoteSource, state, 5 * time.Minute} +func ServerHealthBlocking(deps ServerDataSourceDeps, remoteSource proxycfg.Health) *serverHealthBlocking { + return &serverHealthBlocking{deps, remoteSource, 5 * time.Minute} } type serverHealthBlocking struct { deps ServerDataSourceDeps remoteSource proxycfg.Health - state *state.Store watchTimeout time.Duration } @@ -66,7 +64,7 @@ func (h *serverHealthBlocking) Notify(ctx context.Context, args *structs.Service } // Determine the function we'll call - var f func(memdb.WatchSet, *state.Store, *structs.ServiceSpecificRequest) (uint64, structs.CheckServiceNodes, error) + var f func(memdb.WatchSet, Store, *structs.ServiceSpecificRequest) (uint64, structs.CheckServiceNodes, error) switch { case args.Connect: f = serviceNodesConnect @@ -108,6 +106,12 @@ func (h *serverHealthBlocking) Notify(ctx context.Context, args *structs.Service // their data, rather than holding onto the last-known list of healthy nodes indefinitely. if hadResults { hadResults = false + h.deps.Logger.Debug("serverHealthBlocking emitting zero check-service-nodes due to insufficient ACL privileges", + "serviceName", structs.NewServiceName(args.ServiceName, &args.EnterpriseMeta), + "correlationID", correlationID, + "connect", args.Connect, + "ingress", args.Ingress, + ) return 0, &structs.IndexedCheckServiceNodes{}, watch.ErrorACLResetData } return 0, nil, acl.ErrPermissionDenied @@ -115,7 +119,7 @@ func (h *serverHealthBlocking) Notify(ctx context.Context, args *structs.Service } var thisReply structs.IndexedCheckServiceNodes - thisReply.Index, thisReply.Nodes, err = f(ws, h.state, args) + thisReply.Index, thisReply.Nodes, err = f(ws, store, args) if err != nil { return 0, nil, err } @@ -134,6 +138,13 @@ func (h *serverHealthBlocking) Notify(ctx context.Context, args *structs.Service } hadResults = true + h.deps.Logger.Trace("serverHealthBlocking emitting check-service-nodes", + "serviceName", structs.NewServiceName(args.ServiceName, &args.EnterpriseMeta), + "correlationID", correlationID, + "connect", args.Connect, + "ingress", args.Ingress, + "nodes", len(thisReply.Nodes), + ) return thisReply.Index, &thisReply, nil }, dispatchBlockingQueryUpdate[*structs.IndexedCheckServiceNodes](ch), @@ -151,14 +162,14 @@ func (h *serverHealthBlocking) filterACL(authz *acl.AuthorizerContext, token str return nil } -func serviceNodesConnect(ws memdb.WatchSet, s *state.Store, args *structs.ServiceSpecificRequest) (uint64, structs.CheckServiceNodes, error) { +func serviceNodesConnect(ws memdb.WatchSet, s Store, args *structs.ServiceSpecificRequest) (uint64, structs.CheckServiceNodes, error) { return s.CheckConnectServiceNodes(ws, args.ServiceName, &args.EnterpriseMeta, args.PeerName) } -func serviceNodesIngress(ws memdb.WatchSet, s *state.Store, args *structs.ServiceSpecificRequest) (uint64, structs.CheckServiceNodes, error) { +func serviceNodesIngress(ws memdb.WatchSet, s Store, args *structs.ServiceSpecificRequest) (uint64, structs.CheckServiceNodes, error) { return s.CheckIngressServiceNodes(ws, args.ServiceName, &args.EnterpriseMeta) } -func serviceNodesDefault(ws memdb.WatchSet, s *state.Store, args *structs.ServiceSpecificRequest) (uint64, structs.CheckServiceNodes, error) { +func serviceNodesDefault(ws memdb.WatchSet, s Store, args *structs.ServiceSpecificRequest) (uint64, structs.CheckServiceNodes, error) { return s.CheckServiceNodes(ws, args.ServiceName, &args.EnterpriseMeta, args.PeerName) } diff --git a/agent/proxycfg-glue/health_blocking_test.go b/agent/proxycfg-glue/health_blocking_test.go index c64381b7fd7fc..461cd726bc5e1 100644 --- a/agent/proxycfg-glue/health_blocking_test.go +++ b/agent/proxycfg-glue/health_blocking_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package proxycfgglue import ( @@ -30,8 +27,7 @@ func TestServerHealthBlocking(t *testing.T) { remoteSource := newMockHealth(t) remoteSource.On("Notify", ctx, req, correlationID, ch).Return(result) - store := state.NewStateStore(nil) - dataSource := ServerHealthBlocking(ServerDataSourceDeps{Datacenter: "dc1"}, remoteSource, store) + dataSource := ServerHealthBlocking(ServerDataSourceDeps{Datacenter: "dc1"}, remoteSource) err := dataSource.Notify(ctx, req, correlationID, ch) require.Equal(t, result, err) }) @@ -52,7 +48,7 @@ func TestServerHealthBlocking(t *testing.T) { Datacenter: datacenter, ACLResolver: aclResolver, Logger: testutil.Logger(t), - }, nil, store) + }, nil) dataSource.watchTimeout = 1 * time.Second // Watch for all events diff --git a/agent/proxycfg-glue/health_test.go b/agent/proxycfg-glue/health_test.go index 821e22a789085..6f5702ca19c87 100644 --- a/agent/proxycfg-glue/health_test.go +++ b/agent/proxycfg-glue/health_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/helpers_test.go b/agent/proxycfg-glue/helpers_test.go index 3c7eb5b7ad153..0d8bd8c9660d0 100644 --- a/agent/proxycfg-glue/helpers_test.go +++ b/agent/proxycfg-glue/helpers_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/intention_upstreams.go b/agent/proxycfg-glue/intention_upstreams.go index dc6731372271f..07a12c4ddb6c3 100644 --- a/agent/proxycfg-glue/intention_upstreams.go +++ b/agent/proxycfg-glue/intention_upstreams.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/intention_upstreams_test.go b/agent/proxycfg-glue/intention_upstreams_test.go index bfaeb55b38646..3028524eb0f29 100644 --- a/agent/proxycfg-glue/intention_upstreams_test.go +++ b/agent/proxycfg-glue/intention_upstreams_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/intentions.go b/agent/proxycfg-glue/intentions.go index f3186c6689ab9..5176054325962 100644 --- a/agent/proxycfg-glue/intentions.go +++ b/agent/proxycfg-glue/intentions.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/intentions_ce.go b/agent/proxycfg-glue/intentions_ce.go index d4bdef266e099..bd1823adb192d 100644 --- a/agent/proxycfg-glue/intentions_ce.go +++ b/agent/proxycfg-glue/intentions_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/proxycfg-glue/intentions_test.go b/agent/proxycfg-glue/intentions_test.go index 0e1ab10918865..07d3a8067e34b 100644 --- a/agent/proxycfg-glue/intentions_test.go +++ b/agent/proxycfg-glue/intentions_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/internal_service_dump.go b/agent/proxycfg-glue/internal_service_dump.go index d1c701083d520..e41dc020b1d04 100644 --- a/agent/proxycfg-glue/internal_service_dump.go +++ b/agent/proxycfg-glue/internal_service_dump.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/internal_service_dump_test.go b/agent/proxycfg-glue/internal_service_dump_test.go index 1eba4c043828c..a6e6c3b028607 100644 --- a/agent/proxycfg-glue/internal_service_dump_test.go +++ b/agent/proxycfg-glue/internal_service_dump_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/leafcerts.go b/agent/proxycfg-glue/leafcerts.go index b805586a154a3..24631ffc31134 100644 --- a/agent/proxycfg-glue/leafcerts.go +++ b/agent/proxycfg-glue/leafcerts.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/peered_upstreams.go b/agent/proxycfg-glue/peered_upstreams.go index f345c26df572e..df38b3f0daf4d 100644 --- a/agent/proxycfg-glue/peered_upstreams.go +++ b/agent/proxycfg-glue/peered_upstreams.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/peered_upstreams_test.go b/agent/proxycfg-glue/peered_upstreams_test.go index 026fd67a3455f..b0e7c0d8f83c4 100644 --- a/agent/proxycfg-glue/peered_upstreams_test.go +++ b/agent/proxycfg-glue/peered_upstreams_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/peering_list.go b/agent/proxycfg-glue/peering_list.go index 6e7a78c707f15..219bf9b955298 100644 --- a/agent/proxycfg-glue/peering_list.go +++ b/agent/proxycfg-glue/peering_list.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/peering_list_test.go b/agent/proxycfg-glue/peering_list_test.go index 575d161b4e5d3..f570dbbcc2a86 100644 --- a/agent/proxycfg-glue/peering_list_test.go +++ b/agent/proxycfg-glue/peering_list_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/resolved_service_config.go b/agent/proxycfg-glue/resolved_service_config.go index 11654cd767b2e..89611bbc07114 100644 --- a/agent/proxycfg-glue/resolved_service_config.go +++ b/agent/proxycfg-glue/resolved_service_config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/resolved_service_config_test.go b/agent/proxycfg-glue/resolved_service_config_test.go index 248ab4eab363f..60d39eec205f0 100644 --- a/agent/proxycfg-glue/resolved_service_config_test.go +++ b/agent/proxycfg-glue/resolved_service_config_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/service_http_checks.go b/agent/proxycfg-glue/service_http_checks.go index 2d0a9dfcff51f..45521f712ae8b 100644 --- a/agent/proxycfg-glue/service_http_checks.go +++ b/agent/proxycfg-glue/service_http_checks.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/service_http_checks_test.go b/agent/proxycfg-glue/service_http_checks_test.go index 87bdfc7abe609..cfe28c7e89f9f 100644 --- a/agent/proxycfg-glue/service_http_checks_test.go +++ b/agent/proxycfg-glue/service_http_checks_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/service_list.go b/agent/proxycfg-glue/service_list.go index f4a9380df715a..418103aef6fed 100644 --- a/agent/proxycfg-glue/service_list.go +++ b/agent/proxycfg-glue/service_list.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/service_list_test.go b/agent/proxycfg-glue/service_list_test.go index c6372aaf4ea1d..154c1300a3275 100644 --- a/agent/proxycfg-glue/service_list_test.go +++ b/agent/proxycfg-glue/service_list_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/trust_bundle.go b/agent/proxycfg-glue/trust_bundle.go index f623d2a5555c9..108e7ea9f9aec 100644 --- a/agent/proxycfg-glue/trust_bundle.go +++ b/agent/proxycfg-glue/trust_bundle.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-glue/trust_bundle_test.go b/agent/proxycfg-glue/trust_bundle_test.go index e2082e3d240be..da77e32a56e86 100644 --- a/agent/proxycfg-glue/trust_bundle_test.go +++ b/agent/proxycfg-glue/trust_bundle_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfgglue diff --git a/agent/proxycfg-sources/catalog/config_source.go b/agent/proxycfg-sources/catalog/config_source.go index 9ded9aa7fd4ed..3fbca88de5087 100644 --- a/agent/proxycfg-sources/catalog/config_source.go +++ b/agent/proxycfg-sources/catalog/config_source.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package catalog @@ -17,8 +17,6 @@ import ( "github.com/hashicorp/consul/agent/local" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - "github.com/hashicorp/consul/proto-public/pbresource" ) const source proxycfg.ProxySource = "catalog" @@ -50,13 +48,11 @@ func NewConfigSource(cfg Config) *ConfigSource { // Watch wraps the underlying proxycfg.Manager and dynamically registers // services from the catalog with it when requested by the xDS server. -func (m *ConfigSource) Watch(id *pbresource.ID, nodeName string, token string) (<-chan proxysnapshot.ProxySnapshot, limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) { - // Create service ID - serviceID := structs.NewServiceID(id.Name, GetEnterpriseMetaFromResourceID(id)) +func (m *ConfigSource) Watch(serviceID structs.ServiceID, nodeName string, token string) (<-chan *proxycfg.ConfigSnapshot, limiter.SessionTerminatedChan, proxycfg.CancelFunc, error) { // If the service is registered to the local agent, use the LocalConfigSource // rather than trying to configure it from the catalog. if nodeName == m.NodeName && m.LocalState.ServiceExists(serviceID) { - return m.LocalConfigSource.Watch(id, nodeName, token) + return m.LocalConfigSource.Watch(serviceID, nodeName, token) } // Begin a session with the xDS session concurrency limiter. @@ -280,7 +276,7 @@ type Config struct { //go:generate mockery --name ConfigManager --inpackage type ConfigManager interface { - Watch(req proxycfg.ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc) + Watch(req proxycfg.ProxyID) (<-chan *proxycfg.ConfigSnapshot, proxycfg.CancelFunc) Register(proxyID proxycfg.ProxyID, service *structs.NodeService, source proxycfg.ProxySource, token string, overwrite bool) error Deregister(proxyID proxycfg.ProxyID, source proxycfg.ProxySource) } @@ -293,11 +289,10 @@ type Store interface { //go:generate mockery --name Watcher --inpackage type Watcher interface { - Watch(proxyID *pbresource.ID, nodeName string, token string) (<-chan proxysnapshot.ProxySnapshot, limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) + Watch(proxyID structs.ServiceID, nodeName string, token string) (<-chan *proxycfg.ConfigSnapshot, limiter.SessionTerminatedChan, proxycfg.CancelFunc, error) } //go:generate mockery --name SessionLimiter --inpackage type SessionLimiter interface { BeginSession() (limiter.Session, error) - Run(ctx context.Context) } diff --git a/agent/proxycfg-sources/catalog/config_source_oss.go b/agent/proxycfg-sources/catalog/config_source_oss.go deleted file mode 100644 index 21ddede8821bb..0000000000000 --- a/agent/proxycfg-sources/catalog/config_source_oss.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !consulent -// +build !consulent - -package catalog - -import ( - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func GetEnterpriseMetaFromResourceID(id *pbresource.ID) *acl.EnterpriseMeta { - return acl.DefaultEnterpriseMeta() -} diff --git a/agent/proxycfg-sources/catalog/config_source_test.go b/agent/proxycfg-sources/catalog/config_source_test.go index 46b69746688cb..661fae9c082b1 100644 --- a/agent/proxycfg-sources/catalog/config_source_test.go +++ b/agent/proxycfg-sources/catalog/config_source_test.go @@ -1,10 +1,9 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package catalog import ( - "context" "errors" "testing" "time" @@ -20,9 +19,6 @@ import ( "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/token" - "github.com/hashicorp/consul/internal/mesh" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" ) func TestConfigSource_Success(t *testing.T) { @@ -79,15 +75,15 @@ func TestConfigSource_Success(t *testing.T) { }) t.Cleanup(mgr.Shutdown) - snapCh, termCh, cancelWatch1, err := mgr.Watch(rtest.Resource(mesh.ProxyConfigurationType, serviceID.ID).ID(), nodeName, token) + snapCh, termCh, cancelWatch1, err := mgr.Watch(serviceID, nodeName, token) require.NoError(t, err) require.Equal(t, session1TermCh, termCh) // Expect Register to have been called with the proxy's inital port. select { case snap := <-snapCh: - require.Equal(t, 9999, snap.(*proxycfg.ConfigSnapshot).Port) - require.Equal(t, token, snap.(*proxycfg.ConfigSnapshot).ProxyID.Token) + require.Equal(t, 9999, snap.Port) + require.Equal(t, token, snap.ProxyID.Token) case <-time.After(100 * time.Millisecond): t.Fatal("timeout waiting for snapshot") } @@ -111,7 +107,7 @@ func TestConfigSource_Success(t *testing.T) { // Expect Register to have been called again with the proxy's new port. select { case snap := <-snapCh: - require.Equal(t, 8888, snap.(*proxycfg.ConfigSnapshot).Port) + require.Equal(t, 8888, snap.Port) case <-time.After(100 * time.Millisecond): t.Fatal("timeout waiting for snapshot") } @@ -130,13 +126,13 @@ func TestConfigSource_Success(t *testing.T) { require.Equal(t, map[string]any{ "local_connect_timeout_ms": 123, "max_inbound_connections": 321, - }, snap.(*proxycfg.ConfigSnapshot).Proxy.Config) + }, snap.Proxy.Config) case <-time.After(100 * time.Millisecond): t.Fatal("timeout waiting for snapshot") } // Start another watch. - _, termCh2, cancelWatch2, err := mgr.Watch(rtest.Resource(mesh.ProxyConfigurationType, serviceID.ID).ID(), nodeName, token) + _, termCh2, cancelWatch2, err := mgr.Watch(serviceID, nodeName, token) require.NoError(t, err) require.Equal(t, session2TermCh, termCh2) @@ -170,7 +166,6 @@ func TestConfigSource_Success(t *testing.T) { func TestConfigSource_LocallyManagedService(t *testing.T) { serviceID := structs.NewServiceID("web-sidecar-proxy-1", nil) - proxyID := rtest.Resource(mesh.ProxyConfigurationType, serviceID.ID).ID() nodeName := "node-1" token := "token" @@ -178,8 +173,8 @@ func TestConfigSource_LocallyManagedService(t *testing.T) { localState.AddServiceWithChecks(&structs.NodeService{ID: serviceID.ID}, nil, "", false) localWatcher := NewMockWatcher(t) - localWatcher.On("Watch", proxyID, nodeName, token). - Return(make(<-chan proxysnapshot.ProxySnapshot), nil, proxysnapshot.CancelFunc(func() {}), nil) + localWatcher.On("Watch", serviceID, nodeName, token). + Return(make(<-chan *proxycfg.ConfigSnapshot), nil, proxycfg.CancelFunc(func() {}), nil) mgr := NewConfigSource(Config{ NodeName: nodeName, @@ -191,7 +186,7 @@ func TestConfigSource_LocallyManagedService(t *testing.T) { }) t.Cleanup(mgr.Shutdown) - _, _, _, err := mgr.Watch(proxyID, nodeName, token) + _, _, _, err := mgr.Watch(serviceID, nodeName, token) require.NoError(t, err) } @@ -213,12 +208,12 @@ func TestConfigSource_ErrorRegisteringService(t *testing.T) { })) var canceledWatch bool - cancel := proxysnapshot.CancelFunc(func() { canceledWatch = true }) + cancel := proxycfg.CancelFunc(func() { canceledWatch = true }) cfgMgr := NewMockConfigManager(t) cfgMgr.On("Watch", mock.Anything). - Return(make(<-chan proxysnapshot.ProxySnapshot), cancel) + Return(make(<-chan *proxycfg.ConfigSnapshot), cancel) cfgMgr.On("Register", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). Return(errors.New("KABOOM")) @@ -238,7 +233,7 @@ func TestConfigSource_ErrorRegisteringService(t *testing.T) { }) t.Cleanup(mgr.Shutdown) - _, _, _, err := mgr.Watch(rtest.Resource(mesh.ProxyConfigurationType, serviceID.ID).ID(), nodeName, token) + _, _, _, err := mgr.Watch(serviceID, nodeName, token) require.Error(t, err) require.True(t, canceledWatch, "watch should've been canceled") @@ -263,12 +258,12 @@ func TestConfigSource_NotProxyService(t *testing.T) { })) var canceledWatch bool - cancel := proxysnapshot.CancelFunc(func() { canceledWatch = true }) + cancel := proxycfg.CancelFunc(func() { canceledWatch = true }) cfgMgr := NewMockConfigManager(t) cfgMgr.On("Watch", mock.Anything). - Return(make(<-chan proxysnapshot.ProxySnapshot), cancel) + Return(make(<-chan *proxycfg.ConfigSnapshot), cancel) mgr := NewConfigSource(Config{ Manager: cfgMgr, @@ -279,7 +274,7 @@ func TestConfigSource_NotProxyService(t *testing.T) { }) t.Cleanup(mgr.Shutdown) - _, _, _, err := mgr.Watch(rtest.Resource(mesh.ProxyConfigurationType, serviceID.ID).ID(), nodeName, token) + _, _, _, err := mgr.Watch(serviceID, nodeName, token) require.Error(t, err) require.Contains(t, err.Error(), "must be a sidecar proxy or gateway") require.True(t, canceledWatch, "watch should've been canceled") @@ -296,7 +291,7 @@ func TestConfigSource_SessionLimiterError(t *testing.T) { t.Cleanup(src.Shutdown) _, _, _, err := src.Watch( - rtest.Resource(mesh.ProxyConfigurationType, "web-sidecar-proxy-1").ID(), + structs.NewServiceID("web-sidecar-proxy-1", nil), "node-name", "token", ) @@ -314,9 +309,9 @@ func testConfigManager(t *testing.T, serviceID structs.ServiceID, nodeName strin Token: token, } - snapCh := make(chan proxysnapshot.ProxySnapshot, 1) + snapCh := make(chan *proxycfg.ConfigSnapshot, 1) cfgMgr.On("Watch", proxyID). - Return((<-chan proxysnapshot.ProxySnapshot)(snapCh), proxysnapshot.CancelFunc(func() {}), nil) + Return((<-chan *proxycfg.ConfigSnapshot)(snapCh), proxycfg.CancelFunc(func() {}), nil) cfgMgr.On("Register", mock.Anything, mock.Anything, source, token, false). Run(func(args mock.Arguments) { @@ -360,8 +355,6 @@ func (nullSessionLimiter) BeginSession() (limiter.Session, error) { return nullSession{}, nil } -func (nullSessionLimiter) Run(ctx context.Context) {} - type nullSession struct{} func (nullSession) End() {} diff --git a/agent/proxycfg-sources/catalog/mock_ConfigManager.go b/agent/proxycfg-sources/catalog/mock_ConfigManager.go index 37deffb022d8e..3ae51c5f6a95f 100644 --- a/agent/proxycfg-sources/catalog/mock_ConfigManager.go +++ b/agent/proxycfg-sources/catalog/mock_ConfigManager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.33.1. DO NOT EDIT. +// Code generated by mockery v2.15.0. DO NOT EDIT. package catalog @@ -6,8 +6,6 @@ import ( proxycfg "github.com/hashicorp/consul/agent/proxycfg" mock "github.com/stretchr/testify/mock" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - structs "github.com/hashicorp/consul/agent/structs" ) @@ -36,39 +34,37 @@ func (_m *MockConfigManager) Register(proxyID proxycfg.ProxyID, service *structs } // Watch provides a mock function with given fields: req -func (_m *MockConfigManager) Watch(req proxycfg.ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc) { +func (_m *MockConfigManager) Watch(req proxycfg.ProxyID) (<-chan *proxycfg.ConfigSnapshot, proxycfg.CancelFunc) { ret := _m.Called(req) - var r0 <-chan proxysnapshot.ProxySnapshot - var r1 proxysnapshot.CancelFunc - if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc)); ok { - return rf(req) - } - if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) <-chan proxysnapshot.ProxySnapshot); ok { + var r0 <-chan *proxycfg.ConfigSnapshot + if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) <-chan *proxycfg.ConfigSnapshot); ok { r0 = rf(req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(<-chan proxysnapshot.ProxySnapshot) + r0 = ret.Get(0).(<-chan *proxycfg.ConfigSnapshot) } } - if rf, ok := ret.Get(1).(func(proxycfg.ProxyID) proxysnapshot.CancelFunc); ok { + var r1 proxycfg.CancelFunc + if rf, ok := ret.Get(1).(func(proxycfg.ProxyID) proxycfg.CancelFunc); ok { r1 = rf(req) } else { if ret.Get(1) != nil { - r1 = ret.Get(1).(proxysnapshot.CancelFunc) + r1 = ret.Get(1).(proxycfg.CancelFunc) } } return r0, r1 } -// NewMockConfigManager creates a new instance of MockConfigManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewMockConfigManager(t interface { +type mockConstructorTestingTNewMockConfigManager interface { mock.TestingT Cleanup(func()) -}) *MockConfigManager { +} + +// NewMockConfigManager creates a new instance of MockConfigManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewMockConfigManager(t mockConstructorTestingTNewMockConfigManager) *MockConfigManager { mock := &MockConfigManager{} mock.Mock.Test(t) diff --git a/agent/proxycfg-sources/catalog/mock_SessionLimiter.go b/agent/proxycfg-sources/catalog/mock_SessionLimiter.go index 39cd430f06d3d..3b7147cb064c6 100644 --- a/agent/proxycfg-sources/catalog/mock_SessionLimiter.go +++ b/agent/proxycfg-sources/catalog/mock_SessionLimiter.go @@ -1,10 +1,8 @@ -// Code generated by mockery v2.33.1. DO NOT EDIT. +// Code generated by mockery v2.15.0. DO NOT EDIT. package catalog import ( - context "context" - limiter "github.com/hashicorp/consul/agent/grpc-external/limiter" mock "github.com/stretchr/testify/mock" ) @@ -19,10 +17,6 @@ func (_m *MockSessionLimiter) BeginSession() (limiter.Session, error) { ret := _m.Called() var r0 limiter.Session - var r1 error - if rf, ok := ret.Get(0).(func() (limiter.Session, error)); ok { - return rf() - } if rf, ok := ret.Get(0).(func() limiter.Session); ok { r0 = rf() } else { @@ -31,6 +25,7 @@ func (_m *MockSessionLimiter) BeginSession() (limiter.Session, error) { } } + var r1 error if rf, ok := ret.Get(1).(func() error); ok { r1 = rf() } else { @@ -40,17 +35,13 @@ func (_m *MockSessionLimiter) BeginSession() (limiter.Session, error) { return r0, r1 } -// Run provides a mock function with given fields: ctx -func (_m *MockSessionLimiter) Run(ctx context.Context) { - _m.Called(ctx) +type mockConstructorTestingTNewMockSessionLimiter interface { + mock.TestingT + Cleanup(func()) } // NewMockSessionLimiter creates a new instance of MockSessionLimiter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewMockSessionLimiter(t interface { - mock.TestingT - Cleanup(func()) -}) *MockSessionLimiter { +func NewMockSessionLimiter(t mockConstructorTestingTNewMockSessionLimiter) *MockSessionLimiter { mock := &MockSessionLimiter{} mock.Mock.Test(t) diff --git a/agent/proxycfg-sources/catalog/mock_Watcher.go b/agent/proxycfg-sources/catalog/mock_Watcher.go index b77be5d98ea8f..d5ca046a40602 100644 --- a/agent/proxycfg-sources/catalog/mock_Watcher.go +++ b/agent/proxycfg-sources/catalog/mock_Watcher.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.33.1. DO NOT EDIT. +// Code generated by mockery v2.15.0. DO NOT EDIT. package catalog @@ -6,9 +6,9 @@ import ( limiter "github.com/hashicorp/consul/agent/grpc-external/limiter" mock "github.com/stretchr/testify/mock" - pbresource "github.com/hashicorp/consul/proto-public/pbresource" + proxycfg "github.com/hashicorp/consul/agent/proxycfg" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" + structs "github.com/hashicorp/consul/agent/structs" ) // MockWatcher is an autogenerated mock type for the Watcher type @@ -17,25 +17,20 @@ type MockWatcher struct { } // Watch provides a mock function with given fields: proxyID, nodeName, token -func (_m *MockWatcher) Watch(proxyID *pbresource.ID, nodeName string, token string) (<-chan proxysnapshot.ProxySnapshot, limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) { +func (_m *MockWatcher) Watch(proxyID structs.ServiceID, nodeName string, token string) (<-chan *proxycfg.ConfigSnapshot, limiter.SessionTerminatedChan, proxycfg.CancelFunc, error) { ret := _m.Called(proxyID, nodeName, token) - var r0 <-chan proxysnapshot.ProxySnapshot - var r1 limiter.SessionTerminatedChan - var r2 proxysnapshot.CancelFunc - var r3 error - if rf, ok := ret.Get(0).(func(*pbresource.ID, string, string) (<-chan proxysnapshot.ProxySnapshot, limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error)); ok { - return rf(proxyID, nodeName, token) - } - if rf, ok := ret.Get(0).(func(*pbresource.ID, string, string) <-chan proxysnapshot.ProxySnapshot); ok { + var r0 <-chan *proxycfg.ConfigSnapshot + if rf, ok := ret.Get(0).(func(structs.ServiceID, string, string) <-chan *proxycfg.ConfigSnapshot); ok { r0 = rf(proxyID, nodeName, token) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(<-chan proxysnapshot.ProxySnapshot) + r0 = ret.Get(0).(<-chan *proxycfg.ConfigSnapshot) } } - if rf, ok := ret.Get(1).(func(*pbresource.ID, string, string) limiter.SessionTerminatedChan); ok { + var r1 limiter.SessionTerminatedChan + if rf, ok := ret.Get(1).(func(structs.ServiceID, string, string) limiter.SessionTerminatedChan); ok { r1 = rf(proxyID, nodeName, token) } else { if ret.Get(1) != nil { @@ -43,15 +38,17 @@ func (_m *MockWatcher) Watch(proxyID *pbresource.ID, nodeName string, token stri } } - if rf, ok := ret.Get(2).(func(*pbresource.ID, string, string) proxysnapshot.CancelFunc); ok { + var r2 proxycfg.CancelFunc + if rf, ok := ret.Get(2).(func(structs.ServiceID, string, string) proxycfg.CancelFunc); ok { r2 = rf(proxyID, nodeName, token) } else { if ret.Get(2) != nil { - r2 = ret.Get(2).(proxysnapshot.CancelFunc) + r2 = ret.Get(2).(proxycfg.CancelFunc) } } - if rf, ok := ret.Get(3).(func(*pbresource.ID, string, string) error); ok { + var r3 error + if rf, ok := ret.Get(3).(func(structs.ServiceID, string, string) error); ok { r3 = rf(proxyID, nodeName, token) } else { r3 = ret.Error(3) @@ -60,12 +57,13 @@ func (_m *MockWatcher) Watch(proxyID *pbresource.ID, nodeName string, token stri return r0, r1, r2, r3 } -// NewMockWatcher creates a new instance of MockWatcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewMockWatcher(t interface { +type mockConstructorTestingTNewMockWatcher interface { mock.TestingT Cleanup(func()) -}) *MockWatcher { +} + +// NewMockWatcher creates a new instance of MockWatcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewMockWatcher(t mockConstructorTestingTNewMockWatcher) *MockWatcher { mock := &MockWatcher{} mock.Mock.Test(t) diff --git a/agent/proxycfg-sources/local/config_source.go b/agent/proxycfg-sources/local/config_source.go index 7b3a835fb819d..18b8a045c421b 100644 --- a/agent/proxycfg-sources/local/config_source.go +++ b/agent/proxycfg-sources/local/config_source.go @@ -1,15 +1,12 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package local import ( "github.com/hashicorp/consul/agent/grpc-external/limiter" "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/proxycfg-sources/catalog" structs "github.com/hashicorp/consul/agent/structs" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - "github.com/hashicorp/consul/proto-public/pbresource" ) // ConfigSource wraps a proxycfg.Manager to create watches on services @@ -23,9 +20,7 @@ func NewConfigSource(cfgMgr ConfigManager) *ConfigSource { return &ConfigSource{cfgMgr} } -func (m *ConfigSource) Watch(proxyID *pbresource.ID, nodeName string, _ string) (<-chan proxysnapshot.ProxySnapshot, - limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) { - serviceID := structs.NewServiceID(proxyID.Name, catalog.GetEnterpriseMetaFromResourceID(proxyID)) +func (m *ConfigSource) Watch(serviceID structs.ServiceID, nodeName string, _ string) (<-chan *proxycfg.ConfigSnapshot, limiter.SessionTerminatedChan, proxycfg.CancelFunc, error) { watchCh, cancelWatch := m.manager.Watch(proxycfg.ProxyID{ ServiceID: serviceID, NodeName: nodeName, diff --git a/agent/proxycfg-sources/local/local.go b/agent/proxycfg-sources/local/local.go index 44867eb067515..92eefe1eb85f0 100644 --- a/agent/proxycfg-sources/local/local.go +++ b/agent/proxycfg-sources/local/local.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package local integrates the proxycfg Manager with the agent's local state. package local diff --git a/agent/proxycfg-sources/local/mock_ConfigManager.go b/agent/proxycfg-sources/local/mock_ConfigManager.go index e3b2d3a445872..8f2c8fc6c836c 100644 --- a/agent/proxycfg-sources/local/mock_ConfigManager.go +++ b/agent/proxycfg-sources/local/mock_ConfigManager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.33.1. DO NOT EDIT. +// Code generated by mockery v2.15.0. DO NOT EDIT. package local @@ -6,8 +6,6 @@ import ( proxycfg "github.com/hashicorp/consul/agent/proxycfg" mock "github.com/stretchr/testify/mock" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - structs "github.com/hashicorp/consul/agent/structs" ) @@ -52,39 +50,37 @@ func (_m *MockConfigManager) RegisteredProxies(source proxycfg.ProxySource) []pr } // Watch provides a mock function with given fields: id -func (_m *MockConfigManager) Watch(id proxycfg.ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc) { +func (_m *MockConfigManager) Watch(id proxycfg.ProxyID) (<-chan *proxycfg.ConfigSnapshot, proxycfg.CancelFunc) { ret := _m.Called(id) - var r0 <-chan proxysnapshot.ProxySnapshot - var r1 proxysnapshot.CancelFunc - if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc)); ok { - return rf(id) - } - if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) <-chan proxysnapshot.ProxySnapshot); ok { + var r0 <-chan *proxycfg.ConfigSnapshot + if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) <-chan *proxycfg.ConfigSnapshot); ok { r0 = rf(id) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(<-chan proxysnapshot.ProxySnapshot) + r0 = ret.Get(0).(<-chan *proxycfg.ConfigSnapshot) } } - if rf, ok := ret.Get(1).(func(proxycfg.ProxyID) proxysnapshot.CancelFunc); ok { + var r1 proxycfg.CancelFunc + if rf, ok := ret.Get(1).(func(proxycfg.ProxyID) proxycfg.CancelFunc); ok { r1 = rf(id) } else { if ret.Get(1) != nil { - r1 = ret.Get(1).(proxysnapshot.CancelFunc) + r1 = ret.Get(1).(proxycfg.CancelFunc) } } return r0, r1 } -// NewMockConfigManager creates a new instance of MockConfigManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewMockConfigManager(t interface { +type mockConstructorTestingTNewMockConfigManager interface { mock.TestingT Cleanup(func()) -}) *MockConfigManager { +} + +// NewMockConfigManager creates a new instance of MockConfigManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewMockConfigManager(t mockConstructorTestingTNewMockConfigManager) *MockConfigManager { mock := &MockConfigManager{} mock.Mock.Test(t) diff --git a/agent/proxycfg-sources/local/sync.go b/agent/proxycfg-sources/local/sync.go index b5583db43a3df..86427c9f005ba 100644 --- a/agent/proxycfg-sources/local/sync.go +++ b/agent/proxycfg-sources/local/sync.go @@ -1,11 +1,10 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package local import ( "context" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" "time" "github.com/hashicorp/go-hclog" @@ -136,7 +135,7 @@ func sync(cfg SyncConfig) { //go:generate mockery --name ConfigManager --inpackage type ConfigManager interface { - Watch(id proxycfg.ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc) + Watch(id proxycfg.ProxyID) (<-chan *proxycfg.ConfigSnapshot, proxycfg.CancelFunc) Register(proxyID proxycfg.ProxyID, service *structs.NodeService, source proxycfg.ProxySource, token string, overwrite bool) error Deregister(proxyID proxycfg.ProxyID, source proxycfg.ProxySource) RegisteredProxies(source proxycfg.ProxySource) []proxycfg.ProxyID diff --git a/agent/proxycfg-sources/local/sync_test.go b/agent/proxycfg-sources/local/sync_test.go index 5aa030db4cfc2..8fa4883518197 100644 --- a/agent/proxycfg-sources/local/sync_test.go +++ b/agent/proxycfg-sources/local/sync_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package local diff --git a/agent/proxycfg/api_gateway.go b/agent/proxycfg/api_gateway.go index 3ed39481204c2..b4954cd3973c7 100644 --- a/agent/proxycfg/api_gateway.go +++ b/agent/proxycfg/api_gateway.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg diff --git a/agent/proxycfg/api_gateway_ce.go b/agent/proxycfg/api_gateway_ce.go deleted file mode 100644 index e2a3b375cd10b..0000000000000 --- a/agent/proxycfg/api_gateway_ce.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package proxycfg - -import "context" - -func watchJWTProviders(cxt context.Context, h *handlerAPIGateway) error { - return nil -} - -func setJWTProvider(u UpdateEvent, snap *ConfigSnapshot) error { - return nil -} diff --git a/agent/proxycfg/config_snapshot_glue.go b/agent/proxycfg/config_snapshot_glue.go deleted file mode 100644 index 7d1c1d9770e0d..0000000000000 --- a/agent/proxycfg/config_snapshot_glue.go +++ /dev/null @@ -1,66 +0,0 @@ -package proxycfg - -import ( - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/logging" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -// The below functions are added to ConfigSnapshot to allow it to conform to -// the ProxySnapshot interface. -func (s *ConfigSnapshot) AllowEmptyListeners() bool { - // Ingress and API gateways are allowed to inform LDS of no listeners. - return s.Kind == structs.ServiceKindIngressGateway || - s.Kind == structs.ServiceKindAPIGateway -} - -func (s *ConfigSnapshot) AllowEmptyRoutes() bool { - // Ingress and API gateways are allowed to inform RDS of no routes. - return s.Kind == structs.ServiceKindIngressGateway || - s.Kind == structs.ServiceKindAPIGateway -} - -func (s *ConfigSnapshot) AllowEmptyClusters() bool { - // Mesh, Ingress, API and Terminating gateways are allowed to inform CDS of no clusters. - return s.Kind == structs.ServiceKindMeshGateway || - s.Kind == structs.ServiceKindTerminatingGateway || - s.Kind == structs.ServiceKindIngressGateway || - s.Kind == structs.ServiceKindAPIGateway -} - -func (s *ConfigSnapshot) Authorize(authz acl.Authorizer) error { - var authzContext acl.AuthorizerContext - switch s.Kind { - case structs.ServiceKindConnectProxy: - s.ProxyID.EnterpriseMeta.FillAuthzContext(&authzContext) - if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(s.Proxy.DestinationServiceName, &authzContext); err != nil { - return status.Errorf(codes.PermissionDenied, err.Error()) - } - case structs.ServiceKindMeshGateway, structs.ServiceKindTerminatingGateway, structs.ServiceKindIngressGateway, structs.ServiceKindAPIGateway: - s.ProxyID.EnterpriseMeta.FillAuthzContext(&authzContext) - if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(s.Service, &authzContext); err != nil { - return status.Errorf(codes.PermissionDenied, err.Error()) - } - default: - return status.Errorf(codes.Internal, "Invalid service kind") - } - - // Authed OK! - return nil -} - -func (s *ConfigSnapshot) LoggerName() string { - switch s.Kind { - case structs.ServiceKindConnectProxy: - case structs.ServiceKindTerminatingGateway: - return logging.TerminatingGateway - case structs.ServiceKindMeshGateway: - return logging.MeshGateway - case structs.ServiceKindIngressGateway: - return logging.IngressGateway - } - - return "" -} diff --git a/agent/proxycfg/config_snapshot_glue_test.go b/agent/proxycfg/config_snapshot_glue_test.go deleted file mode 100644 index 6ff20714eb320..0000000000000 --- a/agent/proxycfg/config_snapshot_glue_test.go +++ /dev/null @@ -1,312 +0,0 @@ -package proxycfg - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/structs" -) - -func TestConfigSnapshot_AllowEmptyClusters(t *testing.T) { - type testCase struct { - description string - cfgSnapshot *ConfigSnapshot - expectedResult bool - } - testsCases := []testCase{ - { - description: "Mesh proxies are not allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindConnectProxy}, - expectedResult: false, - }, - { - description: "Ingress gateways are allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindIngressGateway}, - expectedResult: true, - }, - { - description: "Terminating gateways are allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindTerminatingGateway}, - expectedResult: true, - }, - { - description: "API Gateways are allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindAPIGateway}, - expectedResult: true, - }, - { - description: "Mesh Gateways are allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindMeshGateway}, - expectedResult: true, - }, - } - for _, tc := range testsCases { - t.Run(tc.description, func(t *testing.T) { - require.Equal(t, tc.expectedResult, tc.cfgSnapshot.AllowEmptyClusters()) - }) - } -} - -func TestConfigSnapshot_AllowEmptyListeners(t *testing.T) { - type testCase struct { - description string - cfgSnapshot *ConfigSnapshot - expectedResult bool - } - testsCases := []testCase{ - { - description: "Mesh proxies are not allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindConnectProxy}, - expectedResult: false, - }, - { - description: "Ingress gateways are allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindIngressGateway}, - expectedResult: true, - }, - { - description: "Terminating gateways are not allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindTerminatingGateway}, - expectedResult: false, - }, - { - description: "API Gateways are allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindAPIGateway}, - expectedResult: true, - }, - { - description: "Mesh Gateways are not allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindMeshGateway}, - expectedResult: false, - }, - } - for _, tc := range testsCases { - t.Run(tc.description, func(t *testing.T) { - require.Equal(t, tc.expectedResult, tc.cfgSnapshot.AllowEmptyListeners()) - }) - } -} - -func TestConfigSnapshot_AllowEmptyRoutes(t *testing.T) { - type testCase struct { - description string - cfgSnapshot *ConfigSnapshot - expectedResult bool - } - testsCases := []testCase{ - { - description: "Mesh proxies are not allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindConnectProxy}, - expectedResult: false, - }, - { - description: "Ingress gateways are allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindIngressGateway}, - expectedResult: true, - }, - { - description: "Terminating gateways are not allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindTerminatingGateway}, - expectedResult: false, - }, - { - description: "API Gateways are allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindAPIGateway}, - expectedResult: true, - }, - { - description: "Mesh Gateways are not allowed", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindMeshGateway}, - expectedResult: false, - }, - } - for _, tc := range testsCases { - t.Run(tc.description, func(t *testing.T) { - require.Equal(t, tc.expectedResult, tc.cfgSnapshot.AllowEmptyRoutes()) - }) - } -} - -func TestConfigSnapshot_LoggerName(t *testing.T) { - type testCase struct { - description string - cfgSnapshot *ConfigSnapshot - expectedResult string - } - testsCases := []testCase{ - { - description: "Mesh proxies have a logger named ''", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindConnectProxy}, - expectedResult: "", - }, - { - description: "Ingress gateways have a logger named 'ingress_gateway'", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindIngressGateway}, - expectedResult: "ingress_gateway", - }, - { - description: "Terminating gateways have a logger named 'terminating_gateway'", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindTerminatingGateway}, - expectedResult: "terminating_gateway", - }, - { - description: "API Gateways have a logger named ''", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindAPIGateway}, - expectedResult: "", - }, - { - description: "Mesh Gateways have a logger named 'mesh_gateway'", - cfgSnapshot: &ConfigSnapshot{Kind: structs.ServiceKindMeshGateway}, - expectedResult: "mesh_gateway", - }, - } - for _, tc := range testsCases { - t.Run(tc.description, func(t *testing.T) { - require.Equal(t, tc.expectedResult, tc.cfgSnapshot.LoggerName()) - }) - } -} - -func TestConfigSnapshot_Authorize(t *testing.T) { - type testCase struct { - description string - cfgSnapshot *ConfigSnapshot - configureAuthorizer func(authorizer *acl.MockAuthorizer) - expectedErrorMessage string - } - testsCases := []testCase{ - { - description: "ConnectProxy - if service write is allowed for the DestinationService then allow.", - cfgSnapshot: &ConfigSnapshot{ - Kind: structs.ServiceKindConnectProxy, - Proxy: structs.ConnectProxyConfig{ - DestinationServiceName: "DestinationServiceName", - }, - }, - expectedErrorMessage: "", - configureAuthorizer: func(authz *acl.MockAuthorizer) { - authz.On("ServiceWrite", "DestinationServiceName", mock.Anything).Return(acl.Allow) - }, - }, - { - description: "ConnectProxy - if service write is not allowed for the DestinationService then deny.", - cfgSnapshot: &ConfigSnapshot{ - Kind: structs.ServiceKindConnectProxy, - Proxy: structs.ConnectProxyConfig{ - DestinationServiceName: "DestinationServiceName", - }, - }, - expectedErrorMessage: "rpc error: code = PermissionDenied desc = Permission denied: token with AccessorID '' lacks permission 'service:write' on \"DestinationServiceName\"", - configureAuthorizer: func(authz *acl.MockAuthorizer) { - authz.On("ServiceWrite", "DestinationServiceName", mock.Anything).Return(acl.Deny) - }, - }, - { - description: "Mesh Gateway - if service write is allowed for the Service then allow.", - cfgSnapshot: &ConfigSnapshot{ - Kind: structs.ServiceKindMeshGateway, - Service: "Service", - }, - expectedErrorMessage: "", - configureAuthorizer: func(authz *acl.MockAuthorizer) { - authz.On("ServiceWrite", "Service", mock.Anything).Return(acl.Allow) - }, - }, - { - description: "Mesh Gateway - if service write is not allowed for the Service then deny.", - cfgSnapshot: &ConfigSnapshot{ - Kind: structs.ServiceKindMeshGateway, - Service: "Service", - }, - expectedErrorMessage: "rpc error: code = PermissionDenied desc = Permission denied: token with AccessorID '' lacks permission 'service:write' on \"Service\"", - configureAuthorizer: func(authz *acl.MockAuthorizer) { - authz.On("ServiceWrite", "Service", mock.Anything).Return(acl.Deny) - }, - }, - { - description: "Terminating Gateway - if service write is allowed for the Service then allow.", - cfgSnapshot: &ConfigSnapshot{ - Kind: structs.ServiceKindTerminatingGateway, - Service: "Service", - }, - expectedErrorMessage: "rpc error: code = PermissionDenied desc = Permission denied: token with AccessorID '' lacks permission 'service:write' on \"Service\"", - configureAuthorizer: func(authz *acl.MockAuthorizer) { - authz.On("ServiceWrite", "Service", mock.Anything).Return(acl.Deny) - }, - }, - { - description: "Terminating Gateway - if service write is not allowed for the Service then deny.", - cfgSnapshot: &ConfigSnapshot{ - Kind: structs.ServiceKindTerminatingGateway, - Service: "Service", - }, - expectedErrorMessage: "rpc error: code = PermissionDenied desc = Permission denied: token with AccessorID '' lacks permission 'service:write' on \"Service\"", - configureAuthorizer: func(authz *acl.MockAuthorizer) { - authz.On("ServiceWrite", "Service", mock.Anything).Return(acl.Deny) - }, - }, - { - description: "Ingress Gateway - if service write is allowed for the Service then allow.", - cfgSnapshot: &ConfigSnapshot{ - Kind: structs.ServiceKindIngressGateway, - Service: "Service", - }, - expectedErrorMessage: "rpc error: code = PermissionDenied desc = Permission denied: token with AccessorID '' lacks permission 'service:write' on \"Service\"", - configureAuthorizer: func(authz *acl.MockAuthorizer) { - authz.On("ServiceWrite", "Service", mock.Anything).Return(acl.Deny) - }, - }, - { - description: "Ingress Gateway - if service write is not allowed for the Service then deny.", - cfgSnapshot: &ConfigSnapshot{ - Kind: structs.ServiceKindIngressGateway, - Service: "Service", - }, - expectedErrorMessage: "rpc error: code = PermissionDenied desc = Permission denied: token with AccessorID '' lacks permission 'service:write' on \"Service\"", - configureAuthorizer: func(authz *acl.MockAuthorizer) { - authz.On("ServiceWrite", "Service", mock.Anything).Return(acl.Deny) - }, - }, - { - description: "API Gateway - if service write is allowed for the Service then allow.", - cfgSnapshot: &ConfigSnapshot{ - Kind: structs.ServiceKindAPIGateway, - Service: "Service", - }, - expectedErrorMessage: "rpc error: code = PermissionDenied desc = Permission denied: token with AccessorID '' lacks permission 'service:write' on \"Service\"", - configureAuthorizer: func(authz *acl.MockAuthorizer) { - authz.On("ServiceWrite", "Service", mock.Anything).Return(acl.Deny) - }, - }, - { - description: "API Gateway - if service write is not allowed for the Service then deny.", - cfgSnapshot: &ConfigSnapshot{ - Kind: structs.ServiceKindAPIGateway, - Service: "Service", - }, - expectedErrorMessage: "rpc error: code = PermissionDenied desc = Permission denied: token with AccessorID '' lacks permission 'service:write' on \"Service\"", - configureAuthorizer: func(authz *acl.MockAuthorizer) { - authz.On("ServiceWrite", "Service", mock.Anything).Return(acl.Deny) - }, - }, - } - for _, tc := range testsCases { - t.Run(tc.description, func(t *testing.T) { - authz := &acl.MockAuthorizer{} - authz.On("ToAllow").Return(acl.AllowAuthorizer{Authorizer: authz}) - tc.configureAuthorizer(authz) - err := tc.cfgSnapshot.Authorize(authz) - errMsg := "" - if err != nil { - errMsg = err.Error() - } - // using contains because Enterprise tests append the parition and namespace - // information to the message. - require.True(t, strings.Contains(errMsg, tc.expectedErrorMessage)) - }) - } -} diff --git a/agent/proxycfg/connect_proxy.go b/agent/proxycfg/connect_proxy.go index 0a8c1737923ee..7dcbe18e71957 100644 --- a/agent/proxycfg/connect_proxy.go +++ b/agent/proxycfg/connect_proxy.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg diff --git a/agent/proxycfg/data_sources.go b/agent/proxycfg/data_sources.go index dfb9a70f357b8..ee779dfb6c884 100644 --- a/agent/proxycfg/data_sources.go +++ b/agent/proxycfg/data_sources.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg diff --git a/agent/proxycfg/data_sources_ce.go b/agent/proxycfg/data_sources_ce.go index a4a4aaff74762..5a92e9486b0dd 100644 --- a/agent/proxycfg/data_sources_ce.go +++ b/agent/proxycfg/data_sources_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/proxycfg/deep-copy.sh b/agent/proxycfg/deep-copy.sh index 2e1f361dd7101..17791e79b1194 100755 --- a/agent/proxycfg/deep-copy.sh +++ b/agent/proxycfg/deep-copy.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 readonly PACKAGE_DIR="$(dirname "${BASH_SOURCE[0]}")" diff --git a/agent/proxycfg/ingress_gateway.go b/agent/proxycfg/ingress_gateway.go index 3ab5828add40a..efb774c9b17c3 100644 --- a/agent/proxycfg/ingress_gateway.go +++ b/agent/proxycfg/ingress_gateway.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg diff --git a/agent/proxycfg/internal/watch/watchmap.go b/agent/proxycfg/internal/watch/watchmap.go index d4fba2ea03eb8..c36ec3237cc66 100644 --- a/agent/proxycfg/internal/watch/watchmap.go +++ b/agent/proxycfg/internal/watch/watchmap.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package watch diff --git a/agent/proxycfg/internal/watch/watchmap_test.go b/agent/proxycfg/internal/watch/watchmap_test.go index 54fb51d4df9ba..c5bef8e471088 100644 --- a/agent/proxycfg/internal/watch/watchmap_test.go +++ b/agent/proxycfg/internal/watch/watchmap_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package watch diff --git a/agent/proxycfg/manager.go b/agent/proxycfg/manager.go index 71b6270fefc41..a942fd1d1e147 100644 --- a/agent/proxycfg/manager.go +++ b/agent/proxycfg/manager.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg @@ -12,7 +12,6 @@ import ( "golang.org/x/time/rate" "github.com/hashicorp/consul/agent/structs" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" "github.com/hashicorp/consul/tlsutil" ) @@ -37,6 +36,10 @@ type ProxyID struct { // from overwriting each other's registrations. type ProxySource string +// CancelFunc is a type for a returned function that can be called to cancel a +// watch. +type CancelFunc func() + // Manager provides an API with which proxy services can be registered, and // coordinates the fetching (and refreshing) of intentions, upstreams, discovery // chain, certificates etc. @@ -52,7 +55,7 @@ type Manager struct { mu sync.Mutex proxies map[ProxyID]*state - watchers map[ProxyID]map[uint64]chan proxysnapshot.ProxySnapshot + watchers map[ProxyID]map[uint64]chan *ConfigSnapshot maxWatchID uint64 } @@ -103,7 +106,7 @@ func NewManager(cfg ManagerConfig) (*Manager, error) { m := &Manager{ ManagerConfig: cfg, proxies: make(map[ProxyID]*state), - watchers: make(map[ProxyID]map[uint64]chan proxysnapshot.ProxySnapshot), + watchers: make(map[ProxyID]map[uint64]chan *ConfigSnapshot), rateLimiter: rate.NewLimiter(cfg.UpdateRateLimit, 1), } return m, nil @@ -259,7 +262,7 @@ func (m *Manager) notify(snap *ConfigSnapshot) { // it will drain the chan and then re-attempt delivery so that a slow consumer // gets the latest config earlier. This MUST be called from a method where m.mu // is held to be safe since it assumes we are the only goroutine sending on ch. -func (m *Manager) deliverLatest(snap *ConfigSnapshot, ch chan proxysnapshot.ProxySnapshot) { +func (m *Manager) deliverLatest(snap *ConfigSnapshot, ch chan *ConfigSnapshot) { // Send if chan is empty select { case ch <- snap: @@ -296,16 +299,16 @@ OUTER: // will not fail, but no updates will be delivered until the proxy is // registered. If there is already a valid snapshot in memory, it will be // delivered immediately. -func (m *Manager) Watch(id ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc) { +func (m *Manager) Watch(id ProxyID) (<-chan *ConfigSnapshot, CancelFunc) { m.mu.Lock() defer m.mu.Unlock() // This buffering is crucial otherwise we'd block immediately trying to // deliver the current snapshot below if we already have one. - ch := make(chan proxysnapshot.ProxySnapshot, 1) + ch := make(chan *ConfigSnapshot, 1) watchers, ok := m.watchers[id] if !ok { - watchers = make(map[uint64]chan proxysnapshot.ProxySnapshot) + watchers = make(map[uint64]chan *ConfigSnapshot) } watchID := m.maxWatchID m.maxWatchID++ diff --git a/agent/proxycfg/manager_test.go b/agent/proxycfg/manager_test.go index feaa4e431d033..13dd0f95420cd 100644 --- a/agent/proxycfg/manager_test.go +++ b/agent/proxycfg/manager_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg @@ -17,7 +17,6 @@ import ( "github.com/hashicorp/consul/agent/proxycfg/internal/watch" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" "github.com/hashicorp/consul/proto/private/pbpeering" "github.com/hashicorp/consul/sdk/testutil" ) @@ -470,7 +469,7 @@ func testManager_BasicLifecycle( require.Len(t, m.watchers, 0) } -func assertWatchChanBlocks(t *testing.T, ch <-chan proxysnapshot.ProxySnapshot) { +func assertWatchChanBlocks(t *testing.T, ch <-chan *ConfigSnapshot) { t.Helper() select { @@ -480,7 +479,7 @@ func assertWatchChanBlocks(t *testing.T, ch <-chan proxysnapshot.ProxySnapshot) } } -func assertWatchChanRecvs(t *testing.T, ch <-chan proxysnapshot.ProxySnapshot, expect proxysnapshot.ProxySnapshot) { +func assertWatchChanRecvs(t *testing.T, ch <-chan *ConfigSnapshot, expect *ConfigSnapshot) { t.Helper() select { @@ -518,7 +517,7 @@ func TestManager_deliverLatest(t *testing.T) { } // test 1 buffered chan - ch1 := make(chan proxysnapshot.ProxySnapshot, 1) + ch1 := make(chan *ConfigSnapshot, 1) // Sending to an unblocked chan should work m.deliverLatest(snap1, ch1) @@ -534,7 +533,7 @@ func TestManager_deliverLatest(t *testing.T) { require.Equal(t, snap2, <-ch1) // Same again for 5-buffered chan - ch5 := make(chan proxysnapshot.ProxySnapshot, 5) + ch5 := make(chan *ConfigSnapshot, 5) // Sending to an unblocked chan should work m.deliverLatest(snap1, ch5) diff --git a/agent/proxycfg/mesh_gateway.go b/agent/proxycfg/mesh_gateway.go index 0237e84232905..f2fee37d46719 100644 --- a/agent/proxycfg/mesh_gateway.go +++ b/agent/proxycfg/mesh_gateway.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/go-hclog" "github.com/hashicorp/consul/acl" + cachetype "github.com/hashicorp/consul/agent/cache-types" "github.com/hashicorp/consul/agent/leafcert" "github.com/hashicorp/consul/agent/proxycfg/internal/watch" diff --git a/agent/proxycfg/mesh_gateway_ce.go b/agent/proxycfg/mesh_gateway_ce.go index 0c302f27cd7b4..2959a8383a1e8 100644 --- a/agent/proxycfg/mesh_gateway_ce.go +++ b/agent/proxycfg/mesh_gateway_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/proxycfg/naming.go b/agent/proxycfg/naming.go index a9bd5fd8c0ca4..07aa42f2f4dd4 100644 --- a/agent/proxycfg/naming.go +++ b/agent/proxycfg/naming.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg diff --git a/agent/proxycfg/naming_ce.go b/agent/proxycfg/naming_ce.go index a98204a8bbac4..858b8d3553dfd 100644 --- a/agent/proxycfg/naming_ce.go +++ b/agent/proxycfg/naming_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/proxycfg/naming_test.go b/agent/proxycfg/naming_test.go index 0615a81281824..caf917f5d9757 100644 --- a/agent/proxycfg/naming_test.go +++ b/agent/proxycfg/naming_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg diff --git a/agent/proxycfg/proxycfg.deepcopy.go b/agent/proxycfg/proxycfg.deepcopy.go index d6f11319169ad..5b9d9ce3e7e08 100644 --- a/agent/proxycfg/proxycfg.deepcopy.go +++ b/agent/proxycfg/proxycfg.deepcopy.go @@ -13,10 +13,6 @@ import ( // DeepCopy generates a deep copy of *ConfigSnapshot func (o *ConfigSnapshot) DeepCopy() *ConfigSnapshot { var cp ConfigSnapshot = *o - if o.ServiceLocality != nil { - cp.ServiceLocality = new(structs.Locality) - *cp.ServiceLocality = *o.ServiceLocality - } if o.ServiceMeta != nil { cp.ServiceMeta = make(map[string]string, len(o.ServiceMeta)) for k2, v2 := range o.ServiceMeta { diff --git a/agent/proxycfg/proxycfg.go b/agent/proxycfg/proxycfg.go index 9b71156dfe5aa..f73e6ac726ceb 100644 --- a/agent/proxycfg/proxycfg.go +++ b/agent/proxycfg/proxycfg.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package proxycfg contains components for sourcing the data required to // configure Connect proxies. The Manager provides an API with which proxy @@ -45,7 +45,7 @@ // ConfigSource - on a client agent this would be a local config source, on a // server it would be a catalog config source. // 4. On server, the catalog config source will check if service is registered locally. -// 4a. If the service *is* registered locally it hands off the local config +// 4a. If the service *is* registered locally it hands off the the local config // source, which calls Watch on the proxycfg manager (and serves the pre- // fetched data). // 5. Otherwise, it fetches the service from the state store. diff --git a/agent/proxycfg/snapshot.go b/agent/proxycfg/snapshot.go index e9304ec631227..b4093d6f734c0 100644 --- a/agent/proxycfg/snapshot.go +++ b/agent/proxycfg/snapshot.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg @@ -925,7 +925,6 @@ func IngressListenerKeyFromListener(l structs.IngressListener) IngressListenerKe type ConfigSnapshot struct { Kind structs.ServiceKind Service string - ServiceLocality *structs.Locality ProxyID ProxyID Address string Port int diff --git a/agent/proxycfg/snapshot_test.go b/agent/proxycfg/snapshot_test.go index b4b0ab57c957a..ea6700cd249da 100644 --- a/agent/proxycfg/snapshot_test.go +++ b/agent/proxycfg/snapshot_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg diff --git a/agent/proxycfg/state.go b/agent/proxycfg/state.go index 853dca5a9f1bf..55ba287ef1f25 100644 --- a/agent/proxycfg/state.go +++ b/agent/proxycfg/state.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg @@ -126,7 +126,6 @@ type serviceInstance struct { taggedAddresses map[string]structs.ServiceAddress proxyCfg structs.ConnectProxyConfig token string - locality *structs.Locality } func copyProxyConfig(ns *structs.NodeService) (structs.ConnectProxyConfig, error) { @@ -247,7 +246,6 @@ func newServiceInstanceFromNodeService(id ProxyID, ns *structs.NodeService, toke return serviceInstance{ kind: ns.Kind, service: ns.Service, - locality: ns.Locality, proxyID: id, address: ns.Address, port: ns.Port, @@ -307,7 +305,6 @@ func newConfigSnapshotFromServiceInstance(s serviceInstance, config stateConfig) return ConfigSnapshot{ Kind: s.kind, Service: s.service, - ServiceLocality: s.locality, ProxyID: s.proxyID, Address: s.address, Port: s.port, diff --git a/agent/proxycfg/state_ce_test.go b/agent/proxycfg/state_ce_test.go index 36f2e07183e41..e817aeef0b13f 100644 --- a/agent/proxycfg/state_ce_test.go +++ b/agent/proxycfg/state_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/proxycfg/state_test.go b/agent/proxycfg/state_test.go index 2a6792aa22e93..9065db885dc3b 100644 --- a/agent/proxycfg/state_test.go +++ b/agent/proxycfg/state_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg diff --git a/agent/proxycfg/terminating_gateway.go b/agent/proxycfg/terminating_gateway.go index 05085a6ab26dc..7d29ee70501bb 100644 --- a/agent/proxycfg/terminating_gateway.go +++ b/agent/proxycfg/terminating_gateway.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg diff --git a/agent/proxycfg/testing.go b/agent/proxycfg/testing.go index bdd565ec0454e..ac68994cb8f18 100644 --- a/agent/proxycfg/testing.go +++ b/agent/proxycfg/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg @@ -167,7 +167,7 @@ func TestUpstreamNodes(t testing.T, service string) structs.CheckServiceNodes { Datacenter: "dc1", Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(), }, - Service: structs.TestNodeServiceWithName(service), + Service: structs.TestNodeServiceWithName(t, service), }, structs.CheckServiceNode{ Node: &structs.Node{ @@ -177,47 +177,7 @@ func TestUpstreamNodes(t testing.T, service string) structs.CheckServiceNodes { Datacenter: "dc1", Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(), }, - Service: structs.TestNodeServiceWithName(service), - }, - } -} - -// TestUpstreamNodesWithServiceSubset returns a sample service discovery result with one instance tagged v1 -// and the other tagged v2 -func TestUpstreamNodesWithServiceSubset(t testing.T, service string) structs.CheckServiceNodes { - return structs.CheckServiceNodes{ - structs.CheckServiceNode{ - Node: &structs.Node{ - ID: "test1", - Node: "test1", - Address: "10.10.1.3", - Datacenter: "dc1", - Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(), - }, - Service: &structs.NodeService{ - Kind: structs.ServiceKindTypical, - Service: service, - Port: 8080, - Meta: map[string]string{"Version": "1"}, - Weights: &structs.Weights{ - Passing: 300, // Check that this gets normalized to 128 - }, - }, - }, - structs.CheckServiceNode{ - Node: &structs.Node{ - ID: "test2", - Node: "test2", - Address: "10.10.1.4", - Datacenter: "dc1", - Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(), - }, - Service: &structs.NodeService{ - Kind: structs.ServiceKindTypical, - Service: service, - Port: 8080, - Meta: map[string]string{"Version": "2"}, - }, + Service: structs.TestNodeServiceWithName(t, service), }, } } @@ -271,7 +231,7 @@ func TestUpstreamNodesInStatus(t testing.T, status string) structs.CheckServiceN Address: "10.10.1.1", Datacenter: "dc1", }, - Service: structs.TestNodeService(), + Service: structs.TestNodeService(t), Checks: structs.HealthChecks{ &structs.HealthCheck{ Node: "test1", @@ -288,7 +248,7 @@ func TestUpstreamNodesInStatus(t testing.T, status string) structs.CheckServiceN Address: "10.10.1.2", Datacenter: "dc1", }, - Service: structs.TestNodeService(), + Service: structs.TestNodeService(t), Checks: structs.HealthChecks{ &structs.HealthCheck{ Node: "test2", @@ -310,7 +270,7 @@ func TestUpstreamNodesDC2(t testing.T) structs.CheckServiceNodes { Address: "10.20.1.1", Datacenter: "dc2", }, - Service: structs.TestNodeService(), + Service: structs.TestNodeService(t), }, structs.CheckServiceNode{ Node: &structs.Node{ @@ -319,7 +279,7 @@ func TestUpstreamNodesDC2(t testing.T) structs.CheckServiceNodes { Address: "10.20.1.2", Datacenter: "dc2", }, - Service: structs.TestNodeService(), + Service: structs.TestNodeService(t), }, } } @@ -333,7 +293,7 @@ func TestUpstreamNodesInStatusDC2(t testing.T, status string) structs.CheckServi Address: "10.20.1.1", Datacenter: "dc2", }, - Service: structs.TestNodeService(), + Service: structs.TestNodeService(t), Checks: structs.HealthChecks{ &structs.HealthCheck{ Node: "test1", @@ -350,7 +310,7 @@ func TestUpstreamNodesInStatusDC2(t testing.T, status string) structs.CheckServi Address: "10.20.1.2", Datacenter: "dc2", }, - Service: structs.TestNodeService(), + Service: structs.TestNodeService(t), Checks: structs.HealthChecks{ &structs.HealthCheck{ Node: "test2", @@ -372,7 +332,7 @@ func TestUpstreamNodesAlternate(t testing.T) structs.CheckServiceNodes { Address: "10.20.1.1", Datacenter: "dc1", }, - Service: structs.TestNodeService(), + Service: structs.TestNodeService(t), }, structs.CheckServiceNode{ Node: &structs.Node{ @@ -381,7 +341,7 @@ func TestUpstreamNodesAlternate(t testing.T) structs.CheckServiceNodes { Address: "10.20.1.2", Datacenter: "dc1", }, - Service: structs.TestNodeService(), + Service: structs.TestNodeService(t), }, } } diff --git a/agent/proxycfg/testing_api_gateway.go b/agent/proxycfg/testing_api_gateway.go index ddfa17dcf6ab2..87ff58fbf0535 100644 --- a/agent/proxycfg/testing_api_gateway.go +++ b/agent/proxycfg/testing_api_gateway.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg @@ -8,9 +8,10 @@ import ( "github.com/mitchellh/go-testing-interface" - "github.com/hashicorp/consul/agent/configentry" "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul/discoverychain" + + "github.com/hashicorp/consul/agent/configentry" "github.com/hashicorp/consul/agent/structs" ) diff --git a/agent/proxycfg/testing_ce.go b/agent/proxycfg/testing_ce.go index 6aa07588d4d1d..202252a3a7335 100644 --- a/agent/proxycfg/testing_ce.go +++ b/agent/proxycfg/testing_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/proxycfg/testing_connect_proxy.go b/agent/proxycfg/testing_connect_proxy.go index cf6f4a479b1eb..a929aa52f167d 100644 --- a/agent/proxycfg/testing_connect_proxy.go +++ b/agent/proxycfg/testing_connect_proxy.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg @@ -227,14 +227,6 @@ func TestConfigSnapshotExposeConfig(t testing.T, nsFn func(ns *structs.NodeServi } func TestConfigSnapshotExposeChecks(t testing.T) *ConfigSnapshot { - return testConfigSnapshotExposedChecks(t, false) -} - -func TestConfigSnapshotExposeChecksWithBindOverride(t testing.T) *ConfigSnapshot { - return testConfigSnapshotExposedChecks(t, true) -} - -func testConfigSnapshotExposedChecks(t testing.T, overrideBind bool) *ConfigSnapshot { return TestConfigSnapshot(t, func(ns *structs.NodeService) { ns.Address = "1.2.3.4" @@ -243,12 +235,6 @@ func testConfigSnapshotExposedChecks(t testing.T, overrideBind bool) *ConfigSnap ns.Proxy.Expose = structs.ExposeConfig{ Checks: true, } - if overrideBind { - if ns.Proxy.Config == nil { - ns.Proxy.Config = map[string]any{} - } - ns.Proxy.Config["bind_address"] = "6.7.8.9" - } }, []UpdateEvent{ { @@ -267,32 +253,6 @@ func testConfigSnapshotExposedChecks(t testing.T, overrideBind bool) *ConfigSnap ) } -func TestConfigSnapshotExposeChecksGRPC(t testing.T) *ConfigSnapshot { - return TestConfigSnapshot(t, - func(ns *structs.NodeService) { - ns.Address = "1.2.3.4" - ns.Port = 9090 - ns.Proxy.Upstreams = nil - ns.Proxy.Expose = structs.ExposeConfig{ - Checks: true, - } - }, - []UpdateEvent{ - { - CorrelationID: svcChecksWatchIDPrefix + structs.ServiceIDString("web", nil), - Result: []structs.CheckType{{ - CheckID: types.CheckID("grpc"), - Name: "grpc", - GRPC: "localhost:9090/v1.Health", - ProxyGRPC: "localhost:21501/myservice", - Interval: 10 * time.Second, - Timeout: 1 * time.Second, - }}, - }, - }, - ) -} - func TestConfigSnapshotGRPCExposeHTTP1(t testing.T) *ConfigSnapshot { roots, leaf := TestCerts(t) diff --git a/agent/proxycfg/testing_ingress_gateway.go b/agent/proxycfg/testing_ingress_gateway.go index 96918a261bd05..87a3313ecdb50 100644 --- a/agent/proxycfg/testing_ingress_gateway.go +++ b/agent/proxycfg/testing_ingress_gateway.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg @@ -1888,8 +1888,8 @@ func TestConfigSnapshotIngressGateway_TLSMixedMinVersionListeners(t testing.T) * entry.TLS.Enabled = true entry.TLS.TLSMinVersion = types.TLSv1_2 - // One listener should inherit TLS minimum version from the gateway config, - // two others each set explicit TLS minimum versions + // One listener disables TLS, one inherits TLS minimum version from the gateway + // config, two others set different versions entry.Listeners = []structs.IngressListener{ { Port: 8080, @@ -1925,6 +1925,8 @@ func TestConfigSnapshotIngressGateway_TLSMixedMinVersionListeners(t testing.T) * { CorrelationID: gatewayServicesWatchID, Result: &structs.IndexedGatewayServices{ + // One listener should inherit TLS minimum version from the gateway config, + // two others each set explicit TLS minimum versions Services: []*structs.GatewayService{ { Service: s1, @@ -1982,208 +1984,3 @@ func TestConfigSnapshotIngressGateway_TLSMixedMinVersionListeners(t testing.T) * }, }) } - -func TestConfigSnapshotIngressGateway_TLSMixedMaxVersionListeners(t testing.T) *ConfigSnapshot { - var ( - s1 = structs.NewServiceName("s1", nil) - s1UID = NewUpstreamIDFromServiceName(s1) - s1Chain = discoverychain.TestCompileConfigEntries(t, "s1", "default", "default", "dc1", connect.TestClusterID+".consul", nil, nil) - - s2 = structs.NewServiceName("s2", nil) - s2UID = NewUpstreamIDFromServiceName(s2) - s2Chain = discoverychain.TestCompileConfigEntries(t, "s2", "default", "default", "dc1", connect.TestClusterID+".consul", nil, nil) - - s3 = structs.NewServiceName("s3", nil) - s3UID = NewUpstreamIDFromServiceName(s3) - s3Chain = discoverychain.TestCompileConfigEntries(t, "s3", "default", "default", "dc1", connect.TestClusterID+".consul", nil, nil) - ) - - return TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, - func(entry *structs.IngressGatewayConfigEntry) { - entry.TLS.Enabled = true - entry.TLS.TLSMaxVersion = types.TLSv1_2 - - // One listener should inherit TLS maximum version from the gateway config, - // two others each set explicit TLS maximum versions - entry.Listeners = []structs.IngressListener{ - { - Port: 8080, - Protocol: "http", - Services: []structs.IngressService{ - {Name: "s1"}, - }, - }, - { - Port: 8081, - Protocol: "http", - Services: []structs.IngressService{ - {Name: "s2"}, - }, - TLS: &structs.GatewayTLSConfig{ - Enabled: true, - TLSMaxVersion: types.TLSv1_0, - }, - }, - { - Port: 8082, - Protocol: "http", - Services: []structs.IngressService{ - {Name: "s3"}, - }, - TLS: &structs.GatewayTLSConfig{ - Enabled: true, - TLSMaxVersion: types.TLSv1_3, - }, - }, - } - }, []UpdateEvent{ - { - CorrelationID: gatewayServicesWatchID, - Result: &structs.IndexedGatewayServices{ - Services: []*structs.GatewayService{ - { - Service: s1, - Port: 8080, - Protocol: "http", - }, - { - Service: s2, - Port: 8081, - Protocol: "http", - }, - { - Service: s3, - Port: 8082, - Protocol: "http", - }, - }, - }, - }, - { - CorrelationID: "discovery-chain:" + s1UID.String(), - Result: &structs.DiscoveryChainResponse{ - Chain: s1Chain, - }, - }, - { - CorrelationID: "discovery-chain:" + s2UID.String(), - Result: &structs.DiscoveryChainResponse{ - Chain: s2Chain, - }, - }, - { - CorrelationID: "discovery-chain:" + s3UID.String(), - Result: &structs.DiscoveryChainResponse{ - Chain: s3Chain, - }, - }, - { - CorrelationID: "upstream-target:" + s1Chain.ID() + ":" + s1UID.String(), - Result: &structs.IndexedCheckServiceNodes{ - Nodes: TestUpstreamNodes(t, "s1"), - }, - }, - { - CorrelationID: "upstream-target:" + s2Chain.ID() + ":" + s2UID.String(), - Result: &structs.IndexedCheckServiceNodes{ - Nodes: TestUpstreamNodes(t, "s2"), - }, - }, - { - CorrelationID: "upstream-target:" + s3Chain.ID() + ":" + s3UID.String(), - Result: &structs.IndexedCheckServiceNodes{ - Nodes: TestUpstreamNodes(t, "s3"), - }, - }, - }) -} - -func TestConfigSnapshotIngressGateway_TLSMixedCipherVersionListeners(t testing.T) *ConfigSnapshot { - var ( - s1 = structs.NewServiceName("s1", nil) - s1UID = NewUpstreamIDFromServiceName(s1) - s1Chain = discoverychain.TestCompileConfigEntries(t, "s1", "default", "default", "dc1", connect.TestClusterID+".consul", nil, nil) - - s2 = structs.NewServiceName("s2", nil) - s2UID = NewUpstreamIDFromServiceName(s2) - s2Chain = discoverychain.TestCompileConfigEntries(t, "s2", "default", "default", "dc1", connect.TestClusterID+".consul", nil, nil) - ) - - return TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, - func(entry *structs.IngressGatewayConfigEntry) { - entry.TLS.Enabled = true - entry.TLS.CipherSuites = []types.TLSCipherSuite{ - types.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - } - - // One listener should inherit TLS Ciphers from the gateway config, - // the other should be set explicitly from the listener config - entry.Listeners = []structs.IngressListener{ - { - Port: 8080, - Protocol: "http", - Services: []structs.IngressService{ - {Name: "s1"}, - }, - }, - { - Port: 8081, - Protocol: "http", - Services: []structs.IngressService{ - {Name: "s2"}, - }, - TLS: &structs.GatewayTLSConfig{ - Enabled: true, - CipherSuites: []types.TLSCipherSuite{ - types.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, - types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, - }, - }, - }, - } - }, []UpdateEvent{ - { - CorrelationID: gatewayServicesWatchID, - Result: &structs.IndexedGatewayServices{ - // One listener should inherit TLS minimum version from the gateway config, - // two others each set explicit TLS minimum versions - Services: []*structs.GatewayService{ - { - Service: s1, - Port: 8080, - Protocol: "http", - }, - { - Service: s2, - Port: 8081, - Protocol: "http", - }, - }, - }, - }, - { - CorrelationID: "discovery-chain:" + s1UID.String(), - Result: &structs.DiscoveryChainResponse{ - Chain: s1Chain, - }, - }, - { - CorrelationID: "discovery-chain:" + s2UID.String(), - Result: &structs.DiscoveryChainResponse{ - Chain: s2Chain, - }, - }, - { - CorrelationID: "upstream-target:" + s1Chain.ID() + ":" + s1UID.String(), - Result: &structs.IndexedCheckServiceNodes{ - Nodes: TestUpstreamNodes(t, "s1"), - }, - }, - { - CorrelationID: "upstream-target:" + s2Chain.ID() + ":" + s2UID.String(), - Result: &structs.IndexedCheckServiceNodes{ - Nodes: TestUpstreamNodes(t, "s2"), - }, - }, - }) -} diff --git a/agent/proxycfg/testing_mesh_gateway.go b/agent/proxycfg/testing_mesh_gateway.go index 865e219cd4350..0ad9d4524afe7 100644 --- a/agent/proxycfg/testing_mesh_gateway.go +++ b/agent/proxycfg/testing_mesh_gateway.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg @@ -23,10 +23,9 @@ func TestConfigSnapshotMeshGateway(t testing.T, variant string, nsFn func(ns *st roots, _ := TestCertsForMeshGateway(t) var ( - populateServices = true - useFederationStates = false - deleteCrossDCEntry = false - meshGatewayFederation = false + populateServices = true + useFederationStates = false + deleteCrossDCEntry = false ) switch variant { @@ -35,11 +34,6 @@ func TestConfigSnapshotMeshGateway(t testing.T, variant string, nsFn func(ns *st populateServices = true useFederationStates = true deleteCrossDCEntry = true - case "mesh-gateway-federation": - populateServices = true - useFederationStates = true - deleteCrossDCEntry = true - meshGatewayFederation = true case "newer-info-in-federation-states": populateServices = true useFederationStates = true @@ -453,63 +447,6 @@ func TestConfigSnapshotMeshGateway(t testing.T, variant string, nsFn func(ns *st }) } - var serverSNIFn ServerSNIFunc - if meshGatewayFederation { - - // reproduced from tlsutil/config.go - serverSNIFn = func(dc, nodeName string) string { - // Strip the trailing '.' from the domain if any - domain := "consul" - - if nodeName == "" || nodeName == "*" { - return "server." + dc + "." + domain - } - - return nodeName + ".server." + dc + "." + domain - } - - baseEvents = testSpliceEvents(baseEvents, []UpdateEvent{ - { - CorrelationID: consulServerListWatchID, - Result: &structs.IndexedCheckServiceNodes{ - Nodes: structs.CheckServiceNodes{ - { - Node: &structs.Node{ - Datacenter: "dc1", - Node: "node1", - Address: "127.0.0.1", - }, - Service: &structs.NodeService{ - ID: structs.ConsulServiceID, - Service: structs.ConsulServiceName, - Meta: map[string]string{ - "grpc_port": "8502", - "grpc_tls_port": "8503", - }, - }, - }, - { - Node: &structs.Node{ - Datacenter: "dc1", - Node: "node2", - Address: "127.0.0.2", - }, - Service: &structs.NodeService{ - ID: structs.ConsulServiceID, - Service: structs.ConsulServiceName, - Meta: map[string]string{ - "grpc_port": "8502", - "grpc_tls_port": "8503", - }, - }, - }, - }, - }, - }, - }) - - } - return testConfigSnapshotFixture(t, &structs.NodeService{ Kind: structs.ServiceKindMeshGateway, Service: "mesh-gateway", @@ -529,7 +466,7 @@ func TestConfigSnapshotMeshGateway(t testing.T, variant string, nsFn func(ns *st Port: 443, }, }, - }, nsFn, serverSNIFn, testSpliceEvents(baseEvents, extraUpdates)) + }, nsFn, nil, testSpliceEvents(baseEvents, extraUpdates)) } func TestConfigSnapshotPeeredMeshGateway(t testing.T, variant string, nsFn func(ns *structs.NodeService), extraUpdates []UpdateEvent) *ConfigSnapshot { @@ -747,73 +684,6 @@ func TestConfigSnapshotPeeredMeshGateway(t testing.T, variant string, nsFn func( }, }, ) - case "mgw-peered-upstream": - // This is a modified version of "chain-and-l7-stuff" that adds a peer field to the resolver - // and removes some of the extraneous disco-chain testing. - entries = []structs.ConfigEntry{ - &structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, - Config: map[string]interface{}{ - "protocol": "http", - }, - }, - &structs.ServiceResolverConfigEntry{ - Kind: structs.ServiceResolver, - Name: "db", - Redirect: &structs.ServiceResolverRedirect{ - Service: "alt", - Peer: "peer-b", - }, - ConnectTimeout: 33 * time.Second, - RequestTimeout: 33 * time.Second, - }, - } - for _, entry := range entries { - require.NoError(t, entry.Normalize()) - require.NoError(t, entry.Validate()) - } - - set := configentry.NewDiscoveryChainSet() - set.AddEntries(entries...) - - var ( - dbSN = structs.NewServiceName("db", nil) - altSN = structs.NewServiceName("alt", nil) - - dbChain = discoverychain.TestCompileConfigEntries(t, "db", "default", "default", "dc1", connect.TestClusterID+".consul", nil, set) - ) - - needPeerA = true - needLeaf = true - discoChains[dbSN] = dbChain - endpoints[dbSN] = TestUpstreamNodes(t, "db") - endpoints[altSN] = TestUpstreamNodes(t, "alt") - - extraUpdates = append(extraUpdates, - UpdateEvent{ - CorrelationID: datacentersWatchID, - Result: &[]string{"dc1"}, - }, - UpdateEvent{ - CorrelationID: exportedServiceListWatchID, - Result: &structs.IndexedExportedServiceList{ - Services: map[string]structs.ServiceList{ - "peer-a": []structs.ServiceName{dbSN}, - }, - }, - }, - UpdateEvent{ - CorrelationID: serviceListWatchID, - Result: &structs.IndexedServiceList{ - Services: []structs.ServiceName{ - dbSN, - altSN, - }, - }, - }, - ) - case "chain-and-l7-stuff": entries = []structs.ConfigEntry{ &structs.ProxyConfigEntry{ @@ -833,12 +703,8 @@ func TestConfigSnapshotPeeredMeshGateway(t testing.T, variant string, nsFn func( Kind: structs.ServiceResolver, Name: "api", Subsets: map[string]structs.ServiceResolverSubset{ - "v1": { - Filter: "Service.Meta.Version == 1", - }, "v2": { - Filter: "Service.Meta.Version == 2", - OnlyPassing: true, + Filter: "Service.Meta.version == v2", }, }, }, @@ -888,7 +754,6 @@ func TestConfigSnapshotPeeredMeshGateway(t testing.T, variant string, nsFn func( var ( dbSN = structs.NewServiceName("db", nil) altSN = structs.NewServiceName("alt", nil) - apiSN = structs.NewServiceName("api", nil) dbChain = discoverychain.TestCompileConfigEntries(t, "db", "default", "default", "dc1", connect.TestClusterID+".consul", nil, set) ) @@ -898,7 +763,6 @@ func TestConfigSnapshotPeeredMeshGateway(t testing.T, variant string, nsFn func( discoChains[dbSN] = dbChain endpoints[dbSN] = TestUpstreamNodes(t, "db") endpoints[altSN] = TestUpstreamNodes(t, "alt") - endpoints[apiSN] = TestUpstreamNodesWithServiceSubset(t, "api") extraUpdates = append(extraUpdates, UpdateEvent{ @@ -922,29 +786,7 @@ func TestConfigSnapshotPeeredMeshGateway(t testing.T, variant string, nsFn func( }, }, }, - UpdateEvent{ - CorrelationID: serviceResolversWatchID, - Result: &structs.IndexedConfigEntries{ - Kind: structs.ServiceResolver, - Entries: []structs.ConfigEntry{ - &structs.ServiceResolverConfigEntry{ - Kind: structs.ServiceResolver, - Name: "api", - Subsets: map[string]structs.ServiceResolverSubset{ - "v1": { - Filter: "Service.Meta.Version == 1", - }, - "v2": { - Filter: "Service.Meta.Version == 2", - OnlyPassing: true, - }, - }, - }, - }, - }, - }, ) - case "peer-through-mesh-gateway": extraUpdates = append(extraUpdates, diff --git a/agent/proxycfg/testing_peering.go b/agent/proxycfg/testing_peering.go index 0af8bafa9f086..9b754c977f2f6 100644 --- a/agent/proxycfg/testing_peering.go +++ b/agent/proxycfg/testing_peering.go @@ -1,32 +1,16 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg import ( - "bytes" - "text/template" - "github.com/mitchellh/go-testing-interface" - "github.com/stretchr/testify/require" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto/private/pbpeering" ) func TestConfigSnapshotPeering(t testing.T) *ConfigSnapshot { - return testConfigSnapshot(t, false, false) -} - -func TestConfigSnapshotPeeringWithEscapeOverrides(t testing.T) *ConfigSnapshot { - return testConfigSnapshot(t, true, false) -} - -func TestConfigSnapshotPeeringWithHTTP2(t testing.T) *ConfigSnapshot { - return testConfigSnapshot(t, false, true) -} - -func testConfigSnapshot(t testing.T, escapeOverride bool, useHTTP2 bool) *ConfigSnapshot { var ( paymentsUpstream = structs.Upstream{ DestinationName: "payments", @@ -43,11 +27,6 @@ func testConfigSnapshot(t testing.T, escapeOverride bool, useHTTP2 bool) *Config refundsUID = NewUpstreamID(&refundsUpstream) ) - protocol := "tcp" - if useHTTP2 { - protocol = "http2" - } - const peerTrustDomain = "1c053652-8512-4373-90cf-5a7f6263a994.consul" return TestConfigSnapshot(t, func(ns *structs.NodeService) { @@ -55,24 +34,6 @@ func testConfigSnapshot(t testing.T, escapeOverride bool, useHTTP2 bool) *Config paymentsUpstream, refundsUpstream, } - - if escapeOverride { - if ns.Proxy.Upstreams[0].Config == nil { - ns.Proxy.Upstreams[0].Config = map[string]interface{}{} - } - - uid := NewUpstreamID(&ns.Proxy.Upstreams[0]) - - ns.Proxy.Upstreams[0].Config["envoy_listener_json"] = - customListenerJSON(t, customListenerJSONOptions{ - Name: uid.EnvoyID() + ":custom-upstream", - }) - ns.Proxy.Upstreams[0].Config["envoy_cluster_json"] = - customClusterJSON(t, customClusterJSONOptions{ - Name: uid.EnvoyID() + ":custom-upstream", - }) - } - }, []UpdateEvent{ { CorrelationID: peerTrustBundleIDPrefix + "cloud", @@ -111,7 +72,7 @@ func testConfigSnapshot(t testing.T, escapeOverride bool, useHTTP2 bool) *Config SpiffeID: []string{ "spiffe://" + peerTrustDomain + "/ns/default/dc/cloud-dc/svc/payments", }, - Protocol: protocol, + Protocol: "tcp", }, }, }, @@ -140,7 +101,7 @@ func testConfigSnapshot(t testing.T, escapeOverride bool, useHTTP2 bool) *Config SpiffeID: []string{ "spiffe://" + peerTrustDomain + "/ns/default/dc/cloud-dc/svc/refunds", }, - Protocol: protocol, + Protocol: "tcp", }, }, }, @@ -419,93 +380,3 @@ func TestConfigSnapshotPeeringLocalMeshGateway(t testing.T) *ConfigSnapshot { }, }) } - -var ( - customListenerJSONTemplate = template.Must(template.New("").Parse(customListenerJSONTpl)) -) - -func customListenerJSON(t testing.T, opts customListenerJSONOptions) string { - t.Helper() - var buf bytes.Buffer - require.NoError(t, customListenerJSONTemplate.Execute(&buf, opts)) - return buf.String() -} - -type customListenerJSONOptions struct { - Name string - TLSContext string -} - -const customListenerJSONTpl = `{ - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "{{ .Name }}", - "address": { - "socketAddress": { - "address": "11.11.11.11", - "portValue": 11111 - } - }, - "filterChains": [ - { - {{ if .TLSContext -}} - "transport_socket": { - "name": "tls", - "typed_config": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - {{ .TLSContext }} - } - }, - {{- end }} - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "cluster": "random-cluster", - "statPrefix": "foo-stats" - } - } - ] - } - ] -}` - -type customClusterJSONOptions struct { - Name string - TLSContext string -} - -var customClusterJSONTpl = `{ - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "{{ .Name }}", - "connectTimeout": "15s", - "loadAssignment": { - "clusterName": "{{ .Name }}", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8443 - } - } - } - } - ] - } - ] - } -}` - -var customClusterJSONTemplate = template.Must(template.New("").Parse(customClusterJSONTpl)) - -func customClusterJSON(t testing.T, opts customClusterJSONOptions) string { - t.Helper() - var buf bytes.Buffer - err := customClusterJSONTemplate.Execute(&buf, opts) - require.NoError(t, err) - return buf.String() -} diff --git a/agent/proxycfg/testing_terminating_gateway.go b/agent/proxycfg/testing_terminating_gateway.go index 6a718779943f6..2bfdd8fca043a 100644 --- a/agent/proxycfg/testing_terminating_gateway.go +++ b/agent/proxycfg/testing_terminating_gateway.go @@ -1,11 +1,9 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg import ( - "time" - "github.com/mitchellh/go-testing-interface" "github.com/hashicorp/consul/agent/structs" @@ -650,7 +648,6 @@ func testConfigSnapshotTerminatingGatewayLBConfig(t testing.T, variant string) * OnlyPassing: true, }, }, - RequestTimeout: 200 * time.Millisecond, LoadBalancer: &structs.LoadBalancer{ Policy: "ring_hash", RingHashConfig: &structs.RingHashConfig{ diff --git a/agent/proxycfg/testing_tproxy.go b/agent/proxycfg/testing_tproxy.go index 9c1c0934e2b87..52bbf2f5ec3e4 100644 --- a/agent/proxycfg/testing_tproxy.go +++ b/agent/proxycfg/testing_tproxy.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg diff --git a/agent/proxycfg/testing_upstreams.go b/agent/proxycfg/testing_upstreams.go index aa8c6c2e04d65..f9b77c4d62d5c 100644 --- a/agent/proxycfg/testing_upstreams.go +++ b/agent/proxycfg/testing_upstreams.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg @@ -256,9 +256,6 @@ func setupTestVariationConfigEntriesAndSnapshot( case "chain-and-router": case "lb-resolver": case "register-to-terminating-gateway": - case "redirect-to-lb-node": - case "resolver-with-lb": - case "splitter-overweight": default: extraEvents := extraUpdateEvents(t, variation, dbUID) events = append(events, extraEvents...) @@ -583,61 +580,6 @@ func setupTestVariationDiscoveryChain( }, }, ) - case "splitter-overweight": - entries = append(entries, - &structs.ServiceResolverConfigEntry{ - Kind: structs.ServiceResolver, - Name: "db", - EnterpriseMeta: entMeta, - ConnectTimeout: 33 * time.Second, - RequestTimeout: 33 * time.Second, - }, - &structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, - EnterpriseMeta: entMeta, - Config: map[string]interface{}{ - "protocol": "http", - }, - }, - &structs.ServiceSplitterConfigEntry{ - Kind: structs.ServiceSplitter, - Name: "db", - EnterpriseMeta: entMeta, - Splits: []structs.ServiceSplit{ - { - Weight: 100.0, - Service: "big-side", - RequestHeaders: &structs.HTTPHeaderModifiers{ - Set: map[string]string{"x-split-leg": "big"}, - }, - ResponseHeaders: &structs.HTTPHeaderModifiers{ - Set: map[string]string{"x-split-leg": "big"}, - }, - }, - { - Weight: 100.0, - Service: "goldilocks-side", - RequestHeaders: &structs.HTTPHeaderModifiers{ - Set: map[string]string{"x-split-leg": "goldilocks"}, - }, - ResponseHeaders: &structs.HTTPHeaderModifiers{ - Set: map[string]string{"x-split-leg": "goldilocks"}, - }, - }, - { - Weight: 100.0, - Service: "lil-bit-side", - RequestHeaders: &structs.HTTPHeaderModifiers{ - Set: map[string]string{"x-split-leg": "small"}, - }, - ResponseHeaders: &structs.HTTPHeaderModifiers{ - Set: map[string]string{"x-split-leg": "small"}, - }, - }, - }, - }, - ) case "grpc-router": entries = append(entries, &structs.ServiceResolverConfigEntry{ @@ -975,74 +917,12 @@ func setupTestVariationDiscoveryChain( Field: "header", FieldValue: "x-user-id", }, - { - Field: "query_parameter", - FieldValue: "my-pretty-param", - }, { SourceIP: true, Terminal: true, }, }, }, - }) - case "redirect-to-lb-node": - entries = append(entries, - &structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, - EnterpriseMeta: entMeta, - Config: map[string]interface{}{ - "protocol": "http", - }, - }, - &structs.ServiceRouterConfigEntry{ - Kind: structs.ServiceRouter, - Name: "db", - EnterpriseMeta: entMeta, - Routes: []structs.ServiceRoute{ - { - Match: httpMatch(&structs.ServiceRouteHTTPMatch{ - PathPrefix: "/web", - }), - Destination: toService("web"), - }, - }, - }, - &structs.ServiceResolverConfigEntry{ - Kind: structs.ServiceResolver, - Name: "web", - EnterpriseMeta: entMeta, - LoadBalancer: &structs.LoadBalancer{ - Policy: "ring_hash", - RingHashConfig: &structs.RingHashConfig{ - MinimumRingSize: 20, - MaximumRingSize: 30, - }, - }, - }, - ) - case "resolver-with-lb": - entries = append(entries, - &structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, - EnterpriseMeta: entMeta, - Config: map[string]interface{}{ - "protocol": "http", - }, - }, - &structs.ServiceResolverConfigEntry{ - Kind: structs.ServiceResolver, - Name: "db", - EnterpriseMeta: entMeta, - LoadBalancer: &structs.LoadBalancer{ - Policy: "ring_hash", - RingHashConfig: &structs.RingHashConfig{ - MinimumRingSize: 20, - MaximumRingSize: 30, - }, - }, }, ) default: diff --git a/agent/proxycfg/testing_upstreams_ce.go b/agent/proxycfg/testing_upstreams_ce.go index 711a2794b6305..3b8e22d0bda8b 100644 --- a/agent/proxycfg/testing_upstreams_ce.go +++ b/agent/proxycfg/testing_upstreams_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/proxycfg/upstreams.go b/agent/proxycfg/upstreams.go index ff2cbd212aca2..3364b0cfe1038 100644 --- a/agent/proxycfg/upstreams.go +++ b/agent/proxycfg/upstreams.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxycfg @@ -136,6 +136,10 @@ func (s *handlerUpstreams) handleUpdateUpstreams(ctx context.Context, u UpdateEv uid := UpstreamIDFromString(uidString) + s.logger.Debug("upstream-target watch fired", + "correlationID", correlationID, + "nodes", len(resp.Nodes), + ) if _, ok := upstreamsSnapshot.WatchedUpstreamEndpoints[uid]; !ok { upstreamsSnapshot.WatchedUpstreamEndpoints[uid] = make(map[string]structs.CheckServiceNodes) } diff --git a/agent/proxycfg_test.go b/agent/proxycfg_test.go index d3bc15c7d4484..334af2cca0acc 100644 --- a/agent/proxycfg_test.go +++ b/agent/proxycfg_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent @@ -13,11 +13,9 @@ import ( "github.com/stretchr/testify/require" "github.com/hashicorp/consul/agent/grpc-external/limiter" + "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/internal/mesh" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" "github.com/hashicorp/consul/testrpc" ) @@ -54,7 +52,7 @@ func TestAgent_local_proxycfg(t *testing.T) { // This is a little gross, but this gives us the layered pair of // local/catalog sources for now. - cfg := a.xdsServer.ProxyWatcher + cfg := a.xdsServer.CfgSrc var ( timer = time.After(100 * time.Millisecond) @@ -64,9 +62,9 @@ func TestAgent_local_proxycfg(t *testing.T) { var ( firstTime = true - ch <-chan proxysnapshot.ProxySnapshot + ch <-chan *proxycfg.ConfigSnapshot stc limiter.SessionTerminatedChan - cancel proxysnapshot.CancelFunc + cancel proxycfg.CancelFunc ) defer func() { if cancel != nil { @@ -87,7 +85,7 @@ func TestAgent_local_proxycfg(t *testing.T) { // Prior to fixes in https://github.com/hashicorp/consul/pull/16497 // this call to Watch() would deadlock. var err error - ch, stc, cancel, err = cfg.Watch(rtest.Resource(mesh.ProxyConfigurationType, sid.ID).ID(), a.config.NodeName, token) + ch, stc, cancel, err = cfg.Watch(sid, a.config.NodeName, token) require.NoError(t, err) } select { diff --git a/agent/reload.go b/agent/reload.go index cf68481621bc5..ce31fd1a76c1c 100644 --- a/agent/reload.go +++ b/agent/reload.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/remote_exec.go b/agent/remote_exec.go index 876c1898620cd..770221ed2622f 100644 --- a/agent/remote_exec.go +++ b/agent/remote_exec.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/remote_exec_test.go b/agent/remote_exec_test.go index f077de895a396..9994095078d16 100644 --- a/agent/remote_exec_test.go +++ b/agent/remote_exec_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/retry_join.go b/agent/retry_join.go index eb010c0c22c47..a629aa04706e8 100644 --- a/agent/retry_join.go +++ b/agent/retry_join.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/retry_join_test.go b/agent/retry_join_test.go index 4184ab0a9f3df..af90205965b21 100644 --- a/agent/retry_join_test.go +++ b/agent/retry_join_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/router/grpc.go b/agent/router/grpc.go index ce3f079e86b97..9fe6355d4dcf1 100644 --- a/agent/router/grpc.go +++ b/agent/router/grpc.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package router diff --git a/agent/router/manager.go b/agent/router/manager.go index 07d55127f3c8b..cccbc27d081a5 100644 --- a/agent/router/manager.go +++ b/agent/router/manager.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package servers provides a Manager interface for Manager managed // metadata.Server objects. The servers package manages servers from a Consul diff --git a/agent/router/manager_internal_test.go b/agent/router/manager_internal_test.go index 120a5f012c630..0e1fa28189a6d 100644 --- a/agent/router/manager_internal_test.go +++ b/agent/router/manager_internal_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package router diff --git a/agent/router/manager_test.go b/agent/router/manager_test.go index 6490164fda10c..708bb620a0da0 100644 --- a/agent/router/manager_test.go +++ b/agent/router/manager_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package router_test diff --git a/agent/router/router.go b/agent/router/router.go index c261b6ed7cd52..bdba22f42d41b 100644 --- a/agent/router/router.go +++ b/agent/router/router.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package router diff --git a/agent/router/router_test.go b/agent/router/router_test.go index 206b0befe811c..1064dea342a32 100644 --- a/agent/router/router_test.go +++ b/agent/router/router_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package router diff --git a/agent/router/serf_adapter.go b/agent/router/serf_adapter.go index d3a228ca3d5d7..f30449dc05dff 100644 --- a/agent/router/serf_adapter.go +++ b/agent/router/serf_adapter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package router diff --git a/agent/router/serf_flooder.go b/agent/router/serf_flooder.go index 06d59d5c4a89d..34ef318377faa 100644 --- a/agent/router/serf_flooder.go +++ b/agent/router/serf_flooder.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package router diff --git a/agent/routine-leak-checker/leak_test.go b/agent/routine-leak-checker/leak_test.go index f6b3c2a74953c..91d84b071b3f3 100644 --- a/agent/routine-leak-checker/leak_test.go +++ b/agent/routine-leak-checker/leak_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package leakcheck diff --git a/agent/rpc/middleware/interceptors.go b/agent/rpc/middleware/interceptors.go index 1e4a4e591fb27..f614e06cea768 100644 --- a/agent/rpc/middleware/interceptors.go +++ b/agent/rpc/middleware/interceptors.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package middleware diff --git a/agent/rpc/middleware/interceptors_test.go b/agent/rpc/middleware/interceptors_test.go index a8e07c8d4d2ba..a22837fc6d952 100644 --- a/agent/rpc/middleware/interceptors_test.go +++ b/agent/rpc/middleware/interceptors_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package middleware diff --git a/agent/rpc/middleware/rate_limit_mappings.go b/agent/rpc/middleware/rate_limit_mappings.go index f9ca6a3333018..0df249c932338 100644 --- a/agent/rpc/middleware/rate_limit_mappings.go +++ b/agent/rpc/middleware/rate_limit_mappings.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package middleware diff --git a/agent/rpc/middleware/recovery.go b/agent/rpc/middleware/recovery.go index 6c23eb3ed3fa6..df37f969d4120 100644 --- a/agent/rpc/middleware/recovery.go +++ b/agent/rpc/middleware/recovery.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package middleware diff --git a/agent/rpc/operator/service.go b/agent/rpc/operator/service.go index 697b0db254321..6b3302c9f2e46 100644 --- a/agent/rpc/operator/service.go +++ b/agent/rpc/operator/service.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package operator diff --git a/agent/rpc/operator/service_test.go b/agent/rpc/operator/service_test.go index 3cc9e117d4425..465a6d6428d29 100644 --- a/agent/rpc/operator/service_test.go +++ b/agent/rpc/operator/service_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package operator diff --git a/agent/rpc/peering/service.go b/agent/rpc/peering/service.go index d57e0378f98c0..cae0319a62dd1 100644 --- a/agent/rpc/peering/service.go +++ b/agent/rpc/peering/service.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peering diff --git a/agent/rpc/peering/service_ce_test.go b/agent/rpc/peering/service_ce_test.go index 92fb9fac45d2f..d4e5fab0ba40e 100644 --- a/agent/rpc/peering/service_ce_test.go +++ b/agent/rpc/peering/service_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/rpc/peering/service_test.go b/agent/rpc/peering/service_test.go index 8fde278c8b7f8..9ae1f6597700a 100644 --- a/agent/rpc/peering/service_test.go +++ b/agent/rpc/peering/service_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peering_test @@ -15,8 +15,6 @@ import ( "testing" "time" - "github.com/hashicorp/consul/internal/resource" - "github.com/google/tcpproxy" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-uuid" @@ -1820,7 +1818,7 @@ func newTestServer(t *testing.T, cb func(conf *consul.Config)) testingServer { deps := newDefaultDeps(t, conf) externalGRPCServer := external.NewServer(deps.Logger, nil, deps.TLSConfigurator, rate.NullRequestLimitsHandler()) - server, err := consul.NewServer(conf, deps, externalGRPCServer, nil, deps.Logger, nil) + server, err := consul.NewServer(conf, deps, externalGRPCServer, nil, deps.Logger) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, server.Shutdown()) @@ -1952,7 +1950,6 @@ func newDefaultDeps(t *testing.T, c *consul.Config) consul.Deps { NewRequestRecorderFunc: middleware.NewRequestRecorder, GetNetRPCInterceptorFunc: middleware.GetNetRPCInterceptor, XDSStreamLimiter: limiter.NewSessionLimiter(), - Registry: resource.NewRegistry(), } } diff --git a/agent/rpc/peering/testing.go b/agent/rpc/peering/testing.go index 8989950ee29be..ddd9d43a8ad27 100644 --- a/agent/rpc/peering/testing.go +++ b/agent/rpc/peering/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peering diff --git a/agent/rpc/peering/testutil_ce_test.go b/agent/rpc/peering/testutil_ce_test.go index 4602c01fc5abe..d15d62e9f1cb1 100644 --- a/agent/rpc/peering/testutil_ce_test.go +++ b/agent/rpc/peering/testutil_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/rpc/peering/validate.go b/agent/rpc/peering/validate.go index 2de6684d85ff9..1bd3f393bd748 100644 --- a/agent/rpc/peering/validate.go +++ b/agent/rpc/peering/validate.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peering diff --git a/agent/rpc/peering/validate_test.go b/agent/rpc/peering/validate_test.go index 669baf41702fc..c5b3c6c7bdb08 100644 --- a/agent/rpc/peering/validate_test.go +++ b/agent/rpc/peering/validate_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peering diff --git a/agent/rpcclient/common.go b/agent/rpcclient/common.go index 316fb341a9356..8ff1573992362 100644 --- a/agent/rpcclient/common.go +++ b/agent/rpcclient/common.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package rpcclient diff --git a/agent/rpcclient/configentry/configentry.go b/agent/rpcclient/configentry/configentry.go index 2b38455beb074..ada7928dc1af7 100644 --- a/agent/rpcclient/configentry/configentry.go +++ b/agent/rpcclient/configentry/configentry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package configentry diff --git a/agent/rpcclient/configentry/configentry_test.go b/agent/rpcclient/configentry/configentry_test.go index 92e6f4b3c88ae..9f526892fd11a 100644 --- a/agent/rpcclient/configentry/configentry_test.go +++ b/agent/rpcclient/configentry/configentry_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package configentry diff --git a/agent/rpcclient/configentry/view.go b/agent/rpcclient/configentry/view.go index 70271a9220e97..dae3208810bfa 100644 --- a/agent/rpcclient/configentry/view.go +++ b/agent/rpcclient/configentry/view.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package configentry diff --git a/agent/rpcclient/configentry/view_test.go b/agent/rpcclient/configentry/view_test.go index 0209c898cafed..37e642e5c36c1 100644 --- a/agent/rpcclient/configentry/view_test.go +++ b/agent/rpcclient/configentry/view_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package configentry diff --git a/agent/rpcclient/health/health.go b/agent/rpcclient/health/health.go index f062d2aac284e..8a65a50578aad 100644 --- a/agent/rpcclient/health/health.go +++ b/agent/rpcclient/health/health.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package health diff --git a/agent/rpcclient/health/health_test.go b/agent/rpcclient/health/health_test.go index 30900bc04cc01..2d8c57a3beba5 100644 --- a/agent/rpcclient/health/health_test.go +++ b/agent/rpcclient/health/health_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package health diff --git a/agent/rpcclient/health/streaming_test.go b/agent/rpcclient/health/streaming_test.go index 180b61f0eec65..3a0ba734ba9ab 100644 --- a/agent/rpcclient/health/streaming_test.go +++ b/agent/rpcclient/health/streaming_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package health diff --git a/agent/rpcclient/health/view.go b/agent/rpcclient/health/view.go index 8e08ba801e5f1..e1fffd3e23de6 100644 --- a/agent/rpcclient/health/view.go +++ b/agent/rpcclient/health/view.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package health diff --git a/agent/rpcclient/health/view_test.go b/agent/rpcclient/health/view_test.go index 83eba5ab41a07..6b4b8ee85798d 100644 --- a/agent/rpcclient/health/view_test.go +++ b/agent/rpcclient/health/view_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package health diff --git a/agent/service_checks_test.go b/agent/service_checks_test.go index 41372cc47dbbe..c567776587e36 100644 --- a/agent/service_checks_test.go +++ b/agent/service_checks_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/service_manager.go b/agent/service_manager.go index 1c6041f8f0de8..b7e38b393ace2 100644 --- a/agent/service_manager.go +++ b/agent/service_manager.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/service_manager_test.go b/agent/service_manager_test.go index 289503a51ede4..724022d42ad90 100644 --- a/agent/service_manager_test.go +++ b/agent/service_manager_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/session_endpoint.go b/agent/session_endpoint.go index 90c3fa32bae7e..a9b9a6dee6baa 100644 --- a/agent/session_endpoint.go +++ b/agent/session_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/session_endpoint_test.go b/agent/session_endpoint_test.go index ae5a492808d7c..5ce93db7a68fe 100644 --- a/agent/session_endpoint_test.go +++ b/agent/session_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/setup.go b/agent/setup.go index 7a95ba6bf5411..88c883f9bdb71 100644 --- a/agent/setup.go +++ b/agent/setup.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent @@ -260,8 +260,6 @@ func NewBaseDeps(configLoader ConfigLoader, logOut io.Writer, providedLogger hcl d.XDSStreamLimiter = limiter.NewSessionLimiter() - d.Registry = consul.NewTypeRegistry() - return d, nil } diff --git a/agent/setup_ce.go b/agent/setup_ce.go index af24a1515e6be..46c4b80eb4efb 100644 --- a/agent/setup_ce.go +++ b/agent/setup_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/sidecar_service.go b/agent/sidecar_service.go index 8e57d5930bc11..7dfb067b50ef0 100644 --- a/agent/sidecar_service.go +++ b/agent/sidecar_service.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/sidecar_service_test.go b/agent/sidecar_service_test.go index fd39a5a284a10..4960dd73d0542 100644 --- a/agent/sidecar_service_test.go +++ b/agent/sidecar_service_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/signal_unix.go b/agent/signal_unix.go index 83e00f27b351d..bd0b3e7793cdd 100644 --- a/agent/signal_unix.go +++ b/agent/signal_unix.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !windows // +build !windows diff --git a/agent/signal_windows.go b/agent/signal_windows.go index cb49a169c09a0..c6ea0c980ffb6 100644 --- a/agent/signal_windows.go +++ b/agent/signal_windows.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build windows // +build windows diff --git a/agent/snapshot_endpoint.go b/agent/snapshot_endpoint.go index 06805ae5f8c19..60d986256433b 100644 --- a/agent/snapshot_endpoint.go +++ b/agent/snapshot_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/snapshot_endpoint_test.go b/agent/snapshot_endpoint_test.go index a534fe0251135..e68fb22f385fd 100644 --- a/agent/snapshot_endpoint_test.go +++ b/agent/snapshot_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/status_endpoint.go b/agent/status_endpoint.go index 4a40ec8910270..86f9f1a5d0193 100644 --- a/agent/status_endpoint.go +++ b/agent/status_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/status_endpoint_test.go b/agent/status_endpoint_test.go index db231fbc9b834..5be9d6be64a3e 100644 --- a/agent/status_endpoint_test.go +++ b/agent/status_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/streaming_test.go b/agent/streaming_test.go index fed1e8126d41d..9074f66e83441 100644 --- a/agent/streaming_test.go +++ b/agent/streaming_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/structs/acl.go b/agent/structs/acl.go index 813a3b1758438..f34291cc4d5cb 100644 --- a/agent/structs/acl.go +++ b/agent/structs/acl.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs @@ -1305,6 +1305,7 @@ type ACLTokenListRequest struct { Policy string // Policy filter Role string // Role filter AuthMethod string // Auth Method filter + ServiceName string // Service name (from service identities) filter Datacenter string // The datacenter to perform the request within ACLAuthMethodEnterpriseMeta acl.EnterpriseMeta @@ -1323,7 +1324,7 @@ type ACLTokenListResponse struct { } // ACLTokenBatchGetRequest is used for reading multiple tokens, this is -// different from the token list request in that only tokens with the +// different from the the token list request in that only tokens with the // the requested ids are returned type ACLTokenBatchGetRequest struct { AccessorIDs []string // List of accessor ids to fetch diff --git a/agent/structs/acl_cache.go b/agent/structs/acl_cache.go index 15f3a2edc3c26..46d4fdd28117b 100644 --- a/agent/structs/acl_cache.go +++ b/agent/structs/acl_cache.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/acl_cache_test.go b/agent/structs/acl_cache_test.go index 57e218ff21e32..e390da960f4ed 100644 --- a/agent/structs/acl_cache_test.go +++ b/agent/structs/acl_cache_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/acl_ce.go b/agent/structs/acl_ce.go index 54062047606be..9cc4e7813ce85 100644 --- a/agent/structs/acl_ce.go +++ b/agent/structs/acl_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/acl_test.go b/agent/structs/acl_test.go index e1fb35263b95a..6658b8335021a 100644 --- a/agent/structs/acl_test.go +++ b/agent/structs/acl_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/aclfilter/filter.go b/agent/structs/aclfilter/filter.go index d59bf3c9c403b..ddd63db10e686 100644 --- a/agent/structs/aclfilter/filter.go +++ b/agent/structs/aclfilter/filter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package aclfilter diff --git a/agent/structs/aclfilter/filter_test.go b/agent/structs/aclfilter/filter_test.go index 98f3bb63f291b..2339b0acd223d 100644 --- a/agent/structs/aclfilter/filter_test.go +++ b/agent/structs/aclfilter/filter_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package aclfilter diff --git a/agent/structs/auto_encrypt.go b/agent/structs/auto_encrypt.go index cce7c4effa1e3..2e9053f9a5382 100644 --- a/agent/structs/auto_encrypt.go +++ b/agent/structs/auto_encrypt.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/autopilot.go b/agent/structs/autopilot.go index 431e2ad4d374f..a5a14684fa9e3 100644 --- a/agent/structs/autopilot.go +++ b/agent/structs/autopilot.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/autopilot_ce.go b/agent/structs/autopilot_ce.go index 55420d23e19de..3098c0cf3cae6 100644 --- a/agent/structs/autopilot_ce.go +++ b/agent/structs/autopilot_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/catalog.go b/agent/structs/catalog.go index 84795ce47898d..f11af9f87801b 100644 --- a/agent/structs/catalog.go +++ b/agent/structs/catalog.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/catalog_ce.go b/agent/structs/catalog_ce.go index ad5218bf80ae5..91e08264b99d0 100644 --- a/agent/structs/catalog_ce.go +++ b/agent/structs/catalog_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/check_definition.go b/agent/structs/check_definition.go index ec760832609ab..f28201b4d17f5 100644 --- a/agent/structs/check_definition.go +++ b/agent/structs/check_definition.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs @@ -36,6 +36,7 @@ type CheckDefinition struct { Body string DisableRedirects bool TCP string + TCPUseTLS bool UDP string Interval time.Duration DockerContainerID string @@ -76,6 +77,7 @@ func (t *CheckDefinition) UnmarshalJSON(data []byte) (err error) { DockerContainerIDSnake string `json:"docker_container_id"` TLSServerNameSnake string `json:"tls_server_name"` TLSSkipVerifySnake bool `json:"tls_skip_verify"` + TCPUseTLSSnake bool `json:"tcp_use_tls"` GRPCUseTLSSnake bool `json:"grpc_use_tls"` ServiceIDSnake string `json:"service_id"` H2PingUseTLSSnake bool `json:"h2ping_use_tls"` @@ -119,6 +121,9 @@ func (t *CheckDefinition) UnmarshalJSON(data []byte) (err error) { if aux.TLSSkipVerifySnake { t.TLSSkipVerify = aux.TLSSkipVerifySnake } + if aux.TCPUseTLSSnake { + t.TCPUseTLS = aux.TCPUseTLSSnake + } if aux.GRPCUseTLSSnake { t.GRPCUseTLS = aux.GRPCUseTLSSnake } @@ -220,6 +225,7 @@ func (c *CheckDefinition) CheckType() *CheckType { DisableRedirects: c.DisableRedirects, OutputMaxSize: c.OutputMaxSize, TCP: c.TCP, + TCPUseTLS: c.TCPUseTLS, UDP: c.UDP, Interval: c.Interval, DockerContainerID: c.DockerContainerID, diff --git a/agent/structs/check_definition_test.go b/agent/structs/check_definition_test.go index 5a51f377c0e8f..676499ef042a1 100644 --- a/agent/structs/check_definition_test.go +++ b/agent/structs/check_definition_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/check_type.go b/agent/structs/check_type.go index 96254f62d86e7..e6342e8231f93 100644 --- a/agent/structs/check_type.go +++ b/agent/structs/check_type.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs @@ -42,6 +42,7 @@ type CheckType struct { Body string DisableRedirects bool TCP string + TCPUseTLS bool UDP string Interval time.Duration AliasNode string @@ -87,6 +88,7 @@ func (t *CheckType) UnmarshalJSON(data []byte) (err error) { DockerContainerIDSnake string `json:"docker_container_id"` TLSServerNameSnake string `json:"tls_server_name"` TLSSkipVerifySnake bool `json:"tls_skip_verify"` + TCPUseTLSSnake bool `json:"tcp_use_tls"` GRPCUseTLSSnake bool `json:"grpc_use_tls"` H2PingUseTLSSnake bool `json:"h2ping_use_tls"` @@ -131,6 +133,9 @@ func (t *CheckType) UnmarshalJSON(data []byte) (err error) { if aux.TLSSkipVerifySnake { t.TLSSkipVerify = aux.TLSSkipVerifySnake } + if aux.TCPUseTLSSnake { + t.TCPUseTLS = aux.TCPUseTLSSnake + } if aux.GRPCUseTLSSnake { t.GRPCUseTLS = aux.GRPCUseTLSSnake } diff --git a/agent/structs/config_entry.go b/agent/structs/config_entry.go index 4a38ce2f99d4a..c18a8013b6d45 100644 --- a/agent/structs/config_entry.go +++ b/agent/structs/config_entry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs @@ -165,7 +165,6 @@ type ServiceConfigEntry struct { LocalConnectTimeoutMs int `json:",omitempty" alias:"local_connect_timeout_ms"` LocalRequestTimeoutMs int `json:",omitempty" alias:"local_request_timeout_ms"` BalanceInboundConnections string `json:",omitempty" alias:"balance_inbound_connections"` - RateLimits *RateLimits `json:",omitempty" alias:"rate_limits"` EnvoyExtensions EnvoyExtensions `json:",omitempty" alias:"envoy_extensions"` Meta map[string]string `json:",omitempty"` @@ -287,10 +286,6 @@ func (e *ServiceConfigEntry) Validate() error { } } - if err := validateRatelimit(e.RateLimits); err != nil { - validationErr = multierror.Append(validationErr, err) - } - if err := envoyextensions.ValidateExtensions(e.EnvoyExtensions.ToAPI()); err != nil { validationErr = multierror.Append(validationErr, err) } @@ -387,50 +382,14 @@ type DestinationConfig struct { Port int `json:",omitempty"` } -func IsIP(address string) bool { +func IsHostname(address string) bool { ip := net.ParseIP(address) - return ip != nil + return ip == nil } -// RateLimits is rate limiting configuration that is applied to -// inbound traffic for a service. -// Rate limiting is a Consul enterprise feature. -type RateLimits struct { - InstanceLevel InstanceLevelRateLimits `alias:"instance_level"` -} - -// InstanceLevelRateLimits represents rate limit configuration -// that are applied per service instance. -type InstanceLevelRateLimits struct { - // RequestsPerSecond is the average number of requests per second that can be - // made without being throttled. This field is required if RequestsMaxBurst - // is set. The allowed number of requests may exceed RequestsPerSecond up to - // the value specified in RequestsMaxBurst. - // - // Internally, this is the refill rate of the token bucket used for rate limiting. - RequestsPerSecond int `alias:"requests_per_second"` - - // RequestsMaxBurst is the maximum number of requests that can be sent - // in a burst. Should be equal to or greater than RequestsPerSecond. - // If unset, defaults to RequestsPerSecond. - // - // Internally, this is the maximum size of the token bucket used for rate limiting. - RequestsMaxBurst int `alias:"requests_max_burst"` - - // Routes is a list of rate limits applied to specific routes. - // Overrides any top-level configuration. - Routes []InstanceLevelRouteRateLimits -} - -// InstanceLevelRouteRateLimits represents rate limit configuration -// applied to a route matching one of PathExact/PathPrefix/PathRegex. -type InstanceLevelRouteRateLimits struct { - PathExact string `alias:"path_exact"` - PathPrefix string `alias:"path_prefix"` - PathRegex string `alias:"path_regex"` - - RequestsPerSecond int `alias:"requests_per_second"` - RequestsMaxBurst int `alias:"requests_max_burst"` +func IsIP(address string) bool { + ip := net.ParseIP(address) + return ip != nil } // ProxyConfigEntry is the top-level struct for global proxy configuration defaults. @@ -615,7 +574,7 @@ func (e *ProxyConfigEntry) UnmarshalBinary(data []byte) error { // into a concrete type. // // There is an 'api' variation of this in -// command/helpers/helpers.go:newDecodeConfigEntry +// command/config/write/config_write.go:newDecodeConfigEntry func DecodeConfigEntry(raw map[string]interface{}) (ConfigEntry, error) { var entry ConfigEntry @@ -1259,7 +1218,6 @@ type ServiceConfigResponse struct { Mode ProxyMode `json:",omitempty"` Destination DestinationConfig `json:",omitempty"` AccessLogs AccessLogsConfig `json:",omitempty"` - RateLimits RateLimits `json:",omitempty"` Meta map[string]string `json:",omitempty"` EnvoyExtensions []EnvoyExtension `json:",omitempty"` QueryMeta diff --git a/agent/structs/config_entry_apigw_jwt_ce.go b/agent/structs/config_entry_apigw_jwt_ce.go deleted file mode 100644 index 5c0b40b5c8e1a..0000000000000 --- a/agent/structs/config_entry_apigw_jwt_ce.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package structs - -// APIGatewayJWTRequirement holds the list of JWT providers to be verified against -type APIGatewayJWTRequirement struct{} - -// JWTFilter holds the JWT Filter configuration for an HTTPRoute -type JWTFilter struct{} diff --git a/agent/structs/config_entry_ce.go b/agent/structs/config_entry_ce.go index 0cac27bdbf3e4..2977075bff1b7 100644 --- a/agent/structs/config_entry_ce.go +++ b/agent/structs/config_entry_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent @@ -30,8 +30,6 @@ func validateUnusedKeys(unused []string) error { // to exist on the target. case strings.HasSuffix(strings.ToLower(k), "namespace"): err = multierror.Append(err, fmt.Errorf("invalid config key %q, namespaces are a consul enterprise feature", k)) - case strings.Contains(strings.ToLower(k), "jwt"): - err = multierror.Append(err, fmt.Errorf("invalid config key %q, api-gateway jwt validation is a consul enterprise feature", k)) default: err = multierror.Append(err, fmt.Errorf("invalid config key %q", k)) } @@ -53,12 +51,3 @@ func validateExportedServicesName(name string) error { func makeEnterpriseConfigEntry(kind, name string) ConfigEntry { return nil } - -func validateRatelimit(rl *RateLimits) error { - if rl != nil { - return fmt.Errorf("invalid rate_limits config. Rate limiting is a consul enterprise feature") - } - return nil -} - -func (rl RateLimits) ToEnvoyExtension() *EnvoyExtension { return nil } diff --git a/agent/structs/config_entry_ce_test.go b/agent/structs/config_entry_ce_test.go index fd3ed9d350777..4561f4aae3587 100644 --- a/agent/structs/config_entry_ce_test.go +++ b/agent/structs/config_entry_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/config_entry_discoverychain.go b/agent/structs/config_entry_discoverychain.go index 6dc0a05d8212a..587d98561c4ec 100644 --- a/agent/structs/config_entry_discoverychain.go +++ b/agent/structs/config_entry_discoverychain.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_discoverychain_ce.go b/agent/structs/config_entry_discoverychain_ce.go index bdbe463a5bf04..87c22263794e8 100644 --- a/agent/structs/config_entry_discoverychain_ce.go +++ b/agent/structs/config_entry_discoverychain_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/config_entry_discoverychain_ce_test.go b/agent/structs/config_entry_discoverychain_ce_test.go index 4dda3ff39626e..2edcce2bedd8f 100644 --- a/agent/structs/config_entry_discoverychain_ce_test.go +++ b/agent/structs/config_entry_discoverychain_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/config_entry_discoverychain_test.go b/agent/structs/config_entry_discoverychain_test.go index 5961446d1fb78..7378e20787fea 100644 --- a/agent/structs/config_entry_discoverychain_test.go +++ b/agent/structs/config_entry_discoverychain_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_exports.go b/agent/structs/config_entry_exports.go index 97e33dd6e7059..631773072d0be 100644 --- a/agent/structs/config_entry_exports.go +++ b/agent/structs/config_entry_exports.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_exports_ce.go b/agent/structs/config_entry_exports_ce.go index 770139ee2ef90..9f9bb1cc0825e 100644 --- a/agent/structs/config_entry_exports_ce.go +++ b/agent/structs/config_entry_exports_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/config_entry_exports_ce_test.go b/agent/structs/config_entry_exports_ce_test.go index bd74dfc962529..671654b3b2a4a 100644 --- a/agent/structs/config_entry_exports_ce_test.go +++ b/agent/structs/config_entry_exports_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/config_entry_exports_test.go b/agent/structs/config_entry_exports_test.go index 62e5586a0dac2..7905b46009b79 100644 --- a/agent/structs/config_entry_exports_test.go +++ b/agent/structs/config_entry_exports_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_gateways.go b/agent/structs/config_entry_gateways.go index 00c2687d1ec96..0be410d198708 100644 --- a/agent/structs/config_entry_gateways.go +++ b/agent/structs/config_entry_gateways.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs @@ -887,17 +887,6 @@ type APIGatewayListener struct { Protocol APIGatewayListenerProtocol // TLS is the TLS settings for the listener. TLS APIGatewayTLSConfiguration - - // Override is the policy that overrides all other policy and route specific configuration - Override *APIGatewayPolicy `json:",omitempty"` - // Default is the policy that is the default for the listener and route, routes can override this behavior - Default *APIGatewayPolicy `json:",omitempty"` -} - -// APIGatewayPolicy holds the policy that configures the gateway listener, this is used in the `Override` and `Default` fields of a listener -type APIGatewayPolicy struct { - // JWT holds the JWT configuration for the Listener - JWT *APIGatewayJWTRequirement `json:",omitempty"` } func (l APIGatewayListener) GetHostname() string { diff --git a/agent/structs/config_entry_gateways_test.go b/agent/structs/config_entry_gateways_test.go index f05638ec4d2e2..d624b39acd403 100644 --- a/agent/structs/config_entry_gateways_test.go +++ b/agent/structs/config_entry_gateways_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_inline_certificate.go b/agent/structs/config_entry_inline_certificate.go index f397ee2ba16ec..17ffa9082b6fd 100644 --- a/agent/structs/config_entry_inline_certificate.go +++ b/agent/structs/config_entry_inline_certificate.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs @@ -58,7 +58,6 @@ func (e *InlineCertificateConfigEntry) Validate() error { if privateKeyBlock == nil { return errors.New("failed to parse private key PEM") } - err = validateKeyLength(privateKeyBlock) if err != nil { return err diff --git a/agent/structs/config_entry_inline_certificate_test.go b/agent/structs/config_entry_inline_certificate_test.go index 3c537c059161b..b95f3b0e9694d 100644 --- a/agent/structs/config_entry_inline_certificate_test.go +++ b/agent/structs/config_entry_inline_certificate_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_intentions.go b/agent/structs/config_entry_intentions.go index f32aafa9a87d2..bc4d36863b567 100644 --- a/agent/structs/config_entry_intentions.go +++ b/agent/structs/config_entry_intentions.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_intentions_ce.go b/agent/structs/config_entry_intentions_ce.go index e11063b999d14..3c97b55aac56a 100644 --- a/agent/structs/config_entry_intentions_ce.go +++ b/agent/structs/config_entry_intentions_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/config_entry_intentions_ce_test.go b/agent/structs/config_entry_intentions_ce_test.go index 03f82075e5a65..23d4ded4d2617 100644 --- a/agent/structs/config_entry_intentions_ce_test.go +++ b/agent/structs/config_entry_intentions_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/config_entry_intentions_test.go b/agent/structs/config_entry_intentions_test.go index ea8703de05d86..56c04bb21e3cf 100644 --- a/agent/structs/config_entry_intentions_test.go +++ b/agent/structs/config_entry_intentions_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_jwt_provider.go b/agent/structs/config_entry_jwt_provider.go index 12bc7c89d9ede..7336027d70954 100644 --- a/agent/structs/config_entry_jwt_provider.go +++ b/agent/structs/config_entry_jwt_provider.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_jwt_provider_ce.go b/agent/structs/config_entry_jwt_provider_ce.go index 1473cf95d98a2..533f349c01e52 100644 --- a/agent/structs/config_entry_jwt_provider_ce.go +++ b/agent/structs/config_entry_jwt_provider_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/config_entry_jwt_provider_test.go b/agent/structs/config_entry_jwt_provider_test.go index 6a117fe5084f4..a63507663ce45 100644 --- a/agent/structs/config_entry_jwt_provider_test.go +++ b/agent/structs/config_entry_jwt_provider_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_mesh.go b/agent/structs/config_entry_mesh.go index a531821650d83..249973c00b08e 100644 --- a/agent/structs/config_entry_mesh.go +++ b/agent/structs/config_entry_mesh.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_mesh_ce.go b/agent/structs/config_entry_mesh_ce.go index 319bf6adc109e..1612d65682730 100644 --- a/agent/structs/config_entry_mesh_ce.go +++ b/agent/structs/config_entry_mesh_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/config_entry_mesh_test.go b/agent/structs/config_entry_mesh_test.go index f6eaea9e9c546..6bdfaa15cae80 100644 --- a/agent/structs/config_entry_mesh_test.go +++ b/agent/structs/config_entry_mesh_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_routes.go b/agent/structs/config_entry_routes.go index d285a40624435..4d908331511d4 100644 --- a/agent/structs/config_entry_routes.go +++ b/agent/structs/config_entry_routes.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs @@ -7,7 +7,6 @@ import ( "errors" "fmt" "strings" - "time" "github.com/miekg/dns" @@ -418,11 +417,8 @@ type HTTPQueryMatch struct { // HTTPFilters specifies a list of filters used to modify a request // before it is routed to an upstream. type HTTPFilters struct { - Headers []HTTPHeaderFilter - URLRewrite *URLRewrite - RetryFilter *RetryFilter - TimeoutFilter *TimeoutFilter - JWT *JWTFilter + Headers []HTTPHeaderFilter + URLRewrite *URLRewrite } // HTTPHeaderFilter specifies how HTTP headers should be modified. @@ -436,18 +432,6 @@ type URLRewrite struct { Path string } -type RetryFilter struct { - NumRetries *uint32 - RetryOn []string - RetryOnStatusCodes []uint32 - RetryOnConnectFailure *bool -} - -type TimeoutFilter struct { - RequestTimeout time.Duration - IdleTimeout time.Duration -} - // HTTPRouteRule specifies the routing rules used to determine what upstream // service an HTTP request is routed to. type HTTPRouteRule struct { diff --git a/agent/structs/config_entry_routes_test.go b/agent/structs/config_entry_routes_test.go index 5ab85e5977e9d..476ce46eed05d 100644 --- a/agent/structs/config_entry_routes_test.go +++ b/agent/structs/config_entry_routes_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_sameness_group.go b/agent/structs/config_entry_sameness_group.go index dd1b84aa85ed3..a1d0dccb3c7c1 100644 --- a/agent/structs/config_entry_sameness_group.go +++ b/agent/structs/config_entry_sameness_group.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_sameness_group_ce.go b/agent/structs/config_entry_sameness_group_ce.go index 2fd3a3438de46..282ab862fa3b3 100644 --- a/agent/structs/config_entry_sameness_group_ce.go +++ b/agent/structs/config_entry_sameness_group_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/config_entry_status.go b/agent/structs/config_entry_status.go index 749ba1596868d..fb91a0add3743 100644 --- a/agent/structs/config_entry_status.go +++ b/agent/structs/config_entry_status.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/config_entry_test.go b/agent/structs/config_entry_test.go index 9151ef815b158..cdaae4e23d4bf 100644 --- a/agent/structs/config_entry_test.go +++ b/agent/structs/config_entry_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/connect.go b/agent/structs/connect.go index 4a6033efab57c..227c2eb472702 100644 --- a/agent/structs/connect.go +++ b/agent/structs/connect.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/connect_ca.go b/agent/structs/connect_ca.go index 90e139fab0dcb..c8a7cea1df8ae 100644 --- a/agent/structs/connect_ca.go +++ b/agent/structs/connect_ca.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/connect_ca_test.go b/agent/structs/connect_ca_test.go index 5f224e04f76a6..d64efef375bfd 100644 --- a/agent/structs/connect_ca_test.go +++ b/agent/structs/connect_ca_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/connect_ce.go b/agent/structs/connect_ce.go index b78e8b4c6c23a..9547c245148b0 100644 --- a/agent/structs/connect_ce.go +++ b/agent/structs/connect_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/connect_proxy_config.go b/agent/structs/connect_proxy_config.go index 3bd5276f8279a..acca2ad1cbcd4 100644 --- a/agent/structs/connect_proxy_config.go +++ b/agent/structs/connect_proxy_config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/connect_proxy_config_ce.go b/agent/structs/connect_proxy_config_ce.go index dfdc10bbadcff..898ca163a5c2f 100644 --- a/agent/structs/connect_proxy_config_ce.go +++ b/agent/structs/connect_proxy_config_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/connect_proxy_config_test.go b/agent/structs/connect_proxy_config_test.go index be16d17be6a3c..bcf43b2119ca1 100644 --- a/agent/structs/connect_proxy_config_test.go +++ b/agent/structs/connect_proxy_config_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/deep-copy.sh b/agent/structs/deep-copy.sh index cbc1bdc42ae5d..e4ab69273a473 100755 --- a/agent/structs/deep-copy.sh +++ b/agent/structs/deep-copy.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 readonly PACKAGE_DIR="$(dirname "${BASH_SOURCE[0]}")" diff --git a/agent/structs/discovery_chain.go b/agent/structs/discovery_chain.go index c81dd1ec0836e..029fc3b0a8be8 100644 --- a/agent/structs/discovery_chain.go +++ b/agent/structs/discovery_chain.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/discovery_chain_ce.go b/agent/structs/discovery_chain_ce.go index b4a83b890445e..febff8c7762a7 100644 --- a/agent/structs/discovery_chain_ce.go +++ b/agent/structs/discovery_chain_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/envoy_extension.go b/agent/structs/envoy_extension.go index ab9988bf21bc8..c788aedf37e85 100644 --- a/agent/structs/envoy_extension.go +++ b/agent/structs/envoy_extension.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/errors.go b/agent/structs/errors.go index df8123dc60dab..82e2b0b5f0132 100644 --- a/agent/structs/errors.go +++ b/agent/structs/errors.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/federation_state.go b/agent/structs/federation_state.go index 5a0e8eef6d04d..f123a0954be7e 100644 --- a/agent/structs/federation_state.go +++ b/agent/structs/federation_state.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/identity.go b/agent/structs/identity.go index b55f6bb7ae51d..286dd552a3469 100644 --- a/agent/structs/identity.go +++ b/agent/structs/identity.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/intention.go b/agent/structs/intention.go index 3bbc2584f70fc..21d5432b41123 100644 --- a/agent/structs/intention.go +++ b/agent/structs/intention.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/intention_ce.go b/agent/structs/intention_ce.go index cb657b8e37773..af62df50bca44 100644 --- a/agent/structs/intention_ce.go +++ b/agent/structs/intention_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/intention_test.go b/agent/structs/intention_test.go index 077bef0f200d2..600f600729d13 100644 --- a/agent/structs/intention_test.go +++ b/agent/structs/intention_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/operator.go b/agent/structs/operator.go index 9d78cb92143f8..05862861e3f85 100644 --- a/agent/structs/operator.go +++ b/agent/structs/operator.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/peering.go b/agent/structs/peering.go index 927efabb34c25..3ee7acb224025 100644 --- a/agent/structs/peering.go +++ b/agent/structs/peering.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/prepared_query.go b/agent/structs/prepared_query.go index 1c851c476ef00..71b0eba81bc3e 100644 --- a/agent/structs/prepared_query.go +++ b/agent/structs/prepared_query.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs @@ -341,7 +341,7 @@ type PreparedQueryExecuteRemoteRequest struct { Connect bool // QueryOptions (unfortunately named here) controls the consistency - // settings for the service lookups. + // settings for the the service lookups. QueryOptions } diff --git a/agent/structs/prepared_query_test.go b/agent/structs/prepared_query_test.go index 537c6b043818a..a6d6e64849af0 100644 --- a/agent/structs/prepared_query_test.go +++ b/agent/structs/prepared_query_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/protobuf_compat.go b/agent/structs/protobuf_compat.go index c52d85a32c29f..65ebf2eaf4acd 100644 --- a/agent/structs/protobuf_compat.go +++ b/agent/structs/protobuf_compat.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/service_definition.go b/agent/structs/service_definition.go index 9b9fec89e9540..6ee81af0590c9 100644 --- a/agent/structs/service_definition.go +++ b/agent/structs/service_definition.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/service_definition_test.go b/agent/structs/service_definition_test.go index ec6d4fc5374e9..023972092ff44 100644 --- a/agent/structs/service_definition_test.go +++ b/agent/structs/service_definition_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/snapshot.go b/agent/structs/snapshot.go index 3d71fb093d3c6..4f622216751f0 100644 --- a/agent/structs/snapshot.go +++ b/agent/structs/snapshot.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/structs.deepcopy.go b/agent/structs/structs.deepcopy.go index 0434ba1e67da2..cdd007c26cdb5 100644 --- a/agent/structs/structs.deepcopy.go +++ b/agent/structs/structs.deepcopy.go @@ -18,20 +18,6 @@ func (o *APIGatewayListener) DeepCopy() *APIGatewayListener { cp.TLS.CipherSuites = make([]types.TLSCipherSuite, len(o.TLS.CipherSuites)) copy(cp.TLS.CipherSuites, o.TLS.CipherSuites) } - if o.Override != nil { - cp.Override = new(APIGatewayPolicy) - *cp.Override = *o.Override - if o.Override.JWT != nil { - cp.Override.JWT = o.Override.JWT.DeepCopy() - } - } - if o.Default != nil { - cp.Default = new(APIGatewayPolicy) - *cp.Default = *o.Default - if o.Default.JWT != nil { - cp.Default.JWT = o.Default.JWT.DeepCopy() - } - } return &cp } @@ -397,33 +383,6 @@ func (o *HTTPRouteConfigEntry) DeepCopy() *HTTPRouteConfigEntry { cp.Rules[i2].Filters.URLRewrite = new(URLRewrite) *cp.Rules[i2].Filters.URLRewrite = *o.Rules[i2].Filters.URLRewrite } - if o.Rules[i2].Filters.RetryFilter != nil { - cp.Rules[i2].Filters.RetryFilter = new(RetryFilter) - *cp.Rules[i2].Filters.RetryFilter = *o.Rules[i2].Filters.RetryFilter - if o.Rules[i2].Filters.RetryFilter.NumRetries != nil { - cp.Rules[i2].Filters.RetryFilter.NumRetries = new(uint32) - *cp.Rules[i2].Filters.RetryFilter.NumRetries = *o.Rules[i2].Filters.RetryFilter.NumRetries - } - if o.Rules[i2].Filters.RetryFilter.RetryOn != nil { - cp.Rules[i2].Filters.RetryFilter.RetryOn = make([]string, len(o.Rules[i2].Filters.RetryFilter.RetryOn)) - copy(cp.Rules[i2].Filters.RetryFilter.RetryOn, o.Rules[i2].Filters.RetryFilter.RetryOn) - } - if o.Rules[i2].Filters.RetryFilter.RetryOnStatusCodes != nil { - cp.Rules[i2].Filters.RetryFilter.RetryOnStatusCodes = make([]uint32, len(o.Rules[i2].Filters.RetryFilter.RetryOnStatusCodes)) - copy(cp.Rules[i2].Filters.RetryFilter.RetryOnStatusCodes, o.Rules[i2].Filters.RetryFilter.RetryOnStatusCodes) - } - if o.Rules[i2].Filters.RetryFilter.RetryOnConnectFailure != nil { - cp.Rules[i2].Filters.RetryFilter.RetryOnConnectFailure = new(bool) - *cp.Rules[i2].Filters.RetryFilter.RetryOnConnectFailure = *o.Rules[i2].Filters.RetryFilter.RetryOnConnectFailure - } - } - if o.Rules[i2].Filters.TimeoutFilter != nil { - cp.Rules[i2].Filters.TimeoutFilter = new(TimeoutFilter) - *cp.Rules[i2].Filters.TimeoutFilter = *o.Rules[i2].Filters.TimeoutFilter - } - if o.Rules[i2].Filters.JWT != nil { - cp.Rules[i2].Filters.JWT = o.Rules[i2].Filters.JWT.DeepCopy() - } if o.Rules[i2].Matches != nil { cp.Rules[i2].Matches = make([]HTTPMatch, len(o.Rules[i2].Matches)) copy(cp.Rules[i2].Matches, o.Rules[i2].Matches) @@ -468,33 +427,6 @@ func (o *HTTPRouteConfigEntry) DeepCopy() *HTTPRouteConfigEntry { cp.Rules[i2].Services[i4].Filters.URLRewrite = new(URLRewrite) *cp.Rules[i2].Services[i4].Filters.URLRewrite = *o.Rules[i2].Services[i4].Filters.URLRewrite } - if o.Rules[i2].Services[i4].Filters.RetryFilter != nil { - cp.Rules[i2].Services[i4].Filters.RetryFilter = new(RetryFilter) - *cp.Rules[i2].Services[i4].Filters.RetryFilter = *o.Rules[i2].Services[i4].Filters.RetryFilter - if o.Rules[i2].Services[i4].Filters.RetryFilter.NumRetries != nil { - cp.Rules[i2].Services[i4].Filters.RetryFilter.NumRetries = new(uint32) - *cp.Rules[i2].Services[i4].Filters.RetryFilter.NumRetries = *o.Rules[i2].Services[i4].Filters.RetryFilter.NumRetries - } - if o.Rules[i2].Services[i4].Filters.RetryFilter.RetryOn != nil { - cp.Rules[i2].Services[i4].Filters.RetryFilter.RetryOn = make([]string, len(o.Rules[i2].Services[i4].Filters.RetryFilter.RetryOn)) - copy(cp.Rules[i2].Services[i4].Filters.RetryFilter.RetryOn, o.Rules[i2].Services[i4].Filters.RetryFilter.RetryOn) - } - if o.Rules[i2].Services[i4].Filters.RetryFilter.RetryOnStatusCodes != nil { - cp.Rules[i2].Services[i4].Filters.RetryFilter.RetryOnStatusCodes = make([]uint32, len(o.Rules[i2].Services[i4].Filters.RetryFilter.RetryOnStatusCodes)) - copy(cp.Rules[i2].Services[i4].Filters.RetryFilter.RetryOnStatusCodes, o.Rules[i2].Services[i4].Filters.RetryFilter.RetryOnStatusCodes) - } - if o.Rules[i2].Services[i4].Filters.RetryFilter.RetryOnConnectFailure != nil { - cp.Rules[i2].Services[i4].Filters.RetryFilter.RetryOnConnectFailure = new(bool) - *cp.Rules[i2].Services[i4].Filters.RetryFilter.RetryOnConnectFailure = *o.Rules[i2].Services[i4].Filters.RetryFilter.RetryOnConnectFailure - } - } - if o.Rules[i2].Services[i4].Filters.TimeoutFilter != nil { - cp.Rules[i2].Services[i4].Filters.TimeoutFilter = new(TimeoutFilter) - *cp.Rules[i2].Services[i4].Filters.TimeoutFilter = *o.Rules[i2].Services[i4].Filters.TimeoutFilter - } - if o.Rules[i2].Services[i4].Filters.JWT != nil { - cp.Rules[i2].Services[i4].Filters.JWT = o.Rules[i2].Services[i4].Filters.JWT.DeepCopy() - } } } } @@ -897,14 +829,6 @@ func (o *ServiceConfigEntry) DeepCopy() *ServiceConfigEntry { copy(cp.Destination.Addresses, o.Destination.Addresses) } } - if o.RateLimits != nil { - cp.RateLimits = new(RateLimits) - *cp.RateLimits = *o.RateLimits - if o.RateLimits.InstanceLevel.Routes != nil { - cp.RateLimits.InstanceLevel.Routes = make([]InstanceLevelRouteRateLimits, len(o.RateLimits.InstanceLevel.Routes)) - copy(cp.RateLimits.InstanceLevel.Routes, o.RateLimits.InstanceLevel.Routes) - } - } if o.EnvoyExtensions != nil { cp.EnvoyExtensions = make([]EnvoyExtension, len(o.EnvoyExtensions)) copy(cp.EnvoyExtensions, o.EnvoyExtensions) @@ -955,10 +879,6 @@ func (o *ServiceConfigResponse) DeepCopy() *ServiceConfigResponse { cp.Destination.Addresses = make([]string, len(o.Destination.Addresses)) copy(cp.Destination.Addresses, o.Destination.Addresses) } - if o.RateLimits.InstanceLevel.Routes != nil { - cp.RateLimits.InstanceLevel.Routes = make([]InstanceLevelRouteRateLimits, len(o.RateLimits.InstanceLevel.Routes)) - copy(cp.RateLimits.InstanceLevel.Routes, o.RateLimits.InstanceLevel.Routes) - } if o.Meta != nil { cp.Meta = make(map[string]string, len(o.Meta)) for k2, v2 := range o.Meta { diff --git a/agent/structs/structs.deepcopy_ce.go b/agent/structs/structs.deepcopy_ce.go deleted file mode 100644 index d2e909bf49e87..0000000000000 --- a/agent/structs/structs.deepcopy_ce.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package structs - -// DeepCopy generates a deep copy of *APIGatewayJWTRequirement -func (o *APIGatewayJWTRequirement) DeepCopy() *APIGatewayJWTRequirement { - return new(APIGatewayJWTRequirement) -} - -// DeepCopy generates a deep copy of *JWTFilter -func (o *JWTFilter) DeepCopy() *JWTFilter { - return new(JWTFilter) -} diff --git a/agent/structs/structs.go b/agent/structs/structs.go index fbacb36ffe665..b4548a734be99 100644 --- a/agent/structs/structs.go +++ b/agent/structs/structs.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs @@ -1483,10 +1483,6 @@ func (s *NodeService) IsGateway() bool { func (s *NodeService) Validate() error { var result error - if err := s.Locality.Validate(); err != nil { - result = multierror.Append(result, err) - } - if s.Kind == ServiceKindConnectProxy { if s.Port == 0 && s.SocketPath == "" { result = multierror.Append(result, fmt.Errorf("Port or SocketPath must be set for a %s", s.Kind)) @@ -1879,6 +1875,7 @@ type HealthCheckDefinition struct { Body string `json:",omitempty"` DisableRedirects bool `json:",omitempty"` TCP string `json:",omitempty"` + TCPUseTLS bool `json:",omitempty"` UDP string `json:",omitempty"` H2PING string `json:",omitempty"` OSService string `json:",omitempty"` @@ -2031,6 +2028,7 @@ func (c *HealthCheck) CheckType() *CheckType { Body: c.Definition.Body, DisableRedirects: c.Definition.DisableRedirects, TCP: c.Definition.TCP, + TCPUseTLS: c.Definition.TCPUseTLS, UDP: c.Definition.UDP, H2PING: c.Definition.H2PING, OSService: c.Definition.OSService, @@ -2098,18 +2096,6 @@ func (csn *CheckServiceNode) CanRead(authz acl.Authorizer) acl.EnforcementDecisi return acl.Allow } -func (csn *CheckServiceNode) Locality() *Locality { - if csn.Service != nil && csn.Service.Locality != nil { - return csn.Service.Locality - } - - if csn.Node != nil && csn.Node.Locality != nil { - return csn.Node.Locality - } - - return nil -} - type CheckServiceNodes []CheckServiceNode func (csns CheckServiceNodes) DeepCopy() CheckServiceNodes { @@ -3131,15 +3117,3 @@ func (l *Locality) GetRegion() string { } return l.Region } - -func (l *Locality) Validate() error { - if l == nil { - return nil - } - - if l.Region == "" && l.Zone != "" { - return fmt.Errorf("zone cannot be set without region") - } - - return nil -} diff --git a/agent/structs/structs_ce.go b/agent/structs/structs_ce.go index f47fac578afcc..6b004460e5fb7 100644 --- a/agent/structs/structs_ce.go +++ b/agent/structs/structs_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/structs_ce_test.go b/agent/structs/structs_ce_test.go index 6ec8723ae5e12..55e51a70088c3 100644 --- a/agent/structs/structs_ce_test.go +++ b/agent/structs/structs_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/structs/structs_ext_test.go b/agent/structs/structs_ext_test.go index 3b1cd6b6df1cf..9bbc4ca0cb915 100644 --- a/agent/structs/structs_ext_test.go +++ b/agent/structs/structs_ext_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs_test diff --git a/agent/structs/structs_filtering_test.go b/agent/structs/structs_filtering_test.go index 3750adb16ce1f..9739923e0e5a9 100644 --- a/agent/structs/structs_filtering_test.go +++ b/agent/structs/structs_filtering_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/structs_test.go b/agent/structs/structs_test.go index bf909aa41903e..6d887da9ac776 100644 --- a/agent/structs/structs_test.go +++ b/agent/structs/structs_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs @@ -592,43 +592,6 @@ func TestStructs_ServiceNode_Conversions(t *testing.T) { } } -func TestStructs_Locality_Validate(t *testing.T) { - type testCase struct { - locality *Locality - err string - } - cases := map[string]testCase{ - "nil": { - nil, - "", - }, - "region only": { - &Locality{Region: "us-west-1"}, - "", - }, - "region and zone": { - &Locality{Region: "us-west-1", Zone: "us-west-1a"}, - "", - }, - "zone only": { - &Locality{Zone: "us-west-1a"}, - "zone cannot be set without region", - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - err := tc.locality.Validate() - if tc.err == "" { - require.NoError(t, err) - } else { - require.Error(t, err) - require.Contains(t, err.Error(), tc.err) - } - }) - } -} - func TestStructs_NodeService_ValidateMeshGateway(t *testing.T) { type testCase struct { Modify func(*NodeService) @@ -1189,13 +1152,6 @@ func TestStructs_NodeService_ValidateConnectProxy(t *testing.T) { }, "", }, - { - "connect-proxy: invalid locality", - func(x *NodeService) { - x.Locality = &Locality{Zone: "bad"} - }, - "zone cannot be set without region", - }, } for _, tc := range cases { @@ -1358,7 +1314,7 @@ func TestStructs_NodeService_ValidateSidecarService(t *testing.T) { } func TestStructs_NodeService_ConnectNativeEmptyPortError(t *testing.T) { - ns := TestNodeService() + ns := TestNodeService(t) ns.Connect.Native = true ns.Port = 0 err := ns.Validate() diff --git a/agent/structs/system_metadata.go b/agent/structs/system_metadata.go index 555756201a5d2..fa6f6cd0ae58c 100644 --- a/agent/structs/system_metadata.go +++ b/agent/structs/system_metadata.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/testing.go b/agent/structs/testing.go index 527da21c4e890..ad8382b0ce3b1 100644 --- a/agent/structs/testing.go +++ b/agent/structs/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/testing_catalog.go b/agent/structs/testing_catalog.go index 8047695bba564..9e72aebc77458 100644 --- a/agent/structs/testing_catalog.go +++ b/agent/structs/testing_catalog.go @@ -1,14 +1,13 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs import ( "fmt" - "github.com/mitchellh/go-testing-interface" - "github.com/hashicorp/consul/acl" + "github.com/mitchellh/go-testing-interface" ) // TestRegisterRequest returns a RegisterRequest for registering a typical service. @@ -48,11 +47,11 @@ func TestRegisterIngressGateway(t testing.T) *RegisterRequest { } // TestNodeService returns a *NodeService representing a valid regular service: "web". -func TestNodeService() *NodeService { - return TestNodeServiceWithName("web") +func TestNodeService(t testing.T) *NodeService { + return TestNodeServiceWithName(t, "web") } -func TestNodeServiceWithName(name string) *NodeService { +func TestNodeServiceWithName(t testing.T, name string) *NodeService { return &NodeService{ Kind: ServiceKindTypical, Service: name, diff --git a/agent/structs/testing_connect_proxy_config.go b/agent/structs/testing_connect_proxy_config.go index 971e355fba2da..c41cc99651113 100644 --- a/agent/structs/testing_connect_proxy_config.go +++ b/agent/structs/testing_connect_proxy_config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/testing_intention.go b/agent/structs/testing_intention.go index 974a103de1bd4..57c6f9d50154e 100644 --- a/agent/structs/testing_intention.go +++ b/agent/structs/testing_intention.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/testing_service_definition.go b/agent/structs/testing_service_definition.go index da51014f43115..2707067262f5e 100644 --- a/agent/structs/testing_service_definition.go +++ b/agent/structs/testing_service_definition.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/structs/txn.go b/agent/structs/txn.go index efb11aa891eae..a97b4733f5edb 100644 --- a/agent/structs/txn.go +++ b/agent/structs/txn.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/agent/submatview/handler.go b/agent/submatview/handler.go index f33746a7f324c..b3c900e695286 100644 --- a/agent/submatview/handler.go +++ b/agent/submatview/handler.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package submatview diff --git a/agent/submatview/local_materializer.go b/agent/submatview/local_materializer.go index 4ee06a3640298..5eeaefaa665a9 100644 --- a/agent/submatview/local_materializer.go +++ b/agent/submatview/local_materializer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package submatview diff --git a/agent/submatview/local_materializer_test.go b/agent/submatview/local_materializer_test.go index fa7a01845034b..e6600a0516207 100644 --- a/agent/submatview/local_materializer_test.go +++ b/agent/submatview/local_materializer_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package submatview diff --git a/agent/submatview/materializer.go b/agent/submatview/materializer.go index 42754c914da08..240f6cfafbb4e 100644 --- a/agent/submatview/materializer.go +++ b/agent/submatview/materializer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package submatview diff --git a/agent/submatview/rpc_materializer.go b/agent/submatview/rpc_materializer.go index dfeb90172a695..855576b1b339a 100644 --- a/agent/submatview/rpc_materializer.go +++ b/agent/submatview/rpc_materializer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package submatview diff --git a/agent/submatview/store.go b/agent/submatview/store.go index ccfc319e2f4cc..1f189121264c4 100644 --- a/agent/submatview/store.go +++ b/agent/submatview/store.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package submatview diff --git a/agent/submatview/store_integration_test.go b/agent/submatview/store_integration_test.go index 45ba11d3cc3cf..3b6d9fbc2b57d 100644 --- a/agent/submatview/store_integration_test.go +++ b/agent/submatview/store_integration_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package submatview_test diff --git a/agent/submatview/store_test.go b/agent/submatview/store_test.go index c878654d89be9..36a92e7ec02b7 100644 --- a/agent/submatview/store_test.go +++ b/agent/submatview/store_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package submatview diff --git a/agent/submatview/streaming_test.go b/agent/submatview/streaming_test.go index 54b28d1abe6bc..223babf530b13 100644 --- a/agent/submatview/streaming_test.go +++ b/agent/submatview/streaming_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package submatview diff --git a/agent/systemd/notify.go b/agent/systemd/notify.go index 60c71947dc8a4..88ce2c2ece95a 100644 --- a/agent/systemd/notify.go +++ b/agent/systemd/notify.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package systemd diff --git a/agent/testagent.go b/agent/testagent.go index 3d0e2c8038e8b..57b9c1b111833 100644 --- a/agent/testagent.go +++ b/agent/testagent.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/testagent_test.go b/agent/testagent_test.go index 266b6e864cc36..66d1d61f01e53 100644 --- a/agent/testagent_test.go +++ b/agent/testagent_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/token/persistence.go b/agent/token/persistence.go index 117f72359d277..9d543b30edf9d 100644 --- a/agent/token/persistence.go +++ b/agent/token/persistence.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package token diff --git a/agent/token/persistence_test.go b/agent/token/persistence_test.go index 5d6e73f0d228b..093515f70e434 100644 --- a/agent/token/persistence_test.go +++ b/agent/token/persistence_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package token diff --git a/agent/token/store.go b/agent/token/store.go index a32475eb477ed..b0f9732a8cc6f 100644 --- a/agent/token/store.go +++ b/agent/token/store.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package token diff --git a/agent/token/store_ce.go b/agent/token/store_ce.go index f2fab3390dfd6..87fefdbbe0480 100644 --- a/agent/token/store_ce.go +++ b/agent/token/store_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/token/store_test.go b/agent/token/store_test.go index c35c44a7b69fa..8d0992f229ca2 100644 --- a/agent/token/store_test.go +++ b/agent/token/store_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package token diff --git a/agent/translate_addr.go b/agent/translate_addr.go index 1c0f8a4003058..9be80ebc0f8c8 100644 --- a/agent/translate_addr.go +++ b/agent/translate_addr.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/txn_endpoint.go b/agent/txn_endpoint.go index 10117a53c500b..7c2f64c1a9317 100644 --- a/agent/txn_endpoint.go +++ b/agent/txn_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent @@ -313,6 +313,7 @@ func (s *HTTPHandlers) convertOps(resp http.ResponseWriter, req *http.Request) ( Method: check.Definition.Method, Body: check.Definition.Body, TCP: check.Definition.TCP, + TCPUseTLS: check.Definition.TCPUseTLS, GRPC: check.Definition.GRPC, GRPCUseTLS: check.Definition.GRPCUseTLS, OSService: check.Definition.OSService, diff --git a/agent/txn_endpoint_test.go b/agent/txn_endpoint_test.go index fe19ed825301c..19c5925ba7a9c 100644 --- a/agent/txn_endpoint_test.go +++ b/agent/txn_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/ui_endpoint.go b/agent/ui_endpoint.go index d0cc8a5be8329..fa4bb23f84647 100644 --- a/agent/ui_endpoint.go +++ b/agent/ui_endpoint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent @@ -190,6 +190,7 @@ func AgentMembersMapAddrVer(s *HTTPHandlers, req *http.Request) (map[string]stri filter := consul.LANMemberFilter{ Partition: entMeta.PartitionOrDefault(), } + if acl.IsDefaultPartition(filter.Partition) { filter.AllSegments = true } diff --git a/agent/ui_endpoint_ce_test.go b/agent/ui_endpoint_ce_test.go index 82a16b765f5cb..3e57fca667e87 100644 --- a/agent/ui_endpoint_ce_test.go +++ b/agent/ui_endpoint_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/ui_endpoint_test.go b/agent/ui_endpoint_test.go index 1e0c391d0c951..b39a2f31dc931 100644 --- a/agent/ui_endpoint_test.go +++ b/agent/ui_endpoint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/uiserver/buf_index_fs.go b/agent/uiserver/buf_index_fs.go index 283616c36eda6..9ea23316fb10a 100644 --- a/agent/uiserver/buf_index_fs.go +++ b/agent/uiserver/buf_index_fs.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package uiserver diff --git a/agent/uiserver/buffered_file.go b/agent/uiserver/buffered_file.go index daa30c610d29f..5c794dac26908 100644 --- a/agent/uiserver/buffered_file.go +++ b/agent/uiserver/buffered_file.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package uiserver diff --git a/agent/uiserver/redirect_fs.go b/agent/uiserver/redirect_fs.go index 4a61ba7b2c14d..66b48e637fdc8 100644 --- a/agent/uiserver/redirect_fs.go +++ b/agent/uiserver/redirect_fs.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package uiserver diff --git a/agent/uiserver/ui_template_data.go b/agent/uiserver/ui_template_data.go index 726207b148f0c..d8d5fc42ba4e3 100644 --- a/agent/uiserver/ui_template_data.go +++ b/agent/uiserver/ui_template_data.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package uiserver diff --git a/agent/uiserver/uiserver.go b/agent/uiserver/uiserver.go index 0cd20c5fda0b4..8cabb8e3e0cd9 100644 --- a/agent/uiserver/uiserver.go +++ b/agent/uiserver/uiserver.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package uiserver diff --git a/agent/uiserver/uiserver_test.go b/agent/uiserver/uiserver_test.go index ce649276546be..c42792fe320bf 100644 --- a/agent/uiserver/uiserver_test.go +++ b/agent/uiserver/uiserver_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package uiserver diff --git a/agent/user_event.go b/agent/user_event.go index 23cbc90c336d8..25be0dd88f42a 100644 --- a/agent/user_event.go +++ b/agent/user_event.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/user_event_test.go b/agent/user_event_test.go index 62ea5f4adca31..ac807def924cf 100644 --- a/agent/user_event_test.go +++ b/agent/user_event_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/util.go b/agent/util.go index 1bcdbca01f1aa..285ba91df948d 100644 --- a/agent/util.go +++ b/agent/util.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/util_test.go b/agent/util_test.go index 42aa745e70fae..4c3ae5602d39b 100644 --- a/agent/util_test.go +++ b/agent/util_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/watch_handler.go b/agent/watch_handler.go index b926b7167505d..518fd6c77c98a 100644 --- a/agent/watch_handler.go +++ b/agent/watch_handler.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/watch_handler_test.go b/agent/watch_handler_test.go index 151e05e9c0778..f97d4d3982d3f 100644 --- a/agent/watch_handler_test.go +++ b/agent/watch_handler_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/agent/xds/accesslogs/accesslogs.go b/agent/xds/accesslogs/accesslogs.go index 25a3baf192fe0..84cbf55e64d8c 100644 --- a/agent/xds/accesslogs/accesslogs.go +++ b/agent/xds/accesslogs/accesslogs.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package accesslogs diff --git a/agent/xds/clusters.go b/agent/xds/clusters.go index 908aa746bc9c4..dc8245627b0cd 100644 --- a/agent/xds/clusters.go +++ b/agent/xds/clusters.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -19,8 +19,6 @@ import ( envoy_upstreams_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/v3" envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" - "github.com/hashicorp/consul/agent/xds/config" - "github.com/hashicorp/consul/agent/xds/naming" "github.com/hashicorp/go-hclog" "google.golang.org/protobuf/encoding/protojson" @@ -32,7 +30,6 @@ import ( "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/response" "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/proto/private/pbpeering" ) @@ -369,7 +366,7 @@ func makePassthroughClusters(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, !meshConf.TransparentProxy.MeshDestinationsOnly { clusters = append(clusters, &envoy_cluster_v3.Cluster{ - Name: naming.OriginalDestinationClusterName, + Name: OriginalDestinationClusterName, ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{ Type: envoy_cluster_v3.Cluster_ORIGINAL_DST, }, @@ -811,6 +808,27 @@ func (s *ResourceGenerator) makeGatewayOutgoingClusterPeeringServiceClusters(cfg } cluster := s.makeGatewayCluster(cfgSnap, opts) + if serviceGroup.UseCDS { + configureClusterWithHostnames( + s.Logger, + cluster, + "", /*TODO:make configurable?*/ + serviceGroup.Nodes, + true, /*isRemote*/ + false, /*onlyPassing*/ + ) + } else { + cluster.ClusterDiscoveryType = &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_EDS} + cluster.EdsClusterConfig = &envoy_cluster_v3.Cluster_EdsClusterConfig{ + EdsConfig: &envoy_core_v3.ConfigSource{ + ResourceApiVersion: envoy_core_v3.ApiVersion_V3, + ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_Ads{ + Ads: &envoy_core_v3.AggregatedConfigSource{}, + }, + }, + } + } + clusters = append(clusters, cluster) } } @@ -974,10 +992,8 @@ func (s *ResourceGenerator) clustersFromSnapshotAPIGateway(cfgSnap *proxycfg.Con // Grab the discovery chain compiled in handlerAPIGateway.recompileDiscoveryChains chain, ok := cfgSnap.APIGateway.DiscoveryChain[uid] if !ok { - // this should not happen, but it can't error out because the equivalent - // listener generation will continue - s.Logger.Warn("could not find discovery chain for gateway upstream", "upstream", uid) - continue + // this should not happen + return nil, fmt.Errorf("no discovery chain for upstream %q", uid) } // Generate the list of upstream clusters for the discovery chain @@ -1009,11 +1025,11 @@ func (s *ResourceGenerator) configIngressUpstreamCluster(c *envoy_cluster_v3.Clu switch limitType { case "max_connections": - threshold.MaxConnections = response.MakeUint32Value(limit) + threshold.MaxConnections = makeUint32Value(limit) case "max_pending_requests": - threshold.MaxPendingRequests = response.MakeUint32Value(limit) + threshold.MaxPendingRequests = makeUint32Value(limit) case "max_requests": - threshold.MaxRequests = response.MakeUint32Value(limit) + threshold.MaxRequests = makeUint32Value(limit) } } @@ -1044,7 +1060,12 @@ func (s *ResourceGenerator) configIngressUpstreamCluster(c *envoy_cluster_v3.Clu if svc != nil { override = svc.PassiveHealthCheck } - outlierDetection := config.ToOutlierDetection(cfgSnap.IngressGateway.Defaults.PassiveHealthCheck, override, false) + outlierDetection := ToOutlierDetection(cfgSnap.IngressGateway.Defaults.PassiveHealthCheck, override, false) + + // Specail handling for failover peering service, which has set MaxEjectionPercent + if c.OutlierDetection != nil && c.OutlierDetection.MaxEjectionPercent != nil { + outlierDetection.MaxEjectionPercent = &wrapperspb.UInt32Value{Value: c.OutlierDetection.MaxEjectionPercent.Value} + } c.OutlierDetection = outlierDetection } @@ -1053,7 +1074,7 @@ func (s *ResourceGenerator) makeAppCluster(cfgSnap *proxycfg.ConfigSnapshot, nam var c *envoy_cluster_v3.Cluster var err error - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) + cfg, err := ParseProxyConfig(cfgSnap.Proxy.Config) if err != nil { // Don't hard fail on a config typo, just warn. The parse func returns // default config if there is an error so it's safe to continue. @@ -1104,7 +1125,7 @@ func (s *ResourceGenerator) makeAppCluster(cfgSnap *proxycfg.ConfigSnapshot, nam c.CircuitBreakers = &envoy_cluster_v3.CircuitBreakers{ Thresholds: []*envoy_cluster_v3.CircuitBreakers_Thresholds{ { - MaxConnections: response.MakeUint32Value(cfg.MaxInboundConnections), + MaxConnections: makeUint32Value(cfg.MaxInboundConnections), }, }, } @@ -1147,7 +1168,7 @@ func (s *ResourceGenerator) makeUpstreamClusterForPeerService( clusterName := generatePeeredClusterName(uid, tbs) - outlierDetection := config.ToOutlierDetection(upstreamConfig.PassiveHealthCheck, nil, true) + outlierDetection := ToOutlierDetection(upstreamConfig.PassiveHealthCheck, nil, true) // We can't rely on health checks for services on cluster peers because they // don't take into account service resolvers, splitters and routers. Setting // MaxEjectionPercent too 100% gives outlier detection the power to eject the @@ -1282,7 +1303,7 @@ func (s *ResourceGenerator) makeUpstreamClusterForPreparedQuery(upstream structs CircuitBreakers: &envoy_cluster_v3.CircuitBreakers{ Thresholds: makeThresholdsIfNeeded(cfg.Limits), }, - OutlierDetection: config.ToOutlierDetection(cfg.PassiveHealthCheck, nil, true), + OutlierDetection: ToOutlierDetection(cfg.PassiveHealthCheck, nil, true), } if cfg.Protocol == "http2" || cfg.Protocol == "grpc" { if err := s.setHttp2ProtocolOptions(c); err != nil { @@ -1424,7 +1445,7 @@ func (s *ResourceGenerator) makeUpstreamClustersForDiscoveryChain( // These variables are prefixed with primary to avoid shaddowing bugs. primaryTargetID := node.Resolver.Target primaryTarget := chain.Targets[primaryTargetID] - primaryTargetClusterName := s.getTargetClusterName(upstreamsSnapshot, chain, primaryTargetID, forMeshGateway) + primaryTargetClusterName := s.getTargetClusterName(upstreamsSnapshot, chain, primaryTargetID, forMeshGateway, false) if primaryTargetClusterName == "" { continue } @@ -1502,7 +1523,7 @@ func (s *ResourceGenerator) makeUpstreamClustersForDiscoveryChain( CircuitBreakers: &envoy_cluster_v3.CircuitBreakers{ Thresholds: makeThresholdsIfNeeded(upstreamConfig.Limits), }, - OutlierDetection: config.ToOutlierDetection(upstreamConfig.PassiveHealthCheck, nil, true), + OutlierDetection: ToOutlierDetection(upstreamConfig.PassiveHealthCheck, nil, true), } var lb *structs.LoadBalancer @@ -1656,6 +1677,11 @@ func makeClusterFromUserConfig(configJSON string) (*envoy_cluster_v3.Cluster, er return &c, err } +type addressPair struct { + host string + port int +} + type clusterOpts struct { // name for the cluster name string @@ -1679,7 +1705,7 @@ type clusterOpts struct { // makeGatewayCluster creates an Envoy cluster for a mesh or terminating gateway func (s *ResourceGenerator) makeGatewayCluster(snap *proxycfg.ConfigSnapshot, opts clusterOpts) *envoy_cluster_v3.Cluster { - cfg, err := config.ParseGatewayConfig(snap.Proxy.Config) + cfg, err := ParseGatewayConfig(snap.Proxy.Config) if err != nil { // Don't hard fail on a config typo, just warn. The parse func returns // default config if there is an error so it's safe to continue. @@ -1709,13 +1735,13 @@ func (s *ResourceGenerator) makeGatewayCluster(snap *proxycfg.ConfigSnapshot, op TcpKeepalive: &envoy_core_v3.TcpKeepalive{}, } if cfg.TcpKeepaliveTime != 0 { - cluster.UpstreamConnectionOptions.TcpKeepalive.KeepaliveTime = response.MakeUint32Value(cfg.TcpKeepaliveTime) + cluster.UpstreamConnectionOptions.TcpKeepalive.KeepaliveTime = makeUint32Value(cfg.TcpKeepaliveTime) } if cfg.TcpKeepaliveInterval != 0 { - cluster.UpstreamConnectionOptions.TcpKeepalive.KeepaliveInterval = response.MakeUint32Value(cfg.TcpKeepaliveInterval) + cluster.UpstreamConnectionOptions.TcpKeepalive.KeepaliveInterval = makeUint32Value(cfg.TcpKeepaliveInterval) } if cfg.TcpKeepaliveProbes != 0 { - cluster.UpstreamConnectionOptions.TcpKeepalive.KeepaliveProbes = response.MakeUint32Value(cfg.TcpKeepaliveProbes) + cluster.UpstreamConnectionOptions.TcpKeepalive.KeepaliveProbes = makeUint32Value(cfg.TcpKeepaliveProbes) } } @@ -1822,7 +1848,7 @@ func configureClusterWithHostnames( // makeExternalIPCluster creates an Envoy cluster for routing to IP addresses outside of Consul // This is used by terminating gateways for Destinations func (s *ResourceGenerator) makeExternalIPCluster(snap *proxycfg.ConfigSnapshot, opts clusterOpts) *envoy_cluster_v3.Cluster { - cfg, err := config.ParseGatewayConfig(snap.Proxy.Config) + cfg, err := ParseGatewayConfig(snap.Proxy.Config) if err != nil { // Don't hard fail on a config typo, just warn. The parse func returns // default config if there is an error so it's safe to continue. @@ -1861,7 +1887,7 @@ func (s *ResourceGenerator) makeExternalIPCluster(snap *proxycfg.ConfigSnapshot, // makeExternalHostnameCluster creates an Envoy cluster for hostname endpoints that will be resolved with DNS // This is used by both terminating gateways for Destinations, and Mesh Gateways for peering control plane traffice func (s *ResourceGenerator) makeExternalHostnameCluster(snap *proxycfg.ConfigSnapshot, opts clusterOpts) *envoy_cluster_v3.Cluster { - cfg, err := config.ParseGatewayConfig(snap.Proxy.Config) + cfg, err := ParseGatewayConfig(snap.Proxy.Config) if err != nil { // Don't hard fail on a config typo, just warn. The parse func returns // default config if there is an error so it's safe to continue. @@ -1885,7 +1911,7 @@ func (s *ResourceGenerator) makeExternalHostnameCluster(snap *proxycfg.ConfigSna endpoints := make([]*envoy_endpoint_v3.LbEndpoint, 0, len(opts.addresses)) for _, pair := range opts.addresses { - address := response.MakeAddress(pair.Address, pair.Port) + address := makeAddress(pair.Address, pair.Port) endpoint := &envoy_endpoint_v3.LbEndpoint{ HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ @@ -1918,13 +1944,13 @@ func makeThresholdsIfNeeded(limits *structs.UpstreamLimits) []*envoy_cluster_v3. // Likewise, make sure to not set any threshold values on the zero-value in // order to rely on Envoy defaults if limits.MaxConnections != nil { - threshold.MaxConnections = response.MakeUint32Value(*limits.MaxConnections) + threshold.MaxConnections = makeUint32Value(*limits.MaxConnections) } if limits.MaxPendingRequests != nil { - threshold.MaxPendingRequests = response.MakeUint32Value(*limits.MaxPendingRequests) + threshold.MaxPendingRequests = makeUint32Value(*limits.MaxPendingRequests) } if limits.MaxConcurrentRequests != nil { - threshold.MaxRequests = response.MakeUint32Value(*limits.MaxConcurrentRequests) + threshold.MaxRequests = makeUint32Value(*limits.MaxConcurrentRequests) } return []*envoy_cluster_v3.CircuitBreakers_Thresholds{threshold} @@ -1947,7 +1973,7 @@ func makeLbEndpoint(addr string, port int, health envoy_core_v3.HealthStatus, we }, }, HealthStatus: health, - LoadBalancingWeight: response.MakeUint32Value(weight), + LoadBalancingWeight: makeUint32Value(weight), } } @@ -2028,11 +2054,15 @@ func generatePeeredClusterName(uid proxycfg.UpstreamID, tb *pbpeering.PeeringTru }, ".") } -func (s *ResourceGenerator) getTargetClusterName(upstreamsSnapshot *proxycfg.ConfigSnapshotUpstreams, chain *structs.CompiledDiscoveryChain, tid string, forMeshGateway bool) string { +type targetClusterData struct { + targetID string + clusterName string +} + +func (s *ResourceGenerator) getTargetClusterName(upstreamsSnapshot *proxycfg.ConfigSnapshotUpstreams, chain *structs.CompiledDiscoveryChain, tid string, forMeshGateway bool, failover bool) string { target := chain.Targets[tid] clusterName := target.Name targetUID := proxycfg.NewUpstreamIDFromTargetID(tid) - if targetUID.Peer != "" { tbs, ok := upstreamsSnapshot.UpstreamPeerTrustBundles.Get(targetUID.Peer) // We can't generate cluster on peers without the trust bundle. The @@ -2047,7 +2077,10 @@ func (s *ResourceGenerator) getTargetClusterName(upstreamsSnapshot *proxycfg.Con clusterName = generatePeeredClusterName(targetUID, tbs) } - clusterName = naming.CustomizeClusterName(clusterName, chain) + clusterName = CustomizeClusterName(clusterName, chain) + if failover { + clusterName = xdscommon.FailoverClusterNamePrefix + clusterName + } if forMeshGateway { clusterName = meshGatewayExportedClusterNamePrefix + clusterName } diff --git a/agent/xds/clusters_test.go b/agent/xds/clusters_test.go index adeb2b57374fb..954aad7756f06 100644 --- a/agent/xds/clusters_test.go +++ b/agent/xds/clusters_test.go @@ -1,11 +1,10 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds import ( "bytes" - "github.com/hashicorp/consul/types" "path/filepath" "sort" "testing" @@ -21,35 +20,16 @@ import ( "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/proxystateconverter" - "github.com/hashicorp/consul/agent/xds/response" "github.com/hashicorp/consul/agent/xds/testcommon" - "github.com/hashicorp/consul/agent/xdsv2" "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/sdk/testutil" + "github.com/hashicorp/consul/types" ) -type mockCfgFetcher struct { - addressLan string -} - -func (s *mockCfgFetcher) AdvertiseAddrLAN() string { - return s.addressLan -} - type clusterTestCase struct { name string create func(t testinf.T) *proxycfg.ConfigSnapshot overrideGoldenName string - alsoRunTestForV2 bool -} - -func uint32ptr(i uint32) *uint32 { - return &i -} - -func durationPtr(d time.Duration) *time.Duration { - return &d } func makeClusterDiscoChainTests(enterprise bool) []clusterTestCase { @@ -64,125 +44,90 @@ func makeClusterDiscoChainTests(enterprise bool) []clusterTestCase { }) }, nil) }, - // TODO(proxystate): requires custom cluster work - alsoRunTestForV2: false, }, { name: "connect-proxy-with-chain", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, nil, nil) }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-chain-http2", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, func(ns *structs.NodeService) { - ns.Proxy.Upstreams[0].Config["protocol"] = "http2" - }, nil) - }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-chain-external-sni", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "external-sni", enterprise, nil, nil) }, - //TODO(proxystate): this requires terminating gateway work - alsoRunTestForV2: true, }, { name: "connect-proxy-with-chain-and-overrides", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple-with-overrides", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-chain-and-failover", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover", enterprise, nil, nil) }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, }, { name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway", enterprise, nil, nil) }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, }, { name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway-triggered", enterprise, nil, nil) }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, }, { name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway", enterprise, nil, nil) }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, }, { name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway-triggered", enterprise, nil, nil) }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, }, { name: "connect-proxy-with-tcp-chain-failover-through-local-gateway", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway", enterprise, nil, nil) }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, }, { name: "connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway-triggered", enterprise, nil, nil) }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, }, { name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway", enterprise, nil, nil) }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, }, { name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway-triggered", enterprise, nil, nil) }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, }, { name: "splitter-with-resolver-redirect", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-with-resolver-redirect-multidc", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-lb-in-resolver", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "lb-resolver", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, } } @@ -214,7 +159,6 @@ func TestClustersFromSnapshot(t *testing.T) { }, }) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tls-outgoing-min-version", @@ -234,7 +178,6 @@ func TestClustersFromSnapshot(t *testing.T) { }, }) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tls-outgoing-max-version", @@ -254,7 +197,6 @@ func TestClustersFromSnapshot(t *testing.T) { }, }) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tls-outgoing-cipher-suites", @@ -277,7 +219,6 @@ func TestClustersFromSnapshot(t *testing.T) { }, }) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-jwt-config-entry-with-local", @@ -301,8 +242,6 @@ func TestClustersFromSnapshot(t *testing.T) { }, }) }, - // TODO(proxystate): jwt work will come at a later time - alsoRunTestForV2: false, }, { name: "connect-proxy-with-jwt-config-entry-with-remote-jwks", @@ -337,8 +276,6 @@ func TestClustersFromSnapshot(t *testing.T) { }, }) }, - // TODO(proxystate): jwt work will come at a later time - alsoRunTestForV2: false, }, { name: "custom-local-app", @@ -350,8 +287,6 @@ func TestClustersFromSnapshot(t *testing.T) { }) }, nil) }, - // TODO(proxystate): requires custom cluster work - alsoRunTestForV2: false, }, { name: "custom-upstream", @@ -363,8 +298,6 @@ func TestClustersFromSnapshot(t *testing.T) { }) }, nil) }, - // TODO(proxystate): requires custom cluster work - alsoRunTestForV2: false, }, { name: "custom-upstream-ignores-tls", @@ -379,46 +312,6 @@ func TestClustersFromSnapshot(t *testing.T) { }) }, nil) }, - // TODO(proxystate): requires custom cluster work - alsoRunTestForV2: false, - }, - { - name: "custom-upstream-with-prepared-query", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - for i := range ns.Proxy.Upstreams { - - switch ns.Proxy.Upstreams[i].DestinationName { - case "db": - if ns.Proxy.Upstreams[i].Config == nil { - ns.Proxy.Upstreams[i].Config = map[string]interface{}{} - } - - uid := proxycfg.NewUpstreamID(&ns.Proxy.Upstreams[i]) - - // Triggers an override with the presence of the escape hatch listener - ns.Proxy.Upstreams[i].DestinationType = structs.UpstreamDestTypePreparedQuery - - ns.Proxy.Upstreams[i].Config["envoy_cluster_json"] = - customClusterJSON(t, customClusterJSONOptions{ - Name: uid.EnvoyID() + ":custom-upstream", - }) - - // Also test that http2 options are triggered. - // A separate upstream without an override is required to test - case "geo-cache": - if ns.Proxy.Upstreams[i].Config == nil { - ns.Proxy.Upstreams[i].Config = map[string]interface{}{} - } - ns.Proxy.Upstreams[i].Config["protocol"] = "http2" - default: - continue - } - } - }, nil) - }, - // TODO(proxystate): requires custom cluster work - alsoRunTestForV2: false, }, { name: "custom-timeouts", @@ -428,7 +321,6 @@ func TestClustersFromSnapshot(t *testing.T) { ns.Proxy.Upstreams[0].Config["connect_timeout_ms"] = 2345 }, nil) }, - alsoRunTestForV2: true, }, { name: "custom-passive-healthcheck", @@ -443,22 +335,6 @@ func TestClustersFromSnapshot(t *testing.T) { } }, nil) }, - alsoRunTestForV2: true, - }, - { - name: "custom-passive-healthcheck-zero-consecutive_5xx", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Upstreams[0].Config["passive_health_check"] = map[string]interface{}{ - "enforcing_consecutive_5xx": float64(0), - "max_failures": float64(5), - "interval": float64(10 * time.Second), - "max_ejection_percent": float64(100), - "base_ejection_time": float64(10 * time.Second), - } - }, nil) - }, - alsoRunTestForV2: true, }, { name: "custom-max-inbound-connections", @@ -467,7 +343,6 @@ func TestClustersFromSnapshot(t *testing.T) { ns.Proxy.Config["max_inbound_connections"] = 3456 }, nil) }, - alsoRunTestForV2: true, }, { name: "custom-limits-max-connections-only", @@ -488,7 +363,6 @@ func TestClustersFromSnapshot(t *testing.T) { } }, nil) }, - alsoRunTestForV2: true, }, { name: "custom-limits-set-to-zero", @@ -507,7 +381,6 @@ func TestClustersFromSnapshot(t *testing.T) { } }, nil) }, - alsoRunTestForV2: true, }, { name: "custom-limits", @@ -526,14 +399,12 @@ func TestClustersFromSnapshot(t *testing.T) { } }, nil) }, - alsoRunTestForV2: true, }, { name: "expose-paths-local-app-paths", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotExposeConfig(t, nil) }, - alsoRunTestForV2: true, }, { name: "downstream-service-with-unix-sockets", @@ -546,7 +417,6 @@ func TestClustersFromSnapshot(t *testing.T) { ns.Proxy.LocalServiceSocketPath = "/tmp/downstream_proxy.sock" }, nil) }, - alsoRunTestForV2: true, }, { name: "expose-paths-new-cluster-http2", @@ -560,89 +430,58 @@ func TestClustersFromSnapshot(t *testing.T) { } }) }, - alsoRunTestForV2: true, }, { - name: "expose-checks", - create: proxycfg.TestConfigSnapshotExposeChecks, - alsoRunTestForV2: true, - }, - { - name: "expose-paths-grpc-new-cluster-http1", - create: proxycfg.TestConfigSnapshotGRPCExposeHTTP1, - alsoRunTestForV2: true, + name: "expose-paths-grpc-new-cluster-http1", + create: proxycfg.TestConfigSnapshotGRPCExposeHTTP1, }, { name: "mesh-gateway", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "default", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-using-federation-states", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "federation-states", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-using-federation-control-plane", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "mesh-gateway-federation", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-no-services", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "no-services", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-service-subsets", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "service-subsets", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-ignore-extra-resolvers", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "ignore-extra-resolvers", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-service-timeouts", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "service-timeouts", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-non-hash-lb-injected", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "non-hash-lb-injected", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-hash-lb-ignored", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "hash-lb-ignored", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-tcp-keepalives", @@ -654,8 +493,6 @@ func TestClustersFromSnapshot(t *testing.T) { ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_probes"] = 7 }, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-gateway", @@ -663,16 +500,12 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-gateway-nil-config-entry", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotIngressGateway_NilConfigEntry(t) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-gateway-with-tls-outgoing-min-version", @@ -692,8 +525,6 @@ func TestClustersFromSnapshot(t *testing.T) { }, }) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-gateway-with-tls-outgoing-max-version", @@ -713,8 +544,6 @@ func TestClustersFromSnapshot(t *testing.T) { }, }) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-gateway-with-tls-outgoing-cipher-suites", @@ -737,8 +566,6 @@ func TestClustersFromSnapshot(t *testing.T) { }, }) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-gateway-no-services", @@ -746,8 +573,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, false, "tcp", "default", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-chain", @@ -755,8 +580,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "simple", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-service-max-connections", @@ -767,8 +590,6 @@ func TestClustersFromSnapshot(t *testing.T) { entry.Listeners[0].Services[0].MaxConnections = 4096 }, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-defaults-service-max-connections", @@ -783,8 +604,6 @@ func TestClustersFromSnapshot(t *testing.T) { } }, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-overwrite-defaults-service-max-connections", @@ -800,8 +619,6 @@ func TestClustersFromSnapshot(t *testing.T) { entry.Listeners[0].Services[0].MaxPendingRequests = 2048 }, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-service-passive-health-check", @@ -811,14 +628,11 @@ func TestClustersFromSnapshot(t *testing.T) { func(entry *structs.IngressGatewayConfigEntry) { entry.Listeners[0].Services[0].MaxConnections = 4096 entry.Listeners[0].Services[0].PassiveHealthCheck = &structs.PassiveHealthCheck{ - Interval: 5000000000, - MaxFailures: 10, - MaxEjectionPercent: uint32ptr(90), + Interval: 5000000000, + MaxFailures: 10, } }, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-defaults-passive-health-check", @@ -835,13 +649,10 @@ func TestClustersFromSnapshot(t *testing.T) { Interval: 5000000000, MaxFailures: 10, EnforcingConsecutive5xx: &enforcingConsecutive5xx, - MaxEjectionPercent: uint32ptr(90), }, } }, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-overwrite-defaults-passive-health-check", @@ -856,7 +667,6 @@ func TestClustersFromSnapshot(t *testing.T) { PassiveHealthCheck: &structs.PassiveHealthCheck{ Interval: 5000000000, EnforcingConsecutive5xx: &defaultEnforcingConsecutive5xx, - MaxEjectionPercent: uint32ptr(80), }, } enforcingConsecutive5xx := uint32(50) @@ -865,13 +675,9 @@ func TestClustersFromSnapshot(t *testing.T) { entry.Listeners[0].Services[0].PassiveHealthCheck = &structs.PassiveHealthCheck{ Interval: 8000000000, EnforcingConsecutive5xx: &enforcingConsecutive5xx, - MaxEjectionPercent: uint32ptr(90), - BaseEjectionTime: durationPtr(12 * time.Second), } }, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-chain-external-sni", @@ -879,8 +685,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "external-sni", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-chain-and-failover", @@ -888,8 +692,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-chain-and-failover-to-cluster-peer", @@ -897,8 +699,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-to-cluster-peer", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-failover-through-remote-gateway", @@ -906,8 +706,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-remote-gateway", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-failover-through-remote-gateway-triggered", @@ -915,8 +713,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-remote-gateway-triggered", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-double-failover-through-remote-gateway", @@ -924,8 +720,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-double-remote-gateway", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered", @@ -933,8 +727,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-double-remote-gateway-triggered", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-failover-through-local-gateway", @@ -942,8 +734,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-local-gateway", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-failover-through-local-gateway-triggered", @@ -951,8 +741,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-local-gateway-triggered", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-double-failover-through-local-gateway", @@ -960,8 +748,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-double-local-gateway", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-double-failover-through-local-gateway-triggered", @@ -969,8 +755,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-double-local-gateway-triggered", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-splitter-with-resolver-redirect", @@ -978,8 +762,6 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", "splitter-with-resolver-redirect-multidc", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-lb-in-resolver", @@ -987,66 +769,46 @@ func TestClustersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", "lb-resolver", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, nil) }, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway-no-services", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotTerminatingGateway(t, false, nil, nil) }, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway-service-subsets", create: proxycfg.TestConfigSnapshotTerminatingGatewayServiceSubsetsWebAndCache, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway-hostname-service-subsets", create: proxycfg.TestConfigSnapshotTerminatingGatewayHostnameSubsets, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway-sni", create: proxycfg.TestConfigSnapshotTerminatingGatewaySNI, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway-http2-upstream", create: proxycfg.TestConfigSnapshotTerminatingGatewayHTTP2, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway-http2-upstream-subsets", create: proxycfg.TestConfigSnapshotTerminatingGatewaySubsetsHTTP2, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway-ignore-extra-resolvers", create: proxycfg.TestConfigSnapshotTerminatingGatewayIgnoreExtraResolvers, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway-lb-config", create: proxycfg.TestConfigSnapshotTerminatingGatewayLBConfigNoHashPolicies, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway-tcp-keepalives", @@ -1061,24 +823,18 @@ func TestClustersFromSnapshot(t *testing.T) { ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_probes"] = 5 }, nil) }, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-multiple-listeners-duplicate-service", create: proxycfg.TestConfigSnapshotIngress_MultipleListenersDuplicateService, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { - name: "transparent-proxy-catalog-destinations-only", - create: proxycfg.TestConfigSnapshotTransparentProxyCatalogDestinationsOnly, - alsoRunTestForV2: true, + name: "transparent-proxy-catalog-destinations-only", + create: proxycfg.TestConfigSnapshotTransparentProxyCatalogDestinationsOnly, }, { - name: "transparent-proxy-dial-instances-directly", - create: proxycfg.TestConfigSnapshotTransparentProxyDialDirectly, - alsoRunTestForV2: true, + name: "transparent-proxy-dial-instances-directly", + create: proxycfg.TestConfigSnapshotTransparentProxyDialDirectly, }, } @@ -1110,10 +866,10 @@ func TestClustersFromSnapshot(t *testing.T) { return clusters[i].(*envoy_cluster_v3.Cluster).Name < clusters[j].(*envoy_cluster_v3.Cluster).Name }) - r, err := response.CreateResponse(xdscommon.ClusterType, "00000001", "00000001", clusters) + r, err := createResponse(xdscommon.ClusterType, "00000001", "00000001", clusters) require.NoError(t, err) - t.Run("current-xdsv1", func(t *testing.T) { + t.Run("current", func(t *testing.T) { gotJSON := protoToJSON(t, r) gName := tt.name @@ -1123,40 +879,6 @@ func TestClustersFromSnapshot(t *testing.T) { require.JSONEq(t, goldenEnvoy(t, filepath.Join("clusters", gName), envoyVersion, latestEnvoyVersion, gotJSON), gotJSON) }) - - if tt.alsoRunTestForV2 { - generator := xdsv2.NewResourceGenerator(testutil.Logger(t)) - - converter := proxystateconverter.NewConverter(testutil.Logger(t), &mockCfgFetcher{addressLan: "10.10.10.10"}) - proxyState, err := converter.ProxyStateFromSnapshot(snap) - require.NoError(t, err) - - res, err := generator.AllResourcesFromIR(proxyState) - require.NoError(t, err) - - clusters = res[xdscommon.ClusterType] - - // The order of clusters returned via CDS isn't relevant, so it's safe - // to sort these for the purposes of test comparisons. - sort.Slice(clusters, func(i, j int) bool { - return clusters[i].(*envoy_cluster_v3.Cluster).Name < clusters[j].(*envoy_cluster_v3.Cluster).Name - }) - - r, err := response.CreateResponse(xdscommon.ClusterType, "00000001", "00000001", clusters) - require.NoError(t, err) - - t.Run("current-xdsv2", func(t *testing.T) { - gotJSON := protoToJSON(t, r) - - gName := tt.name - if tt.overrideGoldenName != "" { - gName = tt.overrideGoldenName - } - - expectedJSON := goldenEnvoy(t, filepath.Join("clusters", gName), envoyVersion, latestEnvoyVersion, gotJSON) - require.JSONEq(t, expectedJSON, gotJSON) - }) - } }) } }) @@ -1212,41 +934,6 @@ func customAppClusterJSON(t testinf.T, opts customClusterJSONOptions) string { return buf.String() } -var customClusterJSONTpl = `{ - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "{{ .Name }}", - "connectTimeout": "15s", - "loadAssignment": { - "clusterName": "{{ .Name }}", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8443 - } - } - } - } - ] - } - ] - } -}` - -var customClusterJSONTemplate = template.Must(template.New("").Parse(customClusterJSONTpl)) - -func customClusterJSON(t testinf.T, opts customClusterJSONOptions) string { - t.Helper() - var buf bytes.Buffer - err := customClusterJSONTemplate.Execute(&buf, opts) - require.NoError(t, err) - return buf.String() -} - func TestEnvoyLBConfig_InjectToCluster(t *testing.T) { var tests = []struct { name string diff --git a/agent/xds/config/config.go b/agent/xds/config.go similarity index 98% rename from agent/xds/config/config.go rename to agent/xds/config.go index 32c46d07d3ef6..967bcb213dec5 100644 --- a/agent/xds/config/config.go +++ b/agent/xds/config.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 -package config +package xds import ( "strings" @@ -229,9 +229,9 @@ func ToOutlierDetection(p *structs.PassiveHealthCheck, override *structs.Passive // NOTE: EnforcingConsecutive5xx must be great than 0 for ingress-gateway if *override.EnforcingConsecutive5xx != 0 { od.EnforcingConsecutive_5Xx = &wrapperspb.UInt32Value{Value: *override.EnforcingConsecutive5xx} + } else if allowZero { + od.EnforcingConsecutive_5Xx = &wrapperspb.UInt32Value{Value: *override.EnforcingConsecutive5xx} } - // Because only ingress gateways have overrides and they cannot have a value of 0, there is no allowZero - // override case to handle } if override.MaxEjectionPercent != nil { diff --git a/agent/xds/config/config_test.go b/agent/xds/config_test.go similarity index 99% rename from agent/xds/config/config_test.go rename to agent/xds/config_test.go index 72e9a0e614614..e544c30b393e2 100644 --- a/agent/xds/config/config_test.go +++ b/agent/xds/config_test.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 -package config +package xds import ( "testing" diff --git a/agent/xds/configfetcher/config_fetcher.go b/agent/xds/configfetcher/config_fetcher.go deleted file mode 100644 index db7d4f2035d23..0000000000000 --- a/agent/xds/configfetcher/config_fetcher.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package configfetcher - -// ConfigFetcher is the interface the agent needs to expose -// for the xDS server to fetch agent config, currently only one field is fetched -type ConfigFetcher interface { - AdvertiseAddrLAN() string -} diff --git a/agent/xds/delta.go b/agent/xds/delta.go index d239f2bd51a5c..15c59193e626c 100644 --- a/agent/xds/delta.go +++ b/agent/xds/delta.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -19,6 +19,7 @@ import ( envoy_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" "github.com/hashicorp/go-hclog" goversion "github.com/hashicorp/go-version" + "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" @@ -28,16 +29,11 @@ import ( external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/agent/grpc-external/limiter" "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/xds/configfetcher" + "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/xds/extensionruntime" - "github.com/hashicorp/consul/agent/xdsv2" "github.com/hashicorp/consul/envoyextensions/extensioncommon" "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/internal/mesh" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" "github.com/hashicorp/consul/logging" - "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/version" ) @@ -88,40 +84,6 @@ func (s *Server) DeltaAggregatedResources(stream ADSDeltaStream) error { return err } -// getEnvoyConfiguration is a utility function that instantiates the proper -// Envoy resource generator based on whether it was passed a ConfigSource or -// ProxyState implementation of the ProxySnapshot interface and returns the -// generated Envoy configuration. -func getEnvoyConfiguration(proxySnapshot proxysnapshot.ProxySnapshot, logger hclog.Logger, cfgFetcher configfetcher.ConfigFetcher) (map[string][]proto.Message, error) { - switch proxySnapshot.(type) { - case *proxycfg.ConfigSnapshot: - logger.Trace("ProxySnapshot update channel received a ProxySnapshot of type ConfigSnapshot", - "proxySnapshot", proxySnapshot, - ) - generator := NewResourceGenerator( - logger, - cfgFetcher, - true, - ) - - c := proxySnapshot.(*proxycfg.ConfigSnapshot) - logger.Trace("ConfigSnapshot", c) - return generator.AllResourcesFromSnapshot(c) - case *proxytracker.ProxyState: - logger.Trace("ProxySnapshot update channel received a ProxySnapshot of type ProxyState", - "proxySnapshot", proxySnapshot, - ) - generator := xdsv2.NewResourceGenerator( - logger, - ) - c := proxySnapshot.(*proxytracker.ProxyState) - logger.Trace("ProxyState", c) - return generator.AllResourcesFromIR(c) - default: - return nil, errors.New("proxysnapshot must be of type ProxyState or ConfigSnapshot") - } -} - const ( stateDeltaInit int = iota stateDeltaPendingInitialConfig @@ -136,13 +98,14 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove // Loop state var ( - proxySnapshot proxysnapshot.ProxySnapshot - node *envoy_config_core_v3.Node - stateCh <-chan proxysnapshot.ProxySnapshot - drainCh limiter.SessionTerminatedChan - watchCancel func() - nonce uint64 // xDS requires a unique nonce to correlate response/request pairs - ready bool // set to true after the first snapshot arrives + cfgSnap *proxycfg.ConfigSnapshot + node *envoy_config_core_v3.Node + stateCh <-chan *proxycfg.ConfigSnapshot + drainCh limiter.SessionTerminatedChan + watchCancel func() + proxyID structs.ServiceID + nonce uint64 // xDS requires a unique nonce to correlate response/request pairs + ready bool // set to true after the first snapshot arrives streamStartTime = time.Now() streamStartOnce sync.Once @@ -154,30 +117,42 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove // type => name => proto resourceMap = xdscommon.EmptyIndexedResources() - // currentVersions is the xDS versioning represented by Resources. + // currentVersions is the the xDS versioning represented by Resources. // // type => name => version (as consul knows right now) currentVersions = make(map[string]map[string]string) ) - logger := s.Logger.Named(logging.XDS).With("xdsVersion", "v3") + generator := NewResourceGenerator( + s.Logger.Named(logging.XDS).With("xdsVersion", "v3"), + s.CfgFetcher, + true, + ) // need to run a small state machine to get through initial authentication. var state = stateDeltaInit // Configure handlers for each type of request we currently care about. handlers := map[string]*xDSDeltaType{ - xdscommon.ListenerType: newDeltaType(logger, stream, xdscommon.ListenerType, func() bool { - return proxySnapshot.AllowEmptyListeners() + xdscommon.ListenerType: newDeltaType(generator, stream, xdscommon.ListenerType, func(kind structs.ServiceKind) bool { + // Ingress and API gateways are allowed to inform LDS of no listeners. + return cfgSnap.Kind == structs.ServiceKindIngressGateway || + cfgSnap.Kind == structs.ServiceKindAPIGateway }), - xdscommon.RouteType: newDeltaType(logger, stream, xdscommon.RouteType, func() bool { - return proxySnapshot.AllowEmptyRoutes() + xdscommon.RouteType: newDeltaType(generator, stream, xdscommon.RouteType, func(kind structs.ServiceKind) bool { + // Ingress and API gateways are allowed to inform RDS of no routes. + return cfgSnap.Kind == structs.ServiceKindIngressGateway || + cfgSnap.Kind == structs.ServiceKindAPIGateway }), - xdscommon.ClusterType: newDeltaType(logger, stream, xdscommon.ClusterType, func() bool { - return proxySnapshot.AllowEmptyClusters() + xdscommon.ClusterType: newDeltaType(generator, stream, xdscommon.ClusterType, func(kind structs.ServiceKind) bool { + // Mesh, Ingress, API and Terminating gateways are allowed to inform CDS of no clusters. + return cfgSnap.Kind == structs.ServiceKindMeshGateway || + cfgSnap.Kind == structs.ServiceKindTerminatingGateway || + cfgSnap.Kind == structs.ServiceKindIngressGateway || + cfgSnap.Kind == structs.ServiceKindAPIGateway }), - xdscommon.EndpointType: newDeltaType(logger, stream, xdscommon.EndpointType, nil), - xdscommon.SecretType: newDeltaType(logger, stream, xdscommon.SecretType, nil), // TODO allowEmptyFn + xdscommon.EndpointType: newDeltaType(generator, stream, xdscommon.EndpointType, nil), + xdscommon.SecretType: newDeltaType(generator, stream, xdscommon.SecretType, nil), // TODO allowEmptyFn } // Endpoints are stored within a Cluster (and Routes @@ -203,19 +178,19 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove authTimer = time.After(s.AuthCheckFrequency) } - checkStreamACLs := func(proxySnap proxysnapshot.ProxySnapshot) error { - return s.authorize(stream.Context(), proxySnap) + checkStreamACLs := func(cfgSnap *proxycfg.ConfigSnapshot) error { + return s.authorize(stream.Context(), cfgSnap) } for { select { case <-drainCh: - logger.Debug("draining stream to rebalance load") + generator.Logger.Debug("draining stream to rebalance load") metrics.IncrCounter([]string{"xds", "server", "streamDrained"}, 1) return errOverwhelmed case <-authTimer: // It's been too long since a Discovery{Request,Response} so recheck ACLs. - if err := checkStreamACLs(proxySnapshot); err != nil { + if err := checkStreamACLs(cfgSnap); err != nil { return err } extendAuthTimer() @@ -229,29 +204,28 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove return nil } - logTraceRequest(logger, "Incremental xDS v3", req) + generator.logTraceRequest("Incremental xDS v3", req) if req.TypeUrl == "" { return status.Errorf(codes.InvalidArgument, "type URL is required for ADS") } - var proxyFeatures xdscommon.SupportedProxyFeatures if node == nil && req.Node != nil { node = req.Node var err error - proxyFeatures, err = xdscommon.DetermineSupportedProxyFeatures(req.Node) + generator.ProxyFeatures, err = xdscommon.DetermineSupportedProxyFeatures(req.Node) if err != nil { return status.Errorf(codes.InvalidArgument, err.Error()) } } if handler, ok := handlers[req.TypeUrl]; ok { - switch handler.Recv(req, proxyFeatures) { + switch handler.Recv(req, generator.ProxyFeatures) { case deltaRecvNewSubscription: - logger.Trace("subscribing to type", "typeUrl", req.TypeUrl) + generator.Logger.Trace("subscribing to type", "typeUrl", req.TypeUrl) case deltaRecvResponseNack: - logger.Trace("got nack response for type", "typeUrl", req.TypeUrl) + generator.Logger.Trace("got nack response for type", "typeUrl", req.TypeUrl) // There is no reason to believe that generating new xDS resources from the same snapshot // would lead to an ACK from Envoy. Instead we continue to the top of this for loop and wait @@ -270,21 +244,21 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove // would've already exited this loop. return status.Error(codes.Aborted, "xDS stream terminated due to an irrecoverable error, please try again") } - proxySnapshot = cs + cfgSnap = cs - newRes, err := getEnvoyConfiguration(proxySnapshot, logger, s.CfgFetcher) + newRes, err := generator.AllResourcesFromSnapshot(cfgSnap) if err != nil { return status.Errorf(codes.Unavailable, "failed to generate all xDS resources from the snapshot: %v", err) } // index and hash the xDS structures - newResourceMap := xdscommon.IndexResources(logger, newRes) + newResourceMap := xdscommon.IndexResources(generator.Logger, newRes) if s.ResourceMapMutateFn != nil { s.ResourceMapMutateFn(newResourceMap) } - if newResourceMap, err = s.applyEnvoyExtensions(newResourceMap, proxySnapshot, node); err != nil { + if newResourceMap, err = s.applyEnvoyExtensions(newResourceMap, cfgSnap, node); err != nil { // err is already the result of calling status.Errorf return err } @@ -318,7 +292,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove } // Start authentication process, we need the proxyID - proxyID := newResourceIDFromEnvoyNode(node) + proxyID = structs.NewServiceID(node.Id, parseEnterpriseMeta(node)) // Start watching config for that proxy var err error @@ -327,12 +301,12 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove return status.Errorf(codes.Internal, "failed to watch proxy service: %s", err) } - stateCh, drainCh, watchCancel, err = s.ProxyWatcher.Watch(proxyID, nodeName, options.Token) + stateCh, drainCh, watchCancel, err = s.CfgSrc.Watch(proxyID, nodeName, options.Token) switch { case errors.Is(err, limiter.ErrCapacityReached): return errOverwhelmed case err != nil: - return status.Errorf(codes.Internal, "failed to watch proxy: %s", err) + return status.Errorf(codes.Internal, "failed to watch proxy service: %s", err) } // Note that in this case we _intend_ the defer to only be triggered when // this whole process method ends (i.e. when streaming RPC aborts) not at @@ -341,14 +315,14 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove // state machine. defer watchCancel() - logger = logger.With("service_id", proxyID.Name) // enhance future logs + generator.Logger = generator.Logger.With("service_id", proxyID.String()) // enhance future logs - logger.Trace("watching proxy, pending initial proxycfg snapshot for xDS") + generator.Logger.Trace("watching proxy, pending initial proxycfg snapshot for xDS") // Now wait for the config so we can check ACL state = stateDeltaPendingInitialConfig case stateDeltaPendingInitialConfig: - if proxySnapshot == nil { + if cfgSnap == nil { // Nothing we can do until we get the initial config continue } @@ -357,18 +331,23 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove state = stateDeltaRunning // Upgrade the logger - loggerName := proxySnapshot.LoggerName() - if loggerName != "" { - logger = logger.Named(loggerName) + switch cfgSnap.Kind { + case structs.ServiceKindConnectProxy: + case structs.ServiceKindTerminatingGateway: + generator.Logger = generator.Logger.Named(logging.TerminatingGateway) + case structs.ServiceKindMeshGateway: + generator.Logger = generator.Logger.Named(logging.MeshGateway) + case structs.ServiceKindIngressGateway: + generator.Logger = generator.Logger.Named(logging.IngressGateway) } - logger.Trace("Got initial config snapshot") + generator.Logger.Trace("Got initial config snapshot") // Let's actually process the config we just got, or we'll miss responding fallthrough case stateDeltaRunning: // Check ACLs on every Discovery{Request,Response}. - if err := checkStreamACLs(proxySnapshot); err != nil { + if err := checkStreamACLs(cfgSnap); err != nil { return err } // For the first time through the state machine, this is when the @@ -376,11 +355,11 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove extendAuthTimer() if !ready { - logger.Trace("Skipping delta computation because we haven't gotten a snapshot yet") + generator.Logger.Trace("Skipping delta computation because we haven't gotten a snapshot yet") continue } - logger.Trace("Invoking all xDS resource handlers and sending changed data if there are any") + generator.Logger.Trace("Invoking all xDS resource handlers and sending changed data if there are any") streamStartOnce.Do(func() { metrics.MeasureSince([]string{"xds", "server", "streamStart"}, streamStartTime) @@ -389,7 +368,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove for _, op := range xDSUpdateOrder { if op.TypeUrl == xdscommon.ListenerType || op.TypeUrl == xdscommon.RouteType { if clusterHandler := handlers[xdscommon.ClusterType]; clusterHandler.registered && len(clusterHandler.pendingUpdates) > 0 { - logger.Trace("Skipping delta computation for resource because there are dependent updates pending", + generator.Logger.Trace("Skipping delta computation for resource because there are dependent updates pending", "typeUrl", op.TypeUrl, "dependent", xdscommon.ClusterType) // Receiving an ACK from Envoy will unblock the select statement above, @@ -397,7 +376,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove break } if endpointHandler := handlers[xdscommon.EndpointType]; endpointHandler.registered && len(endpointHandler.pendingUpdates) > 0 { - logger.Trace("Skipping delta computation for resource because there are dependent updates pending", + generator.Logger.Trace("Skipping delta computation for resource because there are dependent updates pending", "typeUrl", op.TypeUrl, "dependent", xdscommon.EndpointType) // Receiving an ACK from Envoy will unblock the select statement above, @@ -405,7 +384,14 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove break } } - err, _ := handlers[op.TypeUrl].SendIfNew(currentVersions[op.TypeUrl], resourceMap, &nonce, op.Upsert, op.Remove) + err, _ := handlers[op.TypeUrl].SendIfNew( + cfgSnap.Kind, + currentVersions[op.TypeUrl], + resourceMap, + &nonce, + op.Upsert, + op.Remove, + ) if err != nil { return status.Errorf(codes.Unavailable, "failed to send %sreply for type %q: %v", @@ -417,37 +403,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove } } -// newResourceIDFromEnvoyNode is a utility function that allows creating a -// Resource ID from an Envoy proxy node so that existing delta calls can easily -// use ProxyWatcher interface arguments for Watch(). -func newResourceIDFromEnvoyNode(node *envoy_config_core_v3.Node) *pbresource.ID { - entMeta := parseEnterpriseMeta(node) - - return &pbresource.ID{ - Name: node.Id, - Tenancy: &pbresource.Tenancy{ - Namespace: entMeta.NamespaceOrDefault(), - Partition: entMeta.PartitionOrDefault(), - }, - Type: mesh.ProxyStateTemplateConfigurationV1Alpha1Type, - } -} - -func (s *Server) applyEnvoyExtensions(resources *xdscommon.IndexedResources, proxySnapshot proxysnapshot.ProxySnapshot, node *envoy_config_core_v3.Node) (*xdscommon.IndexedResources, error) { - // TODO(proxystate) - // This is a workaround for now as envoy extensions are not yet supported with ProxyState. - // For now, we cast to proxycfg.ConfigSnapshot and no-op if it's the pbmesh.ProxyState type. - var snapshot *proxycfg.ConfigSnapshot - switch proxySnapshot.(type) { - //TODO(proxystate): implement envoy extensions for ProxyState - case *proxytracker.ProxyState: - return resources, nil - case *proxycfg.ConfigSnapshot: - snapshot = proxySnapshot.(*proxycfg.ConfigSnapshot) - default: - return nil, status.Errorf(codes.InvalidArgument, - "unsupported config snapshot type to apply envoy extensions to %T", proxySnapshot) - } +func (s *Server) applyEnvoyExtensions(resources *xdscommon.IndexedResources, cfgSnap *proxycfg.ConfigSnapshot, node *envoy_config_core_v3.Node) (*xdscommon.IndexedResources, error) { var err error envoyVersion := xdscommon.DetermineEnvoyVersionFromNode(node) consulVersion, err := goversion.NewVersion(version.Version) @@ -456,10 +412,10 @@ func (s *Server) applyEnvoyExtensions(resources *xdscommon.IndexedResources, pro return nil, status.Errorf(codes.InvalidArgument, "failed to parse Consul version") } - serviceConfigs := extensionruntime.GetRuntimeConfigurations(snapshot) + serviceConfigs := extensionruntime.GetRuntimeConfigurations(cfgSnap) for _, cfgs := range serviceConfigs { for _, cfg := range cfgs { - resources, err = validateAndApplyEnvoyExtension(s.Logger, snapshot, resources, cfg, envoyVersion, consulVersion) + resources, err = validateAndApplyEnvoyExtension(s.Logger, cfgSnap, resources, cfg, envoyVersion, consulVersion) if err != nil { return nil, err @@ -669,10 +625,10 @@ type xDSDeltaChild struct { } type xDSDeltaType struct { - logger hclog.Logger + generator *ResourceGenerator stream ADSDeltaStream typeURL string - allowEmptyFn func() bool + allowEmptyFn func(kind structs.ServiceKind) bool // deltaChild contains data for an xDS child type if there is one. // For example, endpoints are a child type of clusters. @@ -721,13 +677,13 @@ type PendingUpdate struct { } func newDeltaType( - logger hclog.Logger, + generator *ResourceGenerator, stream ADSDeltaStream, typeUrl string, - allowEmptyFn func() bool, + allowEmptyFn func(kind structs.ServiceKind) bool, ) *xDSDeltaType { return &xDSDeltaType{ - logger: logger, + generator: generator, stream: stream, typeURL: typeUrl, allowEmptyFn: allowEmptyFn, @@ -744,6 +700,7 @@ func (t *xDSDeltaType) Recv(req *envoy_discovery_v3.DeltaDiscoveryRequest, sf xd if t == nil { return deltaRecvUnknownType // not something we care about } + logger := t.generator.Logger.With("typeUrl", t.typeURL) registeredThisTime := false if !t.registered { @@ -780,10 +737,10 @@ func (t *xDSDeltaType) Recv(req *envoy_discovery_v3.DeltaDiscoveryRequest, sf xd response_nonce, with presence of error_detail making it a NACK). */ if req.ErrorDetail == nil { - t.logger.Trace("got ok response from envoy proxy", "nonce", req.ResponseNonce) + logger.Trace("got ok response from envoy proxy", "nonce", req.ResponseNonce) t.ack(req.ResponseNonce) } else { - t.logger.Error("got error response from envoy proxy", "nonce", req.ResponseNonce, + logger.Error("got error response from envoy proxy", "nonce", req.ResponseNonce, "error", status.ErrorProto(req.ErrorDetail)) t.nack(req.ResponseNonce) return deltaRecvResponseNack @@ -799,7 +756,7 @@ func (t *xDSDeltaType) Recv(req *envoy_discovery_v3.DeltaDiscoveryRequest, sf xd the client already possesses, using the initial_resource_versions field. */ - t.logger.Trace("setting initial resource versions for stream", + logger.Trace("setting initial resource versions for stream", "resources", req.InitialResourceVersions) t.resourceVersions = req.InitialResourceVersions if !t.wildcard { @@ -850,9 +807,9 @@ func (t *xDSDeltaType) Recv(req *envoy_discovery_v3.DeltaDiscoveryRequest, sf xd } if alreadySubscribed { - t.logger.Trace("re-subscribing resource for stream", "resource", name) + logger.Trace("re-subscribing resource for stream", "resource", name) } else { - t.logger.Trace("subscribing resource for stream", "resource", name) + logger.Trace("subscribing resource for stream", "resource", name) } } @@ -861,7 +818,7 @@ func (t *xDSDeltaType) Recv(req *envoy_discovery_v3.DeltaDiscoveryRequest, sf xd continue } delete(t.subscriptions, name) - t.logger.Trace("unsubscribing resource for stream", "resource", name) + logger.Trace("unsubscribing resource for stream", "resource", name) // NOTE: we'll let the normal differential comparison handle cleaning up resourceVersions } } @@ -895,6 +852,7 @@ func (t *xDSDeltaType) nack(nonce string) { } func (t *xDSDeltaType) SendIfNew( + kind structs.ServiceKind, currentVersions map[string]string, // type => name => version (as consul knows right now) resourceMap *xdscommon.IndexedResources, nonce *uint64, @@ -909,9 +867,9 @@ func (t *xDSDeltaType) SendIfNew( return nil, false } - logger := t.logger.With("typeUrl", t.typeURL) + logger := t.generator.Logger.With("typeUrl", t.typeURL) - allowEmpty := t.allowEmptyFn != nil && t.allowEmptyFn() + allowEmpty := t.allowEmptyFn != nil && t.allowEmptyFn(kind) // Zero length resource responses should be ignored and are the result of no // data yet. Notice that this caused a bug originally where we had zero @@ -936,7 +894,7 @@ func (t *xDSDeltaType) SendIfNew( *nonce++ resp.Nonce = fmt.Sprintf("%08x", *nonce) - logTraceResponse(t.logger, "Incremental xDS v3", resp) + t.generator.logTraceResponse("Incremental xDS v3", resp) logger.Trace("sending response", "nonce", resp.Nonce) if err := t.stream.Send(resp); err != nil { @@ -1088,7 +1046,7 @@ func (t *xDSDeltaType) ensureChildResend(parentName, childName string) { return } - t.logger.Trace( + t.generator.Logger.Trace( "triggering implicit update of resource", "typeUrl", t.typeURL, "resource", parentName, diff --git a/agent/xds/delta_envoy_extender_ce_test.go b/agent/xds/delta_envoy_extender_ce_test.go index 0607919ef5a5b..10411e353cec5 100644 --- a/agent/xds/delta_envoy_extender_ce_test.go +++ b/agent/xds/delta_envoy_extender_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent @@ -21,12 +21,12 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" + "github.com/hashicorp/consul/agent/xds/testcommon" + propertyoverride "github.com/hashicorp/consul/agent/envoyextensions/builtin/property-override" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/xds/extensionruntime" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/agent/xds/testcommon" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/envoyextensions/extensioncommon" "github.com/hashicorp/consul/envoyextensions/xdscommon" @@ -803,7 +803,7 @@ end`, } sort.Slice(msgs, entity.sorter(msgs)) - r, err := response.CreateResponse(entity.key, "00000001", "00000001", msgs) + r, err := createResponse(entity.key, "00000001", "00000001", msgs) require.NoError(t, err) t.Run(entity.name, func(t *testing.T) { diff --git a/agent/xds/delta_envoy_extender_test.go b/agent/xds/delta_envoy_extender_test.go index cfa762cb049ed..6cd57fa53a041 100644 --- a/agent/xds/delta_envoy_extender_test.go +++ b/agent/xds/delta_envoy_extender_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds diff --git a/agent/xds/delta_test.go b/agent/xds/delta_test.go index d93d06271bac2..052e72ad558d8 100644 --- a/agent/xds/delta_test.go +++ b/agent/xds/delta_test.go @@ -1,12 +1,11 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds import ( "errors" "fmt" - "github.com/hashicorp/consul/envoyextensions/xdscommon" "strconv" "strings" "sync" @@ -18,22 +17,24 @@ import ( envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" + "github.com/hashicorp/go-hclog" + goversion "github.com/hashicorp/go-version" + "github.com/stretchr/testify/require" + rpcstatus "google.golang.org/genproto/googleapis/rpc/status" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/grpc-external/limiter" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/envoyextensions/extensioncommon" + "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/version" - "github.com/hashicorp/go-hclog" - goversion "github.com/hashicorp/go-version" - "github.com/stretchr/testify/require" - rpcstatus "google.golang.org/genproto/googleapis/rpc/status" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" ) // NOTE: For these tests, prefer not using xDS protobuf "factory" methods if @@ -1695,12 +1696,6 @@ func Test_validateAndApplyEnvoyExtension_Validations(t *testing.T) { runtimeConfig: makeRuntimeConfig(false, ">= 1.15.0", ">= 1.25.0", map[string]interface{}{"bad": "args"}), err: false, }, - { - name: "valid everything - no resources and required", - runtimeConfig: makeRuntimeConfig(true, ">= 1.15.0", ">= 1.25.0", nil), - err: true, - errString: "failed to patch xDS resources in", - }, { name: "valid everything", runtimeConfig: makeRuntimeConfig(false, ">= 1.15.0", ">= 1.25.0", nil), diff --git a/agent/xds/endpoints.go b/agent/xds/endpoints.go index a2c36f06bdc23..021f9ae23ef3d 100644 --- a/agent/xds/endpoints.go +++ b/agent/xds/endpoints.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -8,20 +8,17 @@ import ( "fmt" "strconv" - "github.com/hashicorp/go-hclog" - envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" + "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/go-bexpr" "google.golang.org/protobuf/proto" "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/response" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/envoyextensions/xdscommon" ) const ( @@ -138,10 +135,7 @@ func (s *ResourceGenerator) endpointsFromSnapshotConnectProxy(cfgSnap *proxycfg. endpoints, ok := cfgSnap.ConnectProxy.PreparedQueryEndpoints[uid] if ok { la := makeLoadAssignment( - s.Logger, - cfgSnap, clusterName, - nil, []loadAssignmentEndpointGroup{ {Endpoints: endpoints}, }, @@ -164,10 +158,7 @@ func (s *ResourceGenerator) endpointsFromSnapshotConnectProxy(cfgSnap *proxycfg. endpoints, ok := cfgSnap.ConnectProxy.DestinationGateways.Get(uid) if ok { la := makeLoadAssignment( - s.Logger, - cfgSnap, name, - nil, []loadAssignmentEndpointGroup{ {Endpoints: endpoints}, }, @@ -233,10 +224,7 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C clusterName := connect.GatewaySNI(key.Datacenter, key.Partition, cfgSnap.Roots.TrustDomain) la := makeLoadAssignment( - s.Logger, - cfgSnap, clusterName, - nil, []loadAssignmentEndpointGroup{ {Endpoints: endpoints}, }, @@ -251,10 +239,7 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C clusterName := cfgSnap.ServerSNIFn(key.Datacenter, "") la := makeLoadAssignment( - s.Logger, - cfgSnap, clusterName, - nil, []loadAssignmentEndpointGroup{ {Endpoints: endpoints}, }, @@ -279,7 +264,7 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C lbEndpoint := &envoy_endpoint_v3.LbEndpoint{ HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ Endpoint: &envoy_endpoint_v3.Endpoint{ - Address: response.MakeAddress(addr, port), + Address: makeAddress(addr, port), }, }, HealthStatus: envoy_core_v3.HealthStatus_UNKNOWN, @@ -336,7 +321,7 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C serverEndpoints = append(serverEndpoints, &envoy_endpoint_v3.LbEndpoint{ HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ Endpoint: &envoy_endpoint_v3.Endpoint{ - Address: response.MakeAddress(addr, port), + Address: makeAddress(addr, port), }, }, }) @@ -424,10 +409,7 @@ func (s *ResourceGenerator) endpointsFromServicesAndResolvers( for subsetName, groups := range clusterEndpoints { clusterName := connect.ServiceSNI(svc.Name, subsetName, svc.NamespaceOrDefault(), svc.PartitionOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain) la := makeLoadAssignment( - s.Logger, - cfgSnap, clusterName, - nil, groups, cfgSnap.Locality, ) @@ -462,10 +444,7 @@ func (s *ResourceGenerator) makeEndpointsForOutgoingPeeredServices( groups := []loadAssignmentEndpointGroup{{Endpoints: serviceGroup.Nodes, OnlyPassing: false}} la := makeLoadAssignment( - s.Logger, - cfgSnap, clusterName, - nil, groups, // Use an empty key here so that it never matches. This will force the mesh gateway to always // reference the remote mesh gateway's wan addr. @@ -585,7 +564,7 @@ func makeEndpoint(host string, port int) *envoy_endpoint_v3.LbEndpoint { return &envoy_endpoint_v3.LbEndpoint{ HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ Endpoint: &envoy_endpoint_v3.Endpoint{ - Address: response.MakeAddress(host, port), + Address: makeAddress(host, port), }, }, } @@ -595,7 +574,7 @@ func makePipeEndpoint(path string) *envoy_endpoint_v3.LbEndpoint { return &envoy_endpoint_v3.LbEndpoint{ HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ Endpoint: &envoy_endpoint_v3.Endpoint{ - Address: response.MakePipeAddress(path, 0), + Address: makePipeAddress(path, 0), }, }, } @@ -627,10 +606,7 @@ func (s *ResourceGenerator) makeUpstreamLoadAssignmentForPeerService( return la, nil } la = makeLoadAssignment( - s.Logger, - cfgSnap, clusterName, - nil, []loadAssignmentEndpointGroup{ {Endpoints: localGw}, }, @@ -650,10 +626,7 @@ func (s *ResourceGenerator) makeUpstreamLoadAssignmentForPeerService( return nil, nil } la = makeLoadAssignment( - s.Logger, - cfgSnap, clusterName, - nil, []loadAssignmentEndpointGroup{ {Endpoints: endpoints}, }, @@ -750,6 +723,7 @@ func (s *ResourceGenerator) endpointsFromDiscoveryChain( } switch len(groupedTarget.Targets) { case 0: + s.Logger.Trace("skipping endpoint generation for zero-length target group", "cluster", clusterName) continue case 1: // We expect one target so this passes through to continue setting the load assignment up. @@ -757,7 +731,7 @@ func (s *ResourceGenerator) endpointsFromDiscoveryChain( return nil, fmt.Errorf("cannot have more than one target") } ti := groupedTarget.Targets[0] - s.Logger.Debug("generating endpoints for", "cluster", clusterName, "targetID", ti.TargetID) + s.Logger.Trace("generating endpoints for", "cluster", clusterName, "targetID", ti.TargetID, "gatewayKey", gatewayKey) targetUID := proxycfg.NewUpstreamIDFromTargetID(ti.TargetID) if targetUID.Peer != "" { loadAssignment, err := s.makeUpstreamLoadAssignmentForPeerService(cfgSnap, clusterName, targetUID, mgwMode) @@ -779,14 +753,12 @@ func (s *ResourceGenerator) endpointsFromDiscoveryChain( forMeshGateway, ) if !valid { + s.Logger.Trace("skipping endpoint generation for invalid target group", "cluster", clusterName) continue // skip the cluster if we're still populating the snapshot } la := makeLoadAssignment( - s.Logger, - cfgSnap, clusterName, - ti.PrioritizeByLocality, []loadAssignmentEndpointGroup{endpointGroup}, gatewayKey, ) @@ -872,7 +844,7 @@ type loadAssignmentEndpointGroup struct { OverrideHealth envoy_core_v3.HealthStatus } -func makeLoadAssignment(logger hclog.Logger, cfgSnap *proxycfg.ConfigSnapshot, clusterName string, policy *structs.DiscoveryPrioritizeByLocality, endpointGroups []loadAssignmentEndpointGroup, localKey proxycfg.GatewayKey) *envoy_endpoint_v3.ClusterLoadAssignment { +func makeLoadAssignment(clusterName string, endpointGroups []loadAssignmentEndpointGroup, localKey proxycfg.GatewayKey) *envoy_endpoint_v3.ClusterLoadAssignment { cla := &envoy_endpoint_v3.ClusterLoadAssignment{ ClusterName: clusterName, Endpoints: make([]*envoy_endpoint_v3.LocalityLbEndpoints, 0, len(endpointGroups)), @@ -882,50 +854,39 @@ func makeLoadAssignment(logger hclog.Logger, cfgSnap *proxycfg.ConfigSnapshot, c cla.Policy = &envoy_endpoint_v3.ClusterLoadAssignment_Policy{ // We choose such a large value here that the failover math should // in effect not happen until zero instances are healthy. - OverprovisioningFactor: response.MakeUint32Value(100000), + OverprovisioningFactor: makeUint32Value(100000), } } - var priority uint32 + for priority, endpointGroup := range endpointGroups { + endpoints := endpointGroup.Endpoints + es := make([]*envoy_endpoint_v3.LbEndpoint, 0, len(endpoints)) - for _, endpointGroup := range endpointGroups { - endpointsByLocality, err := groupedEndpoints(logger, cfgSnap.ServiceLocality, policy, endpointGroup.Endpoints) + for _, ep := range endpoints { + // TODO (mesh-gateway) - should we respect the translate_wan_addrs configuration here or just always use the wan for cross-dc? + _, addr, port := ep.BestAddress(!localKey.Matches(ep.Node.Datacenter, ep.Node.PartitionOrDefault())) + healthStatus, weight := calculateEndpointHealthAndWeight(ep, endpointGroup.OnlyPassing) - if err != nil { - continue - } - - for _, endpoints := range endpointsByLocality { - es := make([]*envoy_endpoint_v3.LbEndpoint, 0, len(endpointGroup.Endpoints)) - - for _, ep := range endpoints { - // TODO (mesh-gateway) - should we respect the translate_wan_addrs configuration here or just always use the wan for cross-dc? - _, addr, port := ep.BestAddress(!localKey.Matches(ep.Node.Datacenter, ep.Node.PartitionOrDefault())) - healthStatus, weight := calculateEndpointHealthAndWeight(ep, endpointGroup.OnlyPassing) - - if endpointGroup.OverrideHealth != envoy_core_v3.HealthStatus_UNKNOWN { - healthStatus = endpointGroup.OverrideHealth - } - - endpoint := &envoy_endpoint_v3.Endpoint{ - Address: response.MakeAddress(addr, port), - } - es = append(es, &envoy_endpoint_v3.LbEndpoint{ - HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ - Endpoint: endpoint, - }, - HealthStatus: healthStatus, - LoadBalancingWeight: response.MakeUint32Value(weight), - }) + if endpointGroup.OverrideHealth != envoy_core_v3.HealthStatus_UNKNOWN { + healthStatus = endpointGroup.OverrideHealth } - cla.Endpoints = append(cla.Endpoints, &envoy_endpoint_v3.LocalityLbEndpoints{ - Priority: priority, - LbEndpoints: es, + endpoint := &envoy_endpoint_v3.Endpoint{ + Address: makeAddress(addr, port), + } + es = append(es, &envoy_endpoint_v3.LbEndpoint{ + HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ + Endpoint: endpoint, + }, + HealthStatus: healthStatus, + LoadBalancingWeight: makeUint32Value(weight), }) - - priority++ } + + cla.Endpoints = append(cla.Endpoints, &envoy_endpoint_v3.LocalityLbEndpoints{ + Priority: uint32(priority), + LbEndpoints: es, + }) } return cla diff --git a/agent/xds/endpoints_test.go b/agent/xds/endpoints_test.go index 9daf5b31f55b3..ebdd06aa41e23 100644 --- a/agent/xds/endpoints_test.go +++ b/agent/xds/endpoints_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -10,18 +10,16 @@ import ( envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/proxystateconverter" - "github.com/hashicorp/consul/agent/xds/response" "github.com/hashicorp/consul/agent/xds/testcommon" - "github.com/hashicorp/consul/agent/xdsv2" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/go-hclog" + "github.com/mitchellh/copystructure" testinf "github.com/mitchellh/go-testing-interface" "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/agent/proxycfg" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/envoyextensions/xdscommon" + "github.com/hashicorp/consul/sdk/testutil" ) func Test_makeLoadAssignment(t *testing.T) { @@ -103,7 +101,6 @@ func Test_makeLoadAssignment(t *testing.T) { tests := []struct { name string clusterName string - locality *structs.Locality endpoints []loadAssignmentEndpointGroup want *envoy_endpoint_v3.ClusterLoadAssignment }{ @@ -133,18 +130,18 @@ func Test_makeLoadAssignment(t *testing.T) { { HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ Endpoint: &envoy_endpoint_v3.Endpoint{ - Address: response.MakeAddress("10.10.10.10", 1234), + Address: makeAddress("10.10.10.10", 1234), }}, HealthStatus: envoy_core_v3.HealthStatus_HEALTHY, - LoadBalancingWeight: response.MakeUint32Value(1), + LoadBalancingWeight: makeUint32Value(1), }, { HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ Endpoint: &envoy_endpoint_v3.Endpoint{ - Address: response.MakeAddress("10.10.10.20", 1234), + Address: makeAddress("10.10.10.20", 1234), }}, HealthStatus: envoy_core_v3.HealthStatus_HEALTHY, - LoadBalancingWeight: response.MakeUint32Value(1), + LoadBalancingWeight: makeUint32Value(1), }, }, }}, @@ -163,18 +160,18 @@ func Test_makeLoadAssignment(t *testing.T) { { HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ Endpoint: &envoy_endpoint_v3.Endpoint{ - Address: response.MakeAddress("10.10.10.10", 1234), + Address: makeAddress("10.10.10.10", 1234), }}, HealthStatus: envoy_core_v3.HealthStatus_HEALTHY, - LoadBalancingWeight: response.MakeUint32Value(10), + LoadBalancingWeight: makeUint32Value(10), }, { HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ Endpoint: &envoy_endpoint_v3.Endpoint{ - Address: response.MakeAddress("10.10.10.20", 1234), + Address: makeAddress("10.10.10.20", 1234), }}, HealthStatus: envoy_core_v3.HealthStatus_HEALTHY, - LoadBalancingWeight: response.MakeUint32Value(5), + LoadBalancingWeight: makeUint32Value(5), }, }, }}, @@ -193,18 +190,18 @@ func Test_makeLoadAssignment(t *testing.T) { { HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ Endpoint: &envoy_endpoint_v3.Endpoint{ - Address: response.MakeAddress("10.10.10.10", 1234), + Address: makeAddress("10.10.10.10", 1234), }}, HealthStatus: envoy_core_v3.HealthStatus_HEALTHY, - LoadBalancingWeight: response.MakeUint32Value(1), + LoadBalancingWeight: makeUint32Value(1), }, { HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ Endpoint: &envoy_endpoint_v3.Endpoint{ - Address: response.MakeAddress("10.10.10.20", 1234), + Address: makeAddress("10.10.10.20", 1234), }}, HealthStatus: envoy_core_v3.HealthStatus_UNHEALTHY, - LoadBalancingWeight: response.MakeUint32Value(1), + LoadBalancingWeight: makeUint32Value(1), }, }, }}, @@ -214,26 +211,11 @@ func Test_makeLoadAssignment(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := makeLoadAssignment( - hclog.NewNullLogger(), - &proxycfg.ConfigSnapshot{ServiceLocality: tt.locality}, tt.clusterName, - nil, tt.endpoints, proxycfg.GatewayKey{Datacenter: "dc1"}, ) require.Equal(t, tt.want, got) - - if tt.locality == nil { - got := makeLoadAssignment( - hclog.NewNullLogger(), - &proxycfg.ConfigSnapshot{ServiceLocality: &structs.Locality{Region: "us-west-1", Zone: "us-west-1a"}}, - tt.clusterName, - nil, - tt.endpoints, - proxycfg.GatewayKey{Datacenter: "dc1"}, - ) - require.Equal(t, tt.want, got) - } }) } } @@ -242,7 +224,6 @@ type endpointTestCase struct { name string create func(t testinf.T) *proxycfg.ConfigSnapshot overrideGoldenName string - alsoRunTestForV2 bool } func makeEndpointDiscoChainTests(enterprise bool) []endpointTestCase { @@ -252,84 +233,72 @@ func makeEndpointDiscoChainTests(enterprise bool) []endpointTestCase { create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-chain-external-sni", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "external-sni", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-chain-and-overrides", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple-with-overrides", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-chain-and-failover", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway-triggered", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway-triggered", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tcp-chain-failover-through-local-gateway", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway-triggered", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway-triggered", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-default-chain-and-custom-cluster", @@ -341,15 +310,12 @@ func makeEndpointDiscoChainTests(enterprise bool) []endpointTestCase { }) }, nil) }, - // TODO(proxystate): requires custom cluster work - alsoRunTestForV2: false, }, { name: "splitter-with-resolver-redirect", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-with-resolver-redirect-multidc", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, } } @@ -368,64 +334,42 @@ func TestEndpointsFromSnapshot(t *testing.T) { create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "default", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-using-federation-states", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "federation-states", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-newer-information-in-federation-states", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "newer-info-in-federation-states", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-using-federation-control-plane", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "mesh-gateway-federation", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-older-information-in-federation-states", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "older-info-in-federation-states", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-no-services", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "no-services", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-service-subsets", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "service-subsets2", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "mesh-gateway-default-service-subset", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotMeshGateway(t, "default-service-subsets2", nil, nil) }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-gateway", @@ -433,16 +377,12 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-gateway-nil-config-entry", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotIngressGateway_NilConfigEntry(t) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-gateway-no-services", @@ -450,8 +390,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, false, "tcp", "default", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-chain", @@ -459,8 +397,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "simple", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-chain-external-sni", @@ -468,8 +404,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "external-sni", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-chain-and-failover", @@ -477,8 +411,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-chain-and-failover-to-cluster-peer", @@ -486,8 +418,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-to-cluster-peer", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-failover-through-remote-gateway", @@ -495,8 +425,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-remote-gateway", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-failover-through-remote-gateway-triggered", @@ -504,8 +432,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-remote-gateway-triggered", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-double-failover-through-remote-gateway", @@ -513,8 +439,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-double-remote-gateway", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered", @@ -522,8 +446,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-double-remote-gateway-triggered", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-failover-through-local-gateway", @@ -531,8 +453,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-local-gateway", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-failover-through-local-gateway-triggered", @@ -540,8 +460,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-local-gateway-triggered", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-double-failover-through-local-gateway", @@ -549,8 +467,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-double-local-gateway", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-tcp-chain-double-failover-through-local-gateway-triggered", @@ -558,8 +474,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "failover-through-double-local-gateway-triggered", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-splitter-with-resolver-redirect", @@ -567,42 +481,30 @@ func TestEndpointsFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", "splitter-with-resolver-redirect-multidc", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, nil) }, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway-no-services", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotTerminatingGateway(t, false, nil, nil) }, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway-service-subsets", create: proxycfg.TestConfigSnapshotTerminatingGatewayServiceSubsets, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway-default-service-subset", create: proxycfg.TestConfigSnapshotTerminatingGatewayDefaultServiceSubset, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-multiple-listeners-duplicate-service", create: proxycfg.TestConfigSnapshotIngress_MultipleListenersDuplicateService, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, } @@ -633,10 +535,10 @@ func TestEndpointsFromSnapshot(t *testing.T) { sort.Slice(endpoints, func(i, j int) bool { return endpoints[i].(*envoy_endpoint_v3.ClusterLoadAssignment).ClusterName < endpoints[j].(*envoy_endpoint_v3.ClusterLoadAssignment).ClusterName }) - r, err := response.CreateResponse(xdscommon.EndpointType, "00000001", "00000001", endpoints) + r, err := createResponse(xdscommon.EndpointType, "00000001", "00000001", endpoints) require.NoError(t, err) - t.Run("current-xdsv1", func(t *testing.T) { + t.Run("current", func(t *testing.T) { gotJSON := protoToJSON(t, r) gName := tt.name @@ -646,39 +548,6 @@ func TestEndpointsFromSnapshot(t *testing.T) { require.JSONEq(t, goldenEnvoy(t, filepath.Join("endpoints", gName), envoyVersion, latestEnvoyVersion, gotJSON), gotJSON) }) - - if tt.alsoRunTestForV2 { - generator := xdsv2.NewResourceGenerator(testutil.Logger(t)) - - converter := proxystateconverter.NewConverter(testutil.Logger(t), &mockCfgFetcher{addressLan: "10.10.10.10"}) - proxyState, err := converter.ProxyStateFromSnapshot(snap) - require.NoError(t, err) - - res, err := generator.AllResourcesFromIR(proxyState) - require.NoError(t, err) - - endpoints = res[xdscommon.EndpointType] - // The order of listeners returned via LDS isn't relevant, so it's safe - // to sort these for the purposes of test comparisons. - sort.Slice(endpoints, func(i, j int) bool { - return endpoints[i].(*envoy_endpoint_v3.ClusterLoadAssignment).ClusterName < endpoints[j].(*envoy_endpoint_v3.ClusterLoadAssignment).ClusterName - }) - - r, err := response.CreateResponse(xdscommon.EndpointType, "00000001", "00000001", endpoints) - require.NoError(t, err) - - t.Run("current-xdsv2", func(t *testing.T) { - gotJSON := protoToJSON(t, r) - - gName := tt.name - if tt.overrideGoldenName != "" { - gName = tt.overrideGoldenName - } - - expectedJSON := goldenEnvoy(t, filepath.Join("endpoints", gName), envoyVersion, latestEnvoyVersion, gotJSON) - require.JSONEq(t, expectedJSON, gotJSON) - }) - } }) } }) diff --git a/agent/xds/extensionruntime/runtime_config.go b/agent/xds/extensionruntime/runtime_config.go index 924368ebdf2a6..110e3db1df8b4 100644 --- a/agent/xds/extensionruntime/runtime_config.go +++ b/agent/xds/extensionruntime/runtime_config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package extensionruntime diff --git a/agent/xds/extensionruntime/runtime_config_ce_test.go b/agent/xds/extensionruntime/runtime_config_ce_test.go index 1a38c044ef359..c70a3f47f4f34 100644 --- a/agent/xds/extensionruntime/runtime_config_ce_test.go +++ b/agent/xds/extensionruntime/runtime_config_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/xds/failover_policy.go b/agent/xds/failover_policy.go index ab3e86f25d1db..5edcae914d52c 100644 --- a/agent/xds/failover_policy.go +++ b/agent/xds/failover_policy.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -27,8 +27,6 @@ type targetInfo struct { // Region is the region from the failover target's Locality. nil means the // target is in the local Consul cluster. Region *string - - PrioritizeByLocality *structs.DiscoveryPrioritizeByLocality } type discoChainTargetGroup struct { @@ -70,7 +68,7 @@ func (s *ResourceGenerator) mapDiscoChainTargets(cfgSnap *proxycfg.ConfigSnapsho return discoChainTargets{}, err } - failoverTargets.baseClusterName = s.getTargetClusterName(upstreamsSnapshot, chain, primaryTargetID, forMeshGateway) + failoverTargets.baseClusterName = s.getTargetClusterName(upstreamsSnapshot, chain, primaryTargetID, forMeshGateway, false) tids := []string{primaryTargetID} failover := node.Resolver.Failover @@ -89,7 +87,7 @@ func (s *ResourceGenerator) mapDiscoChainTargets(cfgSnap *proxycfg.ConfigSnapsho var sni, rootPEMs string var spiffeIDs []string targetUID := proxycfg.NewUpstreamIDFromTargetID(tid) - ti := targetInfo{TargetID: tid, PrioritizeByLocality: target.PrioritizeByLocality} + ti := targetInfo{TargetID: tid} configureTLS := true if forMeshGateway { diff --git a/agent/xds/failover_policy_ce.go b/agent/xds/failover_policy_ce.go index ac8d843e40ba8..e22d717e2a110 100644 --- a/agent/xds/failover_policy_ce.go +++ b/agent/xds/failover_policy_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/xds/golden_test.go b/agent/xds/golden_test.go index d77ffda6a6a6e..9209678bb52ea 100644 --- a/agent/xds/golden_test.go +++ b/agent/xds/golden_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds diff --git a/agent/xds/gw_per_route_filters_ce.go b/agent/xds/gw_per_route_filters_ce.go deleted file mode 100644 index cbf406cd07a17..0000000000000 --- a/agent/xds/gw_per_route_filters_ce.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package xds - -import ( - envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/agent/structs" -) - -type perRouteFilterBuilder struct { - providerMap map[string]*structs.JWTProviderConfigEntry - listener *structs.APIGatewayListener - route *structs.HTTPRouteConfigEntry -} - -func (p perRouteFilterBuilder) buildFilter(match *envoy_route_v3.RouteMatch) (map[string]*anypb.Any, error) { - return nil, nil -} diff --git a/agent/xds/jwt_authn.go b/agent/xds/jwt_authn.go index 36b8e05cb30c1..17b34e5cd6ce8 100644 --- a/agent/xds/jwt_authn.go +++ b/agent/xds/jwt_authn.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds diff --git a/agent/xds/jwt_authn_ce.go b/agent/xds/jwt_authn_ce.go deleted file mode 100644 index ac6d0a31d7991..0000000000000 --- a/agent/xds/jwt_authn_ce.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package xds - -import ( - envoy_http_jwt_authn_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/jwt_authn/v3" - envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - - "github.com/hashicorp/consul/agent/structs" -) - -type GatewayAuthFilterBuilder struct { - listener structs.APIGatewayListener - route *structs.HTTPRouteConfigEntry - providers map[string]*structs.JWTProviderConfigEntry - envoyProviders map[string]*envoy_http_jwt_authn_v3.JwtProvider -} - -func (g *GatewayAuthFilterBuilder) makeGatewayAuthFilters() ([]*envoy_http_v3.HttpFilter, error) { - return nil, nil -} diff --git a/agent/xds/jwt_authn_test.go b/agent/xds/jwt_authn_test.go index 834f62ad4c1a0..ab8665b1dc3aa 100644 --- a/agent/xds/jwt_authn_test.go +++ b/agent/xds/jwt_authn_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds diff --git a/agent/xds/listeners.go b/agent/xds/listeners.go index 846cbf6d536fe..520b58e0a6132 100644 --- a/agent/xds/listeners.go +++ b/agent/xds/listeners.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -29,9 +29,6 @@ import ( envoy_tcp_proxy_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/tcp_proxy/v3" envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" - "github.com/hashicorp/consul/agent/xds/config" - "github.com/hashicorp/consul/agent/xds/naming" - "github.com/hashicorp/consul/agent/xds/platform" "github.com/hashicorp/go-hclog" "google.golang.org/protobuf/encoding/protojson" @@ -45,7 +42,6 @@ import ( "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/xds/accesslogs" - "github.com/hashicorp/consul/agent/xds/response" "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/stringslice" @@ -54,6 +50,8 @@ import ( "github.com/hashicorp/consul/types" ) +const virtualIPTag = "virtual" + // listenersFromSnapshot returns the xDS API representation of the "listeners" in the snapshot. func (s *ResourceGenerator) listenersFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) { if cfgSnap == nil { @@ -120,7 +118,7 @@ func (s *ResourceGenerator) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg. } } - proxyCfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) + proxyCfg, err := ParseProxyConfig(cfgSnap.Proxy.Config) if err != nil { // Don't hard fail on a config typo, just warn. The parse func returns // default config if there is an error so it's safe to continue. @@ -169,7 +167,7 @@ func (s *ResourceGenerator) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg. return nil, err } - clusterName = s.getTargetClusterName(upstreamsSnapshot, chain, target.ID, false) + clusterName = s.getTargetClusterName(upstreamsSnapshot, chain, target.ID, false, false) if clusterName == "" { continue } @@ -260,7 +258,7 @@ func (s *ResourceGenerator) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg. // We only match on this virtual IP if the upstream is in the proxy's partition. // This is because the IP is not guaranteed to be unique across k8s clusters. if acl.EqualPartitions(e.Node.PartitionOrDefault(), cfgSnap.ProxyID.PartitionOrDefault()) { - if vip := e.Service.TaggedAddresses[naming.VirtualIPTag]; vip.Address != "" { + if vip := e.Service.TaggedAddresses[virtualIPTag]; vip.Address != "" { uniqueAddrs[vip.Address] = struct{}{} } } @@ -464,7 +462,7 @@ func (s *ResourceGenerator) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg. // The virtualIPTag is used by consul-k8s to store the ClusterIP for a service. // For services imported from a peer,the partition will be equal in all cases. if acl.EqualPartitions(e.Node.PartitionOrDefault(), cfgSnap.ProxyID.PartitionOrDefault()) { - if vip := e.Service.TaggedAddresses[naming.VirtualIPTag]; vip.Address != "" { + if vip := e.Service.TaggedAddresses[virtualIPTag]; vip.Address != "" { uniqueAddrs[vip.Address] = struct{}{} } } @@ -554,8 +552,8 @@ func (s *ResourceGenerator) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg. filterChain, err := s.makeUpstreamFilterChain(filterChainOpts{ accessLogs: &cfgSnap.Proxy.AccessLogs, - clusterName: naming.OriginalDestinationClusterName, - filterName: naming.OriginalDestinationClusterName, + clusterName: OriginalDestinationClusterName, + filterName: OriginalDestinationClusterName, protocol: "tcp", }) if err != nil { @@ -789,7 +787,7 @@ func parseCheckPath(check structs.CheckType) (structs.ExposePath, error) { // listenersFromSnapshotGateway returns the "listener" for a terminating-gateway or mesh-gateway service func (s *ResourceGenerator) listenersFromSnapshotGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) { - cfg, err := config.ParseGatewayConfig(cfgSnap.Proxy.Config) + cfg, err := ParseGatewayConfig(cfgSnap.Proxy.Config) if err != nil { // Don't hard fail on a config typo, just warn. The parse func returns // default config if there is an error so it's safe to continue. @@ -937,7 +935,7 @@ func makeListenerWithDefault(opts makeListenerOpts) *envoy_listener_v3.Listener return &envoy_listener_v3.Listener{ Name: fmt.Sprintf("%s:%s:%d", opts.name, opts.addr, opts.port), AccessLog: accessLog, - Address: response.MakeAddress(opts.addr, opts.port), + Address: makeAddress(opts.addr, opts.port), TrafficDirection: opts.direction, } } @@ -956,7 +954,7 @@ func makePipeListener(opts makeListenerOpts) *envoy_listener_v3.Listener { return &envoy_listener_v3.Listener{ Name: fmt.Sprintf("%s:%s", opts.name, opts.path), AccessLog: accessLog, - Address: response.MakePipeAddress(opts.path, uint32(modeInt)), + Address: makePipeAddress(opts.path, uint32(modeInt)), TrafficDirection: opts.direction, } } @@ -1173,7 +1171,7 @@ func createDownstreamTransportSocketForConnectTLS(cfgSnap *proxycfg.ConfigSnapsh // Determine listener protocol type from configured service protocol. Don't hard fail on a config typo, //The parse func returns default config if there is an error, so it's safe to continue. - cfg, _ := config.ParseProxyConfig(cfgSnap.Proxy.Config) + cfg, _ := ParseProxyConfig(cfgSnap.Proxy.Config) // Create TLS validation context for mTLS with leaf certificate and root certs. tlsContext := makeCommonTLSContext( @@ -1265,7 +1263,7 @@ func (s *ResourceGenerator) makeInboundListener(cfgSnap *proxycfg.ConfigSnapshot var l *envoy_listener_v3.Listener var err error - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) + cfg, err := ParseProxyConfig(cfgSnap.Proxy.Config) if err != nil { // Don't hard fail on a config typo, just warn. The parse func returns // default config if there is an error so it's safe to continue. @@ -1515,7 +1513,7 @@ func (s *ResourceGenerator) finalizePublicListenerFromConfig(l *envoy_listener_v } func (s *ResourceGenerator) makeExposedCheckListener(cfgSnap *proxycfg.ConfigSnapshot, cluster string, path structs.ExposePath) (proto.Message, error) { - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) + cfg, err := ParseProxyConfig(cfgSnap.Proxy.Config) if err != nil { // Don't hard fail on a config typo, just warn. The parse func returns // default config if there is an error so it's safe to continue. @@ -1590,7 +1588,7 @@ func (s *ResourceGenerator) makeExposedCheckListener(cfgSnap *proxycfg.ConfigSna &envoy_core_v3.CidrRange{AddressPrefix: advertise, PrefixLen: &wrapperspb.UInt32Value{Value: uint32(advertiseLen)}}, ) - if ok, err := platform.SupportsIPv6(); err != nil { + if ok, err := kernelSupportsIPv6(); err != nil { return nil, err } else if ok { ranges = append(ranges, @@ -1641,7 +1639,7 @@ func (s *ResourceGenerator) makeTerminatingGatewayListener( intentions := cfgSnap.TerminatingGateway.Intentions[svc] svcConfig := cfgSnap.TerminatingGateway.ServiceConfigs[svc] - cfg, err := config.ParseProxyConfig(svcConfig.ProxyConfig) + cfg, err := ParseProxyConfig(svcConfig.ProxyConfig) if err != nil { // Don't hard fail on a config typo, just warn. The parse func returns // default config if there is an error so it's safe to continue. @@ -1685,7 +1683,7 @@ func (s *ResourceGenerator) makeTerminatingGatewayListener( intentions := cfgSnap.TerminatingGateway.Intentions[svc] svcConfig := cfgSnap.TerminatingGateway.ServiceConfigs[svc] - cfg, err := config.ParseProxyConfig(svcConfig.ProxyConfig) + cfg, err := ParseProxyConfig(svcConfig.ProxyConfig) if err != nil { // Don't hard fail on a config typo, just warn. The parse func returns // default config if there is an error so it's safe to continue. @@ -1809,7 +1807,7 @@ func (s *ResourceGenerator) makeFilterChainTerminatingGateway(cfgSnap *proxycfg. filterChain.Filters = append(filterChain.Filters, authFilter) } - proxyCfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) + proxyCfg, err := ParseProxyConfig(cfgSnap.Proxy.Config) if err != nil { // Don't hard fail on a config typo, just warn. The parse func returns // default config if there is an error so it's safe to continue. @@ -2130,7 +2128,7 @@ func (s *ResourceGenerator) makeMeshGatewayPeerFilterChain( if err != nil { return nil, err } - clusterName = meshGatewayExportedClusterNamePrefix + naming.CustomizeClusterName(target.Name, chain) + clusterName = meshGatewayExportedClusterNamePrefix + CustomizeClusterName(target.Name, chain) } uid := proxycfg.NewUpstreamIDFromServiceName(svc) @@ -2593,7 +2591,7 @@ func makeHTTPFilter(opts listenerFilterOpts) (*envoy_listener_v3.Filter, error) "envoy.filters.http.grpc_stats", &envoy_grpc_stats_v3.FilterConfig{ PerMethodStatSpecifier: &envoy_grpc_stats_v3.FilterConfig_StatsForAllMethods{ - StatsForAllMethods: response.MakeBoolValue(true), + StatsForAllMethods: makeBoolValue(true), }, }, ) diff --git a/agent/xds/listeners_apigateway.go b/agent/xds/listeners_apigateway.go index 07566017cea94..633c04f0524b8 100644 --- a/agent/xds/listeners_apigateway.go +++ b/agent/xds/listeners_apigateway.go @@ -1,15 +1,13 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds import ( "fmt" - envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" - "github.com/hashicorp/consul/agent/xds/naming" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/wrapperspb" @@ -71,7 +69,7 @@ func (s *ResourceGenerator) makeAPIGatewayListeners(address string, cfgSnap *pro if err != nil { return nil, err } - clusterName = naming.CustomizeClusterName(target.Name, chain) + clusterName = CustomizeClusterName(target.Name, chain) } filterName := fmt.Sprintf("%s.%s.%s.%s", chain.ServiceName, chain.Namespace, chain.Partition, chain.Datacenter) @@ -286,7 +284,10 @@ func makeCommonTLSContextFromSnapshotAPIGatewayListenerConfig(cfgSnap *proxycfg. connectTLSEnabled := (!listenerCfg.TLS.IsEmpty()) - if connectTLSEnabled { + if tlsCfg.SDS != nil { + // Set up listener TLS from SDS + tlsContext = makeCommonTLSContextFromGatewayTLSConfig(*tlsCfg) + } else if connectTLSEnabled { tlsContext = makeCommonTLSContext(cfgSnap.Leaf(), cfgSnap.RootPEMs(), makeTLSParametersFromGatewayTLSConfig(*tlsCfg)) } @@ -315,6 +316,29 @@ func resolveAPIListenerTLSConfig(listenerTLSCfg structs.APIGatewayTLSConfigurati return &mergedCfg, nil } +func routeNameForAPIGatewayUpstream(l structs.IngressListener, s structs.IngressService) string { + key := proxycfg.IngressListenerKeyFromListener(l) + + // If the upstream service doesn't have any TLS overrides then it can just use + // the combined filterchain with all the merged routes. + if !ingressServiceHasSDSOverrides(s) { + return key.RouteName() + } + + // Return a specific route for this service as it needs a custom FilterChain + // to serve its custom cert so we should attach its routes to a separate Route + // too. We need this to be consistent between OSS and Enterprise to avoid xDS + // config golden files in tests conflicting so we can't use ServiceID.String() + // which normalizes to included all identifiers in Enterprise. + sn := s.ToServiceName() + svcIdentifier := sn.Name + if !sn.InDefaultPartition() || !sn.InDefaultNamespace() { + // Non-default partition/namespace, use a full identifier + svcIdentifier = sn.String() + } + return fmt.Sprintf("%s_%s", key.RouteName(), svcIdentifier) +} + // when we have multiple certificates on a single listener, we need // to duplicate the filter chains with multiple TLS contexts func makeInlineOverrideFilterChains(cfgSnap *proxycfg.ConfigSnapshot, diff --git a/agent/xds/listeners_ingress.go b/agent/xds/listeners_ingress.go index e5e5a4980c411..031709e2a818c 100644 --- a/agent/xds/listeners_ingress.go +++ b/agent/xds/listeners_ingress.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -9,7 +9,6 @@ import ( envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" - "github.com/hashicorp/consul/agent/xds/naming" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/durationpb" @@ -63,7 +62,7 @@ func (s *ResourceGenerator) makeIngressGatewayListeners(address string, cfgSnap if err != nil { return nil, err } - clusterName = naming.CustomizeClusterName(target.Name, chain) + clusterName = CustomizeClusterName(target.Name, chain) } filterName := fmt.Sprintf("%s.%s.%s.%s", chain.ServiceName, chain.Namespace, chain.Partition, chain.Datacenter) diff --git a/agent/xds/listeners_test.go b/agent/xds/listeners_test.go index 130f2234517e2..d6dbee0964b05 100644 --- a/agent/xds/listeners_test.go +++ b/agent/xds/listeners_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -10,8 +10,8 @@ import ( "testing" "text/template" + "github.com/hashicorp/consul/agent/xds/testcommon" "github.com/stretchr/testify/assert" - "google.golang.org/protobuf/proto" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" testinf "github.com/mitchellh/go-testing-interface" @@ -19,11 +19,6 @@ import ( "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/configfetcher" - "github.com/hashicorp/consul/agent/xds/proxystateconverter" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/agent/xds/testcommon" - "github.com/hashicorp/consul/agent/xdsv2" "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/types" @@ -37,7 +32,6 @@ type listenerTestCase struct { // test input. overrideGoldenName string generatorSetup func(*ResourceGenerator) - alsoRunTestForV2 bool } func makeListenerDiscoChainTests(enterprise bool) []listenerTestCase { @@ -75,7 +69,6 @@ func makeListenerDiscoChainTests(enterprise bool) []listenerTestCase { create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-http-chain", @@ -124,7 +117,6 @@ func makeListenerDiscoChainTests(enterprise bool) []listenerTestCase { create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "external-sni", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-chain-and-overrides", @@ -137,14 +129,12 @@ func makeListenerDiscoChainTests(enterprise bool) []listenerTestCase { create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tcp-chain-failover-through-local-gateway", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-jwt-config-entry-with-local", @@ -235,7 +225,6 @@ func TestListenersFromSnapshot(t *testing.T) { }, }) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tls-incoming-min-version", @@ -255,7 +244,6 @@ func TestListenersFromSnapshot(t *testing.T) { }, }) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tls-incoming-max-version", @@ -275,7 +263,6 @@ func TestListenersFromSnapshot(t *testing.T) { }, }) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-tls-incoming-cipher-suites", @@ -298,7 +285,6 @@ func TestListenersFromSnapshot(t *testing.T) { }, }) }, - alsoRunTestForV2: true, }, { name: "grpc-public-listener", @@ -315,7 +301,6 @@ func TestListenersFromSnapshot(t *testing.T) { ns.Proxy.Config["bind_address"] = "127.0.0.2" }, nil) }, - alsoRunTestForV2: true, }, { name: "listener-bind-port", @@ -324,7 +309,6 @@ func TestListenersFromSnapshot(t *testing.T) { ns.Proxy.Config["bind_port"] = 8888 }, nil) }, - alsoRunTestForV2: true, }, { name: "listener-bind-address-port", @@ -334,7 +318,6 @@ func TestListenersFromSnapshot(t *testing.T) { ns.Proxy.Config["bind_port"] = 8888 }, nil) }, - alsoRunTestForV2: true, }, { name: "listener-unix-domain-socket", @@ -346,7 +329,6 @@ func TestListenersFromSnapshot(t *testing.T) { ns.Proxy.Upstreams[0].LocalBindSocketMode = "0640" }, nil) }, - alsoRunTestForV2: true, }, { name: "listener-max-inbound-connections", @@ -355,7 +337,6 @@ func TestListenersFromSnapshot(t *testing.T) { ns.Proxy.Config["max_inbound_connections"] = 222 }, nil) }, - alsoRunTestForV2: true, }, { name: "http2-public-listener", @@ -372,7 +353,6 @@ func TestListenersFromSnapshot(t *testing.T) { ns.Proxy.Config["balance_inbound_connections"] = "exact_balance" }, nil) }, - alsoRunTestForV2: true, }, { name: "listener-balance-outbound-connections-bind-port", @@ -381,7 +361,6 @@ func TestListenersFromSnapshot(t *testing.T) { ns.Proxy.Upstreams[0].Config["balance_outbound_connections"] = "exact_balance" }, nil) }, - alsoRunTestForV2: true, }, { name: "http-public-listener", @@ -515,31 +494,6 @@ func TestListenersFromSnapshot(t *testing.T) { }, nil) }, }, - { - name: "custom-upstream-with-prepared-query", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - for i := range ns.Proxy.Upstreams { - if ns.Proxy.Upstreams[i].DestinationName != "db" { - continue // only tweak the db upstream - } - if ns.Proxy.Upstreams[i].Config == nil { - ns.Proxy.Upstreams[i].Config = map[string]interface{}{} - } - - uid := proxycfg.NewUpstreamID(&ns.Proxy.Upstreams[i]) - - // Triggers an override with the presence of the escape hatch listener - ns.Proxy.Upstreams[i].DestinationType = structs.UpstreamDestTypePreparedQuery - - ns.Proxy.Upstreams[i].Config["envoy_listener_json"] = - customListenerJSON(t, customListenerJSONOptions{ - Name: uid.EnvoyID() + ":custom-upstream", - }) - } - }, nil) - }, - }, { name: "connect-proxy-upstream-defaults", create: func(t testinf.T) *proxycfg.ConfigSnapshot { @@ -579,9 +533,9 @@ func TestListenersFromSnapshot(t *testing.T) { }, { // NOTE: if IPv6 is not supported in the kernel per - // platform.SupportsIPv6() then this test will fail because the golden + // kernelSupportsIPv6() then this test will fail because the golden // files were generated assuming ipv6 support was present - name: "expose-checks-http", + name: "expose-checks", create: proxycfg.TestConfigSnapshotExposeChecks, generatorSetup: func(s *ResourceGenerator) { s.CfgFetcher = configFetcherFunc(func() string { @@ -589,30 +543,6 @@ func TestListenersFromSnapshot(t *testing.T) { }) }, }, - { - // NOTE: if IPv6 is not supported in the kernel per - // platform.SupportsIPv6() then this test will fail because the golden - // files were generated assuming ipv6 support was present - name: "expose-checks-http-with-bind-override", - create: proxycfg.TestConfigSnapshotExposeChecksWithBindOverride, - generatorSetup: func(s *ResourceGenerator) { - s.CfgFetcher = configFetcherFunc(func() string { - return "192.0.2.1" - }) - }, - }, - { - // NOTE: if IPv6 is not supported in the kernel per - // platform.SupportsIPv6() then this test will fail because the golden - // files were generated assuming ipv6 support was present - name: "expose-checks-grpc", - create: proxycfg.TestConfigSnapshotExposeChecksGRPC, - generatorSetup: func(s *ResourceGenerator) { - s.CfgFetcher = configFetcherFunc(func() string { - return "192.0.2.1" - }) - }, - }, { name: "mesh-gateway", create: func(t testinf.T) *proxycfg.ConfigSnapshot { @@ -625,12 +555,6 @@ func TestListenersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotMeshGateway(t, "federation-states", nil, nil) }, }, - { - name: "mesh-gateway-using-federation-control-plane", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "mesh-gateway-federation", nil, nil) - }, - }, { name: "mesh-gateway-no-services", create: func(t testinf.T) *proxycfg.ConfigSnapshot { @@ -947,16 +871,6 @@ func TestListenersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, nil) }, }, - { - name: "terminating-gateway-custom-trace-listener", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, func(ns *structs.NodeService) { - ns.Proxy.Config = map[string]interface{}{} - ns.Proxy.Config["protocol"] = "http" - ns.Proxy.Config["envoy_listener_tracing_json"] = customTraceJSON(t) - }, nil) - }, - }, { name: "terminating-gateway-with-tls-incoming-min-version", create: func(t testinf.T) *proxycfg.ConfigSnapshot { @@ -1127,14 +1041,6 @@ func TestListenersFromSnapshot(t *testing.T) { name: "ingress-with-tls-mixed-min-version-listeners", create: proxycfg.TestConfigSnapshotIngressGateway_TLSMixedMinVersionListeners, }, - { - name: "ingress-with-tls-mixed-max-version-listeners", - create: proxycfg.TestConfigSnapshotIngressGateway_TLSMixedMaxVersionListeners, - }, - { - name: "ingress-with-tls-mixed-cipher-suites-listeners", - create: proxycfg.TestConfigSnapshotIngressGateway_TLSMixedCipherVersionListeners, - }, { name: "ingress-with-sds-listener-gw-level", create: proxycfg.TestConfigSnapshotIngressGatewaySDS_GatewayLevel, @@ -1190,19 +1096,16 @@ func TestListenersFromSnapshot(t *testing.T) { create: proxycfg.TestConfigSnapshotTransparentProxyResolverRedirectUpstream, }, { - name: "transparent-proxy-catalog-destinations-only", - create: proxycfg.TestConfigSnapshotTransparentProxyCatalogDestinationsOnly, - alsoRunTestForV2: true, + name: "transparent-proxy-catalog-destinations-only", + create: proxycfg.TestConfigSnapshotTransparentProxyCatalogDestinationsOnly, }, { - name: "transparent-proxy-dial-instances-directly", - create: proxycfg.TestConfigSnapshotTransparentProxyDialDirectly, - alsoRunTestForV2: true, + name: "transparent-proxy-dial-instances-directly", + create: proxycfg.TestConfigSnapshotTransparentProxyDialDirectly, }, { - name: "transparent-proxy-terminating-gateway", - create: proxycfg.TestConfigSnapshotTransparentProxyTerminatingGatewayCatalogDestinationsOnly, - alsoRunTestForV2: true, + name: "transparent-proxy-terminating-gateway", + create: proxycfg.TestConfigSnapshotTransparentProxyTerminatingGatewayCatalogDestinationsOnly, }, { name: "custom-trace-listener", @@ -1261,11 +1164,9 @@ func TestListenersFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { ns.Proxy.MutualTLSMode = structs.MutualTLSModePermissive ns.Proxy.Mode = structs.ProxyModeTransparent - ns.Proxy.TransparentProxy.OutboundListenerPort = 1234 }, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-without-tproxy-and-permissive-mtls", @@ -1275,7 +1176,6 @@ func TestListenersFromSnapshot(t *testing.T) { }, nil) }, - alsoRunTestForV2: true, }, } @@ -1288,7 +1188,6 @@ func TestListenersFromSnapshot(t *testing.T) { t.Run("envoy-"+envoyVersion, func(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Sanity check default with no overrides first snap := tt.create(t) @@ -1300,26 +1199,26 @@ func TestListenersFromSnapshot(t *testing.T) { // golder files for every test case and so not be any use! testcommon.SetupTLSRootsAndLeaf(t, snap) - var listeners []proto.Message - // Need server just for logger dependency g := NewResourceGenerator(testutil.Logger(t), nil, false) g.ProxyFeatures = sf if tt.generatorSetup != nil { tt.generatorSetup(g) } - listeners, err = g.listenersFromSnapshot(snap) + + listeners, err := g.listenersFromSnapshot(snap) require.NoError(t, err) + // The order of listeners returned via LDS isn't relevant, so it's safe // to sort these for the purposes of test comparisons. sort.Slice(listeners, func(i, j int) bool { return listeners[i].(*envoy_listener_v3.Listener).Name < listeners[j].(*envoy_listener_v3.Listener).Name }) - r, err := response.CreateResponse(xdscommon.ListenerType, "00000001", "00000001", listeners) + r, err := createResponse(xdscommon.ListenerType, "00000001", "00000001", listeners) require.NoError(t, err) - t.Run("current-xdsv1", func(t *testing.T) { + t.Run("current", func(t *testing.T) { gotJSON := protoToJSON(t, r) gName := tt.name @@ -1330,39 +1229,6 @@ func TestListenersFromSnapshot(t *testing.T) { expectedJSON := goldenEnvoy(t, filepath.Join("listeners", gName), envoyVersion, latestEnvoyVersion, gotJSON) require.JSONEq(t, expectedJSON, gotJSON) }) - - if tt.alsoRunTestForV2 { - generator := xdsv2.NewResourceGenerator(testutil.Logger(t)) - converter := proxystateconverter.NewConverter(testutil.Logger(t), nil) - proxyState, err := converter.ProxyStateFromSnapshot(snap) - require.NoError(t, err) - - res, err := generator.AllResourcesFromIR(proxyState) - require.NoError(t, err) - - listeners = res[xdscommon.ListenerType] - // The order of listeners returned via LDS isn't relevant, so it's safe - // to sort these for the purposes of test comparisons. - sort.Slice(listeners, func(i, j int) bool { - return listeners[i].(*envoy_listener_v3.Listener).Name < listeners[j].(*envoy_listener_v3.Listener).Name - }) - - r, err := response.CreateResponse(xdscommon.ListenerType, "00000001", "00000001", listeners) - require.NoError(t, err) - - t.Run("current-xdsv2", func(t *testing.T) { - gotJSON := protoToJSON(t, r) - - gName := tt.name - if tt.overrideGoldenName != "" { - gName = tt.overrideGoldenName - } - - expectedJSON := goldenEnvoy(t, filepath.Join("listeners", gName), envoyVersion, latestEnvoyVersion, gotJSON) - require.JSONEq(t, expectedJSON, gotJSON) - }) - } - }) } }) @@ -1520,7 +1386,7 @@ func customTraceJSON(t testinf.T) string { type configFetcherFunc func() string -var _ configfetcher.ConfigFetcher = (configFetcherFunc)(nil) +var _ ConfigFetcher = (configFetcherFunc)(nil) func (f configFetcherFunc) AdvertiseAddrLAN() string { return f() diff --git a/agent/xds/locality_policy.go b/agent/xds/locality_policy.go deleted file mode 100644 index c94ba95ea2865..0000000000000 --- a/agent/xds/locality_policy.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "fmt" - "github.com/hashicorp/go-hclog" - - "github.com/hashicorp/consul/agent/structs" -) - -func groupedEndpoints(logger hclog.Logger, locality *structs.Locality, policy *structs.DiscoveryPrioritizeByLocality, csns structs.CheckServiceNodes) ([]structs.CheckServiceNodes, error) { - switch { - case policy == nil || policy.Mode == "" || policy.Mode == "none": - return []structs.CheckServiceNodes{csns}, nil - case policy.Mode == "failover": - log := logger.Named("locality") - return prioritizeByLocalityFailover(log, locality, csns), nil - default: - return nil, fmt.Errorf("unexpected priortize-by-locality mode %q", policy.Mode) - } -} diff --git a/agent/xds/locality_policy_ce.go b/agent/xds/locality_policy_ce.go deleted file mode 100644 index fbc17775d689d..0000000000000 --- a/agent/xds/locality_policy_ce.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package xds - -import ( - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/go-hclog" -) - -func prioritizeByLocalityFailover(_ hclog.Logger, _ *structs.Locality, _ structs.CheckServiceNodes) []structs.CheckServiceNodes { - return nil -} diff --git a/agent/xds/naming.go b/agent/xds/naming.go new file mode 100644 index 0000000000000..ab9224f71ce8b --- /dev/null +++ b/agent/xds/naming.go @@ -0,0 +1,19 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package xds + +import ( + "fmt" + + "github.com/hashicorp/consul/agent/structs" +) + +func CustomizeClusterName(clusterName string, chain *structs.CompiledDiscoveryChain) string { + if chain == nil || chain.CustomizationHash == "" { + return clusterName + } + // Use a colon to delimit this prefix instead of a dot to avoid a + // theoretical collision problem with subsets. + return fmt.Sprintf("%s~%s", chain.CustomizationHash, clusterName) +} diff --git a/agent/xds/naming/naming.go b/agent/xds/naming/naming.go deleted file mode 100644 index 3e19d93270038..0000000000000 --- a/agent/xds/naming/naming.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package naming - -import ( - "fmt" - - "github.com/hashicorp/consul/agent/structs" -) - -const ( - // OriginalDestinationClusterName is the name we give to the passthrough - // cluster which redirects transparently-proxied requests to their original - // destination outside the mesh. This cluster prevents Consul from blocking - // connections to destinations outside of the catalog when in transparent - // proxy mode. - OriginalDestinationClusterName = "original-destination" - VirtualIPTag = "virtual" -) - -func CustomizeClusterName(clusterName string, chain *structs.CompiledDiscoveryChain) string { - if chain == nil || chain.CustomizationHash == "" { - return clusterName - } - // Use a colon to delimit this prefix instead of a dot to avoid a - // theoretical collision problem with subsets. - return fmt.Sprintf("%s~%s", chain.CustomizationHash, clusterName) -} diff --git a/agent/xds/platform/net_fallback.go b/agent/xds/net_fallback.go similarity index 50% rename from agent/xds/platform/net_fallback.go rename to agent/xds/net_fallback.go index e37c97633b285..7230c18ef2e85 100644 --- a/agent/xds/platform/net_fallback.go +++ b/agent/xds/net_fallback.go @@ -1,11 +1,11 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !linux // +build !linux -package platform +package xds -func SupportsIPv6() (bool, error) { +func kernelSupportsIPv6() (bool, error) { return true, nil } diff --git a/agent/xds/platform/net_linux.go b/agent/xds/net_linux.go similarity index 87% rename from agent/xds/platform/net_linux.go rename to agent/xds/net_linux.go index acf8c53a85e47..96932ca307309 100644 --- a/agent/xds/platform/net_linux.go +++ b/agent/xds/net_linux.go @@ -1,10 +1,10 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build linux // +build linux -package platform +package xds import ( "fmt" @@ -20,7 +20,7 @@ var ( ipv6SupportedErr error ) -func SupportsIPv6() (bool, error) { +func kernelSupportsIPv6() (bool, error) { ipv6SupportOnce.Do(func() { ipv6Supported, ipv6SupportedErr = checkIfKernelSupportsIPv6() }) diff --git a/agent/xds/protocol_trace.go b/agent/xds/protocol_trace.go index cfe905d70bf99..42d82d76012bc 100644 --- a/agent/xds/protocol_trace.go +++ b/agent/xds/protocol_trace.go @@ -1,27 +1,26 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds import ( envoy_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" - "github.com/hashicorp/go-hclog" "github.com/mitchellh/copystructure" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) -func logTraceRequest(logger hclog.Logger, msg string, pb proto.Message) { - logTraceProto(logger, msg, pb, false) +func (s *ResourceGenerator) logTraceRequest(msg string, pb proto.Message) { + s.logTraceProto(msg, pb, false) } -func logTraceResponse(logger hclog.Logger, msg string, pb proto.Message) { - logTraceProto(logger, msg, pb, true) +func (s *ResourceGenerator) logTraceResponse(msg string, pb proto.Message) { + s.logTraceProto(msg, pb, true) } -func logTraceProto(logger hclog.Logger, msg string, pb proto.Message, response bool) { - if !logger.IsTrace() { +func (s *ResourceGenerator) logTraceProto(msg string, pb proto.Message, response bool) { + if !s.Logger.IsTrace() { return } @@ -56,5 +55,5 @@ func logTraceProto(logger hclog.Logger, msg string, pb proto.Message, response b out = string(outBytes) } - logger.Trace(msg, "direction", dir, "protobuf", out) + s.Logger.Trace(msg, "direction", dir, "protobuf", out) } diff --git a/agent/xds/proxystateconverter/clusters.go b/agent/xds/proxystateconverter/clusters.go deleted file mode 100644 index e12211f670782..0000000000000 --- a/agent/xds/proxystateconverter/clusters.go +++ /dev/null @@ -1,1251 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "errors" - "fmt" - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-uuid" - "strings" - "time" - - envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/wrapperspb" - - "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/config" - "github.com/hashicorp/consul/agent/xds/naming" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" - "github.com/hashicorp/consul/proto/private/pbpeering" -) - -const ( - meshGatewayExportedClusterNamePrefix = "exported~" -) - -type namedCluster struct { - name string - cluster *pbproxystate.Cluster -} - -// clustersFromSnapshot returns the xDS API representation of the "clusters" in the snapshot. -func (s *Converter) clustersFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) error { - if cfgSnap == nil { - return errors.New("nil config given") - } - - switch cfgSnap.Kind { - case structs.ServiceKindConnectProxy: - return s.clustersFromSnapshotConnectProxy(cfgSnap) - // TODO(proxystate): Terminating Gateways will be added in the future. - //case structs.ServiceKindTerminatingGateway: - // err := s.clustersFromSnapshotTerminatingGateway(cfgSnap) - // if err != nil { - // return err - // } - // return nil - // TODO(proxystate): Mesh Gateways will be added in the future. - //case structs.ServiceKindMeshGateway: - // err := s.clustersFromSnapshotMeshGateway(cfgSnap) - // if err != nil { - // return err - // } - // return nil - // TODO(proxystate): Ingress Gateways will be added in the future. - //case structs.ServiceKindIngressGateway: - // err := s.clustersFromSnapshotIngressGateway(cfgSnap) - // if err != nil { - // return err - // } - // return nil - // TODO(proxystate): API Gateways will be added in the future. - //case structs.ServiceKindAPIGateway: - // res, err := s.clustersFromSnapshotAPIGateway(cfgSnap) - // if err != nil { - // return err - // } - // return nil - default: - return fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind) - } -} - -// clustersFromSnapshot returns the xDS API representation of the "clusters" -// (upstreams) in the snapshot. -func (s *Converter) clustersFromSnapshotConnectProxy(cfgSnap *proxycfg.ConfigSnapshot) error { - // This is the list of listeners we add to. It will be empty to start. - clusters := s.proxyState.Clusters - var err error - - // Include the "app" cluster for the public listener - appCluster, err := s.makeAppCluster(cfgSnap, xdscommon.LocalAppClusterName, "", cfgSnap.Proxy.LocalServicePort) - if err != nil { - return err - } - clusters[appCluster.name] = appCluster.cluster - - if cfgSnap.Proxy.Mode == structs.ProxyModeTransparent { - passthroughs, err := s.makePassthroughClusters(cfgSnap) - if err != nil { - return fmt.Errorf("failed to make passthrough clusters for transparent proxy: %v", err) - } - for clusterName, cluster := range passthroughs { - clusters[clusterName] = cluster - } - } - - // NOTE: Any time we skip a chain below we MUST also skip that discovery chain in endpoints.go - // so that the sets of endpoints generated matches the sets of clusters. - for uid, chain := range cfgSnap.ConnectProxy.DiscoveryChain { - upstream, skip := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta) - if skip { - continue - } - - upstreamClusters, err := s.makeUpstreamClustersForDiscoveryChain( - uid, - upstream, - chain, - cfgSnap, - false, - ) - if err != nil { - return err - } - - for name, cluster := range upstreamClusters { - clusters[name] = cluster - } - } - - // TODO(proxystate): peering will be added in the future. - //// NOTE: Any time we skip an upstream below we MUST also skip that same - //// upstream in endpoints.go so that the sets of endpoints generated matches - //// the sets of clusters. - //for _, uid := range cfgSnap.ConnectProxy.PeeredUpstreamIDs() { - // upstream, skip := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta) - // if skip { - // continue - // } - // - // peerMeta, found := cfgSnap.ConnectProxy.UpstreamPeerMeta(uid) - // if !found { - // s.Logger.Warn("failed to fetch upstream peering metadata for cluster", "uid", uid) - // } - // cfg := s.getAndModifyUpstreamConfigForPeeredListener(uid, upstream, peerMeta) - // - // upstreamCluster, err := s.makeUpstreamClusterForPeerService(uid, cfg, peerMeta, cfgSnap) - // if err != nil { - // return nil, err - // } - // clusters = append(clusters, upstreamCluster) - //} - - // TODO(proxystate): L7 Intentions and JWT Auth will be added in the future. - //// add clusters for jwt-providers - //for _, prov := range cfgSnap.JWTProviders { - // //skip cluster creation for local providers - // if prov.JSONWebKeySet == nil || prov.JSONWebKeySet.Remote == nil { - // continue - // } - // - // cluster, err := makeJWTProviderCluster(prov) - // if err != nil { - // s.Logger.Warn("failed to make jwt-provider cluster", "provider name", prov.Name, "error", err) - // continue - // } - // - // clusters[cluster.GetName()] = cluster - //} - - for _, u := range cfgSnap.Proxy.Upstreams { - if u.DestinationType != structs.UpstreamDestTypePreparedQuery { - continue - } - - upstreamCluster, err := s.makeUpstreamClusterForPreparedQuery(u, cfgSnap) - if err != nil { - return err - } - clusters[upstreamCluster.name] = upstreamCluster.cluster - } - - cfgSnap.Proxy.Expose.Finalize() - paths := cfgSnap.Proxy.Expose.Paths - - // Add service health checks to the list of paths to create clusters for if needed - if cfgSnap.Proxy.Expose.Checks { - psid := structs.NewServiceID(cfgSnap.Proxy.DestinationServiceID, &cfgSnap.ProxyID.EnterpriseMeta) - for _, check := range cfgSnap.ConnectProxy.WatchedServiceChecks[psid] { - p, err := parseCheckPath(check) - if err != nil { - s.Logger.Warn("failed to create cluster for", "check", check.CheckID, "error", err) - continue - } - paths = append(paths, p) - } - } - - // Create a new cluster if we need to expose a port that is different from the service port - for _, path := range paths { - if path.LocalPathPort == cfgSnap.Proxy.LocalServicePort { - continue - } - c, err := s.makeAppCluster(cfgSnap, makeExposeClusterName(path.LocalPathPort), path.Protocol, path.LocalPathPort) - if err != nil { - s.Logger.Warn("failed to make local cluster", "path", path.Path, "error", err) - continue - } - clusters[c.name] = c.cluster - } - - return nil -} - -// TODO(proxystate): L7 Intentions and JWT Auth will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeJWTProviderCluster -// func makeJWKSDiscoveryClusterType -// func makeJWTCertValidationContext -// func parseJWTRemoteURL - -func makeExposeClusterName(destinationPort int) string { - return fmt.Sprintf("exposed_cluster_%d", destinationPort) -} - -// In transparent proxy mode there are potentially multiple passthrough clusters added. -// The first is for destinations outside of Consul's catalog. This is for a plain TCP proxy. -// All of these use Envoy's ORIGINAL_DST listener filter, which forwards to the original -// destination address (before the iptables redirection). -// The rest are for destinations inside the mesh, which require certificates for mTLS. -func (s *Converter) makePassthroughClusters(cfgSnap *proxycfg.ConfigSnapshot) (map[string]*pbproxystate.Cluster, error) { - // This size is an upper bound. - clusters := make(map[string]*pbproxystate.Cluster, 0) - if meshConf := cfgSnap.MeshConfig(); meshConf == nil || - !meshConf.TransparentProxy.MeshDestinationsOnly { - - clusters[naming.OriginalDestinationClusterName] = &pbproxystate.Cluster{ - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Passthrough{ - Passthrough: &pbproxystate.PassthroughEndpointGroup{ - Config: &pbproxystate.PassthroughEndpointGroupConfig{ - ConnectTimeout: durationpb.New(5 * time.Second), - }, - }, - }, - }, - }, - } - } - - for uid, chain := range cfgSnap.ConnectProxy.DiscoveryChain { - targetMap, ok := cfgSnap.ConnectProxy.PassthroughUpstreams[uid] - if !ok { - continue - } - - for targetID := range targetMap { - uid := proxycfg.NewUpstreamIDFromTargetID(targetID) - - sni := connect.ServiceSNI( - uid.Name, "", uid.NamespaceOrDefault(), - uid.PartitionOrDefault(), cfgSnap.Datacenter, - cfgSnap.Roots.TrustDomain) - - // Prefixed with passthrough to distinguish from non-passthrough clusters for the same upstream. - name := "passthrough~" + sni - - c := pbproxystate.Cluster{ - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Passthrough{ - Passthrough: &pbproxystate.PassthroughEndpointGroup{ - Config: &pbproxystate.PassthroughEndpointGroupConfig{ - ConnectTimeout: durationpb.New(5 * time.Second), - }, - }, - }, - }, - }, - } - - if discoTarget, ok := chain.Targets[targetID]; ok && discoTarget.ConnectTimeout > 0 { - c.GetEndpointGroup().GetPassthrough().GetConfig(). - ConnectTimeout = durationpb.New(discoTarget.ConnectTimeout) - } - - transportSocket, err := s.createOutboundMeshMTLS(cfgSnap, []string{getSpiffeID(cfgSnap, uid)}, sni) - if err != nil { - return nil, err - } - c.GetEndpointGroup().GetPassthrough().OutboundTls = transportSocket - - clusters[name] = &c - } - } - - err := cfgSnap.ConnectProxy.DestinationsUpstream.ForEachKeyE(func(uid proxycfg.UpstreamID) error { - svcConfig, ok := cfgSnap.ConnectProxy.DestinationsUpstream.Get(uid) - if !ok || svcConfig.Destination == nil { - return nil - } - - // One Cluster per Destination Address - for _, address := range svcConfig.Destination.Addresses { - name := clusterNameForDestination(cfgSnap, uid.Name, address, uid.NamespaceOrDefault(), uid.PartitionOrDefault()) - - c := &pbproxystate.Cluster{ - AltStatName: name, - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Dynamic{ - Dynamic: &pbproxystate.DynamicEndpointGroup{ - Config: &pbproxystate.DynamicEndpointGroupConfig{ - ConnectTimeout: durationpb.New(5 * time.Second), - // Endpoints are managed separately by EDS - // Having an empty config enables outlier detection with default config. - OutlierDetection: &pbproxystate.OutlierDetection{}, - }, - }, - }, - }, - }, - } - sni := connect.ServiceSNI( - uid.Name, "", uid.NamespaceOrDefault(), - uid.PartitionOrDefault(), cfgSnap.Datacenter, - cfgSnap.Roots.TrustDomain) - transportSocket, err := s.createOutboundMeshMTLS(cfgSnap, []string{getSpiffeID(cfgSnap, uid)}, sni) - if err != nil { - return err - } - c.GetEndpointGroup().GetDynamic().OutboundTls = transportSocket - clusters[name] = c - } - return nil - }) - if err != nil { - return nil, err - } - - return clusters, nil -} - -func getSpiffeID(cfgSnap *proxycfg.ConfigSnapshot, uid proxycfg.UpstreamID) string { - spiffeIDService := &connect.SpiffeIDService{ - Host: cfgSnap.Roots.TrustDomain, - Partition: uid.PartitionOrDefault(), - Namespace: uid.NamespaceOrDefault(), - Datacenter: cfgSnap.Datacenter, - Service: uid.Name, - } - return spiffeIDService.URI().String() -} -func clusterNameForDestination(cfgSnap *proxycfg.ConfigSnapshot, name string, - address string, namespace string, partition string) string { - name = destinationSpecificServiceName(name, address) - sni := connect.ServiceSNI(name, "", namespace, partition, - cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain) - - // Prefixed with destination to distinguish from non-passthrough clusters - // for the same upstream. - return "destination." + sni -} - -func destinationSpecificServiceName(name string, address string) string { - address = strings.ReplaceAll(address, ":", "-") - address = strings.ReplaceAll(address, ".", "-") - return fmt.Sprintf("%s.%s", address, name) -} - -// TODO(proxystate): Mesh Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func clustersFromSnapshotMeshGateway -// func haveVoters - -// TODO(proxystate): Peering will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makePeerServerClusters - -// TODO(proxystate): Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func clustersFromSnapshotTerminatingGateway - -// TODO(proxystate): Mesh Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeGatewayServiceClusters - -// TODO(proxystate): Cluster Peering will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeGatewayOutgoingClusterPeeringServiceClusters - -// TODO(proxystate): Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeDestinationClusters - -// TODO(proxystate): Mesh Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func injectGatewayServiceAddons - -// TODO(proxystate): Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func injectGatewayDestinationAddons - -// TODO(proxystate): Ingress Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func clustersFromSnapshotIngressGateway - -// TODO(proxystate): API Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func clustersFromSnapshotAPIGateway - -// TODO(proxystate): Ingress Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func configIngressUpstreamCluster - -func (s *Converter) makeAppCluster(cfgSnap *proxycfg.ConfigSnapshot, name, pathProtocol string, port int) (*namedCluster, error) { - var err error - namedCluster := &namedCluster{} - - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } - - //// If we have overridden local cluster config try to parse it into an Envoy cluster - //if cfg.LocalClusterJSON != "" { - // return makeClusterFromUserConfig(cfg.LocalClusterJSON) - //} - - var endpoint *pbproxystate.Endpoint - if cfgSnap.Proxy.LocalServiceSocketPath != "" { - endpoint = makeUnixSocketEndpoint(cfgSnap.Proxy.LocalServiceSocketPath) - } else { - addr := cfgSnap.Proxy.LocalServiceAddress - if addr == "" { - addr = "127.0.0.1" - } - endpoint = makeHostPortEndpoint(addr, port) - } - s.proxyState.Endpoints[name] = &pbproxystate.Endpoints{ - Endpoints: []*pbproxystate.Endpoint{endpoint}, - } - - namedCluster.name = name - namedCluster.cluster = &pbproxystate.Cluster{ - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Static{ - Static: &pbproxystate.StaticEndpointGroup{ - Config: &pbproxystate.StaticEndpointGroupConfig{ - ConnectTimeout: durationpb.New(time.Duration(cfg.LocalConnectTimeoutMs) * time.Millisecond), - }, - }, - }, - }, - }, - } - - protocol := pathProtocol - if protocol == "" { - protocol = cfg.Protocol - } - namedCluster.cluster.Protocol = protocol - if cfg.MaxInboundConnections > 0 { - namedCluster.cluster.GetEndpointGroup().GetStatic().GetConfig(). - CircuitBreakers = &pbproxystate.CircuitBreakers{ - UpstreamLimits: &pbproxystate.UpstreamLimits{ - MaxConnections: response.MakeUint32Value(cfg.MaxInboundConnections), - }, - } - } - - return namedCluster, err -} - -func (s *Converter) makeUpstreamClusterForPeerService( - uid proxycfg.UpstreamID, - upstreamConfig structs.UpstreamConfig, - peerMeta structs.PeeringServiceMeta, - cfgSnap *proxycfg.ConfigSnapshot, -) (string, *pbproxystate.Cluster, *pbproxystate.Endpoints, error) { - var ( - c *pbproxystate.Cluster - e *pbproxystate.Endpoints - err error - ) - - // TODO(proxystate): escapeHatches will be implemented in the future - //if upstreamConfig.EnvoyClusterJSON != "" { - // c, err = makeClusterFromUserConfig(upstreamConfig.EnvoyClusterJSON) - // if err != nil { - // return "", c, e, err - // } - // // In the happy path don't return yet as we need to inject TLS config still. - //} - - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - - if err != nil { - return "", c, e, err - } - - tbs, ok := upstreamsSnapshot.UpstreamPeerTrustBundles.Get(uid.Peer) - if !ok { - // this should never happen since we loop through upstreams with - // set trust bundles - return "", c, e, fmt.Errorf("trust bundle not ready for peer %s", uid.Peer) - } - - clusterName := generatePeeredClusterName(uid, tbs) - - outlierDetection := makeOutlierDetection(upstreamConfig.PassiveHealthCheck, nil, true) - // We can't rely on health checks for services on cluster peers because they - // don't take into account service resolvers, splitters and routers. Setting - // MaxEjectionPercent too 100% gives outlier detection the power to eject the - // entire cluster. - outlierDetection.MaxEjectionPercent = &wrapperspb.UInt32Value{Value: 100} - - s.Logger.Trace("generating cluster for", "cluster", clusterName) - if c == nil { - c = &pbproxystate.Cluster{} - - useEDS := true - if _, ok := cfgSnap.ConnectProxy.PeerUpstreamEndpointsUseHostnames[uid]; ok { - // If we're using local mesh gw, the fact that upstreams use hostnames don't matter. - // If we're not using local mesh gw, then resort to CDS. - if upstreamConfig.MeshGateway.Mode != structs.MeshGatewayModeLocal { - useEDS = false - } - } - - // If none of the service instances are addressed by a hostname we - // provide the endpoint IP addresses via EDS - if useEDS { - d := &pbproxystate.DynamicEndpointGroup{ - Config: &pbproxystate.DynamicEndpointGroupConfig{ - UseAltStatName: false, - ConnectTimeout: durationpb.New(time.Duration(upstreamConfig.ConnectTimeoutMs) * time.Millisecond), - DisablePanicThreshold: true, - CircuitBreakers: &pbproxystate.CircuitBreakers{ - UpstreamLimits: makeUpstreamLimitsIfNeeded(upstreamConfig.Limits), - }, - OutlierDetection: outlierDetection, - }, - } - c.Group = &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Dynamic{ - Dynamic: d, - }, - }, - } - transportSocket := &pbproxystate.TransportSocket{ - ConnectionTls: &pbproxystate.TransportSocket_OutboundMesh{ - OutboundMesh: &pbproxystate.OutboundMeshMTLS{ - ValidationContext: &pbproxystate.MeshOutboundValidationContext{ - SpiffeIds: peerMeta.SpiffeID, - TrustBundlePeerNameKey: uid.Peer, - }, - Sni: peerMeta.PrimarySNI(), - }, - }, - } - d.OutboundTls = transportSocket - } else { - d := &pbproxystate.DNSEndpointGroup{ - Config: &pbproxystate.DNSEndpointGroupConfig{ - UseAltStatName: false, - ConnectTimeout: durationpb.New(time.Duration(upstreamConfig.ConnectTimeoutMs) * time.Millisecond), - DisablePanicThreshold: true, - CircuitBreakers: &pbproxystate.CircuitBreakers{ - UpstreamLimits: makeUpstreamLimitsIfNeeded(upstreamConfig.Limits), - }, - OutlierDetection: outlierDetection, - }, - } - c.Group = &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Dns{ - Dns: d, - }, - }, - } - e = &pbproxystate.Endpoints{ - Endpoints: make([]*pbproxystate.Endpoint, 0), - } - - ep, _ := cfgSnap.ConnectProxy.PeerUpstreamEndpoints.Get(uid) - configureClusterWithHostnames( - s.Logger, - d, - e, - "", /*TODO:make configurable?*/ - ep, - true, /*isRemote*/ - false, /*onlyPassing*/ - ) - transportSocket := &pbproxystate.TransportSocket{ - ConnectionTls: &pbproxystate.TransportSocket_OutboundMesh{ - OutboundMesh: &pbproxystate.OutboundMeshMTLS{ - ValidationContext: &pbproxystate.MeshOutboundValidationContext{ - SpiffeIds: peerMeta.SpiffeID, - TrustBundlePeerNameKey: uid.Peer, - }, - Sni: peerMeta.PrimarySNI(), - }, - }, - } - d.OutboundTls = transportSocket - } - } - - return clusterName, c, e, nil -} - -func (s *Converter) makeUpstreamClusterForPreparedQuery(upstream structs.Upstream, cfgSnap *proxycfg.ConfigSnapshot) (*namedCluster, error) { - var c *pbproxystate.Cluster - var err error - - uid := proxycfg.NewUpstreamID(&upstream) - - dc := upstream.Datacenter - if dc == "" { - dc = cfgSnap.Datacenter - } - sni := connect.UpstreamSNI(&upstream, "", dc, cfgSnap.Roots.TrustDomain) - - cfg, _ := structs.ParseUpstreamConfig(upstream.Config) - // TODO(proxystate): add logger and enable this - //if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - //s.Logger.Warn("failed to parse", "upstream", uid, "error", err) - //} - - // TODO(proxystate): escapeHatches will be implemented in the future - //if cfg.EnvoyClusterJSON != "" { - // c, err = makeClusterFromUserConfig(cfg.EnvoyClusterJSON) - // if err != nil { - // return c, err - // } - // // In the happy path don't return yet as we need to inject TLS config still. - //} - - if c == nil { - c = &pbproxystate.Cluster{ - Protocol: cfg.Protocol, - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Dynamic{ - Dynamic: &pbproxystate.DynamicEndpointGroup{ - Config: &pbproxystate.DynamicEndpointGroupConfig{ - ConnectTimeout: durationpb.New(time.Duration(cfg.ConnectTimeoutMs) * time.Millisecond), - // Endpoints are managed separately by EDS - // Having an empty config enables outlier detection with default config. - OutlierDetection: makeOutlierDetection(cfg.PassiveHealthCheck, nil, true), - DisablePanicThreshold: true, - CircuitBreakers: &pbproxystate.CircuitBreakers{ - UpstreamLimits: makeUpstreamLimitsIfNeeded(cfg.Limits), - }, - }, - }, - }, - }, - }, - } - } - - endpoints := cfgSnap.ConnectProxy.PreparedQueryEndpoints[uid] - var ( - spiffeIDs = make([]string, 0) - seen = make(map[string]struct{}) - ) - for _, e := range endpoints { - id := fmt.Sprintf("%s/%s", e.Node.Datacenter, e.Service.CompoundServiceName()) - if _, ok := seen[id]; ok { - continue - } - seen[id] = struct{}{} - - name := e.Service.Proxy.DestinationServiceName - if e.Service.Connect.Native { - name = e.Service.Service - } - - spiffeIDs = append(spiffeIDs, connect.SpiffeIDService{ - Host: cfgSnap.Roots.TrustDomain, - Namespace: e.Service.NamespaceOrDefault(), - Partition: e.Service.PartitionOrDefault(), - Datacenter: e.Node.Datacenter, - Service: name, - }.URI().String()) - } - - transportSocket, err := s.createOutboundMeshMTLS(cfgSnap, spiffeIDs, sni) - if err != nil { - return nil, err - } - c.GetEndpointGroup().GetDynamic().OutboundTls = transportSocket - - return &namedCluster{name: sni, cluster: c}, nil -} - -func finalizeUpstreamConfig(cfg structs.UpstreamConfig, chain *structs.CompiledDiscoveryChain, connectTimeout time.Duration) structs.UpstreamConfig { - if cfg.Protocol == "" { - cfg.Protocol = chain.Protocol - } - - if cfg.Protocol == "" { - cfg.Protocol = "tcp" - } - - if cfg.ConnectTimeoutMs == 0 { - cfg.ConnectTimeoutMs = int(connectTimeout / time.Millisecond) - } - return cfg -} - -func (s *Converter) createOutboundMeshMTLS(cfgSnap *proxycfg.ConfigSnapshot, spiffeIDs []string, sni string) (*pbproxystate.TransportSocket, error) { - switch cfgSnap.Kind { - case structs.ServiceKindConnectProxy: - case structs.ServiceKindMeshGateway: - default: - return nil, fmt.Errorf("cannot inject peering trust bundles for kind %q", cfgSnap.Kind) - } - - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } - - // Add all trust bundle peer names, including local. - trustBundlePeerNames := []string{"local"} - for _, tb := range cfgSnap.PeeringTrustBundles() { - trustBundlePeerNames = append(trustBundlePeerNames, tb.PeerName) - } - // Arbitrary UUID to reference the identity by. - uuid, err := uuid.GenerateUUID() - if err != nil { - return nil, err - } - - // Create the transport socket - ts := &pbproxystate.TransportSocket{} - - ts.ConnectionTls = &pbproxystate.TransportSocket_OutboundMesh{ - OutboundMesh: &pbproxystate.OutboundMeshMTLS{ - IdentityKey: uuid, - ValidationContext: &pbproxystate.MeshOutboundValidationContext{ - TrustBundlePeerNameKey: trustBundlePeerNames[0], - SpiffeIds: spiffeIDs, - }, - Sni: sni, - }, - } - s.proxyState.LeafCertificates[uuid] = &pbproxystate.LeafCertificate{ - Cert: cfgSnap.Leaf().CertPEM, - Key: cfgSnap.Leaf().PrivateKeyPEM, - } - ts.TlsParameters = makeTLSParametersFromProxyTLSConfig(cfgSnap.MeshConfigTLSOutgoing()) - ts.AlpnProtocols = getAlpnProtocols(cfg.Protocol) - - return ts, nil -} -func (s *Converter) makeUpstreamClustersForDiscoveryChain( - uid proxycfg.UpstreamID, - upstream *structs.Upstream, - chain *structs.CompiledDiscoveryChain, - cfgSnap *proxycfg.ConfigSnapshot, - forMeshGateway bool, -) (map[string]*pbproxystate.Cluster, error) { - if chain == nil { - return nil, fmt.Errorf("cannot create upstream cluster without discovery chain for %s", uid) - } - - if uid.Peer != "" && forMeshGateway { - return nil, fmt.Errorf("impossible to get a peer discovery chain in a mesh gateway") - } - - upstreamConfigMap := make(map[string]interface{}) - if upstream != nil { - upstreamConfigMap = upstream.Config - } - - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - - // Mesh gateways are exempt because upstreamsSnapshot is only used for - // cluster peering targets and transative failover/redirects are unsupported. - if err != nil && !forMeshGateway { - return nil, err - } - - rawUpstreamConfig, err := structs.ParseUpstreamConfigNoDefaults(upstreamConfigMap) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse", "upstream", uid, - "error", err) - } - - // TODO(proxystate): escapeHatches will be implemented in the future - //var escapeHatchCluster *pbproxystate.Cluster - //if !forMeshGateway { - // if rawUpstreamConfig.EnvoyClusterJSON != "" { - // if chain.Default { - // // If you haven't done anything to setup the discovery chain, then - // // you can use the envoy_cluster_json escape hatch. - // escapeHatchCluster = &pbproxystate.Cluster{ - // EscapeHatchClusterJson: rawUpstreamConfig.EnvoyClusterJSON, - // } - // } else { - // s.Logger.Warn("ignoring escape hatch setting, because a discovery chain is configured for", - // "discovery chain", chain.ServiceName, "upstream", uid, - // "envoy_cluster_json", chain.ServiceName) - // } - // } - //} - - out := make(map[string]*pbproxystate.Cluster) - for _, node := range chain.Nodes { - switch { - case node == nil: - return nil, fmt.Errorf("impossible to process a nil node") - case node.Type != structs.DiscoveryGraphNodeTypeResolver: - continue - case node.Resolver == nil: - return nil, fmt.Errorf("impossible to process a non-resolver node") - } - // These variables are prefixed with primary to avoid shaddowing bugs. - primaryTargetID := node.Resolver.Target - primaryTarget := chain.Targets[primaryTargetID] - primaryTargetClusterName := s.getTargetClusterName(upstreamsSnapshot, chain, primaryTargetID, forMeshGateway) - if primaryTargetClusterName == "" { - continue - } - if forMeshGateway && !cfgSnap.Locality.Matches(primaryTarget.Datacenter, primaryTarget.Partition) { - s.Logger.Warn("ignoring discovery chain target that crosses a datacenter or partition boundary in a mesh gateway", - "target", primaryTarget, - "gatewayLocality", cfgSnap.Locality, - ) - continue - } - - upstreamConfig := finalizeUpstreamConfig(rawUpstreamConfig, chain, node.Resolver.ConnectTimeout) - - mappedTargets, err := s.mapDiscoChainTargets(cfgSnap, chain, node, upstreamConfig, forMeshGateway) - if err != nil { - return nil, err - } - - targetGroups, err := mappedTargets.groupedTargets() - if err != nil { - return nil, err - } - - var failoverGroup *pbproxystate.FailoverGroup - endpointGroups := make([]*pbproxystate.EndpointGroup, 0) - if mappedTargets.failover { - // Create a failover group. The endpoint groups that are part of this failover group are created by the loop - // below. - failoverGroup = &pbproxystate.FailoverGroup{ - Config: &pbproxystate.FailoverGroupConfig{ - ConnectTimeout: durationpb.New(node.Resolver.ConnectTimeout), - }, - } - } - - // Construct the target dynamic endpoint groups. If these are not part of a failover group, they will get added - // directly to the map of pbproxystate.Cluster, if they are a part of a failover group, they will be added to - // the failover group. - for _, groupedTarget := range targetGroups { - s.Logger.Debug("generating cluster for", "cluster", groupedTarget.ClusterName) - dynamic := &pbproxystate.DynamicEndpointGroup{ - Config: &pbproxystate.DynamicEndpointGroupConfig{ - UseAltStatName: true, - ConnectTimeout: durationpb.New(node.Resolver.ConnectTimeout), - // TODO(peering): make circuit breakers or outlier detection work? - CircuitBreakers: &pbproxystate.CircuitBreakers{ - UpstreamLimits: makeUpstreamLimitsIfNeeded(upstreamConfig.Limits), - }, - OutlierDetection: makeOutlierDetection(upstreamConfig.PassiveHealthCheck, nil, true), - }, - } - ti := groupedTarget.Targets[0] - transportSocket, err := s.createOutboundMeshMTLS(cfgSnap, ti.SpiffeIDs, ti.SNI) - if err != nil { - return nil, err - } - dynamic.OutboundTls = transportSocket - - var lb *structs.LoadBalancer - if node.LoadBalancer != nil { - lb = node.LoadBalancer - } - if err := injectLBToCluster(lb, dynamic.Config); err != nil { - return nil, fmt.Errorf("failed to apply load balancer configuration to cluster %q: %v", groupedTarget.ClusterName, err) - } - - // TODO: IR: http2 options not currently supported - //if upstreamConfig.Protocol == "http2" || upstreamConfig.Protocol == "grpc" { - // if err := s.setHttp2ProtocolOptions(c); err != nil { - // return nil, err - // } - //} - - switch len(groupedTarget.Targets) { - case 0: - continue - case 1: - // We expect one target so this passes through to continue setting the cluster up. - default: - return nil, fmt.Errorf("cannot have more than one target") - } - - if targetInfo := groupedTarget.Targets[0]; targetInfo.TransportSocket != nil { - dynamic.OutboundTls = targetInfo.TransportSocket - } - - // If the endpoint group is part of a failover group, add it to the failover group. Otherwise add it - // directly to the clusters. - if failoverGroup != nil { - eg := &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Dynamic{ - Dynamic: dynamic, - }, - } - endpointGroups = append(endpointGroups, eg) - } else { - cluster := &pbproxystate.Cluster{ - AltStatName: mappedTargets.baseClusterName, - Protocol: upstreamConfig.Protocol, - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Dynamic{ - Dynamic: dynamic, - }, - }, - }, - } - - out[mappedTargets.baseClusterName] = cluster - } - } - - // If there's a failover group, we only add the failover group to the top level list of clusters. Its endpoint - // groups are inlined. - if failoverGroup != nil { - failoverGroup.EndpointGroups = endpointGroups - cluster := &pbproxystate.Cluster{ - AltStatName: mappedTargets.baseClusterName, - Protocol: upstreamConfig.Protocol, - Group: &pbproxystate.Cluster_FailoverGroup{ - FailoverGroup: failoverGroup, - }, - } - out[mappedTargets.baseClusterName] = cluster - } - } - - //if escapeHatchCluster != nil { - // if len(out) != 1 { - // return nil, fmt.Errorf("cannot inject escape hatch cluster when discovery chain had no nodes") - // } - // var defaultCluster *pbproxystate.Cluster - // for _, k := range out { - // defaultCluster = k - // break - // } - // - // // Overlay what the user provided. - // escapeHatchCluster.GetEndpointGroup().GetDynamic().OutboundTls.ConnectionTls = - // defaultCluster.GetEndpointGroup().GetDynamic().OutboundTls.ConnectionTls - // - // out = append(out, escapeHatchCluster) - //} - - return out, nil -} - -// TODO(proxystate): Mesh Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeExportedUpstreamClustersForMeshGateway - -// makeClusterFromUserConfig returns the listener config decoded from an -// arbitrary proto3 json format string or an error if it's invalid. -// -// For now we only support embedding in JSON strings because of the hcl parsing -// pain (see Background section in the comment for decode.HookWeakDecodeFromSlice). -// This may be fixed in decode.HookWeakDecodeFromSlice in the future. -// -// When we do that we can support just nesting the config directly into the -// JSON/hcl naturally but this is a stop-gap that gets us an escape hatch -// immediately. It's also probably not a bad thing to support long-term since -// any config generated by other systems will likely be in canonical protobuf -// from rather than our slight variant in JSON/hcl. - -// TODO(proxystate): Mesh and Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeGatewayCluster - -func configureClusterWithHostnames( - logger hclog.Logger, - dnsEndpointGroup *pbproxystate.DNSEndpointGroup, - endpointList *pbproxystate.Endpoints, - dnsDiscoveryType string, - // hostnameEndpoints is a list of endpoints with a hostname as their address - hostnameEndpoints structs.CheckServiceNodes, - // isRemote determines whether the cluster is in a remote DC or partition and we should prefer a WAN address - isRemote bool, - // onlyPassing determines whether endpoints that do not have a passing status should be considered unhealthy - onlyPassing bool, -) { - // When a service instance is addressed by a hostname we have Envoy do the DNS resolution - // by setting a DNS cluster type and passing the hostname endpoints via CDS. - if dnsEndpointGroup.Config == nil { - dnsEndpointGroup.Config = &pbproxystate.DNSEndpointGroupConfig{} - } - dnsEndpointGroup.Config.DiscoveryType = pbproxystate.DiscoveryType_DISCOVERY_TYPE_LOGICAL - if dnsDiscoveryType == "strict_dns" { - dnsEndpointGroup.Config.DiscoveryType = pbproxystate.DiscoveryType_DISCOVERY_TYPE_STRICT - } - - endpoints := make([]*envoy_endpoint_v3.LbEndpoint, 0, 1) - uniqueHostnames := make(map[string]bool) - - var ( - hostname string - idx int - fallback *pbproxystate.Endpoint - ) - for i, e := range hostnameEndpoints { - _, addr, port := e.BestAddress(isRemote) - uniqueHostnames[addr] = true - - health, weight := calculateEndpointHealthAndWeight(e, onlyPassing) - if health == pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY { - fallback = makeLbEndpoint(addr, port, health, weight) - continue - } - - if len(endpoints) == 0 { - endpointList.Endpoints = append(endpointList.Endpoints, makeLbEndpoint(addr, port, health, weight)) - - hostname = addr - idx = i - break - } - } - - dc := hostnameEndpoints[idx].Node.Datacenter - service := hostnameEndpoints[idx].Service.CompoundServiceName() - - // Fall back to last unhealthy endpoint if none were healthy - if len(endpoints) == 0 { - logger.Warn("upstream service does not contain any healthy instances", - "dc", dc, "service", service.String()) - - //endpoints = append(endpoints, fallback) - endpointList.Endpoints = append(endpointList.Endpoints, fallback) - } - if len(uniqueHostnames) > 1 { - logger.Warn(fmt.Sprintf("service contains instances with more than one unique hostname; only %q be resolved by Envoy", hostname), - "dc", dc, "service", service.String()) - } - -} - -// TODO(proxystate): Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeExternalIPCluster - -// TODO(proxystate): Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeExternalHostnameCluster - -func makeUpstreamLimitsIfNeeded(limits *structs.UpstreamLimits) *pbproxystate.UpstreamLimits { - if limits == nil { - return nil - } - - upstreamLimits := &pbproxystate.UpstreamLimits{} - - // Likewise, make sure to not set any threshold values on the zero-value in - // order to rely on Envoy defaults - if limits.MaxConnections != nil { - upstreamLimits.MaxConnections = response.MakeUint32Value(*limits.MaxConnections) - } - if limits.MaxPendingRequests != nil { - upstreamLimits.MaxPendingRequests = response.MakeUint32Value(*limits.MaxPendingRequests) - } - if limits.MaxConcurrentRequests != nil { - upstreamLimits.MaxConcurrentRequests = response.MakeUint32Value(*limits.MaxConcurrentRequests) - } - - return upstreamLimits -} - -func injectLBToCluster(ec *structs.LoadBalancer, dc *pbproxystate.DynamicEndpointGroupConfig) error { - if ec == nil { - return nil - } - - switch ec.Policy { - case "": - return nil - case structs.LBPolicyLeastRequest: - lr := &pbproxystate.DynamicEndpointGroupConfig_LeastRequest{ - LeastRequest: &pbproxystate.LBPolicyLeastRequest{}, - } - - dc.LbPolicy = lr - - if ec.LeastRequestConfig != nil { - lr.LeastRequest.ChoiceCount = &wrapperspb.UInt32Value{Value: ec.LeastRequestConfig.ChoiceCount} - } - case structs.LBPolicyRoundRobin: - dc.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_RoundRobin{ - RoundRobin: &pbproxystate.LBPolicyRoundRobin{}, - } - - case structs.LBPolicyRandom: - dc.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_Random{ - Random: &pbproxystate.LBPolicyRandom{}, - } - - case structs.LBPolicyRingHash: - rh := &pbproxystate.DynamicEndpointGroupConfig_RingHash{ - RingHash: &pbproxystate.LBPolicyRingHash{}, - } - - dc.LbPolicy = rh - - if ec.RingHashConfig != nil { - rh.RingHash.MinimumRingSize = &wrapperspb.UInt64Value{Value: ec.RingHashConfig.MinimumRingSize} - rh.RingHash.MaximumRingSize = &wrapperspb.UInt64Value{Value: ec.RingHashConfig.MaximumRingSize} - } - case structs.LBPolicyMaglev: - dc.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_Maglev{ - Maglev: &pbproxystate.LBPolicyMaglev{}, - } - - default: - return fmt.Errorf("unsupported load balancer policy %q", ec.Policy) - } - return nil -} - -// generatePeeredClusterName returns an SNI-like cluster name which mimics PeeredServiceSNI -// but excludes partition information which could be ambiguous (local vs remote partition). -func generatePeeredClusterName(uid proxycfg.UpstreamID, tb *pbpeering.PeeringTrustBundle) string { - return strings.Join([]string{ - uid.Name, - uid.NamespaceOrDefault(), - uid.Peer, - "external", - tb.TrustDomain, - }, ".") -} - -func (s *Converter) getTargetClusterName(upstreamsSnapshot *proxycfg.ConfigSnapshotUpstreams, chain *structs.CompiledDiscoveryChain, tid string, forMeshGateway bool) string { - target := chain.Targets[tid] - clusterName := target.Name - targetUID := proxycfg.NewUpstreamIDFromTargetID(tid) - if targetUID.Peer != "" { - tbs, ok := upstreamsSnapshot.UpstreamPeerTrustBundles.Get(targetUID.Peer) - // We can't generate cluster on peers without the trust bundle. The - // trust bundle should be ready soon. - if !ok { - s.Logger.Debug("peer trust bundle not ready for discovery chain target", - "peer", targetUID.Peer, - "target", tid, - ) - return "" - } - - clusterName = generatePeeredClusterName(targetUID, tbs) - } - clusterName = naming.CustomizeClusterName(clusterName, chain) - if forMeshGateway { - clusterName = meshGatewayExportedClusterNamePrefix + clusterName - } - return clusterName -} - -// Return an pbproxystate.OutlierDetection populated by the values from structs.PassiveHealthCheck. -// If all values are zero a default empty OutlierDetection will be returned to -// enable outlier detection with default values. -// - If override is not nil, it will overwrite the values from p, e.g., ingress gateway defaults -// - allowZero is added to handle the legacy case where connect-proxy and mesh gateway can set 0 -// for EnforcingConsecutive5xx. Due to the definition of proto of PassiveHealthCheck, ingress -// gateway's EnforcingConsecutive5xx must be > 0. -func makeOutlierDetection(p *structs.PassiveHealthCheck, override *structs.PassiveHealthCheck, allowZero bool) *pbproxystate.OutlierDetection { - od := &pbproxystate.OutlierDetection{} - if p != nil { - - if p.Interval != 0 { - od.Interval = durationpb.New(p.Interval) - } - if p.MaxFailures != 0 { - od.Consecutive_5Xx = &wrapperspb.UInt32Value{Value: p.MaxFailures} - } - - if p.EnforcingConsecutive5xx != nil { - // NOTE: EnforcingConsecutive5xx must be greater than 0 for ingress-gateway - if *p.EnforcingConsecutive5xx != 0 { - od.EnforcingConsecutive_5Xx = &wrapperspb.UInt32Value{Value: *p.EnforcingConsecutive5xx} - } else if allowZero { - od.EnforcingConsecutive_5Xx = &wrapperspb.UInt32Value{Value: *p.EnforcingConsecutive5xx} - } - } - - if p.MaxEjectionPercent != nil { - od.MaxEjectionPercent = &wrapperspb.UInt32Value{Value: *p.MaxEjectionPercent} - } - if p.BaseEjectionTime != nil { - od.BaseEjectionTime = durationpb.New(*p.BaseEjectionTime) - } - } - - if override == nil { - return od - } - - // override the default outlier detection value - if override.Interval != 0 { - od.Interval = durationpb.New(override.Interval) - } - if override.MaxFailures != 0 { - od.Consecutive_5Xx = &wrapperspb.UInt32Value{Value: override.MaxFailures} - } - - if override.EnforcingConsecutive5xx != nil { - // NOTE: EnforcingConsecutive5xx must be great than 0 for ingress-gateway - if *override.EnforcingConsecutive5xx != 0 { - od.EnforcingConsecutive_5Xx = &wrapperspb.UInt32Value{Value: *override.EnforcingConsecutive5xx} - } - // Because only ingress gateways have overrides and they cannot have a value of 0, there is no allowZero - // override case to handle - } - - if override.MaxEjectionPercent != nil { - od.MaxEjectionPercent = &wrapperspb.UInt32Value{Value: *override.MaxEjectionPercent} - } - if override.BaseEjectionTime != nil { - od.BaseEjectionTime = durationpb.New(*override.BaseEjectionTime) - } - - return od -} diff --git a/agent/xds/proxystateconverter/converter.go b/agent/xds/proxystateconverter/converter.go deleted file mode 100644 index 954e30857e4bb..0000000000000 --- a/agent/xds/proxystateconverter/converter.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "fmt" - - "github.com/hashicorp/go-hclog" - - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/configfetcher" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" -) - -// Converter converts a single snapshot into a ProxyState. -type Converter struct { - Logger hclog.Logger - CfgFetcher configfetcher.ConfigFetcher - proxyState *proxytracker.ProxyState -} - -func NewConverter( - logger hclog.Logger, - cfgFetcher configfetcher.ConfigFetcher, -) *Converter { - return &Converter{ - Logger: logger, - CfgFetcher: cfgFetcher, - proxyState: &proxytracker.ProxyState{ - ProxyState: &pbmesh.ProxyState{ - Listeners: make([]*pbproxystate.Listener, 0), - Clusters: make(map[string]*pbproxystate.Cluster), - Routes: make(map[string]*pbproxystate.Route), - Endpoints: make(map[string]*pbproxystate.Endpoints), - }, - }, - } -} - -func (g *Converter) ProxyStateFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) (*proxytracker.ProxyState, error) { - err := g.resourcesFromSnapshot(cfgSnap) - if err != nil { - return nil, fmt.Errorf("failed to generate FullProxyState: %v", err) - } - - return g.proxyState, nil -} - -func (g *Converter) resourcesFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) error { - err := g.tlsConfigFromSnapshot(cfgSnap) - if err != nil { - return err - } - - err = g.listenersFromSnapshot(cfgSnap) - if err != nil { - return err - } - - err = g.endpointsFromSnapshot(cfgSnap) - if err != nil { - return err - } - err = g.clustersFromSnapshot(cfgSnap) - if err != nil { - return err - } - err = g.routesFromSnapshot(cfgSnap) - if err != nil { - return err - } - - //g.secretsFromSnapshot(cfgSnap) - return nil -} - -const localPeerKey = "local" - -func (g *Converter) tlsConfigFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) error { - proxyStateTLS := &pbproxystate.TLS{} - g.proxyState.TrustBundles = make(map[string]*pbproxystate.TrustBundle) - g.proxyState.LeafCertificates = make(map[string]*pbproxystate.LeafCertificate) - - // Set the TLS in the top level proxyState - g.proxyState.Tls = proxyStateTLS - - // Add local trust bundle - g.proxyState.TrustBundles[localPeerKey] = &pbproxystate.TrustBundle{ - TrustDomain: cfgSnap.Roots.TrustDomain, - Roots: []string{cfgSnap.RootPEMs()}, - } - - // Add peered trust bundles for remote peers that will dial this proxy. - for _, peeringTrustBundle := range cfgSnap.PeeringTrustBundles() { - g.proxyState.TrustBundles[peeringTrustBundle.PeerName] = &pbproxystate.TrustBundle{ - TrustDomain: peeringTrustBundle.GetTrustDomain(), - Roots: peeringTrustBundle.RootPEMs, - } - } - - // Add upstream peer trust bundles for dialing upstreams in remote peers. - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - if err != nil { - if !(cfgSnap.Kind == structs.ServiceKindMeshGateway || cfgSnap.Kind == structs.ServiceKindTerminatingGateway) { - return err - } - } - if upstreamsSnapshot != nil { - upstreamsSnapshot.UpstreamPeerTrustBundles.ForEachKeyE(func(k proxycfg.PeerName) error { - tbs, ok := upstreamsSnapshot.UpstreamPeerTrustBundles.Get(k) - if ok { - g.proxyState.TrustBundles[k] = &pbproxystate.TrustBundle{ - TrustDomain: tbs.TrustDomain, - Roots: tbs.RootPEMs, - } - } - return nil - }) - } - - if cfgSnap.MeshConfigTLSOutgoing() != nil { - proxyStateTLS.OutboundTlsParameters = makeTLSParametersFromTLSConfig(cfgSnap.MeshConfigTLSOutgoing().TLSMinVersion, - cfgSnap.MeshConfigTLSOutgoing().TLSMaxVersion, cfgSnap.MeshConfigTLSOutgoing().CipherSuites) - } - - if cfgSnap.MeshConfigTLSIncoming() != nil { - proxyStateTLS.InboundTlsParameters = makeTLSParametersFromTLSConfig(cfgSnap.MeshConfigTLSIncoming().TLSMinVersion, - cfgSnap.MeshConfigTLSIncoming().TLSMaxVersion, cfgSnap.MeshConfigTLSIncoming().CipherSuites) - } - - return nil -} diff --git a/agent/xds/proxystateconverter/endpoints.go b/agent/xds/proxystateconverter/endpoints.go deleted file mode 100644 index 78ebe95e2d47d..0000000000000 --- a/agent/xds/proxystateconverter/endpoints.go +++ /dev/null @@ -1,671 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "errors" - "fmt" - - "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" - "github.com/hashicorp/go-bexpr" - - "google.golang.org/protobuf/types/known/wrapperspb" -) - -func makeLbEndpoint(addr string, port int, health pbproxystate.HealthStatus, weight int) *pbproxystate.Endpoint { - ep := &pbproxystate.Endpoint{ - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: addr, - Port: uint32(port), - }, - }, - } - ep.HealthStatus = health - ep.LoadBalancingWeight = &wrapperspb.UInt32Value{Value: uint32(weight)} - return ep -} - -// endpointsFromSnapshot returns the mesh API representation of the "routes" in the snapshot. -func (s *Converter) endpointsFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) error { - - if cfgSnap == nil { - return errors.New("nil config given") - } - - switch cfgSnap.Kind { - case structs.ServiceKindConnectProxy: - return s.endpointsFromSnapshotConnectProxy(cfgSnap) - //case structs.ServiceKindTerminatingGateway: - // return s.endpointsFromSnapshotTerminatingGateway(cfgSnap) - //case structs.ServiceKindMeshGateway: - // return s.endpointsFromSnapshotMeshGateway(cfgSnap) - //case structs.ServiceKindIngressGateway: - // return s.endpointsFromSnapshotIngressGateway(cfgSnap) - //case structs.ServiceKindAPIGateway: - // return s.endpointsFromSnapshotAPIGateway(cfgSnap) - default: - return fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind) - } -} - -// endpointsFromSnapshotConnectProxy returns the xDS API representation of the "endpoints" -// (upstream instances) in the snapshot. -func (s *Converter) endpointsFromSnapshotConnectProxy(cfgSnap *proxycfg.ConfigSnapshot) error { - eps := make(map[string]*pbproxystate.Endpoints) - - // NOTE: Any time we skip a chain below we MUST also skip that discovery chain in clusters.go - // so that the sets of endpoints generated matches the sets of clusters. - for uid, chain := range cfgSnap.ConnectProxy.DiscoveryChain { - upstream, skip := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta) - if skip { - // Discovery chain is not associated with a known explicit or implicit upstream so it is skipped. - continue - } - - var upstreamConfigMap map[string]interface{} - if upstream != nil { - upstreamConfigMap = upstream.Config - } - - es, err := s.endpointsFromDiscoveryChain( - uid, - chain, - cfgSnap, - cfgSnap.Locality, - upstreamConfigMap, - cfgSnap.ConnectProxy.WatchedUpstreamEndpoints[uid], - cfgSnap.ConnectProxy.WatchedGatewayEndpoints[uid], - false, - ) - if err != nil { - return err - } - - for clusterName, endpoints := range es { - eps[clusterName] = &pbproxystate.Endpoints{ - Endpoints: endpoints, - } - - } - } - - // NOTE: Any time we skip an upstream below we MUST also skip that same - // upstream in clusters.go so that the sets of endpoints generated matches - // the sets of clusters. - for _, uid := range cfgSnap.ConnectProxy.PeeredUpstreamIDs() { - upstream, skip := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta) - if skip { - // Discovery chain is not associated with a known explicit or implicit upstream so it is skipped. - continue - } - - tbs, ok := cfgSnap.ConnectProxy.UpstreamPeerTrustBundles.Get(uid.Peer) - if !ok { - // this should never happen since we loop through upstreams with - // set trust bundles - return fmt.Errorf("trust bundle not ready for peer %s", uid.Peer) - } - - clusterName := generatePeeredClusterName(uid, tbs) - - mgwMode := structs.MeshGatewayModeDefault - if upstream != nil { - mgwMode = upstream.MeshGateway.Mode - } - peerServiceEndpoints, err := s.makeEndpointsForPeerService(cfgSnap, uid, mgwMode) - if err != nil { - return err - } - - if peerServiceEndpoints != nil { - pbEndpoints := &pbproxystate.Endpoints{ - Endpoints: peerServiceEndpoints, - } - - eps[clusterName] = pbEndpoints - } - } - - // Looping over explicit upstreams is only needed for prepared queries because they do not have discovery chains - for _, u := range cfgSnap.Proxy.Upstreams { - if u.DestinationType != structs.UpstreamDestTypePreparedQuery { - continue - } - uid := proxycfg.NewUpstreamID(&u) - - dc := u.Datacenter - if dc == "" { - dc = cfgSnap.Datacenter - } - clusterName := connect.UpstreamSNI(&u, "", dc, cfgSnap.Roots.TrustDomain) - - endpoints, ok := cfgSnap.ConnectProxy.PreparedQueryEndpoints[uid] - if ok { - epts := makeEndpointsForLoadAssignment( - cfgSnap, - nil, - []loadAssignmentEndpointGroup{ - {Endpoints: endpoints}, - }, - cfgSnap.Locality, - ) - pbEndpoints := &pbproxystate.Endpoints{ - Endpoints: epts, - } - - eps[clusterName] = pbEndpoints - } - } - - // Loop over potential destinations in the mesh, then grab the gateway nodes associated with each - cfgSnap.ConnectProxy.DestinationsUpstream.ForEachKey(func(uid proxycfg.UpstreamID) bool { - svcConfig, ok := cfgSnap.ConnectProxy.DestinationsUpstream.Get(uid) - if !ok || svcConfig.Destination == nil { - return true - } - - for _, address := range svcConfig.Destination.Addresses { - clusterName := clusterNameForDestination(cfgSnap, uid.Name, address, uid.NamespaceOrDefault(), uid.PartitionOrDefault()) - - endpoints, ok := cfgSnap.ConnectProxy.DestinationGateways.Get(uid) - if ok { - epts := makeEndpointsForLoadAssignment( - cfgSnap, - nil, - []loadAssignmentEndpointGroup{ - {Endpoints: endpoints}, - }, - proxycfg.GatewayKey{ /*empty so it never matches*/ }, - ) - pbEndpoints := &pbproxystate.Endpoints{ - Endpoints: epts, - } - eps[clusterName] = pbEndpoints - } - } - - return true - }) - - s.proxyState.Endpoints = eps - return nil -} - -func (s *Converter) makeEndpointsForPeerService( - cfgSnap *proxycfg.ConfigSnapshot, - uid proxycfg.UpstreamID, - upstreamGatewayMode structs.MeshGatewayMode, -) ([]*pbproxystate.Endpoint, error) { - var eps []*pbproxystate.Endpoint - - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - if err != nil { - return eps, err - } - - if upstreamGatewayMode == structs.MeshGatewayModeNone { - s.Logger.Warn(fmt.Sprintf("invalid mesh gateway mode 'none', defaulting to 'remote' for %q", uid)) - } - - // If an upstream is configured with local mesh gw mode, we make a load assignment - // from the gateway endpoints instead of those of the upstreams. - if upstreamGatewayMode == structs.MeshGatewayModeLocal { - localGw, ok := cfgSnap.ConnectProxy.WatchedLocalGWEndpoints.Get(cfgSnap.Locality.String()) - if !ok { - // local GW is not ready; return early - return eps, nil - } - eps = makeEndpointsForLoadAssignment( - cfgSnap, - nil, - []loadAssignmentEndpointGroup{ - {Endpoints: localGw}, - }, - cfgSnap.Locality, - ) - return eps, nil - } - - // Also skip peer instances with a hostname as their address. EDS - // cannot resolve hostnames, so we provide them through CDS instead. - if _, ok := upstreamsSnapshot.PeerUpstreamEndpointsUseHostnames[uid]; ok { - return eps, nil - } - - endpoints, ok := upstreamsSnapshot.PeerUpstreamEndpoints.Get(uid) - if !ok { - return nil, nil - } - eps = makeEndpointsForLoadAssignment( - cfgSnap, - nil, - []loadAssignmentEndpointGroup{ - {Endpoints: endpoints}, - }, - proxycfg.GatewayKey{ /*empty so it never matches*/ }, - ) - return eps, nil -} - -func (s *Converter) filterSubsetEndpoints(subset *structs.ServiceResolverSubset, endpoints structs.CheckServiceNodes) (structs.CheckServiceNodes, error) { - // locally execute the subsets filter - if subset.Filter != "" { - filter, err := bexpr.CreateFilter(subset.Filter, nil, endpoints) - if err != nil { - return nil, err - } - - raw, err := filter.Execute(endpoints) - if err != nil { - return nil, err - } - return raw.(structs.CheckServiceNodes), nil - } - return endpoints, nil -} - -// TODO(proxystate): Terminating Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func endpointsFromSnapshotTerminatingGateway - -// TODO(proxystate): Mesh Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func endpointsFromSnapshotMeshGateway - -// TODO(proxystate): Cluster Peering will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func makeEndpointsForOutgoingPeeredServices - -// TODO(proxystate): Mesh Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func endpointsFromServicesAndResolvers - -// TODO(proxystate): Mesh Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func makePeerServerEndpointsForMeshGateway - -// TODO(proxystate): Ingress Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func endpointsFromSnapshotIngressGateway - -// TODO(proxystate): API Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func endpointsFromSnapshotAPIGateway - -// used in clusters.go -func makeHostPortEndpoint(host string, port int) *pbproxystate.Endpoint { - return &pbproxystate.Endpoint{ - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: host, - Port: uint32(port), - }, - }, - } -} - -func makeUnixSocketEndpoint(path string) *pbproxystate.Endpoint { - return &pbproxystate.Endpoint{ - Address: &pbproxystate.Endpoint_UnixSocket{ - UnixSocket: &pbproxystate.UnixSocketAddress{ - Path: path, - // envoy's mode is particular to a pipe address and is uint32. - // it also says "The mode for the Pipe. Not applicable for abstract sockets." - // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-pipe - Mode: "0", - }, - }, - } -} - -func (s *Converter) makeUpstreamLoadAssignmentEndpointForPeerService( - cfgSnap *proxycfg.ConfigSnapshot, - uid proxycfg.UpstreamID, - upstreamGatewayMode structs.MeshGatewayMode, -) ([]*pbproxystate.Endpoint, error) { - var eps []*pbproxystate.Endpoint - - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - if err != nil { - return eps, err - } - - if upstreamGatewayMode == structs.MeshGatewayModeNone { - s.Logger.Warn(fmt.Sprintf("invalid mesh gateway mode 'none', defaulting to 'remote' for %q", uid)) - } - - // If an upstream is configured with local mesh gw mode, we make a load assignment - // from the gateway endpoints instead of those of the upstreams. - if upstreamGatewayMode == structs.MeshGatewayModeLocal { - localGw, ok := cfgSnap.ConnectProxy.WatchedLocalGWEndpoints.Get(cfgSnap.Locality.String()) - if !ok { - // local GW is not ready; return early - return eps, nil - } - eps = makeEndpointsForLoadAssignment( - cfgSnap, - nil, - []loadAssignmentEndpointGroup{ - {Endpoints: localGw}, - }, - cfgSnap.Locality, - ) - return eps, nil - } - - // Also skip peer instances with a hostname as their address. EDS - // cannot resolve hostnames, so we provide them through CDS instead. - if _, ok := upstreamsSnapshot.PeerUpstreamEndpointsUseHostnames[uid]; ok { - return eps, nil - } - - endpoints, ok := upstreamsSnapshot.PeerUpstreamEndpoints.Get(uid) - if !ok { - return nil, nil - } - eps = makeEndpointsForLoadAssignment( - cfgSnap, - nil, - []loadAssignmentEndpointGroup{ - {Endpoints: endpoints}, - }, - proxycfg.GatewayKey{ /*empty so it never matches*/ }, - ) - return eps, nil -} - -func (s *Converter) endpointsFromDiscoveryChain( - uid proxycfg.UpstreamID, - chain *structs.CompiledDiscoveryChain, - cfgSnap *proxycfg.ConfigSnapshot, - gatewayKey proxycfg.GatewayKey, - upstreamConfigMap map[string]interface{}, - upstreamEndpoints map[string]structs.CheckServiceNodes, - gatewayEndpoints map[string]structs.CheckServiceNodes, - forMeshGateway bool, -) (map[string][]*pbproxystate.Endpoint, error) { - if chain == nil { - if forMeshGateway { - return nil, fmt.Errorf("missing discovery chain for %s", uid) - } - return nil, nil - } - - if upstreamConfigMap == nil { - upstreamConfigMap = make(map[string]interface{}) // TODO:needed? - } - - clusterEndpoints := make(map[string][]*pbproxystate.Endpoint) - - // TODO(proxystate): escape hatches will be implemented in the future - //var escapeHatchCluster *pbproxystate.Cluster - //if !forMeshGateway { - - //cfg, err := structs.ParseUpstreamConfigNoDefaults(upstreamConfigMap) - //if err != nil { - // // Don't hard fail on a config typo, just warn. The parse func returns - // // default config if there is an error so it's safe to continue. - // s.Logger.Warn("failed to parse", "upstream", uid, - // "error", err) - //} - - //if cfg.EnvoyClusterJSON != "" { - // if chain.Default { - // // If you haven't done anything to setup the discovery chain, then - // // you can use the envoy_cluster_json escape hatch. - // escapeHatchCluster, err = makeClusterFromUserConfig(cfg.EnvoyClusterJSON) - // if err != nil { - // return ce, nil - // } - // } else { - // s.Logger.Warn("ignoring escape hatch setting, because a discovery chain is configued for", - // "discovery chain", chain.ServiceName, "upstream", uid, - // "envoy_cluster_json", chain.ServiceName) - // } - //} - //} - - mgwMode := structs.MeshGatewayModeDefault - if upstream, _ := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta); upstream != nil { - mgwMode = upstream.MeshGateway.Mode - } - - // Find all resolver nodes. - for _, node := range chain.Nodes { - switch { - case node == nil: - return nil, fmt.Errorf("impossible to process a nil node") - case node.Type != structs.DiscoveryGraphNodeTypeResolver: - continue - case node.Resolver == nil: - return nil, fmt.Errorf("impossible to process a non-resolver node") - } - rawUpstreamConfig, err := structs.ParseUpstreamConfigNoDefaults(upstreamConfigMap) - if err != nil { - return nil, err - } - upstreamConfig := finalizeUpstreamConfig(rawUpstreamConfig, chain, node.Resolver.ConnectTimeout) - - mappedTargets, err := s.mapDiscoChainTargets(cfgSnap, chain, node, upstreamConfig, forMeshGateway) - if err != nil { - return nil, err - } - - targetGroups, err := mappedTargets.groupedTargets() - if err != nil { - return nil, err - } - - for _, groupedTarget := range targetGroups { - clusterName := groupedTarget.ClusterName - // TODO(proxystate): escape hatches will be implemented in the future - //if escapeHatchCluster != nil { - // clusterName = escapeHatchCluster.Name - //} - switch len(groupedTarget.Targets) { - case 0: - continue - case 1: - // We expect one target so this passes through to continue setting the load assignment up. - default: - return nil, fmt.Errorf("cannot have more than one target") - } - ti := groupedTarget.Targets[0] - s.Logger.Debug("generating endpoints for", "cluster", clusterName, "targetID", ti.TargetID) - targetUID := proxycfg.NewUpstreamIDFromTargetID(ti.TargetID) - if targetUID.Peer != "" { - peerServiceEndpoints, err := s.makeEndpointsForPeerService(cfgSnap, targetUID, mgwMode) - if err != nil { - return nil, err - } - if peerServiceEndpoints != nil { - clusterEndpoints[clusterName] = peerServiceEndpoints - } - continue - } - - endpointGroup, valid := makeLoadAssignmentEndpointGroup( - chain.Targets, - upstreamEndpoints, - gatewayEndpoints, - ti.TargetID, - gatewayKey, - forMeshGateway, - ) - if !valid { - continue // skip the cluster if we're still populating the snapshot - } - - epts := makeEndpointsForLoadAssignment( - cfgSnap, - ti.PrioritizeByLocality, - []loadAssignmentEndpointGroup{endpointGroup}, - gatewayKey, - ) - clusterEndpoints[clusterName] = epts - } - } - - return clusterEndpoints, nil -} - -// TODO(proxystate): Mesh Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func makeExportedUpstreamEndpointsForMeshGateway - -type loadAssignmentEndpointGroup struct { - Endpoints structs.CheckServiceNodes - OnlyPassing bool - OverrideHealth pbproxystate.HealthStatus -} - -func makeEndpointsForLoadAssignment(cfgSnap *proxycfg.ConfigSnapshot, - policy *structs.DiscoveryPrioritizeByLocality, - endpointGroups []loadAssignmentEndpointGroup, - localKey proxycfg.GatewayKey) []*pbproxystate.Endpoint { - pbEndpoints := make([]*pbproxystate.Endpoint, 0, len(endpointGroups)) - - // TODO(proxystate): this will be added with property overrides having golden files with this - //if len(endpointGroups) > 1 { - // cla.Policy = &envoy_endpoint_v3.ClusterLoadAssignment_Policy{ - // // We choose such a large value here that the failover math should - // // in effect not happen until zero instances are healthy. - // OverprovisioningFactor: response.MakeUint32Value(100000), - // } - //} - - var priority uint32 - - for _, endpointGroup := range endpointGroups { - endpointsByLocality, err := groupedEndpoints(cfgSnap.ServiceLocality, policy, endpointGroup.Endpoints) - - if err != nil { - continue - } - - for _, endpoints := range endpointsByLocality { - for _, ep := range endpoints { - // TODO (mesh-gateway) - should we respect the translate_wan_addrs configuration here or just always use the wan for cross-dc? - _, addr, port := ep.BestAddress(!localKey.Matches(ep.Node.Datacenter, ep.Node.PartitionOrDefault())) - healthStatus, weight := calculateEndpointHealthAndWeight(ep, endpointGroup.OnlyPassing) - - if endpointGroup.OverrideHealth != pbproxystate.HealthStatus_HEALTH_STATUS_UNKNOWN { - healthStatus = endpointGroup.OverrideHealth - } - - endpoint := makeHostPortEndpoint(addr, port) - endpoint.HealthStatus = healthStatus - endpoint.LoadBalancingWeight = response.MakeUint32Value(weight) - - pbEndpoints = append(pbEndpoints, endpoint) - } - - // TODO(proxystate): what do we do about priority downstream? - //cla.Endpoints = append(cla.Endpoints, &envoy_endpoint_v3.LocalityLbEndpoints{ - // Priority: priority, - // LbEndpoints: es, - //}) - - priority++ - } - } - - return pbEndpoints -} - -func makeLoadAssignmentEndpointGroup( - targets map[string]*structs.DiscoveryTarget, - targetHealth map[string]structs.CheckServiceNodes, - gatewayHealth map[string]structs.CheckServiceNodes, - targetID string, - localKey proxycfg.GatewayKey, - forMeshGateway bool, -) (loadAssignmentEndpointGroup, bool) { - realEndpoints, ok := targetHealth[targetID] - if !ok { - // skip the cluster if we're still populating the snapshot - return loadAssignmentEndpointGroup{}, false - } - target := targets[targetID] - - var gatewayKey proxycfg.GatewayKey - - switch target.MeshGateway.Mode { - case structs.MeshGatewayModeRemote: - gatewayKey.Datacenter = target.Datacenter - gatewayKey.Partition = target.Partition - case structs.MeshGatewayModeLocal: - gatewayKey = localKey - } - - if forMeshGateway || gatewayKey.IsEmpty() || localKey.Matches(target.Datacenter, target.Partition) { - // Gateways are not needed if the request isn't for a remote DC or partition. - return loadAssignmentEndpointGroup{ - Endpoints: realEndpoints, - OnlyPassing: target.Subset.OnlyPassing, - }, true - } - - // If using a mesh gateway we need to pull those endpoints instead. - gatewayEndpoints, ok := gatewayHealth[gatewayKey.String()] - if !ok { - // skip the cluster if we're still populating the snapshot - return loadAssignmentEndpointGroup{}, false - } - - // But we will use the health from the actual backend service. - overallHealth := pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - for _, ep := range realEndpoints { - health, _ := calculateEndpointHealthAndWeight(ep, target.Subset.OnlyPassing) - if health == pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY { - overallHealth = pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY - break - } - } - - return loadAssignmentEndpointGroup{ - Endpoints: gatewayEndpoints, - OverrideHealth: overallHealth, - }, true -} - -func calculateEndpointHealthAndWeight( - ep structs.CheckServiceNode, - onlyPassing bool, -) (pbproxystate.HealthStatus, int) { - healthStatus := pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY - weight := 1 - if ep.Service.Weights != nil { - weight = ep.Service.Weights.Passing - } - - for _, chk := range ep.Checks { - if chk.Status == api.HealthCritical { - healthStatus = pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - } - if onlyPassing && chk.Status != api.HealthPassing { - healthStatus = pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - } - if chk.Status == api.HealthWarning && ep.Service.Weights != nil { - weight = ep.Service.Weights.Warning - } - } - // Make weights fit Envoy's limits. A zero weight means that either Warning - // (likely) or Passing (weirdly) weight has been set to 0 effectively making - // this instance unhealthy and should not be sent traffic. - if weight < 1 { - healthStatus = pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - weight = 1 - } - if weight > 128 { - weight = 128 - } - return healthStatus, weight -} diff --git a/agent/xds/proxystateconverter/failover_policy.go b/agent/xds/proxystateconverter/failover_policy.go deleted file mode 100644 index 6ae120eaf941e..0000000000000 --- a/agent/xds/proxystateconverter/failover_policy.go +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "fmt" - - "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" -) - -type discoChainTargets struct { - baseClusterName string - targets []targetInfo - failover bool - failoverPolicy structs.ServiceResolverFailoverPolicy -} - -type targetInfo struct { - TargetID string - TransportSocket *pbproxystate.TransportSocket - SNI string - RootPEMs string - SpiffeIDs []string - Region *string - - PrioritizeByLocality *structs.DiscoveryPrioritizeByLocality -} - -type discoChainTargetGroup struct { - Targets []targetInfo - ClusterName string -} - -func (ft discoChainTargets) groupedTargets() ([]discoChainTargetGroup, error) { - var targetGroups []discoChainTargetGroup - - if !ft.failover { - targetGroups = append(targetGroups, discoChainTargetGroup{ - ClusterName: ft.baseClusterName, - Targets: ft.targets, - }) - return targetGroups, nil - } - - switch ft.failoverPolicy.Mode { - case "sequential", "": - return ft.sequential() - case "order-by-locality": - return ft.orderByLocality() - default: - return targetGroups, fmt.Errorf("unexpected failover policy") - } -} - -func (s *Converter) mapDiscoChainTargets(cfgSnap *proxycfg.ConfigSnapshot, chain *structs.CompiledDiscoveryChain, node *structs.DiscoveryGraphNode, upstreamConfig structs.UpstreamConfig, forMeshGateway bool) (discoChainTargets, error) { - failoverTargets := discoChainTargets{} - - if node.Resolver == nil { - return discoChainTargets{}, fmt.Errorf("impossible to process a non-resolver node") - } - - primaryTargetID := node.Resolver.Target - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - if err != nil && !forMeshGateway { - return discoChainTargets{}, err - } - - failoverTargets.baseClusterName = s.getTargetClusterName(upstreamsSnapshot, chain, primaryTargetID, forMeshGateway) - - tids := []string{primaryTargetID} - failover := node.Resolver.Failover - if failover != nil && !forMeshGateway { - tids = append(tids, failover.Targets...) - failoverTargets.failover = true - if failover.Policy == nil { - failoverTargets.failoverPolicy = structs.ServiceResolverFailoverPolicy{} - } else { - failoverTargets.failoverPolicy = *failover.Policy - } - } - - for _, tid := range tids { - target := chain.Targets[tid] - targetUID := proxycfg.NewUpstreamIDFromTargetID(tid) - ti := targetInfo{TargetID: tid, PrioritizeByLocality: target.PrioritizeByLocality} - - configureTLS := true - if forMeshGateway { - // We only initiate TLS if we're doing an L7 proxy. - configureTLS = structs.IsProtocolHTTPLike(upstreamConfig.Protocol) - } - - if !configureTLS { - failoverTargets.targets = append(failoverTargets.targets, ti) - continue - } - - if targetUID.Peer != "" { - tbs, _ := upstreamsSnapshot.UpstreamPeerTrustBundles.Get(targetUID.Peer) - - peerMeta, found := upstreamsSnapshot.UpstreamPeerMeta(targetUID) - if !found { - s.Logger.Warn("failed to fetch upstream peering metadata", "target", targetUID) - continue - } - ti.SNI = peerMeta.PrimarySNI() - ti.SpiffeIDs = peerMeta.SpiffeID - region := target.Locality.GetRegion() - ti.Region = ®ion - ti.RootPEMs = tbs.ConcatenatedRootPEMs() - } else { - ti.SNI = target.SNI - ti.RootPEMs = cfgSnap.RootPEMs() - ti.SpiffeIDs = []string{connect.SpiffeIDService{ - Host: cfgSnap.Roots.TrustDomain, - Namespace: target.Namespace, - Partition: target.Partition, - Datacenter: target.Datacenter, - Service: target.Service, - }.URI().String()} - } - //commonTLSContext := makeCommonTLSContext( - // cfgSnap.Leaf(), - // rootPEMs, - // makeTLSParametersFromProxyTLSConfig(cfgSnap.MeshConfigTLSOutgoing()), - //) - // - //err := injectSANMatcher(commonTLSContext, spiffeIDs...) - //if err != nil { - // return failoverTargets, fmt.Errorf("failed to inject SAN matcher rules for cluster %q: %v", sni, err) - //} - - //tlsContext := &envoy_tls_v3.UpstreamTlsContext{ - // CommonTlsContext: commonTLSContext, - // Sni: sni, - //} - //ti.TLSContext = tlsContext - failoverTargets.targets = append(failoverTargets.targets, ti) - } - - return failoverTargets, nil -} - -func (ft discoChainTargets) sequential() ([]discoChainTargetGroup, error) { - var targetGroups []discoChainTargetGroup - for i, t := range ft.targets { - targetGroups = append(targetGroups, discoChainTargetGroup{ - ClusterName: fmt.Sprintf("%s%d~%s", xdscommon.FailoverClusterNamePrefix, i, ft.baseClusterName), - Targets: []targetInfo{t}, - }) - } - return targetGroups, nil -} diff --git a/agent/xds/proxystateconverter/failover_policy_ce.go b/agent/xds/proxystateconverter/failover_policy_ce.go deleted file mode 100644 index a9b2ec24843c3..0000000000000 --- a/agent/xds/proxystateconverter/failover_policy_ce.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package proxystateconverter - -import ( - "fmt" -) - -func (ft discoChainTargets) orderByLocality() ([]discoChainTargetGroup, error) { - return nil, fmt.Errorf("order-by-locality is a Consul Enterprise feature") -} diff --git a/agent/xds/proxystateconverter/listeners.go b/agent/xds/proxystateconverter/listeners.go deleted file mode 100644 index 7e21819260ee9..0000000000000 --- a/agent/xds/proxystateconverter/listeners.go +++ /dev/null @@ -1,1693 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "errors" - "fmt" - "net" - "net/url" - "regexp" - "strconv" - "strings" - "time" - - envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - "github.com/hashicorp/go-uuid" - - "github.com/hashicorp/go-hclog" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/wrapperspb" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/config" - "github.com/hashicorp/consul/agent/xds/naming" - "github.com/hashicorp/consul/agent/xds/platform" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" - "github.com/hashicorp/consul/sdk/iptables" - "github.com/hashicorp/consul/types" -) - -// listenersFromSnapshot adds listeners to pbmesh.ProxyState using the config snapshot. -func (s *Converter) listenersFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) error { - if cfgSnap == nil { - return errors.New("nil config given") - } - - switch cfgSnap.Kind { - case structs.ServiceKindConnectProxy: - return s.listenersFromSnapshotConnectProxy(cfgSnap) - case structs.ServiceKindTerminatingGateway, - structs.ServiceKindMeshGateway, - structs.ServiceKindIngressGateway, - structs.ServiceKindAPIGateway: - // TODO(proxystate): gateway support will be added in the future - //return s.listenersFromSnapshotGateway(cfgSnap) - default: - return fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind) - } - return nil -} - -// listenersFromSnapshotConnectProxy returns the "listeners" for a connect proxy service -func (s *Converter) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg.ConfigSnapshot) error { - // This is the list of listeners we add to. It will be empty to start. - listeners := s.proxyState.Listeners - var err error - - // Configure inbound listener. - inboundListener, err := s.makeInboundListener(cfgSnap, xdscommon.PublicListenerName) - if err != nil { - return err - } - listeners = append(listeners, inboundListener) - - // This outboundListener is exclusively used when transparent proxy mode is active. - // In that situation there is a single listener where we are redirecting outbound traffic, - // and each upstream gets a filter chain attached to that listener. - var outboundListener *pbproxystate.Listener - - if cfgSnap.Proxy.Mode == structs.ProxyModeTransparent { - port := iptables.DefaultTProxyOutboundPort - if cfgSnap.Proxy.TransparentProxy.OutboundListenerPort != 0 { - port = cfgSnap.Proxy.TransparentProxy.OutboundListenerPort - } - - opts := makeListenerOpts{ - name: xdscommon.OutboundListenerName, - //accessLogs: cfgSnap.Proxy.AccessLogs, - addr: "127.0.0.1", - port: port, - direction: pbproxystate.Direction_DIRECTION_OUTBOUND, - logger: s.Logger, - } - outboundListener = makeListener(opts) - if outboundListener.Capabilities == nil { - outboundListener.Capabilities = []pbproxystate.Capability{} - } - outboundListener.Capabilities = append(outboundListener.Capabilities, pbproxystate.Capability_CAPABILITY_TRANSPARENT) - } - - // TODO(proxystate): tracing escape hatch will be added in the future. It will be added to the top level in proxystate, and used in xds generation. - //proxyCfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - //if err != nil { - // // Don't hard fail on a config typo, just warn. The parse func returns - // // default config if there is an error so it's safe to continue. - // s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - //} - //var tracing *envoy_http_v3.HttpConnectionManager_Tracing - //if proxyCfg.ListenerTracingJSON != "" { - // if tracing, err = makeTracingFromUserConfig(proxyCfg.ListenerTracingJSON); err != nil { - // s.Logger.Warn("failed to parse ListenerTracingJSON config", "error", err) - // } - //} - - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - if err != nil { - return err - } - - for uid, chain := range cfgSnap.ConnectProxy.DiscoveryChain { - upstreamCfg, skip := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta) - if skip { - // Discovery chain is not associated with a known explicit or implicit upstream so it is skipped. - continue - } - - cfg := s.getAndModifyUpstreamConfigForListener(uid, upstreamCfg, chain) - - // If escape hatch is present, create a listener from it and move on to the next - if cfg.EnvoyListenerJSON != "" { - upstreamListener := &pbproxystate.Listener{ - EscapeHatchListener: cfg.EnvoyListenerJSON, - } - listeners = append(listeners, upstreamListener) - continue - } - - // RDS, Envoy's Route Discovery Service, is only used for HTTP services with a customized discovery chain. - useRDS := chain.Protocol != "tcp" && !chain.Default - - var clusterName string - if !useRDS { - // When not using RDS we must generate a cluster name to attach to the filter chain. - // With RDS, cluster names get attached to the dynamic routes instead. - target, err := simpleChainTarget(chain) - if err != nil { - return err - } - - clusterName = s.getTargetClusterName(upstreamsSnapshot, chain, target.ID, false) - if clusterName == "" { - continue - } - } - - filterName := fmt.Sprintf("%s.%s.%s.%s", chain.ServiceName, chain.Namespace, chain.Partition, chain.Datacenter) - - // Generate the upstream listeners for when they are explicitly set with a local bind port or socket path - if upstreamCfg != nil && upstreamCfg.HasLocalPortOrSocket() { - router, err := s.makeUpstreamRouter(routerOpts{ - // TODO(proxystate): access logs and tracing will be added in the future. - //accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: uid.EnvoyID(), - clusterName: clusterName, - filterName: filterName, - protocol: cfg.Protocol, - useRDS: useRDS, - //tracing: tracing, - }) - if err != nil { - return err - } - - opts := makeListenerOpts{ - name: uid.EnvoyID(), - //accessLogs: cfgSnap.Proxy.AccessLogs, - direction: pbproxystate.Direction_DIRECTION_OUTBOUND, - logger: s.Logger, - upstream: upstreamCfg, - } - upstreamListener := makeListener(opts) - upstreamListener.BalanceConnections = balanceConnections[cfg.BalanceOutboundConnections] - - upstreamListener.Routers = append(upstreamListener.Routers, router) - listeners = append(listeners, upstreamListener) - - // Avoid creating filter chains below for upstreams that have dedicated listeners - continue - } - - // The rest of this loop is used exclusively for transparent proxies. - // Below we create a filter chain per upstream, rather than a listener per upstream - // as we do for explicit upstreams above. - - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: uid.EnvoyID(), - clusterName: clusterName, - filterName: filterName, - protocol: cfg.Protocol, - useRDS: useRDS, - //tracing: tracing, - }) - if err != nil { - return err - } - - endpoints := cfgSnap.ConnectProxy.WatchedUpstreamEndpoints[uid][chain.ID()] - uniqueAddrs := make(map[string]struct{}) - - if chain.Partition == cfgSnap.ProxyID.PartitionOrDefault() { - for _, ip := range chain.AutoVirtualIPs { - uniqueAddrs[ip] = struct{}{} - } - for _, ip := range chain.ManualVirtualIPs { - uniqueAddrs[ip] = struct{}{} - } - } - - // Match on the virtual IP for the upstream service (identified by the chain's ID). - // We do not match on all endpoints here since it would lead to load balancing across - // all instances when any instance address is dialed. - for _, e := range endpoints { - if e.Service.Kind == structs.ServiceKind(structs.TerminatingGateway) { - key := structs.ServiceGatewayVirtualIPTag(chain.CompoundServiceName()) - - if vip := e.Service.TaggedAddresses[key]; vip.Address != "" { - uniqueAddrs[vip.Address] = struct{}{} - } - - continue - } - if vip := e.Service.TaggedAddresses[structs.TaggedAddressVirtualIP]; vip.Address != "" { - uniqueAddrs[vip.Address] = struct{}{} - } - - // The virtualIPTag is used by consul-k8s to store the ClusterIP for a service. - // We only match on this virtual IP if the upstream is in the proxy's partition. - // This is because the IP is not guaranteed to be unique across k8s clusters. - if acl.EqualPartitions(e.Node.PartitionOrDefault(), cfgSnap.ProxyID.PartitionOrDefault()) { - if vip := e.Service.TaggedAddresses[naming.VirtualIPTag]; vip.Address != "" { - uniqueAddrs[vip.Address] = struct{}{} - } - } - } - if len(uniqueAddrs) > 2 { - s.Logger.Debug("detected multiple virtual IPs for an upstream, all will be used to match traffic", - "upstream", uid, "ip_count", len(uniqueAddrs)) - } - - // For every potential address we collected, create the appropriate address prefix to match on. - // In this case we are matching on exact addresses, so the prefix is the address itself, - // and the prefix length is based on whether it's IPv4 or IPv6. - upstreamRouter.Match = makeRouterMatchFromAddrs(uniqueAddrs) - - // Only attach the filter chain if there are addresses to match on - if upstreamRouter.Match != nil && len(upstreamRouter.Match.PrefixRanges) > 0 { - outboundListener.Routers = append(outboundListener.Routers, upstreamRouter) - } - } - requiresTLSInspector := false - requiresHTTPInspector := false - - configuredPorts := make(map[int]interface{}) - err = cfgSnap.ConnectProxy.DestinationsUpstream.ForEachKeyE(func(uid proxycfg.UpstreamID) error { - svcConfig, ok := cfgSnap.ConnectProxy.DestinationsUpstream.Get(uid) - if !ok || svcConfig == nil { - return nil - } - - if structs.IsProtocolHTTPLike(svcConfig.Protocol) { - if _, ok := configuredPorts[svcConfig.Destination.Port]; ok { - return nil - } - configuredPorts[svcConfig.Destination.Port] = struct{}{} - const name = "~http" // name used for the shared route name - routeName := clusterNameForDestination(cfgSnap, name, fmt.Sprintf("%d", svcConfig.Destination.Port), svcConfig.NamespaceOrDefault(), svcConfig.PartitionOrDefault()) - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: routeName, - filterName: routeName, - protocol: svcConfig.Protocol, - useRDS: true, - //tracing: tracing, - }) - if err != nil { - return err - } - upstreamRouter.Match = makeRouterMatchFromAddressWithPort("", svcConfig.Destination.Port) - outboundListener.Routers = append(outboundListener.Routers, upstreamRouter) - requiresHTTPInspector = true - } else { - for _, address := range svcConfig.Destination.Addresses { - clusterName := clusterNameForDestination(cfgSnap, uid.Name, address, uid.NamespaceOrDefault(), uid.PartitionOrDefault()) - - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: uid.EnvoyID(), - clusterName: clusterName, - filterName: clusterName, - protocol: svcConfig.Protocol, - //tracing: tracing, - }) - if err != nil { - return err - } - - upstreamRouter.Match = makeRouterMatchFromAddressWithPort(address, svcConfig.Destination.Port) - outboundListener.Routers = append(outboundListener.Routers, upstreamRouter) - - requiresTLSInspector = len(upstreamRouter.Match.ServerNames) != 0 || requiresTLSInspector - } - } - return nil - }) - if err != nil { - return err - } - - if requiresTLSInspector { - outboundListener.Capabilities = append(outboundListener.Capabilities, pbproxystate.Capability_CAPABILITY_L4_TLS_INSPECTION) - } - - if requiresHTTPInspector { - outboundListener.Capabilities = append(outboundListener.Capabilities, pbproxystate.Capability_CAPABILITY_L7_PROTOCOL_INSPECTION) - } - - // Looping over explicit and implicit upstreams is only needed for cross-peer - // because they do not have discovery chains. - for _, uid := range cfgSnap.ConnectProxy.PeeredUpstreamIDs() { - upstreamCfg, skip := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta) - if skip { - // Not associated with a known explicit or implicit upstream so it is skipped. - continue - } - - peerMeta, found := cfgSnap.ConnectProxy.UpstreamPeerMeta(uid) - if !found { - s.Logger.Warn("failed to fetch upstream peering metadata for listener", "uid", uid) - } - cfg := s.getAndModifyUpstreamConfigForPeeredListener(uid, upstreamCfg, peerMeta) - - // If escape hatch is present, create a listener from it and move on to the next - if cfg.EnvoyListenerJSON != "" { - upstreamListener := &pbproxystate.Listener{ - EscapeHatchListener: cfg.EnvoyListenerJSON, - } - listeners = append(listeners, upstreamListener) - continue - } - - tbs, ok := cfgSnap.ConnectProxy.UpstreamPeerTrustBundles.Get(uid.Peer) - if !ok { - // this should never happen since we loop through upstreams with - // set trust bundles - return fmt.Errorf("trust bundle not ready for peer %s", uid.Peer) - } - - clusterName := generatePeeredClusterName(uid, tbs) - - // Generate the upstream listeners for when they are explicitly set with a local bind port or socket path - if upstreamCfg != nil && upstreamCfg.HasLocalPortOrSocket() { - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - clusterName: clusterName, - filterName: fmt.Sprintf("%s.%s.%s", - upstreamCfg.DestinationName, - upstreamCfg.DestinationNamespace, - upstreamCfg.DestinationPeer), - routeName: uid.EnvoyID(), - protocol: cfg.Protocol, - useRDS: false, - statPrefix: "upstream_peered.", - }) - if err != nil { - return err - } - - opts := makeListenerOpts{ - name: uid.EnvoyID(), - //accessLogs: cfgSnap.Proxy.AccessLogs, - direction: pbproxystate.Direction_DIRECTION_OUTBOUND, - logger: s.Logger, - upstream: upstreamCfg, - } - upstreamListener := makeListener(opts) - upstreamListener.BalanceConnections = balanceConnections[cfg.BalanceOutboundConnections] - - upstreamListener.Routers = []*pbproxystate.Router{ - upstreamRouter, - } - listeners = append(listeners, upstreamListener) - - // Avoid creating filter chains below for upstreams that have dedicated listeners - continue - } - - // The rest of this loop is used exclusively for transparent proxies. - // Below we create a filter chain per upstream, rather than a listener per upstream - // as we do for explicit upstreams above. - - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: uid.EnvoyID(), - clusterName: clusterName, - filterName: fmt.Sprintf("%s.%s.%s", - uid.Name, - uid.NamespaceOrDefault(), - uid.Peer), - protocol: cfg.Protocol, - useRDS: false, - statPrefix: "upstream_peered.", - //tracing: tracing, - }) - if err != nil { - return err - } - - endpoints, _ := cfgSnap.ConnectProxy.PeerUpstreamEndpoints.Get(uid) - uniqueAddrs := make(map[string]struct{}) - - // Match on the virtual IP for the upstream service (identified by the chain's ID). - // We do not match on all endpoints here since it would lead to load balancing across - // all instances when any instance address is dialed. - for _, e := range endpoints { - if vip := e.Service.TaggedAddresses[structs.TaggedAddressVirtualIP]; vip.Address != "" { - uniqueAddrs[vip.Address] = struct{}{} - } - - // The virtualIPTag is used by consul-k8s to store the ClusterIP for a service. - // For services imported from a peer,the partition will be equal in all cases. - if acl.EqualPartitions(e.Node.PartitionOrDefault(), cfgSnap.ProxyID.PartitionOrDefault()) { - if vip := e.Service.TaggedAddresses[naming.VirtualIPTag]; vip.Address != "" { - uniqueAddrs[vip.Address] = struct{}{} - } - } - } - if len(uniqueAddrs) > 2 { - s.Logger.Debug("detected multiple virtual IPs for an upstream, all will be used to match traffic", - "upstream", uid, "ip_count", len(uniqueAddrs)) - } - - // For every potential address we collected, create the appropriate address prefix to match on. - // In this case we are matching on exact addresses, so the prefix is the address itself, - // and the prefix length is based on whether it's IPv4 or IPv6. - upstreamRouter.Match = makeRouterMatchFromAddrs(uniqueAddrs) - - // Only attach the filter chain if there are addresses to match on - if upstreamRouter.Match != nil && len(upstreamRouter.Match.PrefixRanges) > 0 { - outboundListener.Routers = append(outboundListener.Routers, upstreamRouter) - } - - } - - if outboundListener != nil { - // Add a passthrough for every mesh endpoint that can be dialed directly, - // as opposed to via a virtual IP. - var passthroughRouters []*pbproxystate.Router - - for _, targets := range cfgSnap.ConnectProxy.PassthroughUpstreams { - for tid, addrs := range targets { - uid := proxycfg.NewUpstreamIDFromTargetID(tid) - - sni := connect.ServiceSNI( - uid.Name, "", uid.NamespaceOrDefault(), uid.PartitionOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain) - - routerName := fmt.Sprintf("%s.%s.%s.%s", uid.Name, uid.NamespaceOrDefault(), uid.PartitionOrDefault(), cfgSnap.Datacenter) - - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - clusterName: "passthrough~" + sni, - filterName: routerName, - protocol: "tcp", - }) - if err != nil { - return err - } - upstreamRouter.Match = makeRouterMatchFromAddrs(addrs) - - passthroughRouters = append(passthroughRouters, upstreamRouter) - } - } - - outboundListener.Routers = append(outboundListener.Routers, passthroughRouters...) - - // Add a catch-all filter chain that acts as a TCP proxy to destinations outside the mesh - if meshConf := cfgSnap.MeshConfig(); meshConf == nil || - !meshConf.TransparentProxy.MeshDestinationsOnly { - - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - clusterName: naming.OriginalDestinationClusterName, - filterName: naming.OriginalDestinationClusterName, - protocol: "tcp", - }) - if err != nil { - return err - } - outboundListener.DefaultRouter = upstreamRouter - } - - // Only add the outbound listener if configured. - if len(outboundListener.Routers) > 0 || outboundListener.DefaultRouter != nil { - listeners = append(listeners, outboundListener) - - } - } - - // Looping over explicit upstreams is only needed for prepared queries because they do not have discovery chains - for uid, u := range cfgSnap.ConnectProxy.UpstreamConfig { - if u.DestinationType != structs.UpstreamDestTypePreparedQuery { - continue - } - - cfg, err := structs.ParseUpstreamConfig(u.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse", "upstream", uid, "error", err) - } - - // If escape hatch is present, create a listener from it and move on to the next - if cfg.EnvoyListenerJSON != "" { - upstreamListener := &pbproxystate.Listener{ - EscapeHatchListener: cfg.EnvoyListenerJSON, - } - listeners = append(listeners, upstreamListener) - continue - } - - opts := makeListenerOpts{ - name: uid.EnvoyID(), - //accessLogs: cfgSnap.Proxy.AccessLogs, - direction: pbproxystate.Direction_DIRECTION_OUTBOUND, - logger: s.Logger, - upstream: u, - } - upstreamListener := makeListener(opts) - upstreamListener.BalanceConnections = balanceConnections[cfg.BalanceOutboundConnections] - - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - // TODO (SNI partition) add partition for upstream SNI - //accessLogs: &cfgSnap.Proxy.AccessLogs, - clusterName: connect.UpstreamSNI(u, "", cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain), - filterName: uid.EnvoyID(), - routeName: uid.EnvoyID(), - protocol: cfg.Protocol, - //tracing: tracing, - }) - if err != nil { - return err - } - upstreamListener.Routers = []*pbproxystate.Router{ - upstreamRouter, - } - listeners = append(listeners, upstreamListener) - } - - cfgSnap.Proxy.Expose.Finalize() - paths := cfgSnap.Proxy.Expose.Paths - - // Add service health checks to the list of paths to create listeners for if needed - if cfgSnap.Proxy.Expose.Checks { - psid := structs.NewServiceID(cfgSnap.Proxy.DestinationServiceID, &cfgSnap.ProxyID.EnterpriseMeta) - for _, check := range cfgSnap.ConnectProxy.WatchedServiceChecks[psid] { - p, err := parseCheckPath(check) - if err != nil { - s.Logger.Warn("failed to create listener for", "check", check.CheckID, "error", err) - continue - } - paths = append(paths, p) - } - } - - // Configure additional listener for exposed check paths - for _, path := range paths { - clusterName := xdscommon.LocalAppClusterName - if path.LocalPathPort != cfgSnap.Proxy.LocalServicePort { - clusterName = makeExposeClusterName(path.LocalPathPort) - } - - l, err := s.makeExposedCheckListener(cfgSnap, clusterName, path) - if err != nil { - return err - } - listeners = append(listeners, l) - } - - // Set listeners on the proxy state. - s.proxyState.Listeners = listeners - - return nil -} - -func makeRouterMatchFromAddrs(addrs map[string]struct{}) *pbproxystate.Match { - ranges := make([]*pbproxystate.CidrRange, 0) - - for addr := range addrs { - ip := net.ParseIP(addr) - if ip == nil { - continue - } - - pfxLen := uint32(32) - if ip.To4() == nil { - pfxLen = 128 - } - ranges = append(ranges, &pbproxystate.CidrRange{ - AddressPrefix: addr, - PrefixLen: &wrapperspb.UInt32Value{Value: pfxLen}, - }) - } - - return &pbproxystate.Match{ - PrefixRanges: ranges, - } -} - -func makeRouterMatchFromAddressWithPort(address string, port int) *pbproxystate.Match { - ranges := make([]*pbproxystate.CidrRange, 0) - - ip := net.ParseIP(address) - if ip == nil { - if address != "" { - return &pbproxystate.Match{ - ServerNames: []string{address}, - DestinationPort: &wrapperspb.UInt32Value{Value: uint32(port)}, - } - } - return &pbproxystate.Match{ - DestinationPort: &wrapperspb.UInt32Value{Value: uint32(port)}, - } - } - - pfxLen := uint32(32) - if ip.To4() == nil { - pfxLen = 128 - } - ranges = append(ranges, &pbproxystate.CidrRange{ - AddressPrefix: address, - PrefixLen: &wrapperspb.UInt32Value{Value: pfxLen}, - }) - - return &pbproxystate.Match{ - PrefixRanges: ranges, - DestinationPort: &wrapperspb.UInt32Value{Value: uint32(port)}, - } -} - -func parseCheckPath(check structs.CheckType) (structs.ExposePath, error) { - var path structs.ExposePath - - if check.HTTP != "" { - path.Protocol = "http" - - // Get path and local port from original HTTP target - u, err := url.Parse(check.HTTP) - if err != nil { - return path, fmt.Errorf("failed to parse url '%s': %v", check.HTTP, err) - } - path.Path = u.Path - - _, portStr, err := net.SplitHostPort(u.Host) - if err != nil { - return path, fmt.Errorf("failed to parse port from '%s': %v", check.HTTP, err) - } - path.LocalPathPort, err = strconv.Atoi(portStr) - if err != nil { - return path, fmt.Errorf("failed to parse port from '%s': %v", check.HTTP, err) - } - - // Get listener port from proxied HTTP target - u, err = url.Parse(check.ProxyHTTP) - if err != nil { - return path, fmt.Errorf("failed to parse url '%s': %v", check.ProxyHTTP, err) - } - - _, portStr, err = net.SplitHostPort(u.Host) - if err != nil { - return path, fmt.Errorf("failed to parse port from '%s': %v", check.ProxyHTTP, err) - } - path.ListenerPort, err = strconv.Atoi(portStr) - if err != nil { - return path, fmt.Errorf("failed to parse port from '%s': %v", check.ProxyHTTP, err) - } - } - - if check.GRPC != "" { - path.Path = "/grpc.health.v1.Health/Check" - path.Protocol = "http2" - - // Get local port from original GRPC target of the form: host/service - proxyServerAndService := strings.SplitN(check.GRPC, "/", 2) - _, portStr, err := net.SplitHostPort(proxyServerAndService[0]) - if err != nil { - return path, fmt.Errorf("failed to split host/port from '%s': %v", check.GRPC, err) - } - path.LocalPathPort, err = strconv.Atoi(portStr) - if err != nil { - return path, fmt.Errorf("failed to parse port from '%s': %v", check.GRPC, err) - } - - // Get listener port from proxied GRPC target of the form: host/service - proxyServerAndService = strings.SplitN(check.ProxyGRPC, "/", 2) - _, portStr, err = net.SplitHostPort(proxyServerAndService[0]) - if err != nil { - return path, fmt.Errorf("failed to split host/port from '%s': %v", check.ProxyGRPC, err) - } - path.ListenerPort, err = strconv.Atoi(portStr) - if err != nil { - return path, fmt.Errorf("failed to parse port from '%s': %v", check.ProxyGRPC, err) - } - } - - path.ParsedFromCheck = true - - return path, nil -} - -// TODO(proxystate): Gateway support will be added in the future. -// Functions to add from agent/xds/listeners.go: -// func listenersFromSnapshotGateway - -// makeListener returns a listener with name and bind details set. Routers and destinations -// must be added before it's useful. -// -// Note on names: Envoy listeners attempt graceful transitions of connections -// when their config changes but that means they can't have their bind address -// or port changed in a running instance. Since our users might choose to change -// a bind address or port for the public or upstream listeners, we need to -// encode those into the unique name for the listener such that if the user -// changes them, we actually create a whole new listener on the new address and -// port. Envoy should take care of closing the old one once it sees it's no -// longer in the config. -type makeListenerOpts struct { - addr string - //accessLogs structs.AccessLogsConfig - logger hclog.Logger - mode string - name string - path string - port int - direction pbproxystate.Direction - upstream *structs.Upstream -} - -func makeListener(opts makeListenerOpts) *pbproxystate.Listener { - if opts.upstream != nil && opts.upstream.LocalBindPort == 0 && opts.upstream.LocalBindSocketPath != "" { - opts.path = opts.upstream.LocalBindSocketPath - opts.mode = opts.upstream.LocalBindSocketMode - return makePipeListener(opts) - } - if opts.upstream != nil { - opts.port = opts.upstream.LocalBindPort - opts.addr = opts.upstream.LocalBindAddress - return makeListenerWithDefault(opts) - } - - return makeListenerWithDefault(opts) -} - -func makeListenerWithDefault(opts makeListenerOpts) *pbproxystate.Listener { - if opts.addr == "" { - opts.addr = "127.0.0.1" - } - // TODO(proxystate): Access logs will be added in the future. It will be added to top level IR, and used by xds code generation. - //accessLog, err := accesslogs.MakeAccessLogs(&opts.accessLogs, true) - //if err != nil && opts.logger != nil { - // // Since access logging is non-essential for routing, warn and move on - // opts.logger.Warn("error generating access log xds", err) - //} - return &pbproxystate.Listener{ - Name: fmt.Sprintf("%s:%s:%d", opts.name, opts.addr, opts.port), - //AccessLog: accessLog, - BindAddress: &pbproxystate.Listener_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: opts.addr, - Port: uint32(opts.port), - }, - }, - Direction: opts.direction, - } -} - -func makePipeListener(opts makeListenerOpts) *pbproxystate.Listener { - // TODO(proxystate): Access logs will be added in the future. It will be added to top level IR, and used by xds code generation. - //accessLog, err := accesslogs.MakeAccessLogs(&opts.accessLogs, true) - //if err != nil && opts.logger != nil { - // // Since access logging is non-essential for routing, warn and move on - // opts.logger.Warn("error generating access log xds", err) - //} - return &pbproxystate.Listener{ - Name: fmt.Sprintf("%s:%s", opts.name, opts.path), - //AccessLog: accessLog, - BindAddress: &pbproxystate.Listener_UnixSocket{ - UnixSocket: &pbproxystate.UnixSocketAddress{Path: opts.path, Mode: opts.mode}, - }, - Direction: opts.direction, - } -} - -// TODO(proxystate): Escape hatches will be added in the future. -// Functions to add from agent/xds/listeners.go: -// func makeListenerFromUserConfig - -// TODO(proxystate): Intentions will be added in the future -// Functions to add from agent/xds/listeners.go: -// func injectConnectFilters - -// TODO(proxystate): httpConnectionManager constants will need to be added when used for listeners L7 in the future. -// Constants to add from agent/xds/listeners.go: -// const httpConnectionManagerOldName -// const httpConnectionManagerNewName - -// TODO(proxystate): Extracting RDS resource names will be used when wiring up xds v2 server in the future. -// Functions to add from agent/xds/listeners.go: -// func extractRdsResourceNames - -// TODO(proxystate): Intentions will be added in the future. -// Functions to add from agent/xds/listeners.go: -// func injectHTTPFilterOnFilterChains - -// NOTE: This method MUST only be used for connect proxy public listeners, -// since TLS validation will be done against root certs for all peers -// that might dial this proxy. -func (s *Converter) injectConnectTLSForPublicListener(cfgSnap *proxycfg.ConfigSnapshot, listener *pbproxystate.Listener) error { - transportSocket, err := s.createInboundMeshMTLS(cfgSnap) - if err != nil { - return err - } - - for idx := range listener.Routers { - listener.Routers[idx].InboundTls = transportSocket - } - return nil -} - -func getAlpnProtocols(protocol string) []string { - var alpnProtocols []string - - switch protocol { - case "grpc", "http2": - alpnProtocols = append(alpnProtocols, "h2", "http/1.1") - case "http": - alpnProtocols = append(alpnProtocols, "http/1.1") - } - - return alpnProtocols -} - -func (s *Converter) createInboundMeshMTLS(cfgSnap *proxycfg.ConfigSnapshot) (*pbproxystate.TransportSocket, error) { - switch cfgSnap.Kind { - case structs.ServiceKindConnectProxy: - case structs.ServiceKindMeshGateway: - default: - return nil, fmt.Errorf("cannot inject peering trust bundles for kind %q", cfgSnap.Kind) - } - - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } - - // Add all trust bundle peer names, including local. - trustBundlePeerNames := []string{"local"} - for _, tb := range cfgSnap.PeeringTrustBundles() { - trustBundlePeerNames = append(trustBundlePeerNames, tb.PeerName) - } - // Arbitrary UUID to reference the identity by. - uuid, err := uuid.GenerateUUID() - if err != nil { - return nil, err - } - // Create the transport socket - ts := &pbproxystate.TransportSocket{} - ts.ConnectionTls = &pbproxystate.TransportSocket_InboundMesh{ - InboundMesh: &pbproxystate.InboundMeshMTLS{ - IdentityKey: uuid, - ValidationContext: &pbproxystate.MeshInboundValidationContext{ - TrustBundlePeerNameKeys: trustBundlePeerNames, - }, - }, - } - s.proxyState.LeafCertificates[uuid] = &pbproxystate.LeafCertificate{ - Cert: cfgSnap.Leaf().CertPEM, - Key: cfgSnap.Leaf().PrivateKeyPEM, - } - ts.TlsParameters = makeTLSParametersFromProxyTLSConfig(cfgSnap.MeshConfigTLSIncoming()) - ts.AlpnProtocols = getAlpnProtocols(cfg.Protocol) - - return ts, nil -} - -func (s *Converter) makeInboundListener(cfgSnap *proxycfg.ConfigSnapshot, name string) (*pbproxystate.Listener, error) { - l := &pbproxystate.Listener{} - l.Routers = make([]*pbproxystate.Router, 0) - var err error - - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } - - // This controls if we do L4 or L7 intention checks. - useHTTPFilter := structs.IsProtocolHTTPLike(cfg.Protocol) - - // TODO(proxystate): Escape hatches will be added in the future. This one is a top level escape hatch. - // Generate and return custom public listener from config if one was provided. - //if cfg.PublicListenerJSON != "" { - // l, err = makeListenerFromUserConfig(cfg.PublicListenerJSON) - // if err != nil { - // return nil, err - // } - // - // // For HTTP-like services attach an RBAC http filter and do a best-effort insert - // if useHTTPFilter { - // httpAuthzFilter, err := makeRBACHTTPFilter( - // cfgSnap.ConnectProxy.Intentions, - // cfgSnap.IntentionDefaultAllow, - // rbacLocalInfo{ - // trustDomain: cfgSnap.Roots.TrustDomain, - // datacenter: cfgSnap.Datacenter, - // partition: cfgSnap.ProxyID.PartitionOrDefault(), - // }, - // cfgSnap.ConnectProxy.InboundPeerTrustBundles, - // ) - // if err != nil { - // return nil, err - // } - // - // // Try our best to inject the HTTP RBAC filter. - // if err := injectHTTPFilterOnFilterChains(l, httpAuthzFilter); err != nil { - // s.Logger.Warn( - // "could not inject the HTTP RBAC filter to enforce intentions on user-provided "+ - // "'envoy_public_listener_json' config; falling back on the RBAC network filter instead", - // "proxy", cfgSnap.ProxyID, - // "error", err, - // ) - // - // // If we get an error inject the RBAC network filter instead. - // useHTTPFilter = false - // } - // } - // - // err := s.finalizePublicListenerFromConfig(l, cfgSnap, useHTTPFilter) - // if err != nil { - // return nil, fmt.Errorf("failed to attach Consul filters and TLS context to custom public listener: %v", err) - // } - // return l, nil - //} - - // No JSON user config, use default listener address - // Default to listening on all addresses, but override with bind address if one is set. - addr := cfgSnap.Address - if addr == "" { - addr = "0.0.0.0" - } - if cfg.BindAddress != "" { - addr = cfg.BindAddress - } - - // Override with bind port if one is set, otherwise default to - // proxy service's address - port := cfgSnap.Port - if cfg.BindPort != 0 { - port = cfg.BindPort - } - - opts := makeListenerOpts{ - name: name, - //accessLogs: cfgSnap.Proxy.AccessLogs, - addr: addr, - port: port, - direction: pbproxystate.Direction_DIRECTION_INBOUND, - logger: s.Logger, - } - l = makeListener(opts) - l.BalanceConnections = balanceConnections[cfg.BalanceInboundConnections] - - // TODO(proxystate): Escape hatches will be added in the future. This one is a top level escape hatch. - //var tracing *envoy_http_v3.HttpConnectionManager_Tracing - //if cfg.ListenerTracingJSON != "" { - // if tracing, err = makeTracingFromUserConfig(cfg.ListenerTracingJSON); err != nil { - // s.Logger.Warn("failed to parse ListenerTracingJSON config", "error", err) - // } - //} - - // make local app cluster router - localAppRouter := &pbproxystate.Router{} - - destOpts := destinationOpts{ - protocol: cfg.Protocol, - filterName: name, - routeName: name, - cluster: xdscommon.LocalAppClusterName, - requestTimeoutMs: cfg.LocalRequestTimeoutMs, - idleTimeoutMs: cfg.LocalIdleTimeoutMs, - //tracing: tracing, - //accessLogs: &cfgSnap.Proxy.AccessLogs, - logger: s.Logger, - } - - err = s.addRouterDestination(destOpts, localAppRouter) - if err != nil { - return nil, err - } - - if useHTTPFilter { - l7Dest := localAppRouter.GetL7() - if l7Dest == nil { - return nil, fmt.Errorf("l7 destination on inbound listener should not be empty") - } - l7Dest.AddEmptyIntention = true - - // TODO(proxystate): L7 Intentions and JWT Auth will be added in the future. - //jwtFilter, jwtFilterErr := makeJWTAuthFilter(cfgSnap.JWTProviders, cfgSnap.ConnectProxy.Intentions) - //if jwtFilterErr != nil { - // return nil, jwtFilterErr - //} - //rbacFilter, err := makeRBACHTTPFilter( - // cfgSnap.ConnectProxy.Intentions, - // cfgSnap.IntentionDefaultAllow, - // rbacLocalInfo{ - // trustDomain: cfgSnap.Roots.TrustDomain, - // datacenter: cfgSnap.Datacenter, - // partition: cfgSnap.ProxyID.PartitionOrDefault(), - // }, - // cfgSnap.ConnectProxy.InboundPeerTrustBundles, - //) - //if err != nil { - // return nil, err - //} - // - //filterOpts.httpAuthzFilters = []*envoy_http_v3.HttpFilter{rbacFilter} - // - //if jwtFilter != nil { - // filterOpts.httpAuthzFilters = append(filterOpts.httpAuthzFilters, jwtFilter) - //} - - meshConfig := cfgSnap.MeshConfig() - includeXFCC := meshConfig == nil || meshConfig.HTTP == nil || !meshConfig.HTTP.SanitizeXForwardedClientCert - l7Dest.IncludeXfcc = includeXFCC - l7Dest.Protocol = l7Protocols[cfg.Protocol] - if cfg.MaxInboundConnections > 0 { - l7Dest.MaxInboundConnections = uint64(cfg.MaxInboundConnections) - } - } else { - l4Dest := localAppRouter.GetL4() - if l4Dest == nil { - return nil, fmt.Errorf("l4 destination on inbound listener should not be empty") - } - - if cfg.MaxInboundConnections > 0 { - l4Dest.MaxInboundConnections = uint64(cfg.MaxInboundConnections) - } - - // TODO(proxystate): Intentions will be added to l4 destination in the future. This is currently done in finalizePublicListenerFromConfig. - l4Dest.AddEmptyIntention = true - } - l.Routers = append(l.Routers, localAppRouter) - - err = s.finalizePublicListenerFromConfig(l, cfgSnap) - if err != nil { - return nil, fmt.Errorf("failed to attach Consul filters and TLS context to custom public listener: %v", err) - } - - // When permissive mTLS mode is enabled, include an additional router - // that matches on the `destination_port == `. Traffic sent - // directly to the service port is passed through to the application - // unmodified. - if cfgSnap.Proxy.Mode == structs.ProxyModeTransparent && - cfgSnap.Proxy.MutualTLSMode == structs.MutualTLSModePermissive { - router, err := makePermissiveRouter(cfgSnap, destOpts) - if err != nil { - return nil, fmt.Errorf("unable to add permissive mtls router: %w", err) - } - if router == nil { - s.Logger.Debug("no service port defined for service in permissive mTLS mode; not adding filter chain for non-mTLS traffic") - } else { - l.Routers = append(l.Routers, router) - - // With tproxy, the REDIRECT iptables target rewrites the destination ip/port - // to the proxy ip/port (e.g. 127.0.0.1:20000) for incoming packets. - // We need the original_dst filter to recover the original destination address. - l.Capabilities = append(l.Capabilities, pbproxystate.Capability_CAPABILITY_TRANSPARENT) - } - } - return l, err -} - -func makePermissiveRouter(cfgSnap *proxycfg.ConfigSnapshot, opts destinationOpts) (*pbproxystate.Router, error) { - servicePort := cfgSnap.Proxy.LocalServicePort - if servicePort <= 0 { - // No service port means the service does not accept incoming traffic, so - // the connect proxy does not need to listen for incoming non-mTLS traffic. - return nil, nil - } - - opts.statPrefix += "permissive_" - dest, err := makeL4Destination(opts) - if err != nil { - return nil, err - } - - router := &pbproxystate.Router{ - Match: &pbproxystate.Match{ - DestinationPort: &wrapperspb.UInt32Value{Value: uint32(servicePort)}, - }, - Destination: &pbproxystate.Router_L4{L4: dest}, - } - return router, nil -} - -// finalizePublicListenerFromConfig is used for best-effort injection of L4 intentions and TLS onto listeners. -func (s *Converter) finalizePublicListenerFromConfig(l *pbproxystate.Listener, cfgSnap *proxycfg.ConfigSnapshot) error { - // TODO(proxystate): L4 intentions will be added in the future. - //if !useHTTPFilter { - // // Best-effort injection of L4 intentions - // if err := s.injectConnectFilters(cfgSnap, l); err != nil { - // return nil - // } - //} - - // Always apply TLS certificates - if err := s.injectConnectTLSForPublicListener(cfgSnap, l); err != nil { - return nil - } - - return nil -} - -func (s *Converter) makeExposedCheckListener(cfgSnap *proxycfg.ConfigSnapshot, cluster string, path structs.ExposePath) (*pbproxystate.Listener, error) { - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } - - // No user config, use default listener - addr := cfgSnap.Address - - // Override with bind address if one is set, otherwise default to 0.0.0.0 - if cfg.BindAddress != "" { - addr = cfg.BindAddress - } else if addr == "" { - addr = "0.0.0.0" - } - - // Strip any special characters from path to make a valid and hopefully unique name - r := regexp.MustCompile(`[^a-zA-Z0-9]+`) - strippedPath := r.ReplaceAllString(path.Path, "") - listenerName := fmt.Sprintf("exposed_path_%s", strippedPath) - - listenerOpts := makeListenerOpts{ - name: listenerName, - //accessLogs: cfgSnap.Proxy.AccessLogs, - addr: addr, - port: path.ListenerPort, - direction: pbproxystate.Direction_DIRECTION_INBOUND, - logger: s.Logger, - } - l := makeListener(listenerOpts) - - filterName := fmt.Sprintf("exposed_path_filter_%s_%d", strippedPath, path.ListenerPort) - - destOpts := destinationOpts{ - useRDS: false, - protocol: path.Protocol, - filterName: filterName, - routeName: filterName, - cluster: cluster, - statPrefix: "", - routePath: path.Path, - httpAuthzFilters: nil, - //accessLogs: &cfgSnap.Proxy.AccessLogs, - logger: s.Logger, - // in the exposed check listener we don't set the tracing configuration - } - - router := &pbproxystate.Router{} - err = s.addRouterDestination(destOpts, router) - if err != nil { - return nil, err - } - - // For registered checks restrict traffic sources to localhost and Consul's advertise addr - if path.ParsedFromCheck { - - // For the advertise addr we use a CidrRange that only matches one address - advertise := s.CfgFetcher.AdvertiseAddrLAN() - - // Get prefix length based on whether address is ipv4 (32 bits) or ipv6 (128 bits) - advertiseLen := 32 - ip := net.ParseIP(advertise) - if ip != nil && strings.Contains(advertise, ":") { - advertiseLen = 128 - } - - ranges := make([]*pbproxystate.CidrRange, 0, 3) - ranges = append(ranges, - &pbproxystate.CidrRange{AddressPrefix: "127.0.0.1", PrefixLen: &wrapperspb.UInt32Value{Value: 8}}, - &pbproxystate.CidrRange{AddressPrefix: advertise, PrefixLen: &wrapperspb.UInt32Value{Value: uint32(advertiseLen)}}, - ) - - if ok, err := platform.SupportsIPv6(); err != nil { - return nil, err - } else if ok { - ranges = append(ranges, - &pbproxystate.CidrRange{AddressPrefix: "::1", PrefixLen: &wrapperspb.UInt32Value{Value: 128}}, - ) - } - - router.Match = &pbproxystate.Match{ - SourcePrefixRanges: ranges, - } - } - - l.Routers = []*pbproxystate.Router{router} - - return l, err -} - -// TODO(proxystate): Gateway support will be added in the future. -// Functions and types to convert from agent/xds/listeners.go: -// func makeTerminatingGatewayListener -// type terminatingGatewayFilterChainOpts -// func makeFilterChainTerminatingGateway -// func makeMeshGatewayListener -// func makeMeshGatewayPeerFilterChain - -type routerOpts struct { - //accessLogs *structs.AccessLogsConfig - routeName string - clusterName string - filterName string - protocol string - useRDS bool - statPrefix string - //forwardClientDetails bool - //forwardClientPolicy envoy_http_v3.HttpConnectionManager_ForwardClientCertDetails - //tracing *envoy_http_v3.HttpConnectionManager_Tracing -} - -func (g *Converter) makeUpstreamRouter(opts routerOpts) (*pbproxystate.Router, error) { - if opts.statPrefix == "" { - opts.statPrefix = "upstream." - } - - router := &pbproxystate.Router{} - - err := g.addRouterDestination(destinationOpts{ - useRDS: opts.useRDS, - protocol: opts.protocol, - filterName: opts.filterName, - routeName: opts.routeName, - cluster: opts.clusterName, - statPrefix: opts.statPrefix, - //forwardClientDetails: opts.forwardClientDetails, - //forwardClientPolicy: opts.forwardClientPolicy, - //tracing: opts.tracing, - //accessLogs: opts.accessLogs, - logger: g.Logger, - }, router) - if err != nil { - return nil, err - } - - return router, nil -} - -// simpleChainTarget returns the discovery target for a chain with a single node. -// A chain can have a single target if it is for a TCP service or an HTTP service without -// multiple splits/routes/failovers. -func simpleChainTarget(chain *structs.CompiledDiscoveryChain) (*structs.DiscoveryTarget, error) { - startNode := chain.Nodes[chain.StartNode] - if startNode == nil { - return nil, fmt.Errorf("missing first node in compiled discovery chain for: %s", chain.ServiceName) - } - if startNode.Type != structs.DiscoveryGraphNodeTypeResolver { - return nil, fmt.Errorf("expected discovery chain with single node, found unexpected start node: %s", startNode.Type) - } - targetID := startNode.Resolver.Target - return chain.Targets[targetID], nil -} - -func (s *Converter) getAndModifyUpstreamConfigForListener( - uid proxycfg.UpstreamID, - u *structs.Upstream, - chain *structs.CompiledDiscoveryChain, -) structs.UpstreamConfig { - var ( - cfg structs.UpstreamConfig - err error - ) - - configMap := make(map[string]interface{}) - if u != nil { - configMap = u.Config - } - if chain == nil || chain.Default { - cfg, err = structs.ParseUpstreamConfigNoDefaults(configMap) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse", "upstream", uid, "error", err) - } - } else { - // Use NoDefaults here so that we can set the protocol to the chain - // protocol if necessary - cfg, err = structs.ParseUpstreamConfigNoDefaults(configMap) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse", "upstream", uid, "error", err) - } - - if cfg.EnvoyListenerJSON != "" { - s.Logger.Warn("ignoring escape hatch setting because already configured for", - "discovery chain", chain.ServiceName, "upstream", uid, "config", "envoy_listener_json") - - // Remove from config struct so we don't use it later on - cfg.EnvoyListenerJSON = "" - } - } - protocol := cfg.Protocol - if chain != nil { - if protocol == "" { - protocol = chain.Protocol - } - if protocol == "" { - protocol = "tcp" - } - } else { - protocol = "tcp" - } - - // set back on the config so that we can use it from return value - cfg.Protocol = protocol - - return cfg -} - -func (s *Converter) getAndModifyUpstreamConfigForPeeredListener( - uid proxycfg.UpstreamID, - u *structs.Upstream, - peerMeta structs.PeeringServiceMeta, -) structs.UpstreamConfig { - var ( - cfg structs.UpstreamConfig - err error - ) - - configMap := make(map[string]interface{}) - if u != nil { - configMap = u.Config - } - - cfg, err = structs.ParseUpstreamConfigNoDefaults(configMap) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse", "upstream", uid, "error", err) - } - - // Ignore the configured protocol for peer upstreams, since it is defined by the remote - // cluster, which we cannot control. - protocol := peerMeta.Protocol - if protocol == "" { - protocol = "tcp" - } - - // set back on the config so that we can use it from return value - cfg.Protocol = protocol - - if cfg.ConnectTimeoutMs == 0 { - cfg.ConnectTimeoutMs = 5000 - } - - if cfg.MeshGateway.Mode == "" && u != nil { - cfg.MeshGateway = u.MeshGateway - } - - return cfg -} - -type destinationOpts struct { - // All listener filters - // TODO(proxystate): access logs support will be added later - //accessLogs *structs.AccessLogsConfig - cluster string - filterName string - logger hclog.Logger - protocol string - statPrefix string - - // HTTP listener filter options - forwardClientDetails bool - forwardClientPolicy envoy_http_v3.HttpConnectionManager_ForwardClientCertDetails - httpAuthzFilters []*envoy_http_v3.HttpFilter - idleTimeoutMs *int - requestTimeoutMs *int - routeName string - routePath string - // TODO(proxystate): tracing support will be added later - //tracing *envoy_http_v3.HttpConnectionManager_Tracing - useRDS bool -} - -func (g *Converter) addRouterDestination(opts destinationOpts, router *pbproxystate.Router) error { - switch opts.protocol { - case "grpc", "http2", "http": - dest, err := g.makeL7Destination(opts) - if err != nil { - return err - } - router.Destination = &pbproxystate.Router_L7{ - L7: dest, - } - return nil - case "tcp": - fallthrough - default: - if opts.useRDS { - return fmt.Errorf("RDS is not compatible with the tcp proxy filter") - } else if opts.cluster == "" { - return fmt.Errorf("cluster name is required for a tcp proxy filter") - } - dest, err := makeL4Destination(opts) - if err != nil { - return err - } - router.Destination = &pbproxystate.Router_L4{ - L4: dest, - } - return nil - } -} - -func makeL4Destination(opts destinationOpts) (*pbproxystate.L4Destination, error) { - // TODO(proxystate): implement access logs at top level - //accessLogs, err := accesslogs.MakeAccessLogs(opts.accessLogs, false) - //if err != nil && opts.logger != nil { - // opts.logger.Warn("could not make access log xds for tcp proxy", err) - //} - - l4Dest := &pbproxystate.L4Destination{ - //AccessLog: accessLogs, - Name: opts.cluster, - StatPrefix: makeStatPrefix(opts.statPrefix, opts.filterName), - } - return l4Dest, nil -} - -func makeStatPrefix(prefix, filterName string) string { - // Replace colons here because Envoy does that in the metrics for the actual - // clusters but doesn't in the stat prefix here while dashboards assume they - // will match. - return fmt.Sprintf("%s%s", prefix, strings.Replace(filterName, ":", "_", -1)) -} - -func (g *Converter) makeL7Destination(opts destinationOpts) (*pbproxystate.L7Destination, error) { - dest := &pbproxystate.L7Destination{} - - // TODO(proxystate) access logs will be added to proxystate top level and in xds generation - //accessLogs, err := accesslogs.MakeAccessLogs(opts.accessLogs, false) - //if err != nil && opts.logger != nil { - // opts.logger.Warn("could not make access log xds for http connection manager", err) - //} - - // An L7 Destination's name will be the route name, so during xds generation the route can be looked up. - dest.Name = opts.routeName - dest.StatPrefix = makeStatPrefix(opts.statPrefix, opts.filterName) - - // TODO(proxystate) tracing will be added at the top level proxystate and xds generation - //if opts.tracing != nil { - // cfg.Tracing = opts.tracing - //} - - if opts.useRDS { - if opts.cluster != "" { - return nil, fmt.Errorf("cannot specify cluster name when using RDS") - } - } else { - dest.StaticRoute = true - - if opts.cluster == "" { - return nil, fmt.Errorf("must specify cluster name when not using RDS") - } - - routeRule := &pbproxystate.RouteRule{ - Match: &pbproxystate.RouteMatch{ - PathMatch: &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Prefix{ - Prefix: "/", - }, - }, - // TODO(banks) Envoy supports matching only valid GRPC - // requests which might be nice to add here for gRPC services - // but it's not supported in our current envoy SDK version - // although docs say it was supported by 1.8.0. Going to defer - // that until we've updated the deps. - }, - Destination: &pbproxystate.RouteDestination{ - Destination: &pbproxystate.RouteDestination_Cluster{ - Cluster: &pbproxystate.DestinationCluster{ - Name: opts.cluster, - }, - }, - }, - } - - var timeoutCfg *pbproxystate.TimeoutConfig - r := routeRule.GetDestination() - - if opts.requestTimeoutMs != nil { - if timeoutCfg == nil { - timeoutCfg = &pbproxystate.TimeoutConfig{} - } - timeoutCfg.Timeout = durationpb.New(time.Duration(*opts.requestTimeoutMs) * time.Millisecond) - } - - if opts.idleTimeoutMs != nil { - if timeoutCfg == nil { - timeoutCfg = &pbproxystate.TimeoutConfig{} - } - timeoutCfg.IdleTimeout = durationpb.New(time.Duration(*opts.idleTimeoutMs) * time.Millisecond) - } - r.DestinationConfiguration = &pbproxystate.DestinationConfiguration{ - TimeoutConfig: timeoutCfg, - } - - // If a path is provided, do not match on a catch-all prefix - if opts.routePath != "" { - routeRule.Match.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Exact{ - Exact: opts.routePath, - }, - } - } - - // Create static route object - route := &pbproxystate.Route{ - VirtualHosts: []*pbproxystate.VirtualHost{ - { - Name: opts.filterName, - Domains: []string{"*"}, - RouteRules: []*pbproxystate.RouteRule{ - routeRule, - }, - }, - }, - } - // Save the route to proxy state. - g.proxyState.Routes[opts.routeName] = route - } - - dest.Protocol = l7Protocols[opts.protocol] - - // TODO(proxystate) need to include xfcc policy in future L7 task - //// Note the default leads to setting HttpConnectionManager_SANITIZE - //if opts.forwardClientDetails { - // cfg.ForwardClientCertDetails = opts.forwardClientPolicy - // cfg.SetCurrentClientCertDetails = &envoy_http_v3.HttpConnectionManager_SetCurrentClientCertDetails{ - // Subject: &wrapperspb.BoolValue{Value: true}, - // Cert: true, - // Chain: true, - // Dns: true, - // Uri: true, - // } - //} - - // Like injectConnectFilters for L4, here we ensure that the first filter - // (other than the "envoy.grpc_http1_bridge" filter) in the http filter - // chain of a public listener is the authz filter to prevent unauthorized - // access and that every filter chain uses our TLS certs. - if len(opts.httpAuthzFilters) > 0 { - // TODO(proxystate) support intentions in the future - dest.Intentions = make([]*pbproxystate.L7Intention, 0) - //cfg.HttpFilters = append(opts.httpAuthzFilters, cfg.HttpFilters...) - } - - // TODO(proxystate) add grpc http filters in xds in future L7 task - //if opts.protocol == "grpc" { - // grpcHttp1Bridge, err := makeEnvoyHTTPFilter( - // "envoy.filters.http.grpc_http1_bridge", - // &envoy_grpc_http1_bridge_v3.Config{}, - // ) - // if err != nil { - // return nil, err - // } - // - // // In envoy 1.14.x the default value "stats_for_all_methods=true" was - // // deprecated, and was changed to "false" in 1.18.x. Avoid using the - // // default. TODO: we may want to expose this to users somehow easily. - // grpcStatsFilter, err := makeEnvoyHTTPFilter( - // "envoy.filters.http.grpc_stats", - // &envoy_grpc_stats_v3.FilterConfig{ - // PerMethodStatSpecifier: &envoy_grpc_stats_v3.FilterConfig_StatsForAllMethods{ - // StatsForAllMethods: makeBoolValue(true), - // }, - // }, - // ) - // if err != nil { - // return nil, err - // } - // - // // Add grpc bridge before router and authz, and the stats in front of that. - // cfg.HttpFilters = append([]*envoy_http_v3.HttpFilter{ - // grpcStatsFilter, - // grpcHttp1Bridge, - // }, cfg.HttpFilters...) - //} - - return dest, nil -} - -var tlsVersionsWithConfigurableCipherSuites = map[types.TLSVersion]struct{}{ - // Remove these two if Envoy ever sets TLS 1.3 as default minimum - types.TLSVersionUnspecified: {}, - types.TLSVersionAuto: {}, - - types.TLSv1_0: {}, - types.TLSv1_1: {}, - types.TLSv1_2: {}, -} - -func makeTLSParametersFromProxyTLSConfig(tlsConf *structs.MeshDirectionalTLSConfig) *pbproxystate.TLSParameters { - if tlsConf == nil { - return &pbproxystate.TLSParameters{} - } - - return makeTLSParametersFromTLSConfig(tlsConf.TLSMinVersion, tlsConf.TLSMaxVersion, tlsConf.CipherSuites) -} - -func makeTLSParametersFromTLSConfig( - tlsMinVersion types.TLSVersion, - tlsMaxVersion types.TLSVersion, - cipherSuites []types.TLSCipherSuite, -) *pbproxystate.TLSParameters { - tlsParams := pbproxystate.TLSParameters{} - - if tlsMinVersion != types.TLSVersionUnspecified { - tlsParams.MinVersion = tlsVersions[tlsMinVersion] - } - if tlsMaxVersion != types.TLSVersionUnspecified { - tlsParams.MaxVersion = tlsVersions[tlsMaxVersion] - } - if len(cipherSuites) != 0 { - var suites []pbproxystate.TLSCipherSuite - for _, cs := range cipherSuites { - suites = append(suites, tlsCipherSuites[cs]) - } - tlsParams.CipherSuites = suites - } - - return &tlsParams -} - -var tlsVersions = map[types.TLSVersion]pbproxystate.TLSVersion{ - types.TLSVersionAuto: pbproxystate.TLSVersion_TLS_VERSION_AUTO, - types.TLSv1_0: pbproxystate.TLSVersion_TLS_VERSION_1_0, - types.TLSv1_1: pbproxystate.TLSVersion_TLS_VERSION_1_1, - types.TLSv1_2: pbproxystate.TLSVersion_TLS_VERSION_1_2, - types.TLSv1_3: pbproxystate.TLSVersion_TLS_VERSION_1_3, -} - -var tlsCipherSuites = map[types.TLSCipherSuite]pbproxystate.TLSCipherSuite{ - types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256, - types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305, - types.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256, - types.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305, - types.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA, - types.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA, - types.TLS_RSA_WITH_AES_128_GCM_SHA256: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES128_GCM_SHA256, - types.TLS_RSA_WITH_AES_128_CBC_SHA: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES128_SHA, - types.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384, - types.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384, - types.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA, - types.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA, - types.TLS_RSA_WITH_AES_256_GCM_SHA384: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES256_GCM_SHA384, - types.TLS_RSA_WITH_AES_256_CBC_SHA: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES256_SHA, -} - -var l7Protocols = map[string]pbproxystate.L7Protocol{ - "http": pbproxystate.L7Protocol_L7_PROTOCOL_HTTP, - "http2": pbproxystate.L7Protocol_L7_PROTOCOL_HTTP2, - "grpc": pbproxystate.L7Protocol_L7_PROTOCOL_GRPC, -} - -var balanceConnections = map[string]pbproxystate.BalanceConnections{ - "": pbproxystate.BalanceConnections_BALANCE_CONNECTIONS_DEFAULT, - structs.ConnectionExactBalance: pbproxystate.BalanceConnections_BALANCE_CONNECTIONS_EXACT, -} diff --git a/agent/xds/proxystateconverter/locality_policy.go b/agent/xds/proxystateconverter/locality_policy.go deleted file mode 100644 index c33f428fc2e27..0000000000000 --- a/agent/xds/proxystateconverter/locality_policy.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "fmt" - - "github.com/hashicorp/consul/agent/structs" -) - -func groupedEndpoints(locality *structs.Locality, policy *structs.DiscoveryPrioritizeByLocality, csns structs.CheckServiceNodes) ([]structs.CheckServiceNodes, error) { - switch { - case policy == nil || policy.Mode == "" || policy.Mode == "none": - return []structs.CheckServiceNodes{csns}, nil - case policy.Mode == "failover": - return prioritizeByLocalityFailover(locality, csns), nil - default: - return nil, fmt.Errorf("unexpected priortize-by-locality mode %q", policy.Mode) - } -} diff --git a/agent/xds/proxystateconverter/locality_policy_ce.go b/agent/xds/proxystateconverter/locality_policy_ce.go deleted file mode 100644 index 014ed0f8b9b57..0000000000000 --- a/agent/xds/proxystateconverter/locality_policy_ce.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package proxystateconverter - -import ( - "github.com/hashicorp/consul/agent/structs" -) - -func prioritizeByLocalityFailover(locality *structs.Locality, csns structs.CheckServiceNodes) []structs.CheckServiceNodes { - return nil -} diff --git a/agent/xds/proxystateconverter/routes.go b/agent/xds/proxystateconverter/routes.go deleted file mode 100644 index f9559f7878a89..0000000000000 --- a/agent/xds/proxystateconverter/routes.go +++ /dev/null @@ -1,777 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "errors" - "fmt" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" - "sort" - "strings" - "time" - - "github.com/hashicorp/consul/agent/xds/response" - - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/structs" - "google.golang.org/protobuf/types/known/durationpb" -) - -// routesFromSnapshot returns the xDS API representation of the "routes" in the -// snapshot. -func (s *Converter) routesFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) error { - if cfgSnap == nil { - return errors.New("nil config given") - } - - switch cfgSnap.Kind { - case structs.ServiceKindConnectProxy: - return s.routesForConnectProxy(cfgSnap) - // TODO(proxystate): Ingress Gateways will be added in the future. - //case structs.ServiceKindIngressGateway: - // return s.routesForIngressGateway(cfgSnap) - // TODO(proxystate): API Gateways will be added in the future. - //case structs.ServiceKindAPIGateway: - // return s.routesForAPIGateway(cfgSnap) - // TODO(proxystate): Terminating Gateways will be added in the future. - //case structs.ServiceKindTerminatingGateway: - // return s.routesForTerminatingGateway(cfgSnap) - // TODO(proxystate): Mesh Gateways will be added in the future. - //case structs.ServiceKindMeshGateway: - // return s.routesForMeshGateway(cfgSnap) - default: - return fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind) - } -} - -// routesFromSnapshotConnectProxy returns the xDS API representation of the -// "routes" in the snapshot. -func (s *Converter) routesForConnectProxy(cfgSnap *proxycfg.ConfigSnapshot) error { - for uid, chain := range cfgSnap.ConnectProxy.DiscoveryChain { - if chain.Default { - continue - } - - virtualHost, err := s.makeUpstreamHostForDiscoveryChain(cfgSnap, uid, chain, []string{"*"}, false) - if err != nil { - return err - } - if virtualHost == nil { - continue - } - - route := &pbproxystate.Route{ - VirtualHosts: []*pbproxystate.VirtualHost{virtualHost}, - } - s.proxyState.Routes[uid.EnvoyID()] = route - } - addressesMap := make(map[string]map[string]string) - err := cfgSnap.ConnectProxy.DestinationsUpstream.ForEachKeyE(func(uid proxycfg.UpstreamID) error { - svcConfig, ok := cfgSnap.ConnectProxy.DestinationsUpstream.Get(uid) - if !ok || svcConfig == nil { - return nil - } - if !structs.IsProtocolHTTPLike(svcConfig.Protocol) { - // Routes can only be defined for HTTP services - return nil - } - - for _, address := range svcConfig.Destination.Addresses { - - routeName := clusterNameForDestination(cfgSnap, "~http", fmt.Sprintf("%d", svcConfig.Destination.Port), svcConfig.NamespaceOrDefault(), svcConfig.PartitionOrDefault()) - if _, ok := addressesMap[routeName]; !ok { - addressesMap[routeName] = make(map[string]string) - } - // cluster name is unique per address/port so we should not be doing any override here - clusterName := clusterNameForDestination(cfgSnap, svcConfig.Name, address, svcConfig.NamespaceOrDefault(), svcConfig.PartitionOrDefault()) - addressesMap[routeName][clusterName] = address - } - return nil - }) - - if err != nil { - return err - } - - for routeName, clusters := range addressesMap { - route, err := s.makeRouteForAddresses(clusters) - if err != nil { - return err - } - if route != nil { - s.proxyState.Routes[routeName] = route - } - } - - // TODO(rb): make sure we don't generate an empty result - return nil -} - -func (s *Converter) makeRouteForAddresses(addresses map[string]string) (*pbproxystate.Route, error) { - route, err := makeAddressesRoute(addresses) - if err != nil { - s.Logger.Error("failed to make route", "cluster", "error", err) - return nil, err - } - - return route, nil -} - -// TODO(proxystate): Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func routesForTerminatingGateway - -// TODO(proxystate): Mesh Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func routesForMeshGateway - -func makeAddressesRoute(addresses map[string]string) (*pbproxystate.Route, error) { - route := &pbproxystate.Route{} - for clusterName, address := range addresses { - destination := makeRouteDestinationFromName(clusterName) - virtualHost := &pbproxystate.VirtualHost{ - Name: clusterName, - Domains: []string{address}, - RouteRules: []*pbproxystate.RouteRule{ - { - Match: makeDefaultRouteMatch(), - Destination: destination, - }, - }, - } - route.VirtualHosts = append(route.VirtualHosts, virtualHost) - } - - // sort virtual hosts to have a stable order - sort.SliceStable(route.VirtualHosts, func(i, j int) bool { - return route.VirtualHosts[i].Name > route.VirtualHosts[j].Name - }) - return route, nil -} - -// makeRouteDestinationFromName (fka makeRouteActionFromName) -func makeRouteDestinationFromName(clusterName string) *pbproxystate.RouteDestination { - return &pbproxystate.RouteDestination{ - Destination: &pbproxystate.RouteDestination_Cluster{ - Cluster: &pbproxystate.DestinationCluster{ - Name: clusterName, - }, - }, - } -} - -// TODO(proxystate): Ingress Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func routesForIngressGateway - -// TODO(proxystate): API Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func routesForAPIGateway -// func buildHTTPRouteUpstream - -// TODO(proxystate): Ingress Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func findIngressServiceMatchingUpstream - -// TODO(proxystate): Ingress Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func generateUpstreamIngressDomains - -// TODO(proxystate): Ingress Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func generateUpstreamAPIsDomains - -func (s *Converter) makeUpstreamHostForDiscoveryChain( - cfgSnap *proxycfg.ConfigSnapshot, - uid proxycfg.UpstreamID, - chain *structs.CompiledDiscoveryChain, - serviceDomains []string, - forMeshGateway bool, -) (*pbproxystate.VirtualHost, error) { - var routeRules []*pbproxystate.RouteRule - - startNode := chain.Nodes[chain.StartNode] - if startNode == nil { - return nil, fmt.Errorf("missing first node in compiled discovery chain for: %s", chain.ServiceName) - } - - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - if err != nil && !forMeshGateway { - return nil, err - } - - switch startNode.Type { - case structs.DiscoveryGraphNodeTypeRouter: - routeRules = make([]*pbproxystate.RouteRule, 0, len(startNode.Routes)) - - for _, discoveryRoute := range startNode.Routes { - routeMatch := makeRouteMatchForDiscoveryRoute(discoveryRoute) - - var ( - routeDestination *pbproxystate.RouteDestination - err error - ) - - nextNode := chain.Nodes[discoveryRoute.NextNode] - - var lb *structs.LoadBalancer - if nextNode.LoadBalancer != nil { - lb = nextNode.LoadBalancer - } - - switch nextNode.Type { - case structs.DiscoveryGraphNodeTypeSplitter: - routeDestination, err = s.makeRouteDestinationForSplitter(upstreamsSnapshot, nextNode.Splits, chain, forMeshGateway) - if err != nil { - return nil, err - } - - case structs.DiscoveryGraphNodeTypeResolver: - rd, ok := s.makeRouteDestinationForChainCluster(upstreamsSnapshot, nextNode.Resolver.Target, chain, forMeshGateway) - if !ok { - continue - } - routeDestination = rd - - default: - return nil, fmt.Errorf("unexpected graph node after route %q", nextNode.Type) - } - - routeDestination.DestinationConfiguration = &pbproxystate.DestinationConfiguration{} - if err := injectLBToDestinationConfiguration(lb, routeDestination.DestinationConfiguration); err != nil { - return nil, fmt.Errorf("failed to apply load balancer configuration to route action: %v", err) - } - - // TODO(rb): Better help handle the envoy case where you need (prefix=/foo/,rewrite=/) and (exact=/foo,rewrite=/) to do a full rewrite - - destination := discoveryRoute.Definition.Destination - - routeRule := &pbproxystate.RouteRule{} - - if destination != nil { - configHandle := routeDestination.DestinationConfiguration - if destination.PrefixRewrite != "" { - configHandle.PrefixRewrite = destination.PrefixRewrite - } - - if destination.RequestTimeout > 0 || destination.IdleTimeout > 0 { - configHandle.TimeoutConfig = &pbproxystate.TimeoutConfig{} - } - if destination.RequestTimeout > 0 { - configHandle.TimeoutConfig.Timeout = durationpb.New(destination.RequestTimeout) - } - if destination.IdleTimeout > 0 { - configHandle.TimeoutConfig.IdleTimeout = durationpb.New(destination.IdleTimeout) - } - - if destination.HasRetryFeatures() { - configHandle.RetryPolicy = getRetryPolicyForDestination(destination) - } - - if err := injectHeaderManipToRoute(destination, routeRule); err != nil { - return nil, fmt.Errorf("failed to apply header manipulation configuration to route: %v", err) - } - } - - routeRule.Match = routeMatch - routeRule.Destination = routeDestination - - routeRules = append(routeRules, routeRule) - } - - case structs.DiscoveryGraphNodeTypeSplitter: - routeDestination, err := s.makeRouteDestinationForSplitter(upstreamsSnapshot, startNode.Splits, chain, forMeshGateway) - if err != nil { - return nil, err - } - var lb *structs.LoadBalancer - if startNode.LoadBalancer != nil { - lb = startNode.LoadBalancer - } - routeDestination.DestinationConfiguration = &pbproxystate.DestinationConfiguration{} - if err := injectLBToDestinationConfiguration(lb, routeDestination.DestinationConfiguration); err != nil { - return nil, fmt.Errorf("failed to apply load balancer configuration to route action: %v", err) - } - - defaultRoute := &pbproxystate.RouteRule{ - Match: makeDefaultRouteMatch(), - Destination: routeDestination, - } - - routeRules = []*pbproxystate.RouteRule{defaultRoute} - - case structs.DiscoveryGraphNodeTypeResolver: - routeDestination, ok := s.makeRouteDestinationForChainCluster(upstreamsSnapshot, startNode.Resolver.Target, chain, forMeshGateway) - if !ok { - break - } - var lb *structs.LoadBalancer - if startNode.LoadBalancer != nil { - lb = startNode.LoadBalancer - } - routeDestination.DestinationConfiguration = &pbproxystate.DestinationConfiguration{} - if err := injectLBToDestinationConfiguration(lb, routeDestination.DestinationConfiguration); err != nil { - return nil, fmt.Errorf("failed to apply load balancer configuration to route action: %v", err) - } - - if startNode.Resolver.RequestTimeout > 0 { - to := &pbproxystate.TimeoutConfig{ - Timeout: durationpb.New(startNode.Resolver.RequestTimeout), - } - routeDestination.DestinationConfiguration.TimeoutConfig = to - } - defaultRoute := &pbproxystate.RouteRule{ - Match: makeDefaultRouteMatch(), - Destination: routeDestination, - } - - routeRules = []*pbproxystate.RouteRule{defaultRoute} - - default: - return nil, fmt.Errorf("unknown first node in discovery chain of type: %s", startNode.Type) - } - - host := &pbproxystate.VirtualHost{ - Name: uid.EnvoyID(), - Domains: serviceDomains, - RouteRules: routeRules, - } - - return host, nil -} - -func getRetryPolicyForDestination(destination *structs.ServiceRouteDestination) *pbproxystate.RetryPolicy { - retryPolicy := &pbproxystate.RetryPolicy{} - if destination.NumRetries > 0 { - retryPolicy.NumRetries = response.MakeUint32Value(int(destination.NumRetries)) - } - - // The RetryOn magic values come from: https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/http_filters/router_filter#config-http-filters-router-x-envoy-retry-on - var retryStrings []string - - if len(destination.RetryOn) > 0 { - retryStrings = append(retryStrings, destination.RetryOn...) - } - - if destination.RetryOnConnectFailure { - // connect-failure can be enabled by either adding connect-failure to the RetryOn list or by using the legacy RetryOnConnectFailure option - // Check that it's not already in the RetryOn list, so we don't set it twice - connectFailureExists := false - for _, r := range retryStrings { - if r == "connect-failure" { - connectFailureExists = true - } - } - if !connectFailureExists { - retryStrings = append(retryStrings, "connect-failure") - } - } - - if len(destination.RetryOnStatusCodes) > 0 { - retryStrings = append(retryStrings, "retriable-status-codes") - retryPolicy.RetriableStatusCodes = destination.RetryOnStatusCodes - } - - retryPolicy.RetryOn = strings.Join(retryStrings, ",") - - return retryPolicy -} - -func makeRouteMatchForDiscoveryRoute(discoveryRoute *structs.DiscoveryRoute) *pbproxystate.RouteMatch { - match := discoveryRoute.Definition.Match - if match == nil || match.IsEmpty() { - return makeDefaultRouteMatch() - } - - routeMatch := &pbproxystate.RouteMatch{} - - switch { - case match.HTTP.PathExact != "": - routeMatch.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Exact{ - Exact: match.HTTP.PathExact, - }, - } - case match.HTTP.PathPrefix != "": - routeMatch.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Prefix{ - Prefix: match.HTTP.PathPrefix, - }, - } - case match.HTTP.PathRegex != "": - routeMatch.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Regex{ - Regex: match.HTTP.PathRegex, - }, - } - default: - routeMatch.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Prefix{ - Prefix: "/", - }, - } - } - - if len(match.HTTP.Header) > 0 { - routeMatch.HeaderMatches = make([]*pbproxystate.HeaderMatch, 0, len(match.HTTP.Header)) - for _, hdr := range match.HTTP.Header { - headerMatch := &pbproxystate.HeaderMatch{ - Name: hdr.Name, - } - - switch { - case hdr.Exact != "": - headerMatch.Match = &pbproxystate.HeaderMatch_Exact{ - Exact: hdr.Exact, - } - case hdr.Regex != "": - headerMatch.Match = &pbproxystate.HeaderMatch_Regex{ - Regex: hdr.Regex, - } - case hdr.Prefix != "": - headerMatch.Match = &pbproxystate.HeaderMatch_Prefix{ - Prefix: hdr.Prefix, - } - case hdr.Suffix != "": - headerMatch.Match = &pbproxystate.HeaderMatch_Suffix{ - Suffix: hdr.Suffix, - } - case hdr.Present: - headerMatch.Match = &pbproxystate.HeaderMatch_Present{ - Present: true, - } - default: - continue // skip this impossible situation - } - - if hdr.Invert { - headerMatch.InvertMatch = true - } - - routeMatch.HeaderMatches = append(routeMatch.HeaderMatches, headerMatch) - } - } - - if len(match.HTTP.Methods) > 0 { - routeMatch.MethodMatches = append(routeMatch.MethodMatches, match.HTTP.Methods...) - } - - if len(match.HTTP.QueryParam) > 0 { - routeMatch.QueryParameterMatches = make([]*pbproxystate.QueryParameterMatch, 0, len(match.HTTP.QueryParam)) - for _, qm := range match.HTTP.QueryParam { - - queryMatcher := &pbproxystate.QueryParameterMatch{ - Name: qm.Name, - } - - switch { - case qm.Exact != "": - queryMatcher.Match = &pbproxystate.QueryParameterMatch_Exact{ - Exact: qm.Exact, - } - case qm.Regex != "": - queryMatcher.Match = &pbproxystate.QueryParameterMatch_Regex{ - Regex: qm.Regex, - } - case qm.Present: - queryMatcher.Match = &pbproxystate.QueryParameterMatch_Present{ - Present: true, - } - default: - continue // skip this impossible situation - } - - routeMatch.QueryParameterMatches = append(routeMatch.QueryParameterMatches, queryMatcher) - } - } - - return routeMatch -} - -func makeDefaultRouteMatch() *pbproxystate.RouteMatch { - return &pbproxystate.RouteMatch{ - PathMatch: &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Prefix{ - Prefix: "/", - }, - }, - // TODO(banks) Envoy supports matching only valid GRPC - // requests which might be nice to add here for gRPC services - // but it's not supported in our current envoy SDK version - // although docs say it was supported by 1.8.0. Going to defer - // that until we've updated the deps. - } -} - -func (s *Converter) makeRouteDestinationForChainCluster( - upstreamsSnapshot *proxycfg.ConfigSnapshotUpstreams, - targetID string, - chain *structs.CompiledDiscoveryChain, - forMeshGateway bool, -) (*pbproxystate.RouteDestination, bool) { - clusterName := s.getTargetClusterName(upstreamsSnapshot, chain, targetID, forMeshGateway) - if clusterName == "" { - return nil, false - } - return makeRouteDestinationFromName(clusterName), true -} - -func (s *Converter) makeRouteDestinationForSplitter( - upstreamsSnapshot *proxycfg.ConfigSnapshotUpstreams, - splits []*structs.DiscoverySplit, - chain *structs.CompiledDiscoveryChain, - forMeshGateway bool, -) (*pbproxystate.RouteDestination, error) { - clusters := make([]*pbproxystate.L7WeightedDestinationCluster, 0, len(splits)) - for _, split := range splits { - nextNode := chain.Nodes[split.NextNode] - - if nextNode.Type != structs.DiscoveryGraphNodeTypeResolver { - return nil, fmt.Errorf("unexpected splitter destination node type: %s", nextNode.Type) - } - targetID := nextNode.Resolver.Target - - clusterName := s.getTargetClusterName(upstreamsSnapshot, chain, targetID, forMeshGateway) - if clusterName == "" { - continue - } - - // The smallest representable weight is 1/10000 or .01% but envoy - // deals with integers so scale everything up by 100x. - weight := int(split.Weight * 100) - - clusterWeight := &pbproxystate.L7WeightedDestinationCluster{ - Name: clusterName, - Weight: response.MakeUint32Value(weight), - } - if err := injectHeaderManipToWeightedCluster(split.Definition, clusterWeight); err != nil { - return nil, err - } - - clusters = append(clusters, clusterWeight) - } - - if len(clusters) <= 0 { - return nil, fmt.Errorf("number of clusters in splitter must be > 0; got %d", len(clusters)) - } - - return &pbproxystate.RouteDestination{ - Destination: &pbproxystate.RouteDestination_WeightedClusters{ - WeightedClusters: &pbproxystate.L7WeightedClusterGroup{ - Clusters: clusters, - }, - }, - }, nil -} - -func injectLBToDestinationConfiguration(lb *structs.LoadBalancer, destinationConfig *pbproxystate.DestinationConfiguration) error { - if lb == nil || !lb.IsHashBased() { - return nil - } - - result := make([]*pbproxystate.LoadBalancerHashPolicy, 0, len(lb.HashPolicies)) - for _, policy := range lb.HashPolicies { - if policy.SourceIP { - p := &pbproxystate.LoadBalancerHashPolicy{ - Policy: &pbproxystate.LoadBalancerHashPolicy_ConnectionProperties{ - ConnectionProperties: &pbproxystate.ConnectionPropertiesPolicy{ - SourceIp: true, - Terminal: policy.Terminal, - }, - }, - } - result = append(result, p) - continue - } - - switch policy.Field { - case structs.HashPolicyHeader: - p := &pbproxystate.LoadBalancerHashPolicy{ - Policy: &pbproxystate.LoadBalancerHashPolicy_Header{ - Header: &pbproxystate.HeaderPolicy{ - Name: policy.FieldValue, - Terminal: policy.Terminal, - }, - }, - } - result = append(result, p) - - case structs.HashPolicyCookie: - - cookie := &pbproxystate.CookiePolicy{ - Name: policy.FieldValue, - Terminal: policy.Terminal, - } - if policy.CookieConfig != nil { - cookie.Path = policy.CookieConfig.Path - - if policy.CookieConfig.TTL != 0*time.Second { - cookie.Ttl = durationpb.New(policy.CookieConfig.TTL) - } - - // Envoy will generate a session cookie if the ttl is present and zero. - if policy.CookieConfig.Session { - cookie.Ttl = durationpb.New(0 * time.Second) - } - } - p := &pbproxystate.LoadBalancerHashPolicy{ - Policy: &pbproxystate.LoadBalancerHashPolicy_Cookie{ - Cookie: cookie, - }, - } - result = append(result, p) - - case structs.HashPolicyQueryParam: - p := &pbproxystate.LoadBalancerHashPolicy{ - Policy: &pbproxystate.LoadBalancerHashPolicy_QueryParameter{ - QueryParameter: &pbproxystate.QueryParameterPolicy{ - Name: policy.FieldValue, - Terminal: policy.Terminal, - }, - }, - } - result = append(result, p) - - default: - return fmt.Errorf("unsupported load balancer hash policy field: %v", policy.Field) - } - } - - destinationConfig.HashPolicies = result - return nil -} - -func injectHeaderManipToRoute(dest *structs.ServiceRouteDestination, r *pbproxystate.RouteRule) error { - if !dest.RequestHeaders.IsZero() { - r.HeaderMutations = append( - r.HeaderMutations, - makeRequestHeaderAdd(dest.RequestHeaders.Add, true)..., - ) - r.HeaderMutations = append( - r.HeaderMutations, - makeRequestHeaderAdd(dest.RequestHeaders.Set, false)..., - ) - r.HeaderMutations = append( - r.HeaderMutations, - makeRequestHeaderRemove(dest.RequestHeaders.Remove), - ) - } - if !dest.ResponseHeaders.IsZero() { - r.HeaderMutations = append( - r.HeaderMutations, - makeResponseHeaderAdd(dest.ResponseHeaders.Add, true)..., - ) - r.HeaderMutations = append( - r.HeaderMutations, - makeResponseHeaderAdd(dest.ResponseHeaders.Set, false)..., - ) - r.HeaderMutations = append( - r.HeaderMutations, - makeResponseHeaderRemove(dest.ResponseHeaders.Remove), - ) - } - return nil -} - -func injectHeaderManipToWeightedCluster(split *structs.ServiceSplit, c *pbproxystate.L7WeightedDestinationCluster) error { - if !split.RequestHeaders.IsZero() { - c.HeaderMutations = append( - c.HeaderMutations, - makeRequestHeaderAdd(split.RequestHeaders.Add, true)..., - ) - c.HeaderMutations = append( - c.HeaderMutations, - makeRequestHeaderAdd(split.RequestHeaders.Set, false)..., - ) - c.HeaderMutations = append( - c.HeaderMutations, - makeRequestHeaderRemove(split.RequestHeaders.Remove), - ) - } - if !split.ResponseHeaders.IsZero() { - c.HeaderMutations = append( - c.HeaderMutations, - makeResponseHeaderAdd(split.ResponseHeaders.Add, true)..., - ) - c.HeaderMutations = append( - c.HeaderMutations, - makeResponseHeaderAdd(split.ResponseHeaders.Set, false)..., - ) - c.HeaderMutations = append( - c.HeaderMutations, - makeResponseHeaderRemove(split.ResponseHeaders.Remove), - ) - } - return nil -} - -func makeRequestHeaderAdd(vals map[string]string, add bool) []*pbproxystate.HeaderMutation { - mutations := make([]*pbproxystate.HeaderMutation, 0, len(vals)) - - appendAction := pbproxystate.AppendAction_APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD - if add { - appendAction = pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - } - - for k, v := range vals { - m := &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_RequestHeaderAdd{ - RequestHeaderAdd: &pbproxystate.RequestHeaderAdd{ - Header: &pbproxystate.Header{ - Key: k, - Value: v, - }, - AppendAction: appendAction, - }, - }, - } - mutations = append(mutations, m) - } - return mutations -} - -func makeRequestHeaderRemove(values []string) *pbproxystate.HeaderMutation { - return &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_RequestHeaderRemove{ - RequestHeaderRemove: &pbproxystate.RequestHeaderRemove{ - HeaderKeys: values, - }, - }, - } -} - -func makeResponseHeaderAdd(vals map[string]string, add bool) []*pbproxystate.HeaderMutation { - mutations := make([]*pbproxystate.HeaderMutation, 0, len(vals)) - - appendAction := pbproxystate.AppendAction_APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD - if add { - appendAction = pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - } - - for k, v := range vals { - m := &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_ResponseHeaderAdd{ - ResponseHeaderAdd: &pbproxystate.ResponseHeaderAdd{ - Header: &pbproxystate.Header{ - Key: k, - Value: v, - }, - AppendAction: appendAction, - }, - }, - } - mutations = append(mutations, m) - } - return mutations -} - -func makeResponseHeaderRemove(values []string) *pbproxystate.HeaderMutation { - return &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_ResponseHeaderRemove{ - ResponseHeaderRemove: &pbproxystate.ResponseHeaderRemove{ - HeaderKeys: values, - }, - }, - } -} diff --git a/agent/xds/rbac.go b/agent/xds/rbac.go index 68e91d2945ad4..f38525abb78d9 100644 --- a/agent/xds/rbac.go +++ b/agent/xds/rbac.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -19,15 +19,9 @@ import ( "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/response" "github.com/hashicorp/consul/proto/private/pbpeering" ) -const ( - envoyHTTPRBACFilterKey = "envoy.filters.http.rbac" - envoyNetworkRBACFilterKey = "envoy.filters.network.rbac" -) - func makeRBACNetworkFilter( intentions structs.SimplifiedIntentions, intentionDefaultAllow bool, @@ -43,7 +37,7 @@ func makeRBACNetworkFilter( StatPrefix: "connect_authz", Rules: rules, } - return makeFilter(envoyNetworkRBACFilterKey, cfg) + return makeFilter("envoy.filters.network.rbac", cfg) } func makeRBACHTTPFilter( @@ -61,7 +55,7 @@ func makeRBACHTTPFilter( cfg := &envoy_http_rbac_v3.RBAC{ Rules: rules, } - return makeEnvoyHTTPFilter(envoyHTTPRBACFilterKey, cfg) + return makeEnvoyHTTPFilter("envoy.filters.http.rbac", cfg) } func intentionListToIntermediateRBACForm( @@ -331,7 +325,6 @@ func intentionActionFromBool(v bool) intentionAction { return intentionActionDeny } } - func intentionActionFromString(s structs.IntentionAction) intentionAction { if s == structs.IntentionActionAllow { return intentionActionAllow @@ -815,6 +808,7 @@ func segmentToPermission(segments []*envoy_matcher_v3.MetadataMatcher_PathSegmen // }, // }, func pathToSegments(paths []string, payloadKey string) []*envoy_matcher_v3.MetadataMatcher_PathSegment { + segments := make([]*envoy_matcher_v3.MetadataMatcher_PathSegment, 0, len(paths)) segments = append(segments, makeSegment(payloadKey)) @@ -839,9 +833,6 @@ func optimizePrincipals(orig []*envoy_rbac_v3.Principal) []*envoy_rbac_v3.Princi if !ok { return orig } - // In practice, you can't hit this - // Only JWTs (HTTP-only) generate orPrinciples, but optimizePrinciples is only called - // against the combined list of principles for L4 intentions. orIds = append(orIds, or.OrIds.Ids...) } @@ -993,7 +984,7 @@ func authenticatedPatternPrincipal(pattern string) *envoy_rbac_v3.Principal { Authenticated: &envoy_rbac_v3.Principal_Authenticated{ PrincipalName: &envoy_matcher_v3.StringMatcher{ MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{ - SafeRegex: response.MakeEnvoyRegexMatch(pattern), + SafeRegex: makeEnvoyRegexMatch(pattern), }, }, }, @@ -1025,7 +1016,7 @@ func xfccPrincipal(src rbacService) *envoy_rbac_v3.Principal { HeaderMatchSpecifier: &envoy_route_v3.HeaderMatcher_StringMatch{ StringMatch: &envoy_matcher_v3.StringMatcher{ MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{ - SafeRegex: response.MakeEnvoyRegexMatch(pattern), + SafeRegex: makeEnvoyRegexMatch(pattern), }, }, }, @@ -1034,10 +1025,8 @@ func xfccPrincipal(src rbacService) *envoy_rbac_v3.Principal { } } -const ( - anyPath = `[^/]+` - trustDomain = anyPath + "." + anyPath -) +const anyPath = `[^/]+` +const trustDomain = anyPath + "." + anyPath // downstreamServiceIdentityMatcher needs to match XFCC headers in two cases: // 1. Requests to cluster peered services through a mesh gateway. In this case, the XFCC header looks like the following (I added a new line after each ; for readability) @@ -1232,7 +1221,7 @@ func convertPermission(perm *structs.IntentionPermission) *envoy_rbac_v3.Permiss Rule: &envoy_matcher_v3.PathMatcher_Path{ Path: &envoy_matcher_v3.StringMatcher{ MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{ - SafeRegex: response.MakeEnvoyRegexMatch(perm.HTTP.PathRegex), + SafeRegex: makeEnvoyRegexMatch(perm.HTTP.PathRegex), }, }, }, @@ -1253,7 +1242,7 @@ func convertPermission(perm *structs.IntentionPermission) *envoy_rbac_v3.Permiss } case hdr.Regex != "": eh.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_SafeRegexMatch{ - SafeRegexMatch: response.MakeEnvoyRegexMatch(hdr.Regex), + SafeRegexMatch: makeEnvoyRegexMatch(hdr.Regex), } case hdr.Prefix != "": eh.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_PrefixMatch{ @@ -1288,7 +1277,7 @@ func convertPermission(perm *structs.IntentionPermission) *envoy_rbac_v3.Permiss eh := &envoy_route_v3.HeaderMatcher{ Name: ":method", HeaderMatchSpecifier: &envoy_route_v3.HeaderMatcher_SafeRegexMatch{ - SafeRegexMatch: response.MakeEnvoyRegexMatch(methodHeaderRegex), + SafeRegexMatch: makeEnvoyRegexMatch(methodHeaderRegex), }, } diff --git a/agent/xds/rbac_test.go b/agent/xds/rbac_test.go index 9885052250aa0..6bc36028707a5 100644 --- a/agent/xds/rbac_test.go +++ b/agent/xds/rbac_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds diff --git a/agent/xds/resources.go b/agent/xds/resources.go index fc761040029c2..c7099e5cb50a0 100644 --- a/agent/xds/resources.go +++ b/agent/xds/resources.go @@ -1,12 +1,11 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds import ( "fmt" - "github.com/hashicorp/consul/agent/xds/configfetcher" "github.com/hashicorp/go-hclog" "google.golang.org/protobuf/proto" @@ -19,7 +18,7 @@ import ( // resources for a single client. type ResourceGenerator struct { Logger hclog.Logger - CfgFetcher configfetcher.ConfigFetcher + CfgFetcher ConfigFetcher IncrementalXDS bool ProxyFeatures xdscommon.SupportedProxyFeatures @@ -27,7 +26,7 @@ type ResourceGenerator struct { func NewResourceGenerator( logger hclog.Logger, - cfgFetcher configfetcher.ConfigFetcher, + cfgFetcher ConfigFetcher, incrementalXDS bool, ) *ResourceGenerator { return &ResourceGenerator{ diff --git a/agent/xds/resources_ce_test.go b/agent/xds/resources_ce_test.go index 14d5a35253a40..5da963940ccba 100644 --- a/agent/xds/resources_ce_test.go +++ b/agent/xds/resources_ce_test.go @@ -1,13 +1,11 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent package xds -import "testing" - -func getEnterpriseGoldenTestCases(t *testing.T) []goldenTestCase { +func getEnterpriseGoldenTestCases() []goldenTestCase { return nil } diff --git a/agent/xds/resources_test.go b/agent/xds/resources_test.go index 69a704386b5d5..29743c060bfd4 100644 --- a/agent/xds/resources_test.go +++ b/agent/xds/resources_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -7,27 +7,23 @@ import ( "path/filepath" "sort" "testing" - "time" envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" - "k8s.io/utils/pointer" "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul/discoverychain" "github.com/hashicorp/consul/agent/xds/testcommon" "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/types" testinf "github.com/mitchellh/go-testing-interface" "github.com/stretchr/testify/require" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/response" "github.com/hashicorp/consul/sdk/testutil" ) @@ -121,7 +117,7 @@ func TestAllResourcesFromSnapshot(t *testing.T) { } }) - r, err := response.CreateResponse(typeUrl, "00000001", "00000001", items) + r, err := createResponse(typeUrl, "00000001", "00000001", items) require.NoError(t, err) gotJSON := protoToJSON(t, r) @@ -160,23 +156,13 @@ func TestAllResourcesFromSnapshot(t *testing.T) { }, }, { - name: "transparent-proxy", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTransparentProxy(t) - }, + name: "transparent-proxy", + create: proxycfg.TestConfigSnapshotTransparentProxy, }, { name: "connect-proxy-with-peered-upstreams", create: proxycfg.TestConfigSnapshotPeering, }, - { - name: "connect-proxy-with-peered-upstreams-escape-overrides", - create: proxycfg.TestConfigSnapshotPeeringWithEscapeOverrides, - }, - { - name: "connect-proxy-with-peered-upstreams-http2", - create: proxycfg.TestConfigSnapshotPeeringWithHTTP2, - }, { name: "transparent-proxy-with-peered-upstreams", create: proxycfg.TestConfigSnapshotPeeringTProxy, @@ -193,7 +179,7 @@ func TestAllResourcesFromSnapshot(t *testing.T) { tests = append(tests, getConnectProxyTransparentProxyGoldenTestCases()...) tests = append(tests, getMeshGatewayPeeringGoldenTestCases()...) tests = append(tests, getTrafficControlPeeringGoldenTestCases(false)...) - tests = append(tests, getEnterpriseGoldenTestCases(t)...) + tests = append(tests, getEnterpriseGoldenTestCases()...) tests = append(tests, getAPIGatewayGoldenTestCases(t)...) latestEnvoyVersion := xdscommon.EnvoyVersions[0] @@ -260,11 +246,7 @@ func getMeshGatewayPeeringGoldenTestCases() []goldenTestCase { { name: "mesh-gateway-with-imported-peered-services", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "imported-services", func(ns *structs.NodeService) { - ns.Proxy.Config = map[string]interface{}{ - "envoy_dns_discovery_type": "STRICT_DNS", - } - }, nil) + return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "imported-services", nil, nil) }, }, { @@ -344,54 +326,6 @@ RahYIzNLRBTLrwadLAZkApUpZvB8qDK4knsTWFYujNsylCww2A6ajzIMFNU4GkUK NtyHRuD+KYRmjXtyX1yHNqfGN3vOQmwavHq2R8wHYuBSc6LAHHV9vG+j0VsgMELO qwxn8SmLkSKbf2+MsQVzLCXXN5u+D8Yv+4py+oKP4EQ5aFZuDEx+r/G/31rTthww AAJAMaoXmoYVdgXV+CPuBb2M4XCpuzLu3bcA2PXm5ipSyIgntMKwXV7r ------END CERTIFICATE-----` - // openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -sha256 -days 3650 \ - // -nodes -subj "/C=XX/CN=secondcert.com" -addext "subjectAltName = DNS:secondcert.com" - gatewayTestPrivateKeyTwo = `-----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCiPr2HCbVzbZ1M -IW89rfLLrciPTWWl48DF9CmYHS0C2gSD1W6bxzO7zdA+ced0ajI+YsQ9aBAXRhKl -EHgnhBJ6sGsz1XBQ9+lNDHrg9AjugIiHoscYOeCcxMeXhp97ti+vpVsc2/AvEf2K -GIUuOjcufXuRXkWQ2aB4RGyodkgRF6n8YrLJb7pWIjoCNwDAWtZX4wIVFgGq1ew0 -E/E9EyStMYTb5h1lvCpXYRN9AeSFKUQI/y0xsT3+nZ/gyzx3CrgzuSYRgptbuVwm -5F2Q16sLR/EtCBIhA8npKagx/4U7KOilF31I2locH4Aq5l9VJd/6pTA5F4KCAW/E -ybXz6DojAgMBAAECggEAPcOuuRqsFf4ztIjB5XQ0Cu/kexFW0flLKNDTiNIKkZxX -vaxhyDHkculeDnekSkAnUnKdDFdyULnfXTFQ3JI9yrEgjoIBmQFXsno+ySZ9w/Xw -g9om+wUFigirhva7/geUTcSgU/Myk2jA4XKGONv2p98jTGrcBtGickZyKwukUcTa -M18phLdjejg09d45QV5pEtU5m0HuydvtMNCxL2UeWMxyIVezAH2S48m7IAn7Xs4p -J9bwjboDWQYs+zLPfEZyosiJiKugpEKvApIKsJXf4JqRXHN+vvKKDeXkKrrGR+pg -3e5foPjFrLcDltZMkrfnlm8fa0yLnoxdiyd1pDcJaQKBgQDSnJbM6CDb0b3bUyiz -LpfJSBzEPqABM8mNeVHfEjHcBJ7YBOceBxDNasmAPvFbhoDrlHiEYW2QnDLRXKeF -XVdXjSsUV30SPMeg6yeSd8L+LKXLjrGMNGDcJfnjLavv7Glu1xDnYyFSmeVIhWoo -cOhfaFQ69vnHiU1idrOlz6zhPwKBgQDFNcY0S59f3tht7kgnItg8PSfJqJQrIdLt -x6MC2Nc7Eui7/LTuO2rMG6HRA/8zQa/TfnfG7CsUwLB1NiC2R1TtM9YBYPxhMl1o -JeGTfM+tD0lBwPhYpgnOCppuayRCfAsPYA6NcvXcGZbxOigxliOuvgVBH47EAApA -zJ+8b6nKHQKBgQCZ0GDV/4XX5KNq5Z3o1tNl3jOcIzyKBD9kAkGHz+r4C6vSiioc -pP5hd2b4MX/l3yKSapll3R2+qkT24Fs8LEJYn7Hhpk+inR8SaAs7jhmrtgHT2z/R -7IL85QNOJhHXJGqP16PxyVUR1XE9eKpiJKug2joB4lPjpWQN0DE9nKFe0wKBgEo3 -qpgTva7+1sTIYC8aVfaVrVufLePtnswNzbNMl/OLcjsNJ6pgghi+bW+T6X8IwXr+ -pWUfjDcLLV1vOXBf9/4s++UY8uJBahW/69zto9qlXhR44v25vwbjxqq3d7XtqNvo -cpGZKh3jI4M1N9sxfcxNhvyzO69XtIQefh8UhvmhAoGBAKzSA51l50ocOnWSNAXs -QQoU+dYQjLDMtzc5N68EUf1GSjtgkpa3PYjVo09OMeb7+W9LhwHQDNMqgeeEDCsm -B6NDnI4VyjVae7Hqz48WBERJBFMFWiLxEa1m2UwaV2jAubN8FKgH4KzDzOKtJEUy -Rz9IUct6HXsDSs+Q3/zdFmPo ------END PRIVATE KEY-----` - gatewayTestCertificateTwo = `-----BEGIN CERTIFICATE----- -MIIC7DCCAdSgAwIBAgIJAMHpuSA3ioNPMA0GCSqGSIb3DQEBCwUAMCYxCzAJBgNV -BAYTAlhYMRcwFQYDVQQDDA5zZWNvbmRjZXJ0LmNvbTAeFw0yMzA3MTExNTE1MjBa -Fw0zMzA3MDgxNTE1MjBaMCYxCzAJBgNVBAYTAlhYMRcwFQYDVQQDDA5zZWNvbmRj -ZXJ0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKI+vYcJtXNt -nUwhbz2t8sutyI9NZaXjwMX0KZgdLQLaBIPVbpvHM7vN0D5x53RqMj5ixD1oEBdG -EqUQeCeEEnqwazPVcFD36U0MeuD0CO6AiIeixxg54JzEx5eGn3u2L6+lWxzb8C8R -/YoYhS46Ny59e5FeRZDZoHhEbKh2SBEXqfxisslvulYiOgI3AMBa1lfjAhUWAarV -7DQT8T0TJK0xhNvmHWW8KldhE30B5IUpRAj/LTGxPf6dn+DLPHcKuDO5JhGCm1u5 -XCbkXZDXqwtH8S0IEiEDyekpqDH/hTso6KUXfUjaWhwfgCrmX1Ul3/qlMDkXgoIB -b8TJtfPoOiMCAwEAAaMdMBswGQYDVR0RBBIwEIIOc2Vjb25kY2VydC5jb20wDQYJ -KoZIhvcNAQELBQADggEBAJvP3deuEpJZktAny6/az09GLSUYddiNCE4sG/2ASj7C -mwRTh2HM4BDnkhW9PNjfHoaWa2TDIhOyHQ5hLYz2tnaeU1sOrADCuFSxGiQqgr8J -prahKh6AzNsXba4rumoO08QTTtJzoa8L6TV4PTQ6gi+OMdbyBe3CQ7DSRzLseHNH -KG5tqRRu+Jm7dUuOXDV4MDHoloyZlksOvIYSC+gaS+ke3XlR+GzOW7hpgn5SIDlv -aR/zlIKXUCvVux3/pNFgW6rduFE0f5Hbc1+J4ghTl8EQu1dwDTax7blXQwE+VDgJ -u4fZGRmoUvvO/bjVCbehBxfJn0rHsxpuD5b4Jg2OZNc= -----END CERTIFICATE-----` ) @@ -457,161 +391,7 @@ func getAPIGatewayGoldenTestCases(t *testing.T) []goldenTestCase { }, }, { - name: "api-gateway-with-multiple-inline-certificates", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { - entry.Listeners = []structs.APIGatewayListener{ - { - Name: "listener", - Protocol: structs.ListenerProtocolTCP, - Port: 8080, - TLS: structs.APIGatewayTLSConfiguration{ - Certificates: []structs.ResourceReference{{ - Kind: structs.InlineCertificate, - Name: "certificate", - }}, - MinVersion: types.TLSv1_2, - MaxVersion: types.TLSv1_3, - CipherSuites: []types.TLSCipherSuite{ - types.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - types.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, - }, - }, - }, - } - bound.Listeners = []structs.BoundAPIGatewayListener{ - { - Name: "listener", - Certificates: []structs.ResourceReference{ - { - Kind: structs.InlineCertificate, - Name: "certificate", - }, - { - Kind: structs.InlineCertificate, - Name: "certificate-too", - }, - }, - Routes: []structs.ResourceReference{{ - Kind: structs.TCPRoute, - Name: "route", - }}, - }, - } - }, - []structs.BoundRoute{ - &structs.TCPRouteConfigEntry{ - Kind: structs.TCPRoute, - Name: "route", - Services: []structs.TCPService{{ - Name: "service", - }}, - Parents: []structs.ResourceReference{ - { - Kind: structs.APIGateway, - Name: "api-gateway", - }, - }, - }, - }, []structs.InlineCertificateConfigEntry{ - { - Kind: structs.InlineCertificate, - Name: "certificate", - PrivateKey: gatewayTestPrivateKey, - Certificate: gatewayTestCertificate, - }, - { - Kind: structs.InlineCertificate, - Name: "certificate-too", - PrivateKey: gatewayTestPrivateKeyTwo, - Certificate: gatewayTestCertificateTwo, - }, - }, nil) - }, - }, - { - name: "api-gateway-with-http-route", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { - entry.Listeners = []structs.APIGatewayListener{ - { - Name: "listener", - Protocol: structs.ListenerProtocolHTTP, - Port: 8080, - }, - } - bound.Listeners = []structs.BoundAPIGatewayListener{ - { - Name: "listener", - Certificates: []structs.ResourceReference{{ - Kind: structs.InlineCertificate, - Name: "certificate", - }}, - Routes: []structs.ResourceReference{{ - Kind: structs.HTTPRoute, - Name: "route", - }}, - }, - } - }, []structs.BoundRoute{ - &structs.HTTPRouteConfigEntry{ - Kind: structs.HTTPRoute, - Name: "route", - Rules: []structs.HTTPRouteRule{{ - Filters: structs.HTTPFilters{ - Headers: []structs.HTTPHeaderFilter{ - { - Add: map[string]string{ - "X-Header-Add": "added", - }, - Set: map[string]string{ - "X-Header-Set": "set", - }, - Remove: []string{"X-Header-Remove"}, - }, - }, - RetryFilter: &structs.RetryFilter{ - NumRetries: pointer.Uint32(3), - RetryOn: []string{"cancelled"}, - RetryOnStatusCodes: []uint32{500}, - RetryOnConnectFailure: pointer.Bool(true), - }, - TimeoutFilter: &structs.TimeoutFilter{ - IdleTimeout: time.Second * 30, - RequestTimeout: time.Second * 30, - }, - }, - Services: []structs.HTTPService{{ - Name: "service", - }}, - }}, - Parents: []structs.ResourceReference{ - { - Kind: structs.APIGateway, - Name: "api-gateway", - }, - }, - }, - }, []structs.InlineCertificateConfigEntry{{ - Kind: structs.InlineCertificate, - Name: "certificate", - PrivateKey: gatewayTestPrivateKey, - Certificate: gatewayTestCertificate, - }}, []proxycfg.UpdateEvent{{ - CorrelationID: "discovery-chain:" + serviceUID.String(), - Result: &structs.DiscoveryChainResponse{ - Chain: serviceChain, - }, - }, { - CorrelationID: "upstream-target:" + serviceChain.ID() + ":" + serviceUID.String(), - Result: &structs.IndexedCheckServiceNodes{ - Nodes: proxycfg.TestUpstreamNodes(t, "service"), - }, - }}) - }, - }, - { - name: "api-gateway-with-http-route-timeoutfilter-one-set", + name: "api-gateway-with-http-route-and-inline-certificate", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { entry.Listeners = []structs.APIGatewayListener{ @@ -624,10 +404,6 @@ func getAPIGatewayGoldenTestCases(t *testing.T) []goldenTestCase { bound.Listeners = []structs.BoundAPIGatewayListener{ { Name: "listener", - Certificates: []structs.ResourceReference{{ - Kind: structs.InlineCertificate, - Name: "certificate", - }}, Routes: []structs.ResourceReference{{ Kind: structs.HTTPRoute, Name: "route", @@ -651,9 +427,6 @@ func getAPIGatewayGoldenTestCases(t *testing.T) []goldenTestCase { Remove: []string{"X-Header-Remove"}, }, }, - TimeoutFilter: &structs.TimeoutFilter{ - IdleTimeout: time.Second * 30, - }, }, Services: []structs.HTTPService{{ Name: "service", @@ -666,12 +439,7 @@ func getAPIGatewayGoldenTestCases(t *testing.T) []goldenTestCase { }, }, }, - }, []structs.InlineCertificateConfigEntry{{ - Kind: structs.InlineCertificate, - Name: "certificate", - PrivateKey: gatewayTestPrivateKey, - Certificate: gatewayTestCertificate, - }}, []proxycfg.UpdateEvent{{ + }, nil, []proxycfg.UpdateEvent{{ CorrelationID: "discovery-chain:" + serviceUID.String(), Result: &structs.DiscoveryChainResponse{ Chain: serviceChain, diff --git a/agent/xds/response/response.go b/agent/xds/response.go similarity index 80% rename from agent/xds/response/response.go rename to agent/xds/response.go index 91ce6d7397386..e452e8a2f26e4 100644 --- a/agent/xds/response/response.go +++ b/agent/xds/response.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 -package response +package xds import ( envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" @@ -13,7 +13,7 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" ) -func CreateResponse(typeURL string, version, nonce string, resources []proto.Message) (*envoy_discovery_v3.DiscoveryResponse, error) { +func createResponse(typeURL string, version, nonce string, resources []proto.Message) (*envoy_discovery_v3.DiscoveryResponse, error) { anys := make([]*anypb.Any, 0, len(resources)) for _, r := range resources { if r == nil { @@ -41,7 +41,7 @@ func CreateResponse(typeURL string, version, nonce string, resources []proto.Mes return resp, nil } -func MakePipeAddress(path string, mode uint32) *envoy_core_v3.Address { +func makePipeAddress(path string, mode uint32) *envoy_core_v3.Address { return &envoy_core_v3.Address{ Address: &envoy_core_v3.Address_Pipe{ Pipe: &envoy_core_v3.Pipe{ @@ -52,7 +52,7 @@ func MakePipeAddress(path string, mode uint32) *envoy_core_v3.Address { } } -func MakeAddress(ip string, port int) *envoy_core_v3.Address { +func makeAddress(ip string, port int) *envoy_core_v3.Address { return &envoy_core_v3.Address{ Address: &envoy_core_v3.Address_SocketAddress{ SocketAddress: &envoy_core_v3.SocketAddress{ @@ -65,15 +65,15 @@ func MakeAddress(ip string, port int) *envoy_core_v3.Address { } } -func MakeUint32Value(n int) *wrapperspb.UInt32Value { +func makeUint32Value(n int) *wrapperspb.UInt32Value { return &wrapperspb.UInt32Value{Value: uint32(n)} } -func MakeBoolValue(n bool) *wrapperspb.BoolValue { +func makeBoolValue(n bool) *wrapperspb.BoolValue { return &wrapperspb.BoolValue{Value: n} } -func MakeEnvoyRegexMatch(patt string) *envoy_matcher_v3.RegexMatcher { +func makeEnvoyRegexMatch(patt string) *envoy_matcher_v3.RegexMatcher { return &envoy_matcher_v3.RegexMatcher{ EngineType: &envoy_matcher_v3.RegexMatcher_GoogleRe2{ GoogleRe2: &envoy_matcher_v3.RegexMatcher_GoogleRE2{}, diff --git a/agent/xds/routes.go b/agent/xds/routes.go index 6f0d18b05dcbd..a86747a9c0806 100644 --- a/agent/xds/routes.go +++ b/agent/xds/routes.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -14,16 +14,14 @@ import ( envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" + "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/wrapperspb" "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul/discoverychain" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/config" - "github.com/hashicorp/consul/agent/xds/response" ) // routesFromSnapshot returns the xDS API representation of the "routes" in the @@ -58,13 +56,17 @@ func (s *ResourceGenerator) routesForConnectProxy(cfgSnap *proxycfg.ConfigSnapsh continue } + explicit := cfgSnap.ConnectProxy.UpstreamConfig[uid].HasLocalPortOrSocket() + implicit := cfgSnap.ConnectProxy.IsImplicitUpstream(uid) + if !implicit && !explicit { + // Discovery chain is not associated with a known explicit or implicit upstream so it is skipped. + continue + } + virtualHost, err := s.makeUpstreamRouteForDiscoveryChain(cfgSnap, uid, chain, []string{"*"}, false) if err != nil { return nil, err } - if virtualHost == nil { - continue - } route := &envoy_route_v3.RouteConfiguration{ Name: uid.EnvoyID(), @@ -72,7 +74,7 @@ func (s *ResourceGenerator) routesForConnectProxy(cfgSnap *proxycfg.ConfigSnapsh // ValidateClusters defaults to true when defined statically and false // when done via RDS. Re-set the reasonable value of true to prevent // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), + ValidateClusters: makeBoolValue(true), } resources = append(resources, route) } @@ -142,7 +144,7 @@ func (s *ResourceGenerator) routesForTerminatingGateway(cfgSnap *proxycfg.Config var resources []proto.Message for _, svc := range cfgSnap.TerminatingGateway.ValidServices() { clusterName := connect.ServiceSNI(svc.Name, "", svc.NamespaceOrDefault(), svc.PartitionOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain) - cfg, err := config.ParseProxyConfig(cfgSnap.TerminatingGateway.ServiceConfigs[svc].ProxyConfig) + cfg, err := ParseProxyConfig(cfgSnap.TerminatingGateway.ServiceConfigs[svc].ProxyConfig) if err != nil { // Don't hard fail on a config typo, just warn. The parse func returns // default config if there is an error so it's safe to continue. @@ -170,7 +172,7 @@ func (s *ResourceGenerator) routesForTerminatingGateway(cfgSnap *proxycfg.Config for _, address := range svcConfig.Destination.Addresses { clusterName := clusterNameForDestination(cfgSnap, svc.Name, address, svc.NamespaceOrDefault(), svc.PartitionOrDefault()) - cfg, err := config.ParseProxyConfig(cfgSnap.TerminatingGateway.ServiceConfigs[svc].ProxyConfig) + cfg, err := ParseProxyConfig(cfgSnap.TerminatingGateway.ServiceConfigs[svc].ProxyConfig) if err != nil { // Don't hard fail on a config typo, just warn. The parse func returns // default config if there is an error so it's safe to continue. @@ -247,6 +249,10 @@ func (s *ResourceGenerator) routesForMeshGateway(cfgSnap *proxycfg.ConfigSnapsho continue // ignore; not relevant } + if cfgSnap.MeshGateway.Leaf == nil { + continue // ignore; not ready + } + uid := proxycfg.NewUpstreamIDFromServiceName(svc) virtualHost, err := s.makeUpstreamRouteForDiscoveryChain( @@ -259,9 +265,6 @@ func (s *ResourceGenerator) routesForMeshGateway(cfgSnap *proxycfg.ConfigSnapsho if err != nil { return nil, err } - if virtualHost == nil { - continue - } route := &envoy_route_v3.RouteConfiguration{ Name: uid.EnvoyID(), @@ -269,7 +272,7 @@ func (s *ResourceGenerator) routesForMeshGateway(cfgSnap *proxycfg.ConfigSnapsho // ValidateClusters defaults to true when defined statically and false // when done via RDS. Re-set the reasonable value of true to prevent // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), + ValidateClusters: makeBoolValue(true), } resources = append(resources, route) } @@ -287,7 +290,7 @@ func makeNamedDefaultRouteWithLB(clusterName string, lb *structs.LoadBalancer, t // Configure Envoy to rewrite Host header if autoHostRewrite { action.Route.HostRewriteSpecifier = &envoy_route_v3.RouteAction_AutoHostRewrite{ - AutoHostRewrite: response.MakeBoolValue(true), + AutoHostRewrite: makeBoolValue(true), } } @@ -312,7 +315,7 @@ func makeNamedDefaultRouteWithLB(clusterName string, lb *structs.LoadBalancer, t // ValidateClusters defaults to true when defined statically and false // when done via RDS. Re-set the reasonable value of true to prevent // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), + ValidateClusters: makeBoolValue(true), }, nil } @@ -322,7 +325,7 @@ func makeNamedAddressesRoute(routeName string, addresses map[string]string) (*en // ValidateClusters defaults to true when defined statically and false // when done via RDS. Re-set the reasonable value of true to prevent // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), + ValidateClusters: makeBoolValue(true), } for clusterName, address := range addresses { action := makeRouteActionFromName(clusterName) @@ -364,16 +367,13 @@ func (s *ResourceGenerator) routesForIngressGateway(cfgSnap *proxycfg.ConfigSnap // ValidateClusters defaults to true when defined statically and false // when done via RDS. Re-set the reasonable value of true to prevent // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), + ValidateClusters: makeBoolValue(true), } for _, u := range upstreams { uid := proxycfg.NewUpstreamID(&u) chain := cfgSnap.IngressGateway.DiscoveryChain[uid] if chain == nil { - // Note that if we continue here we must also do this in the cluster generation - s.Logger.Warn("could not find discovery chain for ingress upstream", - "listener", listenerKey, "upstream", uid) continue } @@ -382,9 +382,6 @@ func (s *ResourceGenerator) routesForIngressGateway(cfgSnap *proxycfg.ConfigSnap if err != nil { return nil, err } - if virtualHost == nil { - continue - } // Lookup listener and service config details from ingress gateway // definition. @@ -413,7 +410,7 @@ func (s *ResourceGenerator) routesForIngressGateway(cfgSnap *proxycfg.ConfigSnap } else { svcRoute := &envoy_route_v3.RouteConfiguration{ Name: svcRouteName, - ValidateClusters: response.MakeBoolValue(true), + ValidateClusters: makeBoolValue(true), VirtualHosts: []*envoy_route_v3.VirtualHost{virtualHost}, } result = append(result, svcRoute) @@ -449,7 +446,7 @@ func (s *ResourceGenerator) routesForAPIGateway(cfgSnap *proxycfg.ConfigSnapshot // ValidateClusters defaults to true when defined statically and false // when done via RDS. Re-set the reasonable value of true to prevent // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), + ValidateClusters: makeBoolValue(true), } route, ok := cfgSnap.APIGateway.HTTPRoutes.Get(routeRef) @@ -469,7 +466,6 @@ func (s *ResourceGenerator) routesForAPIGateway(cfgSnap *proxycfg.ConfigSnapshot uid := proxycfg.NewUpstreamID(&upstream) chain := cfgSnap.APIGateway.DiscoveryChain[uid] if chain == nil { - // Note that if we continue here we must also do this in the cluster generation s.Logger.Debug("Discovery chain not found for flattened route", "discovery chain ID", uid) continue } @@ -480,9 +476,6 @@ func (s *ResourceGenerator) routesForAPIGateway(cfgSnap *proxycfg.ConfigSnapshot if err != nil { return nil, err } - if virtualHost == nil { - continue - } defaultRoute.VirtualHosts = append(defaultRoute.VirtualHosts, virtualHost) } @@ -516,7 +509,7 @@ func makeHeadersValueOptions(vals map[string]string, add bool) []*envoy_core_v3. Key: k, Value: v, }, - Append: response.MakeBoolValue(add), + Append: makeBoolValue(add), } opts = append(opts, o) } @@ -753,7 +746,7 @@ func (s *ResourceGenerator) makeUpstreamRouteForDiscoveryChain( func getRetryPolicyForDestination(destination *structs.ServiceRouteDestination) *envoy_route_v3.RetryPolicy { retryPolicy := &envoy_route_v3.RetryPolicy{} if destination.NumRetries > 0 { - retryPolicy.NumRetries = response.MakeUint32Value(int(destination.NumRetries)) + retryPolicy.NumRetries = makeUint32Value(int(destination.NumRetries)) } // The RetryOn magic values come from: https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/http_filters/router_filter#config-http-filters-router-x-envoy-retry-on @@ -806,7 +799,7 @@ func makeRouteMatchForDiscoveryRoute(discoveryRoute *structs.DiscoveryRoute) *en } case match.HTTP.PathRegex != "": em.PathSpecifier = &envoy_route_v3.RouteMatch_SafeRegex{ - SafeRegex: response.MakeEnvoyRegexMatch(match.HTTP.PathRegex), + SafeRegex: makeEnvoyRegexMatch(match.HTTP.PathRegex), } default: em.PathSpecifier = &envoy_route_v3.RouteMatch_Prefix{ @@ -828,7 +821,7 @@ func makeRouteMatchForDiscoveryRoute(discoveryRoute *structs.DiscoveryRoute) *en } case hdr.Regex != "": eh.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_SafeRegexMatch{ - SafeRegexMatch: response.MakeEnvoyRegexMatch(hdr.Regex), + SafeRegexMatch: makeEnvoyRegexMatch(hdr.Regex), } case hdr.Prefix != "": eh.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_PrefixMatch{ @@ -860,7 +853,7 @@ func makeRouteMatchForDiscoveryRoute(discoveryRoute *structs.DiscoveryRoute) *en eh := &envoy_route_v3.HeaderMatcher{ Name: ":method", HeaderMatchSpecifier: &envoy_route_v3.HeaderMatcher_SafeRegexMatch{ - SafeRegexMatch: response.MakeEnvoyRegexMatch(methodHeaderRegex), + SafeRegexMatch: makeEnvoyRegexMatch(methodHeaderRegex), }, } @@ -887,7 +880,7 @@ func makeRouteMatchForDiscoveryRoute(discoveryRoute *structs.DiscoveryRoute) *en eq.QueryParameterMatchSpecifier = &envoy_route_v3.QueryParameterMatcher_StringMatch{ StringMatch: &envoy_matcher_v3.StringMatcher{ MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{ - SafeRegex: response.MakeEnvoyRegexMatch(qm.Regex), + SafeRegex: makeEnvoyRegexMatch(qm.Regex), }, }, } @@ -925,7 +918,7 @@ func (s *ResourceGenerator) makeRouteActionForChainCluster( chain *structs.CompiledDiscoveryChain, forMeshGateway bool, ) (*envoy_route_v3.Route_Route, bool) { - clusterName := s.getTargetClusterName(upstreamsSnapshot, chain, targetID, forMeshGateway) + clusterName := s.getTargetClusterName(upstreamsSnapshot, chain, targetID, forMeshGateway, false) if clusterName == "" { return nil, false } @@ -958,7 +951,7 @@ func (s *ResourceGenerator) makeRouteActionForSplitter( } targetID := nextNode.Resolver.Target - clusterName := s.getTargetClusterName(upstreamsSnapshot, chain, targetID, forMeshGateway) + clusterName := s.getTargetClusterName(upstreamsSnapshot, chain, targetID, forMeshGateway, false) if clusterName == "" { continue } @@ -968,7 +961,7 @@ func (s *ResourceGenerator) makeRouteActionForSplitter( weight := int(split.Weight * 100) totalWeight += weight cw := &envoy_route_v3.WeightedCluster_ClusterWeight{ - Weight: response.MakeUint32Value(weight), + Weight: makeUint32Value(weight), Name: clusterName, } if err := injectHeaderManipToWeightedCluster(split.Definition, cw); err != nil { @@ -982,18 +975,19 @@ func (s *ResourceGenerator) makeRouteActionForSplitter( return nil, fmt.Errorf("number of clusters in splitter must be > 0; got %d", len(clusters)) } - var envoyWeightScale *wrapperspb.UInt32Value - if totalWeight == 10000 { - envoyWeightScale = response.MakeUint32Value(10000) + envoyWeightScale := 10000 + if envoyWeightScale < totalWeight { + clusters[0].Weight.Value += uint32(totalWeight - envoyWeightScale) + } else { + clusters[0].Weight.Value += uint32(envoyWeightScale - totalWeight) } return &envoy_route_v3.Route_Route{ Route: &envoy_route_v3.RouteAction{ ClusterSpecifier: &envoy_route_v3.RouteAction_WeightedClusters{ WeightedClusters: &envoy_route_v3.WeightedCluster{ - Clusters: clusters, - // this field is deprecated, and we should get the desired behavior with the front-end validation - TotalWeight: envoyWeightScale, // scaled up 100% + Clusters: clusters, + TotalWeight: makeUint32Value(envoyWeightScale), // scaled up 100% }, }, }, diff --git a/agent/xds/routes_test.go b/agent/xds/routes_test.go index e2f7d73b5e7ca..eaa8d48c0fc3b 100644 --- a/agent/xds/routes_test.go +++ b/agent/xds/routes_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -10,16 +10,14 @@ import ( "time" envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" + "github.com/hashicorp/consul/agent/xds/testcommon" + testinf "github.com/mitchellh/go-testing-interface" "github.com/stretchr/testify/require" "google.golang.org/protobuf/types/known/durationpb" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/proxystateconverter" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/agent/xds/testcommon" - "github.com/hashicorp/consul/agent/xdsv2" "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/sdk/testutil" ) @@ -28,7 +26,6 @@ type routeTestCase struct { name string create func(t testinf.T) *proxycfg.ConfigSnapshot overrideGoldenName string - alsoRunTestForV2 bool } func makeRouteDiscoChainTests(enterprise bool) []routeTestCase { @@ -38,77 +35,48 @@ func makeRouteDiscoChainTests(enterprise bool) []routeTestCase { create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-chain-external-sni", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "external-sni", enterprise, nil, nil) }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-splitter-overweight", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-overweight", enterprise, nil, nil) - }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-chain-and-overrides", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple-with-overrides", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "splitter-with-resolver-redirect", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-with-resolver-redirect-multidc", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-chain-and-splitter", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "chain-and-splitter", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-grpc-router", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "grpc-router", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-with-chain-and-router", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "chain-and-router", enterprise, nil, nil) }, - alsoRunTestForV2: true, }, { name: "connect-proxy-lb-in-resolver", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotDiscoveryChain(t, "lb-resolver", enterprise, nil, nil) }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-route-to-lb-resolver", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "redirect-to-lb-node", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-resolver-with-lb", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "resolver-with-lb", enterprise, nil, nil) - }, - alsoRunTestForV2: true, }, } } @@ -129,8 +97,6 @@ func TestRoutesFromSnapshot(t *testing.T) { create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotIngressGateway_NilConfigEntry(t) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-defaults-no-chain", @@ -138,8 +104,6 @@ func TestRoutesFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, false, "tcp", "default", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-chain", @@ -147,8 +111,6 @@ func TestRoutesFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "simple", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-chain-external-sni", @@ -156,8 +118,6 @@ func TestRoutesFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "external-sni", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-splitter-with-resolver-redirect", @@ -165,8 +125,6 @@ func TestRoutesFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", "splitter-with-resolver-redirect-multidc", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-chain-and-splitter", @@ -174,8 +132,6 @@ func TestRoutesFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", "chain-and-splitter", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-grpc-router", @@ -183,8 +139,6 @@ func TestRoutesFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", "grpc-router", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-chain-and-router", @@ -192,8 +146,6 @@ func TestRoutesFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", "chain-and-router", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-lb-in-resolver", @@ -201,66 +153,48 @@ func TestRoutesFromSnapshot(t *testing.T) { return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", "lb-resolver", nil, nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-http-multiple-services", create: proxycfg.TestConfigSnapshotIngress_HTTPMultipleServices, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-grpc-multiple-services", create: proxycfg.TestConfigSnapshotIngress_GRPCMultipleServices, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-chain-and-router-header-manip", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "router-header-manip", nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-sds-listener-level", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-listener-level", nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-sds-listener-level-wildcard", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-listener-level-wildcard", nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-sds-service-level", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-service-level", nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "ingress-with-sds-service-level-mixed-tls", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-service-level-mixed-tls", nil, nil) }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, }, { name: "terminating-gateway-lb-config", create: proxycfg.TestConfigSnapshotTerminatingGatewayLBConfig, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, }, } @@ -290,10 +224,10 @@ func TestRoutesFromSnapshot(t *testing.T) { sort.Slice(routes, func(i, j int) bool { return routes[i].(*envoy_route_v3.RouteConfiguration).Name < routes[j].(*envoy_route_v3.RouteConfiguration).Name }) - r, err := response.CreateResponse(xdscommon.RouteType, "00000001", "00000001", routes) + r, err := createResponse(xdscommon.RouteType, "00000001", "00000001", routes) require.NoError(t, err) - t.Run("current-xdsv1", func(t *testing.T) { + t.Run("current", func(t *testing.T) { gotJSON := protoToJSON(t, r) gName := tt.name @@ -303,39 +237,6 @@ func TestRoutesFromSnapshot(t *testing.T) { require.JSONEq(t, goldenEnvoy(t, filepath.Join("routes", gName), envoyVersion, latestEnvoyVersion, gotJSON), gotJSON) }) - - if tt.alsoRunTestForV2 { - generator := xdsv2.NewResourceGenerator(testutil.Logger(t)) - - converter := proxystateconverter.NewConverter(testutil.Logger(t), &mockCfgFetcher{addressLan: "10.10.10.10"}) - proxyState, err := converter.ProxyStateFromSnapshot(snap) - require.NoError(t, err) - - res, err := generator.AllResourcesFromIR(proxyState) - require.NoError(t, err) - - routes = res[xdscommon.RouteType] - // The order of routes returned via RDS isn't relevant, so it's safe - // to sort these for the purposes of test comparisons. - sort.Slice(routes, func(i, j int) bool { - return routes[i].(*envoy_route_v3.Route).Name < routes[j].(*envoy_route_v3.Route).Name - }) - - r, err := response.CreateResponse(xdscommon.RouteType, "00000001", "00000001", routes) - require.NoError(t, err) - - t.Run("current-xdsv2", func(t *testing.T) { - gotJSON := protoToJSON(t, r) - - gName := tt.name - if tt.overrideGoldenName != "" { - gName = tt.overrideGoldenName - } - - expectedJSON := goldenEnvoy(t, filepath.Join("routes", gName), envoyVersion, latestEnvoyVersion, gotJSON) - require.JSONEq(t, expectedJSON, gotJSON) - }) - } }) } }) @@ -542,11 +443,6 @@ func TestEnvoyLBConfig_InjectToRouteAction(t *testing.T) { FieldValue: "special-header", Terminal: true, }, - { - Field: structs.HashPolicyQueryParam, - FieldValue: "my-pretty-param", - Terminal: true, - }, }, }, expected: &envoy_route_v3.RouteAction{ @@ -585,14 +481,6 @@ func TestEnvoyLBConfig_InjectToRouteAction(t *testing.T) { }, Terminal: true, }, - { - PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_QueryParameter_{ - QueryParameter: &envoy_route_v3.RouteAction_HashPolicy_QueryParameter{ - Name: "my-pretty-param", - }, - }, - Terminal: true, - }, }, }, }, diff --git a/agent/xds/secrets.go b/agent/xds/secrets.go index 628cec7905ba1..d150a12dc1611 100644 --- a/agent/xds/secrets.go +++ b/agent/xds/secrets.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds diff --git a/agent/xds/server.go b/agent/xds/server.go index 45c11fa0b3a17..2e012a4cb6fd5 100644 --- a/agent/xds/server.go +++ b/agent/xds/server.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -9,9 +9,12 @@ import ( "sync/atomic" "time" + envoy_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" + + "github.com/hashicorp/consul/envoyextensions/xdscommon" + "github.com/armon/go-metrics" "github.com/armon/go-metrics/prometheus" - envoy_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" "github.com/hashicorp/go-hclog" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -20,10 +23,8 @@ import ( "github.com/hashicorp/consul/acl" external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/agent/grpc-external/limiter" - "github.com/hashicorp/consul/agent/xds/configfetcher" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/agent/proxycfg" + "github.com/hashicorp/consul/agent/structs" ) var ( @@ -69,6 +70,13 @@ const ( // services named "local_agent" in the future. LocalAgentClusterName = "local_agent" + // OriginalDestinationClusterName is the name we give to the passthrough + // cluster which redirects transparently-proxied requests to their original + // destination outside the mesh. This cluster prevents Consul from blocking + // connections to destinations outside of the catalog when in transparent + // proxy mode. + OriginalDestinationClusterName = "original-destination" + // DefaultAuthCheckFrequency is the default value for // Server.AuthCheckFrequency to use when the zero value is provided. DefaultAuthCheckFrequency = 5 * time.Minute @@ -80,10 +88,16 @@ const ( // coupling this to the agent. type ACLResolverFunc func(id string) (acl.Authorizer, error) +// ConfigFetcher is the interface the agent needs to expose +// for the xDS server to fetch agent config, currently only one field is fetched +type ConfigFetcher interface { + AdvertiseAddrLAN() string +} + // ProxyConfigSource is the interface xds.Server requires to consume proxy // config updates. -type ProxyWatcher interface { - Watch(proxyID *pbresource.ID, nodeName string, token string) (<-chan proxysnapshot.ProxySnapshot, limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) +type ProxyConfigSource interface { + Watch(id structs.ServiceID, nodeName string, token string) (<-chan *proxycfg.ConfigSnapshot, limiter.SessionTerminatedChan, proxycfg.CancelFunc, error) } // Server represents a gRPC server that can handle xDS requests from Envoy. All @@ -94,9 +108,9 @@ type ProxyWatcher interface { type Server struct { NodeName string Logger hclog.Logger - ProxyWatcher ProxyWatcher + CfgSrc ProxyConfigSource ResolveToken ACLResolverFunc - CfgFetcher configfetcher.ConfigFetcher + CfgFetcher ConfigFetcher // AuthCheckFrequency is how often we should re-check the credentials used // during a long-lived gRPC Stream after it has been initially established. @@ -145,14 +159,14 @@ func (c *activeStreamCounters) Increment(ctx context.Context) func() { func NewServer( nodeName string, logger hclog.Logger, - proxyWatcher ProxyWatcher, + cfgMgr ProxyConfigSource, resolveTokenSecret ACLResolverFunc, - cfgFetcher configfetcher.ConfigFetcher, + cfgFetcher ConfigFetcher, ) *Server { return &Server{ NodeName: nodeName, Logger: logger, - ProxyWatcher: proxyWatcher, + CfgSrc: cfgMgr, ResolveToken: resolveTokenSecret, CfgFetcher: cfgFetcher, AuthCheckFrequency: DefaultAuthCheckFrequency, @@ -200,9 +214,9 @@ func (s *Server) authenticate(ctx context.Context) (acl.Authorizer, error) { // using a token with the same permissions, and that it stores the data by // proxy ID. We assume that any data in the snapshot was already filtered, // which allows this authorization to be a shallow authorization check -// for all the data in a ProxySnapshot. -func (s *Server) authorize(ctx context.Context, proxySnapshot proxysnapshot.ProxySnapshot) error { - if proxySnapshot == nil { +// for all the data in a ConfigSnapshot. +func (s *Server) authorize(ctx context.Context, cfgSnap *proxycfg.ConfigSnapshot) error { + if cfgSnap == nil { return status.Errorf(codes.Unauthenticated, "unauthenticated: no config snapshot") } @@ -211,5 +225,22 @@ func (s *Server) authorize(ctx context.Context, proxySnapshot proxysnapshot.Prox return err } - return proxySnapshot.Authorize(authz) + var authzContext acl.AuthorizerContext + switch cfgSnap.Kind { + case structs.ServiceKindConnectProxy: + cfgSnap.ProxyID.EnterpriseMeta.FillAuthzContext(&authzContext) + if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(cfgSnap.Proxy.DestinationServiceName, &authzContext); err != nil { + return status.Errorf(codes.PermissionDenied, err.Error()) + } + case structs.ServiceKindMeshGateway, structs.ServiceKindTerminatingGateway, structs.ServiceKindIngressGateway, structs.ServiceKindAPIGateway: + cfgSnap.ProxyID.EnterpriseMeta.FillAuthzContext(&authzContext) + if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(cfgSnap.Service, &authzContext); err != nil { + return status.Errorf(codes.PermissionDenied, err.Error()) + } + default: + return status.Errorf(codes.Internal, "Invalid service kind") + } + + // Authed OK! + return nil } diff --git a/agent/xds/server_ce.go b/agent/xds/server_ce.go index a01e9bf493f71..c1d651c0ad59a 100644 --- a/agent/xds/server_ce.go +++ b/agent/xds/server_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/agent/xds/testcommon/testcommon.go b/agent/xds/testcommon/testcommon.go index 44d2cc3bbe6da..1b0d6ebcbf507 100644 --- a/agent/xds/testcommon/testcommon.go +++ b/agent/xds/testcommon/testcommon.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package testcommon diff --git a/agent/xds/testdata/clusters/api-gateway-with-http-route.latest.golden b/agent/xds/testdata/clusters/api-gateway-with-http-route-and-inline-certificate.latest.golden similarity index 100% rename from agent/xds/testdata/clusters/api-gateway-with-http-route.latest.golden rename to agent/xds/testdata/clusters/api-gateway-with-http-route-and-inline-certificate.latest.golden diff --git a/agent/xds/testdata/clusters/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden b/agent/xds/testdata/clusters/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden deleted file mode 100644 index f18e7e0d97665..0000000000000 --- a/agent/xds/testdata/clusters/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden +++ /dev/null @@ -1,55 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "altStatName": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "circuitBreakers": {}, - "outlierDetection": {}, - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/service" - } - ] - } - }, - "sni": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/api-gateway-with-multiple-inline-certificates.latest.golden b/agent/xds/testdata/clusters/api-gateway-with-multiple-inline-certificates.latest.golden deleted file mode 100644 index e20479dfd1cfc..0000000000000 --- a/agent/xds/testdata/clusters/api-gateway-with-multiple-inline-certificates.latest.golden +++ /dev/null @@ -1,55 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "altStatName": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "circuitBreakers": {}, - "outlierDetection": {}, - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/service" - } - ] - } - }, - "sni": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-chain-and-overrides.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-overrides.latest.golden index a6334a035a797..fd63324de86c4 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-chain-and-overrides.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-overrides.latest.golden @@ -8,30 +8,42 @@ "type": "EDS", "edsClusterConfig": { "edsConfig": { - "ads": {}, + "ads": { + + }, "resourceApiVersion": "V3" } }, "connectTimeout": "66s", - "circuitBreakers": {}, + "circuitBreakers": { + + }, "typedExtensionProtocolOptions": { "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", "explicitHttpConfig": { - "http2ProtocolOptions": {} + "http2ProtocolOptions": { + + } } } }, - "outlierDetection": {}, + "outlierDetection": { + + }, "commonLbConfig": { - "healthyPanicThreshold": {} + "healthyPanicThreshold": { + + } }, "transportSocket": { "name": "tls", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", "commonTlsContext": { - "tlsParams": {}, + "tlsParams": { + + }, "tlsCertificates": [ { "certificateChain": { @@ -63,19 +75,27 @@ "type": "EDS", "edsClusterConfig": { "edsConfig": { - "ads": {}, + "ads": { + + }, "resourceApiVersion": "V3" } }, "connectTimeout": "5s", - "circuitBreakers": {}, - "outlierDetection": {}, + "circuitBreakers": { + + }, + "outlierDetection": { + + }, "transportSocket": { "name": "tls", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", "commonTlsContext": { - "tlsParams": {}, + "tlsParams": { + + }, "tlsCertificates": [ { "certificateChain": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-chain-http2.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-chain-http2.latest.golden deleted file mode 100644 index 4e3181dcffc9a..0000000000000 --- a/agent/xds/testdata/clusters/connect-proxy-with-chain-http2.latest.golden +++ /dev/null @@ -1,135 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "33s", - "circuitBreakers": {}, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - }, - "outlierDetection": {}, - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" - } - ] - } - }, - "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "circuitBreakers": {}, - "outlierDetection": {}, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" - }, - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" - } - ] - } - }, - "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app", - "type": "STATIC", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "local_app", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden deleted file mode 100644 index 23c82215d715d..0000000000000 --- a/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden +++ /dev/null @@ -1,135 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app", - "type": "STATIC", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "local_app", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "payments?peer=cloud:custom-upstream", - "connectTimeout": "15s", - "loadAssignment": { - "clusterName": "payments?peer=cloud:custom-upstream", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8443 - } - } - } - } - ] - } - ] - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICczCCAdwCCQC3BLnEmLCrSjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCQVoxEjAQBgNVBAcMCUZsYWdzdGFmZjEMMAoGA1UECgwDRm9v\nMRAwDgYDVQQLDAdleGFtcGxlMQ8wDQYDVQQDDAZwZWVyLWExHTAbBgkqhkiG9w0B\nCQEWDmZvb0BwZWVyLWEuY29tMB4XDTIyMDUyNjAxMDQ0NFoXDTIzMDUyNjAxMDQ0\nNFowfjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkFaMRIwEAYDVQQHDAlGbGFnc3Rh\nZmYxDDAKBgNVBAoMA0ZvbzEQMA4GA1UECwwHZXhhbXBsZTEPMA0GA1UEAwwGcGVl\nci1hMR0wGwYJKoZIhvcNAQkBFg5mb29AcGVlci1hLmNvbTCBnzANBgkqhkiG9w0B\nAQEFAAOBjQAwgYkCgYEA2zFYGTbXDAntT5pLTpZ2+VTiqx4J63VRJH1kdu11f0FV\nc2jl1pqCuYDbQXknDU0Pv1Q5y0+nSAihD2KqGS571r+vHQiPtKYPYRqPEe9FzAhR\n2KhWH6v/tk5DG1HqOjV9/zWRKB12gdFNZZqnw/e7NjLNq3wZ2UAwxXip5uJ8uwMC\nAwEAATANBgkqhkiG9w0BAQsFAAOBgQC/CJ9Syf4aL91wZizKTejwouRYoWv4gRAk\nyto45ZcNMHfJ0G2z+XAMl9ZbQsLgXmzAx4IM6y5Jckq8pKC4PEijCjlKTktLHlEy\n0ggmFxtNB1tid2NC8dOzcQ3l45+gDjDqdILhAvLDjlAIebdkqVqb2CfFNW/I2CQH\nZAuKN1aoKA==\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/payments" - } - ] - } - }, - "sni": "payments.default.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "refunds.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "circuitBreakers": {}, - "outlierDetection": { - "maxEjectionPercent": 100 - }, - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICczCCAdwCCQC3BLnEmLCrSjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCQVoxEjAQBgNVBAcMCUZsYWdzdGFmZjEMMAoGA1UECgwDRm9v\nMRAwDgYDVQQLDAdleGFtcGxlMQ8wDQYDVQQDDAZwZWVyLWExHTAbBgkqhkiG9w0B\nCQEWDmZvb0BwZWVyLWEuY29tMB4XDTIyMDUyNjAxMDQ0NFoXDTIzMDUyNjAxMDQ0\nNFowfjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkFaMRIwEAYDVQQHDAlGbGFnc3Rh\nZmYxDDAKBgNVBAoMA0ZvbzEQMA4GA1UECwwHZXhhbXBsZTEPMA0GA1UEAwwGcGVl\nci1hMR0wGwYJKoZIhvcNAQkBFg5mb29AcGVlci1hLmNvbTCBnzANBgkqhkiG9w0B\nAQEFAAOBjQAwgYkCgYEA2zFYGTbXDAntT5pLTpZ2+VTiqx4J63VRJH1kdu11f0FV\nc2jl1pqCuYDbQXknDU0Pv1Q5y0+nSAihD2KqGS571r+vHQiPtKYPYRqPEe9FzAhR\n2KhWH6v/tk5DG1HqOjV9/zWRKB12gdFNZZqnw/e7NjLNq3wZ2UAwxXip5uJ8uwMC\nAwEAATANBgkqhkiG9w0BAQsFAAOBgQC/CJ9Syf4aL91wZizKTejwouRYoWv4gRAk\nyto45ZcNMHfJ0G2z+XAMl9ZbQsLgXmzAx4IM6y5Jckq8pKC4PEijCjlKTktLHlEy\n0ggmFxtNB1tid2NC8dOzcQ3l45+gDjDqdILhAvLDjlAIebdkqVqb2CfFNW/I2CQH\nZAuKN1aoKA==\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/refunds" - } - ] - } - }, - "sni": "refunds.default.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-http2.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-http2.latest.golden deleted file mode 100644 index 8f3b49b0a2e74..0000000000000 --- a/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-http2.latest.golden +++ /dev/null @@ -1,163 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app", - "type": "STATIC", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "local_app", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "payments.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", - "type": "LOGICAL_DNS", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "payments.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "123.us-east-1.elb.notaws.com", - "portValue": 8443 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, - "circuitBreakers": {}, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - }, - "dnsRefreshRate": "10s", - "dnsLookupFamily": "V4_ONLY", - "outlierDetection": { - "maxEjectionPercent": 100 - }, - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICczCCAdwCCQC3BLnEmLCrSjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCQVoxEjAQBgNVBAcMCUZsYWdzdGFmZjEMMAoGA1UECgwDRm9v\nMRAwDgYDVQQLDAdleGFtcGxlMQ8wDQYDVQQDDAZwZWVyLWExHTAbBgkqhkiG9w0B\nCQEWDmZvb0BwZWVyLWEuY29tMB4XDTIyMDUyNjAxMDQ0NFoXDTIzMDUyNjAxMDQ0\nNFowfjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkFaMRIwEAYDVQQHDAlGbGFnc3Rh\nZmYxDDAKBgNVBAoMA0ZvbzEQMA4GA1UECwwHZXhhbXBsZTEPMA0GA1UEAwwGcGVl\nci1hMR0wGwYJKoZIhvcNAQkBFg5mb29AcGVlci1hLmNvbTCBnzANBgkqhkiG9w0B\nAQEFAAOBjQAwgYkCgYEA2zFYGTbXDAntT5pLTpZ2+VTiqx4J63VRJH1kdu11f0FV\nc2jl1pqCuYDbQXknDU0Pv1Q5y0+nSAihD2KqGS571r+vHQiPtKYPYRqPEe9FzAhR\n2KhWH6v/tk5DG1HqOjV9/zWRKB12gdFNZZqnw/e7NjLNq3wZ2UAwxXip5uJ8uwMC\nAwEAATANBgkqhkiG9w0BAQsFAAOBgQC/CJ9Syf4aL91wZizKTejwouRYoWv4gRAk\nyto45ZcNMHfJ0G2z+XAMl9ZbQsLgXmzAx4IM6y5Jckq8pKC4PEijCjlKTktLHlEy\n0ggmFxtNB1tid2NC8dOzcQ3l45+gDjDqdILhAvLDjlAIebdkqVqb2CfFNW/I2CQH\nZAuKN1aoKA==\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/payments" - } - ] - } - }, - "sni": "payments.default.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "refunds.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "circuitBreakers": {}, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - }, - "outlierDetection": { - "maxEjectionPercent": 100 - }, - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICczCCAdwCCQC3BLnEmLCrSjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCQVoxEjAQBgNVBAcMCUZsYWdzdGFmZjEMMAoGA1UECgwDRm9v\nMRAwDgYDVQQLDAdleGFtcGxlMQ8wDQYDVQQDDAZwZWVyLWExHTAbBgkqhkiG9w0B\nCQEWDmZvb0BwZWVyLWEuY29tMB4XDTIyMDUyNjAxMDQ0NFoXDTIzMDUyNjAxMDQ0\nNFowfjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkFaMRIwEAYDVQQHDAlGbGFnc3Rh\nZmYxDDAKBgNVBAoMA0ZvbzEQMA4GA1UECwwHZXhhbXBsZTEPMA0GA1UEAwwGcGVl\nci1hMR0wGwYJKoZIhvcNAQkBFg5mb29AcGVlci1hLmNvbTCBnzANBgkqhkiG9w0B\nAQEFAAOBjQAwgYkCgYEA2zFYGTbXDAntT5pLTpZ2+VTiqx4J63VRJH1kdu11f0FV\nc2jl1pqCuYDbQXknDU0Pv1Q5y0+nSAihD2KqGS571r+vHQiPtKYPYRqPEe9FzAhR\n2KhWH6v/tk5DG1HqOjV9/zWRKB12gdFNZZqnw/e7NjLNq3wZ2UAwxXip5uJ8uwMC\nAwEAATANBgkqhkiG9w0BAQsFAAOBgQC/CJ9Syf4aL91wZizKTejwouRYoWv4gRAk\nyto45ZcNMHfJ0G2z+XAMl9ZbQsLgXmzAx4IM6y5Jckq8pKC4PEijCjlKTktLHlEy\n0ggmFxtNB1tid2NC8dOzcQ3l45+gDjDqdILhAvLDjlAIebdkqVqb2CfFNW/I2CQH\nZAuKN1aoKA==\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/refunds" - } - ] - } - }, - "sni": "refunds.default.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden b/agent/xds/testdata/clusters/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden deleted file mode 100644 index 4cc45b94c841a..0000000000000 --- a/agent/xds/testdata/clusters/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden +++ /dev/null @@ -1,133 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "circuitBreakers": {}, - "outlierDetection": { - "consecutive5xx": 5, - "interval": "10s", - "baseEjectionTime": "10s", - "maxEjectionPercent": 100, - "enforcingConsecutive5xx": 0 - }, - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" - } - ] - } - }, - "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "circuitBreakers": {}, - "outlierDetection": {}, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" - }, - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" - } - ] - } - }, - "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app", - "type": "STATIC", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "local_app", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/custom-upstream-with-prepared-query.latest.golden b/agent/xds/testdata/clusters/custom-upstream-with-prepared-query.latest.golden deleted file mode 100644 index b57d44e8ab56c..0000000000000 --- a/agent/xds/testdata/clusters/custom-upstream-with-prepared-query.latest.golden +++ /dev/null @@ -1,136 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "db:custom-upstream", - "connectTimeout": "15s", - "loadAssignment": { - "clusterName": "db:custom-upstream", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8443 - } - } - } - } - ] - } - ] - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - } - }, - "sni": "db.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "circuitBreakers": {}, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - }, - "outlierDetection": {}, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" - }, - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" - } - ] - } - }, - "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app", - "type": "STATIC", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "local_app", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/enterprise-connect-proxy-with-chain-http2.latest.golden b/agent/xds/testdata/clusters/enterprise-connect-proxy-with-chain-http2.latest.golden deleted file mode 100644 index 322c36c0b0fbe..0000000000000 --- a/agent/xds/testdata/clusters/enterprise-connect-proxy-with-chain-http2.latest.golden +++ /dev/null @@ -1,135 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "db.foo.bar.dc1.internal-v1.11111111-2222-3333-4444-555555555555.consul", - "altStatName": "db.foo.bar.dc1.internal-v1.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "33s", - "circuitBreakers": {}, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - }, - "outlierDetection": {}, - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ap/bar/ns/foo/dc/dc1/svc/db" - } - ] - } - }, - "sni": "db.foo.bar.dc1.internal-v1.11111111-2222-3333-4444-555555555555.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "circuitBreakers": {}, - "outlierDetection": {}, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" - }, - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" - } - ] - } - }, - "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app", - "type": "STATIC", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "local_app", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/expose-checks.latest.golden b/agent/xds/testdata/clusters/expose-checks.latest.golden deleted file mode 100644 index 4079d6267ed35..0000000000000 --- a/agent/xds/testdata/clusters/expose-checks.latest.golden +++ /dev/null @@ -1,57 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "exposed_cluster_8181", - "type": "STATIC", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "exposed_cluster_8181", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8181 - } - } - } - } - ] - } - ] - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app", - "type": "STATIC", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "local_app", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-defaults-passive-health-check.latest.golden b/agent/xds/testdata/clusters/ingress-with-defaults-passive-health-check.latest.golden index 71ec2c92ac2ef..fbbcc9856c65f 100644 --- a/agent/xds/testdata/clusters/ingress-with-defaults-passive-health-check.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-defaults-passive-health-check.latest.golden @@ -8,7 +8,9 @@ "type": "EDS", "edsClusterConfig": { "edsConfig": { - "ads": {}, + "ads": { + + }, "resourceApiVersion": "V3" } }, @@ -25,18 +27,21 @@ "outlierDetection": { "consecutive5xx": 10, "interval": "5s", - "maxEjectionPercent": 90, "enforcingConsecutive5xx": 80 }, "commonLbConfig": { - "healthyPanicThreshold": {} + "healthyPanicThreshold": { + + } }, "transportSocket": { "name": "tls", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", "commonTlsContext": { - "tlsParams": {}, + "tlsParams": { + + }, "tlsCertificates": [ { "certificateChain": { diff --git a/agent/xds/testdata/clusters/ingress-with-overwrite-defaults-passive-health-check.latest.golden b/agent/xds/testdata/clusters/ingress-with-overwrite-defaults-passive-health-check.latest.golden index af2488846500e..6c9e0802a3dcc 100644 --- a/agent/xds/testdata/clusters/ingress-with-overwrite-defaults-passive-health-check.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-overwrite-defaults-passive-health-check.latest.golden @@ -1,67 +1,71 @@ { - "versionInfo": "00000001", - "resources": [ + "versionInfo": "00000001", + "resources": [ { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": { + + }, + "resourceApiVersion": "V3" } }, - "connectTimeout": "33s", - "circuitBreakers": { - "thresholds": [ + "connectTimeout": "33s", + "circuitBreakers": { + "thresholds": [ { - "maxConnections": 4096, - "maxPendingRequests": 2048 + "maxConnections": 4096, + "maxPendingRequests": 2048 } ] }, - "outlierDetection": { - "interval": "8s", - "baseEjectionTime": "12s", - "maxEjectionPercent": 90, - "enforcingConsecutive5xx": 50 + "outlierDetection": { + "interval": "8s", + "enforcingConsecutive5xx": 50 }, - "commonLbConfig": { - "healthyPanicThreshold": {} + "commonLbConfig": { + "healthyPanicThreshold": { + + } }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" } } ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" }, - "matchSubjectAltNames": [ + "matchSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" } ] } }, - "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" } } } ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" } \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-service-passive-health-check.latest.golden b/agent/xds/testdata/clusters/ingress-with-service-passive-health-check.latest.golden index 2122e1f3a75e2..892846151b9a3 100644 --- a/agent/xds/testdata/clusters/ingress-with-service-passive-health-check.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-service-passive-health-check.latest.golden @@ -1,65 +1,70 @@ { - "versionInfo": "00000001", - "resources": [ + "versionInfo": "00000001", + "resources": [ { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": { + + }, + "resourceApiVersion": "V3" } }, - "connectTimeout": "33s", - "circuitBreakers": { - "thresholds": [ + "connectTimeout": "33s", + "circuitBreakers": { + "thresholds": [ { - "maxConnections": 4096 + "maxConnections": 4096 } ] }, - "outlierDetection": { - "consecutive5xx": 10, - "interval": "5s", - "maxEjectionPercent": 90 + "outlierDetection": { + "consecutive5xx": 10, + "interval": "5s" }, - "commonLbConfig": { - "healthyPanicThreshold": {} + "commonLbConfig": { + "healthyPanicThreshold": { + + } }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" } } ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" }, - "matchSubjectAltNames": [ + "matchSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" } ] } }, - "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" } } } ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" } \ No newline at end of file diff --git a/agent/xds/testdata/clusters/mesh-gateway-using-federation-control-plane.latest.golden b/agent/xds/testdata/clusters/mesh-gateway-using-federation-control-plane.latest.golden deleted file mode 100644 index 9b177efb46521..0000000000000 --- a/agent/xds/testdata/clusters/mesh-gateway-using-federation-control-plane.latest.golden +++ /dev/null @@ -1,205 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "outlierDetection": {} - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "outlierDetection": {} - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "LOGICAL_DNS", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "123.us-west-2.elb.notaws.com", - "portValue": 443 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, - "dnsRefreshRate": "10s", - "dnsLookupFamily": "V4_ONLY", - "outlierDetection": {} - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "LOGICAL_DNS", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "123.us-east-1.elb.notaws.com", - "portValue": 443 - } - } - }, - "healthStatus": "UNHEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, - "dnsRefreshRate": "10s", - "dnsLookupFamily": "V4_ONLY", - "outlierDetection": {} - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "outlierDetection": {} - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "node1.server.dc1.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "outlierDetection": {} - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "node2.server.dc1.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "outlierDetection": {} - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "server.dc2.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "outlierDetection": {} - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "server.dc4.consul", - "type": "LOGICAL_DNS", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "server.dc4.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "123.us-west-2.elb.notaws.com", - "portValue": 443 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, - "dnsRefreshRate": "10s", - "dnsLookupFamily": "V4_ONLY", - "outlierDetection": {} - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "server.dc6.consul", - "type": "LOGICAL_DNS", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "server.dc6.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "123.us-east-1.elb.notaws.com", - "portValue": 443 - } - } - }, - "healthStatus": "UNHEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, - "dnsRefreshRate": "10s", - "dnsLookupFamily": "V4_ONLY", - "outlierDetection": {} - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden b/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden index 36b196675ca19..8c85bbc827ad1 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden @@ -7,25 +7,16 @@ "type": "EDS", "edsClusterConfig": { "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "outlierDetection": {} - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, + "ads": { + + }, "resourceApiVersion": "V3" } }, "connectTimeout": "5s", - "outlierDetection": {} + "outlierDetection": { + + } }, { "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", @@ -33,12 +24,16 @@ "type": "EDS", "edsClusterConfig": { "edsConfig": { - "ads": {}, + "ads": { + + }, "resourceApiVersion": "V3" } }, "connectTimeout": "5s", - "outlierDetection": {} + "outlierDetection": { + + } }, { "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", @@ -47,22 +42,32 @@ "type": "EDS", "edsClusterConfig": { "edsConfig": { - "ads": {}, + "ads": { + + }, "resourceApiVersion": "V3" } }, "connectTimeout": "5s", - "circuitBreakers": {}, - "outlierDetection": {}, + "circuitBreakers": { + + }, + "outlierDetection": { + + }, "commonLbConfig": { - "healthyPanicThreshold": {} + "healthyPanicThreshold": { + + } }, "transportSocket": { "name": "tls", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", "commonTlsContext": { - "tlsParams": {}, + "tlsParams": { + + }, "tlsCertificates": [ { "certificateChain": { @@ -95,22 +100,32 @@ "type": "EDS", "edsClusterConfig": { "edsConfig": { - "ads": {}, + "ads": { + + }, "resourceApiVersion": "V3" } }, "connectTimeout": "33s", - "circuitBreakers": {}, - "outlierDetection": {}, + "circuitBreakers": { + + }, + "outlierDetection": { + + }, "commonLbConfig": { - "healthyPanicThreshold": {} + "healthyPanicThreshold": { + + } }, "transportSocket": { "name": "tls", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", "commonTlsContext": { - "tlsParams": {}, + "tlsParams": { + + }, "tlsCertificates": [ { "certificateChain": { @@ -143,22 +158,32 @@ "type": "EDS", "edsClusterConfig": { "edsConfig": { - "ads": {}, + "ads": { + + }, "resourceApiVersion": "V3" } }, "connectTimeout": "5s", - "circuitBreakers": {}, - "outlierDetection": {}, + "circuitBreakers": { + + }, + "outlierDetection": { + + }, "commonLbConfig": { - "healthyPanicThreshold": {} + "healthyPanicThreshold": { + + } }, "transportSocket": { "name": "tls", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", "commonTlsContext": { - "tlsParams": {}, + "tlsParams": { + + }, "tlsCertificates": [ { "certificateChain": { @@ -183,34 +208,8 @@ "sni": "v2.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" } } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "v1.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "outlierDetection": {} - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "v2.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "outlierDetection": {} } ], "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", "nonce": "00000001" -} +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/mesh-gateway-with-imported-peered-services.latest.golden b/agent/xds/testdata/clusters/mesh-gateway-with-imported-peered-services.latest.golden index f69ce54c6cb37..88f75c8868909 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-with-imported-peered-services.latest.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-with-imported-peered-services.latest.golden @@ -1,50 +1,56 @@ { - "versionInfo": "00000001", - "resources": [ + "versionInfo": "00000001", + "resources": [ { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "alt.default.default.peer-b.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", - "type": "STRICT_DNS", - "connectTimeout": "5s", - "loadAssignment": { - "clusterName": "alt.default.default.peer-b.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", - "endpoints": [ + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "alt.default.default.peer-b.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", + "type": "LOGICAL_DNS", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "alt.default.default.peer-b.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", + "endpoints": [ { - "lbEndpoints": [ + "lbEndpoints": [ { - "endpoint": { - "address": { - "socketAddress": { - "address": "alt.us-east-1.elb.notaws.com", - "portValue": 8443 + "endpoint": { + "address": { + "socketAddress": { + "address": "alt.us-east-1.elb.notaws.com", + "portValue": 8443 } } }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 } ] } ] }, - "dnsRefreshRate": "10s", - "dnsLookupFamily": "V4_ONLY", - "outlierDetection": {} + "dnsRefreshRate": "10s", + "dnsLookupFamily": "V4_ONLY", + "outlierDetection": { + + } }, { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "db.default.default.peer-a.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "db.default.default.peer-a.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": { + + }, + "resourceApiVersion": "V3" } }, - "connectTimeout": "5s", - "outlierDetection": {} + "connectTimeout": "5s", + "outlierDetection": { + + } } ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" } \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/api-gateway-with-http-route.latest.golden b/agent/xds/testdata/endpoints/api-gateway-with-http-route-and-inline-certificate.latest.golden similarity index 100% rename from agent/xds/testdata/endpoints/api-gateway-with-http-route.latest.golden rename to agent/xds/testdata/endpoints/api-gateway-with-http-route-and-inline-certificate.latest.golden diff --git a/agent/xds/testdata/endpoints/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden b/agent/xds/testdata/endpoints/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden deleted file mode 100644 index bda159302a84d..0000000000000 --- a/agent/xds/testdata/endpoints/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden +++ /dev/null @@ -1,41 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.10.1.1", - "portValue": 8080 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.10.1.2", - "portValue": 8080 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/api-gateway-with-multiple-inline-certificates.latest.golden b/agent/xds/testdata/endpoints/api-gateway-with-multiple-inline-certificates.latest.golden deleted file mode 100644 index 47b46bca225bf..0000000000000 --- a/agent/xds/testdata/endpoints/api-gateway-with-multiple-inline-certificates.latest.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden deleted file mode 100644 index 9dc909faf7c06..0000000000000 --- a/agent/xds/testdata/endpoints/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden +++ /dev/null @@ -1,29 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "refunds.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "106.96.90.233", - "portValue": 443 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-peered-upstreams-http2.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-peered-upstreams-http2.latest.golden deleted file mode 100644 index edcc68b8acda1..0000000000000 --- a/agent/xds/testdata/endpoints/connect-proxy-with-peered-upstreams-http2.latest.golden +++ /dev/null @@ -1,29 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "refunds.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "106.96.90.233", - "portValue": 443 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/mesh-gateway-using-federation-control-plane.latest.golden b/agent/xds/testdata/endpoints/mesh-gateway-using-federation-control-plane.latest.golden deleted file mode 100644 index 231f4b9b2c99a..0000000000000 --- a/agent/xds/testdata/endpoints/mesh-gateway-using-federation-control-plane.latest.golden +++ /dev/null @@ -1,249 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.6", - "portValue": 2222 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.7", - "portValue": 2222 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.8", - "portValue": 2222 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "198.18.1.1", - "portValue": 443 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "198.18.1.2", - "portValue": 443 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.3", - "portValue": 2222 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.4", - "portValue": 2222 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.5", - "portValue": 2222 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.9", - "portValue": 2222 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "node1.server.dc1.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 0 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "node2.server.dc1.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.2", - "portValue": 0 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "server.dc1.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 0 - } - } - } - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.2", - "portValue": 0 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "server.dc2.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "198.18.1.1", - "portValue": 443 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "198.18.1.2", - "portValue": 443 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden b/agent/xds/testdata/endpoints/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden index 03bd971ef6e88..b993f6a71e49f 100644 --- a/agent/xds/testdata/endpoints/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden +++ b/agent/xds/testdata/endpoints/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden @@ -35,40 +35,6 @@ } ] }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.10.1.3", - "portValue": 8080 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 128 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.10.1.4", - "portValue": 8080 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, { "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", @@ -170,72 +136,6 @@ ] } ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "exported~v2.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.10.1.4", - "portValue": 8080 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "v1.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.10.1.3", - "portValue": 8080 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 128 - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "v2.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.10.1.4", - "portValue": 8080 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] } ], "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", diff --git a/agent/xds/testdata/listeners/api-gateway-with-http-route-and-inline-certificate.latest.golden b/agent/xds/testdata/listeners/api-gateway-with-http-route-and-inline-certificate.latest.golden new file mode 100644 index 0000000000000..97fe8332eecf1 --- /dev/null +++ b/agent/xds/testdata/listeners/api-gateway-with-http-route-and-inline-certificate.latest.golden @@ -0,0 +1,54 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "http:1.2.3.4:8080", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "ingress_upstream_8080", + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "8080" + }, + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden b/agent/xds/testdata/listeners/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden deleted file mode 100644 index 935e330a59836..0000000000000 --- a/agent/xds/testdata/listeners/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden +++ /dev/null @@ -1,85 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "http:1.2.3.4:8080", - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8080 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "ingress_upstream_certificate", - "rds": { - "configSource": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "routeConfigName": "8080" - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICljCCAX4CCQCQMDsYO8FrPjANBgkqhkiG9w0BAQsFADANMQswCQYDVQQGEwJV\nUzAeFw0yMjEyMjAxNzUwMjVaFw0yNzEyMTkxNzUwMjVaMA0xCzAJBgNVBAYTAlVT\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx95Opa6t4lGEpiTUogEB\nptqOdam2ch4BHQGhNhX/MrDwwuZQhttBwMfngQ/wd9NmYEPAwj0dumUoAITIq6i2\njQlhqTodElkbsd5vWY8R/bxJWQSoNvVE12TlzECxGpJEiHt4W0r8pGffk+rvplji\nUyCfnT1kGF3znOSjK1hRMTn6RKWCyYaBvXQiB4SGilfLgJcEpOJKtISIxmZ+S409\ng9X5VU88/Bmmrz4cMyxce86Kc2ug5/MOv0CjWDJwlrv8njneV2zvraQ61DDwQftr\nXOvuCbO5IBRHMOBHiHTZ4rtGuhMaIr21V4vb6n8c4YzXiFvhUYcyX7rltGZzVd+W\nmQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBfCqoUIdPf/HGSbOorPyZWbyizNtHJ\nGL7x9cAeIYxpI5Y/WcO1o5v94lvrgm3FNfJoGKbV66+JxOge731FrfMpHplhar1Z\nRahYIzNLRBTLrwadLAZkApUpZvB8qDK4knsTWFYujNsylCww2A6ajzIMFNU4GkUK\nNtyHRuD+KYRmjXtyX1yHNqfGN3vOQmwavHq2R8wHYuBSc6LAHHV9vG+j0VsgMELO\nqwxn8SmLkSKbf2+MsQVzLCXXN5u+D8Yv+4py+oKP4EQ5aFZuDEx+r/G/31rTthww\nAAJAMaoXmoYVdgXV+CPuBb2M4XCpuzLu3bcA2PXm5ipSyIgntMKwXV7r\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAx95Opa6t4lGEpiTUogEBptqOdam2ch4BHQGhNhX/MrDwwuZQ\nhttBwMfngQ/wd9NmYEPAwj0dumUoAITIq6i2jQlhqTodElkbsd5vWY8R/bxJWQSo\nNvVE12TlzECxGpJEiHt4W0r8pGffk+rvpljiUyCfnT1kGF3znOSjK1hRMTn6RKWC\nyYaBvXQiB4SGilfLgJcEpOJKtISIxmZ+S409g9X5VU88/Bmmrz4cMyxce86Kc2ug\n5/MOv0CjWDJwlrv8njneV2zvraQ61DDwQftrXOvuCbO5IBRHMOBHiHTZ4rtGuhMa\nIr21V4vb6n8c4YzXiFvhUYcyX7rltGZzVd+WmQIDAQABAoIBACYvceUzp2MK4gYA\nGWPOP2uKbBdM0l+hHeNV0WAM+dHMfmMuL4pkT36ucqt0ySOLjw6rQyOZG5nmA6t9\nsv0g4ae2eCMlyDIeNi1Yavu4Wt6YX4cTXbQKThm83C6W2X9THKbauBbxD621bsDK\n7PhiGPN60yPue7YwFQAPqqD4YaK+s22HFIzk9gwM/rkvAUNwRv7SyHMiFe4Igc1C\nEev7iHWzvj5Heoz6XfF+XNF9DU+TieSUAdjd56VyUb8XL4+uBTOhHwLiXvAmfaMR\nHvpcxeKnYZusS6NaOxcUHiJnsLNWrxmJj9WEGgQzuLxcLjTe4vVmELVZD8t3QUKj\nPAxu8tUCgYEA7KIWVn9dfVpokReorFym+J8FzLwSktP9RZYEMonJo00i8aii3K9s\nu/aSwRWQSCzmON1ZcxZzWhwQF9usz6kGCk//9+4hlVW90GtNK0RD+j7sp4aT2JI8\n9eLEjTG+xSXa7XWe98QncjjL9lu/yrRncSTxHs13q/XP198nn2aYuQ8CgYEA2Dnt\nsRBzv0fFEvzzFv7G/5f85mouN38TUYvxNRTjBLCXl9DeKjDkOVZ2b6qlfQnYXIru\nH+W+v+AZEb6fySXc8FRab7lkgTMrwE+aeI4rkW7asVwtclv01QJ5wMnyT84AgDD/\nDgt/RThFaHgtU9TW5GOZveL+l9fVPn7vKFdTJdcCgYEArJ99zjHxwJ1whNAOk1av\n09UmRPm6TvRo4heTDk8oEoIWCNatoHI0z1YMLuENNSnT9Q280FFDayvnrY/qnD7A\nkktT/sjwJOG8q8trKzIMqQS4XWm2dxoPcIyyOBJfCbEY6XuRsUuePxwh5qF942EB\nyS9a2s6nC4Ix0lgPrqAIr48CgYBgS/Q6riwOXSU8nqCYdiEkBYlhCJrKpnJxF9T1\nofa0yPzKZP/8ZEfP7VzTwHjxJehQ1qLUW9pG08P2biH1UEKEWdzo8vT6wVJT1F/k\nHtTycR8+a+Hlk2SHVRHqNUYQGpuIe8mrdJ1as4Pd0d/F/P0zO9Rlh+mAsGPM8HUM\nT0+9gwKBgHDoerX7NTskg0H0t8O+iSMevdxpEWp34ZYa9gHiftTQGyrRgERCa7Gj\nnZPAxKb2JoWyfnu3v7G5gZ8fhDFsiOxLbZv6UZJBbUIh1MjJISpXrForDrC2QNLX\nkHrHfwBFDB3KMudhQknsJzEJKCL/KmFH6o0MvsoaT9yzEl3K+ah/\n-----END RSA PRIVATE KEY-----\n" - } - } - ], - "alpnProtocols": [ - "http/1.1" - ] - }, - "requireClientCertificate": false - } - } - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/api-gateway-with-http-route.latest.golden b/agent/xds/testdata/listeners/api-gateway-with-http-route.latest.golden deleted file mode 100644 index 935e330a59836..0000000000000 --- a/agent/xds/testdata/listeners/api-gateway-with-http-route.latest.golden +++ /dev/null @@ -1,85 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "http:1.2.3.4:8080", - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8080 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "ingress_upstream_certificate", - "rds": { - "configSource": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "routeConfigName": "8080" - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICljCCAX4CCQCQMDsYO8FrPjANBgkqhkiG9w0BAQsFADANMQswCQYDVQQGEwJV\nUzAeFw0yMjEyMjAxNzUwMjVaFw0yNzEyMTkxNzUwMjVaMA0xCzAJBgNVBAYTAlVT\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx95Opa6t4lGEpiTUogEB\nptqOdam2ch4BHQGhNhX/MrDwwuZQhttBwMfngQ/wd9NmYEPAwj0dumUoAITIq6i2\njQlhqTodElkbsd5vWY8R/bxJWQSoNvVE12TlzECxGpJEiHt4W0r8pGffk+rvplji\nUyCfnT1kGF3znOSjK1hRMTn6RKWCyYaBvXQiB4SGilfLgJcEpOJKtISIxmZ+S409\ng9X5VU88/Bmmrz4cMyxce86Kc2ug5/MOv0CjWDJwlrv8njneV2zvraQ61DDwQftr\nXOvuCbO5IBRHMOBHiHTZ4rtGuhMaIr21V4vb6n8c4YzXiFvhUYcyX7rltGZzVd+W\nmQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBfCqoUIdPf/HGSbOorPyZWbyizNtHJ\nGL7x9cAeIYxpI5Y/WcO1o5v94lvrgm3FNfJoGKbV66+JxOge731FrfMpHplhar1Z\nRahYIzNLRBTLrwadLAZkApUpZvB8qDK4knsTWFYujNsylCww2A6ajzIMFNU4GkUK\nNtyHRuD+KYRmjXtyX1yHNqfGN3vOQmwavHq2R8wHYuBSc6LAHHV9vG+j0VsgMELO\nqwxn8SmLkSKbf2+MsQVzLCXXN5u+D8Yv+4py+oKP4EQ5aFZuDEx+r/G/31rTthww\nAAJAMaoXmoYVdgXV+CPuBb2M4XCpuzLu3bcA2PXm5ipSyIgntMKwXV7r\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAx95Opa6t4lGEpiTUogEBptqOdam2ch4BHQGhNhX/MrDwwuZQ\nhttBwMfngQ/wd9NmYEPAwj0dumUoAITIq6i2jQlhqTodElkbsd5vWY8R/bxJWQSo\nNvVE12TlzECxGpJEiHt4W0r8pGffk+rvpljiUyCfnT1kGF3znOSjK1hRMTn6RKWC\nyYaBvXQiB4SGilfLgJcEpOJKtISIxmZ+S409g9X5VU88/Bmmrz4cMyxce86Kc2ug\n5/MOv0CjWDJwlrv8njneV2zvraQ61DDwQftrXOvuCbO5IBRHMOBHiHTZ4rtGuhMa\nIr21V4vb6n8c4YzXiFvhUYcyX7rltGZzVd+WmQIDAQABAoIBACYvceUzp2MK4gYA\nGWPOP2uKbBdM0l+hHeNV0WAM+dHMfmMuL4pkT36ucqt0ySOLjw6rQyOZG5nmA6t9\nsv0g4ae2eCMlyDIeNi1Yavu4Wt6YX4cTXbQKThm83C6W2X9THKbauBbxD621bsDK\n7PhiGPN60yPue7YwFQAPqqD4YaK+s22HFIzk9gwM/rkvAUNwRv7SyHMiFe4Igc1C\nEev7iHWzvj5Heoz6XfF+XNF9DU+TieSUAdjd56VyUb8XL4+uBTOhHwLiXvAmfaMR\nHvpcxeKnYZusS6NaOxcUHiJnsLNWrxmJj9WEGgQzuLxcLjTe4vVmELVZD8t3QUKj\nPAxu8tUCgYEA7KIWVn9dfVpokReorFym+J8FzLwSktP9RZYEMonJo00i8aii3K9s\nu/aSwRWQSCzmON1ZcxZzWhwQF9usz6kGCk//9+4hlVW90GtNK0RD+j7sp4aT2JI8\n9eLEjTG+xSXa7XWe98QncjjL9lu/yrRncSTxHs13q/XP198nn2aYuQ8CgYEA2Dnt\nsRBzv0fFEvzzFv7G/5f85mouN38TUYvxNRTjBLCXl9DeKjDkOVZ2b6qlfQnYXIru\nH+W+v+AZEb6fySXc8FRab7lkgTMrwE+aeI4rkW7asVwtclv01QJ5wMnyT84AgDD/\nDgt/RThFaHgtU9TW5GOZveL+l9fVPn7vKFdTJdcCgYEArJ99zjHxwJ1whNAOk1av\n09UmRPm6TvRo4heTDk8oEoIWCNatoHI0z1YMLuENNSnT9Q280FFDayvnrY/qnD7A\nkktT/sjwJOG8q8trKzIMqQS4XWm2dxoPcIyyOBJfCbEY6XuRsUuePxwh5qF942EB\nyS9a2s6nC4Ix0lgPrqAIr48CgYBgS/Q6riwOXSU8nqCYdiEkBYlhCJrKpnJxF9T1\nofa0yPzKZP/8ZEfP7VzTwHjxJehQ1qLUW9pG08P2biH1UEKEWdzo8vT6wVJT1F/k\nHtTycR8+a+Hlk2SHVRHqNUYQGpuIe8mrdJ1as4Pd0d/F/P0zO9Rlh+mAsGPM8HUM\nT0+9gwKBgHDoerX7NTskg0H0t8O+iSMevdxpEWp34ZYa9gHiftTQGyrRgERCa7Gj\nnZPAxKb2JoWyfnu3v7G5gZ8fhDFsiOxLbZv6UZJBbUIh1MjJISpXrForDrC2QNLX\nkHrHfwBFDB3KMudhQknsJzEJKCL/KmFH6o0MvsoaT9yzEl3K+ah/\n-----END RSA PRIVATE KEY-----\n" - } - } - ], - "alpnProtocols": [ - "http/1.1" - ] - }, - "requireClientCertificate": false - } - } - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/api-gateway-with-multiple-inline-certificates.latest.golden b/agent/xds/testdata/listeners/api-gateway-with-multiple-inline-certificates.latest.golden deleted file mode 100644 index 2729468123744..0000000000000 --- a/agent/xds/testdata/listeners/api-gateway-with-multiple-inline-certificates.latest.golden +++ /dev/null @@ -1,102 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "service:1.2.3.4:8080", - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8080 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "serverNames": [ - "" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "ingress_upstream_certificate", - "cluster": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICljCCAX4CCQCQMDsYO8FrPjANBgkqhkiG9w0BAQsFADANMQswCQYDVQQGEwJV\nUzAeFw0yMjEyMjAxNzUwMjVaFw0yNzEyMTkxNzUwMjVaMA0xCzAJBgNVBAYTAlVT\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx95Opa6t4lGEpiTUogEB\nptqOdam2ch4BHQGhNhX/MrDwwuZQhttBwMfngQ/wd9NmYEPAwj0dumUoAITIq6i2\njQlhqTodElkbsd5vWY8R/bxJWQSoNvVE12TlzECxGpJEiHt4W0r8pGffk+rvplji\nUyCfnT1kGF3znOSjK1hRMTn6RKWCyYaBvXQiB4SGilfLgJcEpOJKtISIxmZ+S409\ng9X5VU88/Bmmrz4cMyxce86Kc2ug5/MOv0CjWDJwlrv8njneV2zvraQ61DDwQftr\nXOvuCbO5IBRHMOBHiHTZ4rtGuhMaIr21V4vb6n8c4YzXiFvhUYcyX7rltGZzVd+W\nmQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBfCqoUIdPf/HGSbOorPyZWbyizNtHJ\nGL7x9cAeIYxpI5Y/WcO1o5v94lvrgm3FNfJoGKbV66+JxOge731FrfMpHplhar1Z\nRahYIzNLRBTLrwadLAZkApUpZvB8qDK4knsTWFYujNsylCww2A6ajzIMFNU4GkUK\nNtyHRuD+KYRmjXtyX1yHNqfGN3vOQmwavHq2R8wHYuBSc6LAHHV9vG+j0VsgMELO\nqwxn8SmLkSKbf2+MsQVzLCXXN5u+D8Yv+4py+oKP4EQ5aFZuDEx+r/G/31rTthww\nAAJAMaoXmoYVdgXV+CPuBb2M4XCpuzLu3bcA2PXm5ipSyIgntMKwXV7r\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAx95Opa6t4lGEpiTUogEBptqOdam2ch4BHQGhNhX/MrDwwuZQ\nhttBwMfngQ/wd9NmYEPAwj0dumUoAITIq6i2jQlhqTodElkbsd5vWY8R/bxJWQSo\nNvVE12TlzECxGpJEiHt4W0r8pGffk+rvpljiUyCfnT1kGF3znOSjK1hRMTn6RKWC\nyYaBvXQiB4SGilfLgJcEpOJKtISIxmZ+S409g9X5VU88/Bmmrz4cMyxce86Kc2ug\n5/MOv0CjWDJwlrv8njneV2zvraQ61DDwQftrXOvuCbO5IBRHMOBHiHTZ4rtGuhMa\nIr21V4vb6n8c4YzXiFvhUYcyX7rltGZzVd+WmQIDAQABAoIBACYvceUzp2MK4gYA\nGWPOP2uKbBdM0l+hHeNV0WAM+dHMfmMuL4pkT36ucqt0ySOLjw6rQyOZG5nmA6t9\nsv0g4ae2eCMlyDIeNi1Yavu4Wt6YX4cTXbQKThm83C6W2X9THKbauBbxD621bsDK\n7PhiGPN60yPue7YwFQAPqqD4YaK+s22HFIzk9gwM/rkvAUNwRv7SyHMiFe4Igc1C\nEev7iHWzvj5Heoz6XfF+XNF9DU+TieSUAdjd56VyUb8XL4+uBTOhHwLiXvAmfaMR\nHvpcxeKnYZusS6NaOxcUHiJnsLNWrxmJj9WEGgQzuLxcLjTe4vVmELVZD8t3QUKj\nPAxu8tUCgYEA7KIWVn9dfVpokReorFym+J8FzLwSktP9RZYEMonJo00i8aii3K9s\nu/aSwRWQSCzmON1ZcxZzWhwQF9usz6kGCk//9+4hlVW90GtNK0RD+j7sp4aT2JI8\n9eLEjTG+xSXa7XWe98QncjjL9lu/yrRncSTxHs13q/XP198nn2aYuQ8CgYEA2Dnt\nsRBzv0fFEvzzFv7G/5f85mouN38TUYvxNRTjBLCXl9DeKjDkOVZ2b6qlfQnYXIru\nH+W+v+AZEb6fySXc8FRab7lkgTMrwE+aeI4rkW7asVwtclv01QJ5wMnyT84AgDD/\nDgt/RThFaHgtU9TW5GOZveL+l9fVPn7vKFdTJdcCgYEArJ99zjHxwJ1whNAOk1av\n09UmRPm6TvRo4heTDk8oEoIWCNatoHI0z1YMLuENNSnT9Q280FFDayvnrY/qnD7A\nkktT/sjwJOG8q8trKzIMqQS4XWm2dxoPcIyyOBJfCbEY6XuRsUuePxwh5qF942EB\nyS9a2s6nC4Ix0lgPrqAIr48CgYBgS/Q6riwOXSU8nqCYdiEkBYlhCJrKpnJxF9T1\nofa0yPzKZP/8ZEfP7VzTwHjxJehQ1qLUW9pG08P2biH1UEKEWdzo8vT6wVJT1F/k\nHtTycR8+a+Hlk2SHVRHqNUYQGpuIe8mrdJ1as4Pd0d/F/P0zO9Rlh+mAsGPM8HUM\nT0+9gwKBgHDoerX7NTskg0H0t8O+iSMevdxpEWp34ZYa9gHiftTQGyrRgERCa7Gj\nnZPAxKb2JoWyfnu3v7G5gZ8fhDFsiOxLbZv6UZJBbUIh1MjJISpXrForDrC2QNLX\nkHrHfwBFDB3KMudhQknsJzEJKCL/KmFH6o0MvsoaT9yzEl3K+ah/\n-----END RSA PRIVATE KEY-----\n" - } - } - ] - }, - "requireClientCertificate": false - } - } - }, - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "ingress_upstream_default", - "cluster": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - } - }, - "requireClientCertificate": false - } - } - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-chain-and-overrides.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-chain-and-overrides.latest.golden index 1fc03f74705de..03e15abeaa728 100644 --- a/agent/xds/testdata/listeners/connect-proxy-with-chain-and-overrides.latest.golden +++ b/agent/xds/testdata/listeners/connect-proxy-with-chain-and-overrides.latest.golden @@ -148,4 +148,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "nonce": "00000001" -} +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden deleted file mode 100644 index 76c41c8b7c979..0000000000000 --- a/agent/xds/testdata/listeners/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden +++ /dev/null @@ -1,114 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "payments?peer=cloud:custom-upstream", - "address": { - "socketAddress": { - "address": "11.11.11.11", - "portValue": 11111 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "foo-stats", - "cluster": "random-cluster" - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener:0.0.0.0:9999", - "address": { - "socketAddress": { - "address": "0.0.0.0", - "portValue": 9999 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - } - }, - "requireClientCertificate": true - } - } - } - ], - "trafficDirection": "INBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "refunds?peer=cloud:127.0.0.1:9090", - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream_peered.refunds.default.cloud", - "cluster": "refunds.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul" - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-peered-upstreams-http2.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-peered-upstreams-http2.latest.golden deleted file mode 100644 index a18dfc1484021..0000000000000 --- a/agent/xds/testdata/listeners/connect-proxy-with-peered-upstreams-http2.latest.golden +++ /dev/null @@ -1,189 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "payments?peer=cloud:127.0.0.1:9090", - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "upstream_peered.payments.default.cloud", - "routeConfig": { - "name": "payments?peer=cloud", - "virtualHosts": [ - { - "name": "payments.default.cloud", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "payments.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener:0.0.0.0:9999", - "address": { - "socketAddress": { - "address": "0.0.0.0", - "portValue": 9999 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - } - }, - "requireClientCertificate": true - } - } - } - ], - "trafficDirection": "INBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "refunds?peer=cloud:127.0.0.1:9090", - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "upstream_peered.refunds.default.cloud", - "routeConfig": { - "name": "refunds?peer=cloud", - "virtualHosts": [ - { - "name": "refunds.default.cloud", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "refunds.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden index f091cd40b5521..549af29cb4456 100644 --- a/agent/xds/testdata/listeners/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden +++ b/agent/xds/testdata/listeners/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden @@ -28,11 +28,11 @@ }, { "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "outbound_listener:127.0.0.1:1234", + "name": "outbound_listener:127.0.0.1:15001", "address": { "socketAddress": { "address": "127.0.0.1", - "portValue": 1234 + "portValue": 15001 } }, "defaultFilterChain": { @@ -166,4 +166,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "nonce": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/listeners/custom-upstream-with-prepared-query.latest.golden b/agent/xds/testdata/listeners/custom-upstream-with-prepared-query.latest.golden deleted file mode 100644 index 636fb2f606b8f..0000000000000 --- a/agent/xds/testdata/listeners/custom-upstream-with-prepared-query.latest.golden +++ /dev/null @@ -1,114 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "db:custom-upstream", - "address": { - "socketAddress": { - "address": "11.11.11.11", - "portValue": 11111 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "foo-stats", - "cluster": "random-cluster" - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "prepared_query:geo-cache:127.10.10.10:8181", - "address": { - "socketAddress": { - "address": "127.10.10.10", - "portValue": 8181 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.prepared_query_geo-cache", - "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener:0.0.0.0:9999", - "address": { - "socketAddress": { - "address": "0.0.0.0", - "portValue": 9999 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - } - }, - "requireClientCertificate": true - } - } - } - ], - "trafficDirection": "INBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/expose-checks-grpc.latest.golden b/agent/xds/testdata/listeners/expose-checks-grpc.latest.golden deleted file mode 100644 index 6551d151fc66e..0000000000000 --- a/agent/xds/testdata/listeners/expose-checks-grpc.latest.golden +++ /dev/null @@ -1,143 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "exposed_path_grpchealthv1HealthCheck:1.2.3.4:21501", - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 21501 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "sourcePrefixRanges": [ - { - "addressPrefix": "127.0.0.1", - "prefixLen": 8 - }, - { - "addressPrefix": "192.0.2.1", - "prefixLen": 32 - }, - { - "addressPrefix": "::1", - "prefixLen": 128 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "exposed_path_filter_grpchealthv1HealthCheck_21501", - "routeConfig": { - "name": "exposed_path_filter_grpchealthv1HealthCheck_21501", - "virtualHosts": [ - { - "name": "exposed_path_filter_grpchealthv1HealthCheck_21501", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "path": "/grpc.health.v1.Health/Check" - }, - "route": { - "cluster": "exposed_cluster_9090" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ] - } - ], - "trafficDirection": "INBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener:1.2.3.4:9090", - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 9090 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - } - }, - "requireClientCertificate": true - } - } - } - ], - "trafficDirection": "INBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/expose-checks-http-with-bind-override.latest.golden b/agent/xds/testdata/listeners/expose-checks-http-with-bind-override.latest.golden deleted file mode 100644 index 79f3555eb2782..0000000000000 --- a/agent/xds/testdata/listeners/expose-checks-http-with-bind-override.latest.golden +++ /dev/null @@ -1,142 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "exposed_path_debug:6.7.8.9:21500", - "address": { - "socketAddress": { - "address": "6.7.8.9", - "portValue": 21500 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "sourcePrefixRanges": [ - { - "addressPrefix": "127.0.0.1", - "prefixLen": 8 - }, - { - "addressPrefix": "192.0.2.1", - "prefixLen": 32 - }, - { - "addressPrefix": "::1", - "prefixLen": 128 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "exposed_path_filter_debug_21500", - "routeConfig": { - "name": "exposed_path_filter_debug_21500", - "virtualHosts": [ - { - "name": "exposed_path_filter_debug_21500", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "path": "/debug" - }, - "route": { - "cluster": "exposed_cluster_8181" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ] - } - ], - "trafficDirection": "INBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener:6.7.8.9:8080", - "address": { - "socketAddress": { - "address": "6.7.8.9", - "portValue": 8080 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - } - }, - "requireClientCertificate": true - } - } - } - ], - "trafficDirection": "INBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/expose-checks-http.latest.golden b/agent/xds/testdata/listeners/expose-checks.latest.golden similarity index 100% rename from agent/xds/testdata/listeners/expose-checks-http.latest.golden rename to agent/xds/testdata/listeners/expose-checks.latest.golden diff --git a/agent/xds/testdata/listeners/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden b/agent/xds/testdata/listeners/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden deleted file mode 100644 index 08b36fef24334..0000000000000 --- a/agent/xds/testdata/listeners/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden +++ /dev/null @@ -1,166 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "http:1.2.3.4:8080", - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8080 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "ingress_upstream_8080", - "rds": { - "configSource": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "routeConfigName": "8080" - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": { - "cipherSuites": [ - "ECDHE-RSA-AES256-SHA" - ] - }, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - }, - "alpnProtocols": [ - "http/1.1" - ] - }, - "requireClientCertificate": false - } - } - } - ], - "trafficDirection": "OUTBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "http:1.2.3.4:8081", - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8081 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "ingress_upstream_8081", - "rds": { - "configSource": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "routeConfigName": "8081" - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": { - "cipherSuites": [ - "ECDHE-RSA-CHACHA20-POLY1305", - "ECDHE-ECDSA-CHACHA20-POLY1305" - ] - }, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - }, - "alpnProtocols": [ - "http/1.1" - ] - }, - "requireClientCertificate": false - } - } - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-tls-mixed-max-version-listeners.latest.golden b/agent/xds/testdata/listeners/ingress-with-tls-mixed-max-version-listeners.latest.golden deleted file mode 100644 index c9e56105a5c56..0000000000000 --- a/agent/xds/testdata/listeners/ingress-with-tls-mixed-max-version-listeners.latest.golden +++ /dev/null @@ -1,238 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "http:1.2.3.4:8080", - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8080 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "ingress_upstream_8080", - "rds": { - "configSource": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "routeConfigName": "8080" - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": { - "tlsMaximumProtocolVersion": "TLSv1_2" - }, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - }, - "alpnProtocols": [ - "http/1.1" - ] - }, - "requireClientCertificate": false - } - } - } - ], - "trafficDirection": "OUTBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "http:1.2.3.4:8081", - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8081 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "ingress_upstream_8081", - "rds": { - "configSource": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "routeConfigName": "8081" - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": { - "tlsMaximumProtocolVersion": "TLSv1_0" - }, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - }, - "alpnProtocols": [ - "http/1.1" - ] - }, - "requireClientCertificate": false - } - } - } - ], - "trafficDirection": "OUTBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "http:1.2.3.4:8082", - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8082 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "ingress_upstream_8082", - "rds": { - "configSource": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "routeConfigName": "8082" - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": { - "tlsMaximumProtocolVersion": "TLSv1_3" - }, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - }, - "alpnProtocols": [ - "http/1.1" - ] - }, - "requireClientCertificate": false - } - } - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/mesh-gateway-using-federation-control-plane.latest.golden b/agent/xds/testdata/listeners/mesh-gateway-using-federation-control-plane.latest.golden deleted file mode 100644 index fef17ff195aea..0000000000000 --- a/agent/xds/testdata/listeners/mesh-gateway-using-federation-control-plane.latest.golden +++ /dev/null @@ -1,181 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "default:1.2.3.4:8443", - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8443 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "serverNames": [ - "*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "mesh_gateway_remote.default.dc2", - "cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - ] - }, - { - "filterChainMatch": { - "serverNames": [ - "*.dc4.internal.11111111-2222-3333-4444-555555555555.consul" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "mesh_gateway_remote.default.dc4", - "cluster": "dc4.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - ] - }, - { - "filterChainMatch": { - "serverNames": [ - "*.dc6.internal.11111111-2222-3333-4444-555555555555.consul" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "mesh_gateway_remote.default.dc6", - "cluster": "dc6.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - ] - }, - { - "filterChainMatch": { - "serverNames": [ - "*.server.dc2.consul" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "mesh_gateway_remote.default.dc2", - "cluster": "server.dc2.consul" - } - } - ] - }, - { - "filterChainMatch": { - "serverNames": [ - "*.server.dc4.consul" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "mesh_gateway_remote.default.dc4", - "cluster": "server.dc4.consul" - } - } - ] - }, - { - "filterChainMatch": { - "serverNames": [ - "*.server.dc6.consul" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "mesh_gateway_remote.default.dc6", - "cluster": "server.dc6.consul" - } - } - ] - }, - { - "filterChainMatch": { - "serverNames": [ - "node1.server.dc1.consul" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "mesh_gateway_local_server.default.dc1", - "cluster": "node1.server.dc1.consul" - } - } - ] - }, - { - "filterChainMatch": { - "serverNames": [ - "node2.server.dc1.consul" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "mesh_gateway_local_server.default.dc1", - "cluster": "node2.server.dc1.consul" - } - } - ] - }, - { - "filters": [ - { - "name": "envoy.filters.network.sni_cluster", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "mesh_gateway_local.default", - "cluster": "" - } - } - ] - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/terminating-gateway-custom-trace-listener.latest.golden b/agent/xds/testdata/listeners/terminating-gateway-custom-trace-listener.latest.golden deleted file mode 100644 index e85075430303e..0000000000000 --- a/agent/xds/testdata/listeners/terminating-gateway-custom-trace-listener.latest.golden +++ /dev/null @@ -1,246 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "default:1.2.3.4:8443", - "address": { - "socketAddress": { - "address": "1.2.3.4", - "portValue": 8443 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "serverNames": [ - "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.api.default.default.dc1", - "cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkKgAwIBAgIRAJrvEdaRAkSltrotd/l/j2cwCgYIKoZIzj0EAwIwgbgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjE/MD0GA1UEAxM2Q29uc3VsIEFnZW50IENB\nIDk2NjM4NzM1MDkzNTU5NTIwNDk3MTQwOTU3MDY1MTc0OTg3NDMxMB4XDTIwMDQx\nNDIyMzE1MloXDTIxMDQxNDIyMzE1MlowHDEaMBgGA1UEAxMRc2VydmVyLmRjMS5j\nb25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ4v0FoIYI0OWmxE2MR6w5l\n0pWGhc02RpsOPj/6RS1fmXMMu7JzPzwCmkGcR16RlwwhNFKCZsWpvAjVRHf/pTp+\no4HHMIHEMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\nBQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgk7kABFitAy3PluyNtmzYiC7H\njSN8W/K/OXNJQAQAscMwKwYDVR0jBCQwIoAgNKbPPepvRHXSAPTc+a/BXBzFX1qJ\ny+Zi7qtjlFX7qtUwLQYDVR0RBCYwJIIRc2VydmVyLmRjMS5jb25zdWyCCWxvY2Fs\naG9zdIcEfwAAATAKBggqhkjOPQQDAgNJADBGAiEAhP4HmN5BWysWTbQWClXaWUah\nLpBGFrvc/2cCQuyEZKsCIQD6JyYCYMArtWwZ4G499zktxrFlqfX14bqyONrxtA5I\nDw==\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIE3KbKXHdsa0vvC1fysQaGdoJRgjRALIolI4XJanie+coAoGCCqGSM49\nAwEHoUQDQgAEOL9BaCGCNDlpsRNjEesOZdKVhoXNNkabDj4/+kUtX5lzDLuycz88\nAppBnEdekZcMITRSgmbFqbwI1UR3/6U6fg==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - } - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "serverNames": [ - "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.cache.default.default.dc1", - "cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICmjCCAkGgAwIBAgIQe1ZmC0rzRwer6jaH1YIUIjAKBggqhkjOPQQDAjCBuDEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMT8wPQYDVQQDEzZDb25zdWwgQWdlbnQgQ0Eg\nODE5ODAwNjg0MDM0MTM3ODkyNDYxNTA1MDk0NDU3OTU1MTQxNjEwHhcNMjAwNjE5\nMTU1MjAzWhcNMjEwNjE5MTU1MjAzWjAcMRowGAYDVQQDExFzZXJ2ZXIuZGMxLmNv\nbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2aWaaa3fpQLBayheHiKlrH\n+z53m0frfGknKjOhOPVYDVHV8x0OE01negswVQbKHAtxPf1M8Zy+WbI9rK7Ua1mj\ngccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\nBQcDAjAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCDf9CPBSUwwZvpeW73oJLTmgQE2\ntW1NKpL5t1uq9WFcqDArBgNVHSMEJDAigCCPPd/NxgZB0tq2M8pdVpPj3Cr79iTv\ni4/T1ysodfMb7zAtBgNVHREEJjAkghFzZXJ2ZXIuZGMxLmNvbnN1bIIJbG9jYWxo\nb3N0hwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIFCjFZAoXq0s2ied2eIBv0i1KoW5\nIhCylnKFt6iHkyDeAiBBCByTcjHRgEQmqyPojQKoO584EFiczTub9aWdnf9tEw==\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINsen3S8xzxMrKcRZIvxXzhKDn43Tw9ttqWEFU9TqS5hoAoGCCqGSM49\nAwEHoUQDQgAEfZpZpprd+lAsFrKF4eIqWsf7PnebR+t8aScqM6E49VgNUdXzHQ4T\nTWd6CzBVBsocC3E9/UzxnL5Zsj2srtRrWQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - } - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "serverNames": [ - "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.db.default.default.dc1", - "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkOgAwIBAgIRAKF+qDJbaOULNL1TIatrsBowCgYIKoZIzj0EAwIwgbkx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB\nIDE4Nzg3MDAwNjUzMDcxOTYzNTk1ODkwNTE1ODY1NjEzMDA2MTU0NDAeFw0yMDA2\nMTkxNTMxMzRaFw0yMTA2MTkxNTMxMzRaMBwxGjAYBgNVBAMTEXNlcnZlci5kYzEu\nY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdQ8Igci5f7ZvvCVsxXt9\ntLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZbz/82EwPoS7Dqo3LTK4IuelOimoNNxuk\nkaOBxzCBxDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\nAQUFBwMCMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEILzTLkfJcdWQnTMKUcai/YJq\n0RqH1pjCqtY7SOU4gGOTMCsGA1UdIwQkMCKAIMa2vNcTEC5AGfHIYARJ/4sodX0o\nLzCj3lpw7BcEzPTcMC0GA1UdEQQmMCSCEXNlcnZlci5kYzEuY29uc3Vsgglsb2Nh\nbGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIgBZ/Z4GSLEc98WvT/qjTVCNTG\n1WNaAaesVbkRx+J0yl8CIQDAVoqY9ByA5vKHjnQrxWlc/JUtJz8wudg7e/OCRriP\nSg==\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIN1v14FaNxgY4MgjDOOWthen8dgwB0lNMs9/j2TfrnxzoAoGCCqGSM49\nAwEHoUQDQgAEdQ8Igci5f7ZvvCVsxXt9tLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZ\nbz/82EwPoS7Dqo3LTK4IuelOimoNNxukkQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - } - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "serverNames": [ - "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.web.default.default.dc1", - "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - } - } - }, - "requireClientCertificate": true - } - } - }, - { - "filters": [ - { - "name": "envoy.filters.network.sni_cluster", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "terminating_gateway.default", - "cluster": "" - } - } - ] - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "INBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/routes/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden b/agent/xds/testdata/routes/api-gateway-with-http-route-and-inline-certificate.latest.golden similarity index 94% rename from agent/xds/testdata/routes/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden rename to agent/xds/testdata/routes/api-gateway-with-http-route-and-inline-certificate.latest.golden index 4a41a6d6dfb10..a1669268ec4e0 100644 --- a/agent/xds/testdata/routes/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden +++ b/agent/xds/testdata/routes/api-gateway-with-http-route-and-inline-certificate.latest.golden @@ -17,8 +17,7 @@ "prefix": "/" }, "route": { - "cluster": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "idleTimeout": "30s" + "cluster": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" }, "requestHeadersToAdd": [ { diff --git a/agent/xds/testdata/routes/api-gateway-with-http-route.latest.golden b/agent/xds/testdata/routes/api-gateway-with-http-route.latest.golden deleted file mode 100644 index c79697246fc78..0000000000000 --- a/agent/xds/testdata/routes/api-gateway-with-http-route.latest.golden +++ /dev/null @@ -1,59 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "8080", - "virtualHosts": [ - { - "name": "api-gateway-listener-9b9265b", - "domains": [ - "*", - "*:8080" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "timeout": "30s", - "idleTimeout": "30s", - "retryPolicy": { - "retryOn": "cancelled,connect-failure,retriable-status-codes", - "numRetries": 3, - "retriableStatusCodes": [ - 500 - ] - } - }, - "requestHeadersToAdd": [ - { - "header": { - "key": "X-Header-Add", - "value": "added" - }, - "append": true - }, - { - "header": { - "key": "X-Header-Set", - "value": "set" - }, - "append": false - } - ], - "requestHeadersToRemove": [ - "X-Header-Remove" - ] - } - ] - } - ], - "validateClusters": true - } - ], - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/routes/api-gateway-with-multiple-inline-certificates.latest.golden b/agent/xds/testdata/routes/api-gateway-with-multiple-inline-certificates.latest.golden deleted file mode 100644 index 306f5220e7b9c..0000000000000 --- a/agent/xds/testdata/routes/api-gateway-with-multiple-inline-certificates.latest.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-lb-in-resolver.latest.golden b/agent/xds/testdata/routes/connect-proxy-lb-in-resolver.latest.golden index 75fe8ccc350fa..9cac480402557 100644 --- a/agent/xds/testdata/routes/connect-proxy-lb-in-resolver.latest.golden +++ b/agent/xds/testdata/routes/connect-proxy-lb-in-resolver.latest.golden @@ -47,11 +47,6 @@ "headerName": "x-user-id" } }, - { - "queryParameter": { - "name": "my-pretty-param" - } - }, { "connectionProperties": { "sourceIp": true diff --git a/agent/xds/testdata/routes/connect-proxy-resolver-with-lb.latest.golden b/agent/xds/testdata/routes/connect-proxy-resolver-with-lb.latest.golden deleted file mode 100644 index 547b923b0d6e7..0000000000000 --- a/agent/xds/testdata/routes/connect-proxy-resolver-with-lb.latest.golden +++ /dev/null @@ -1,30 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "db", - "virtualHosts": [ - { - "name": "db", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - ] - } - ], - "validateClusters": true - } - ], - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-route-to-lb-resolver.latest.golden b/agent/xds/testdata/routes/connect-proxy-route-to-lb-resolver.latest.golden deleted file mode 100644 index b364c9f9d0c7d..0000000000000 --- a/agent/xds/testdata/routes/connect-proxy-route-to-lb-resolver.latest.golden +++ /dev/null @@ -1,38 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "db", - "virtualHosts": [ - { - "name": "db", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/web" - }, - "route": { - "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } - }, - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - ] - } - ], - "validateClusters": true - } - ], - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-splitter-overweight.latest.golden b/agent/xds/testdata/routes/connect-proxy-splitter-overweight.latest.golden deleted file mode 100644 index 776509501f62c..0000000000000 --- a/agent/xds/testdata/routes/connect-proxy-splitter-overweight.latest.golden +++ /dev/null @@ -1,99 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "db", - "virtualHosts": [ - { - "name": "db", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "weightedClusters": { - "clusters": [ - { - "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "weight": 10000, - "requestHeadersToAdd": [ - { - "header": { - "key": "x-split-leg", - "value": "big" - }, - "append": false - } - ], - "responseHeadersToAdd": [ - { - "header": { - "key": "x-split-leg", - "value": "big" - }, - "append": false - } - ] - }, - { - "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "weight": 10000, - "requestHeadersToAdd": [ - { - "header": { - "key": "x-split-leg", - "value": "goldilocks" - }, - "append": false - } - ], - "responseHeadersToAdd": [ - { - "header": { - "key": "x-split-leg", - "value": "goldilocks" - }, - "append": false - } - ] - }, - { - "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "weight": 10000, - "requestHeadersToAdd": [ - { - "header": { - "key": "x-split-leg", - "value": "small" - }, - "append": false - } - ], - "responseHeadersToAdd": [ - { - "header": { - "key": "x-split-leg", - "value": "small" - }, - "append": false - } - ] - } - ] - } - } - } - ] - } - ], - "validateClusters": true - } - ], - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden deleted file mode 100644 index 9c050cbe6b4d4..0000000000000 --- a/agent/xds/testdata/routes/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-peered-upstreams-http2.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-peered-upstreams-http2.latest.golden deleted file mode 100644 index 306f5220e7b9c..0000000000000 --- a/agent/xds/testdata/routes/connect-proxy-with-peered-upstreams-http2.latest.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-lb-in-resolver.latest.golden b/agent/xds/testdata/routes/ingress-lb-in-resolver.latest.golden index 959cc72d4ef0b..f2bc276d8e99b 100644 --- a/agent/xds/testdata/routes/ingress-lb-in-resolver.latest.golden +++ b/agent/xds/testdata/routes/ingress-lb-in-resolver.latest.golden @@ -48,11 +48,6 @@ "headerName": "x-user-id" } }, - { - "queryParameter": { - "name": "my-pretty-param" - } - }, { "connectionProperties": { "sourceIp": true diff --git a/agent/xds/testdata/routes/terminating-gateway-lb-config.latest.golden b/agent/xds/testdata/routes/terminating-gateway-lb-config.latest.golden index 30b36d92d1943..cc49c907cce5c 100644 --- a/agent/xds/testdata/routes/terminating-gateway-lb-config.latest.golden +++ b/agent/xds/testdata/routes/terminating-gateway-lb-config.latest.golden @@ -1,41 +1,40 @@ { - "versionInfo": "00000001", - "resources": [ + "versionInfo": "00000001", + "resources": [ { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "virtualHosts": [ + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ { - "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "domains": [ + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "domains": [ "*" ], - "routes": [ + "routes": [ { - "match": { - "prefix": "/" + "match": { + "prefix": "/" }, - "route": { - "cluster": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "autoHostRewrite": true, - "timeout": "0.200s", - "hashPolicy": [ + "route": { + "cluster": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "autoHostRewrite": true, + "hashPolicy": [ { - "cookie": { - "name": "chocolate-chip" + "cookie": { + "name": "chocolate-chip" }, - "terminal": true + "terminal": true }, { - "header": { - "headerName": "x-user-id" + "header": { + "headerName": "x-user-id" } }, { - "connectionProperties": { - "sourceIp": true + "connectionProperties": { + "sourceIp": true }, - "terminal": true + "terminal": true } ] } @@ -43,43 +42,42 @@ ] } ], - "validateClusters": true + "validateClusters": true }, { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "virtualHosts": [ + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ { - "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "domains": [ + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "domains": [ "*" ], - "routes": [ + "routes": [ { - "match": { - "prefix": "/" + "match": { + "prefix": "/" }, - "route": { - "cluster": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "autoHostRewrite": true, - "timeout": "0.200s", - "hashPolicy": [ + "route": { + "cluster": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "autoHostRewrite": true, + "hashPolicy": [ { - "cookie": { - "name": "chocolate-chip" + "cookie": { + "name": "chocolate-chip" }, - "terminal": true + "terminal": true }, { - "header": { - "headerName": "x-user-id" + "header": { + "headerName": "x-user-id" } }, { - "connectionProperties": { - "sourceIp": true + "connectionProperties": { + "sourceIp": true }, - "terminal": true + "terminal": true } ] } @@ -87,43 +85,42 @@ ] } ], - "validateClusters": true + "validateClusters": true }, { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "virtualHosts": [ + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ { - "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "domains": [ + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "domains": [ "*" ], - "routes": [ + "routes": [ { - "match": { - "prefix": "/" + "match": { + "prefix": "/" }, - "route": { - "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "autoHostRewrite": true, - "timeout": "0.200s", - "hashPolicy": [ + "route": { + "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "autoHostRewrite": true, + "hashPolicy": [ { - "cookie": { - "name": "chocolate-chip" + "cookie": { + "name": "chocolate-chip" }, - "terminal": true + "terminal": true }, { - "header": { - "headerName": "x-user-id" + "header": { + "headerName": "x-user-id" } }, { - "connectionProperties": { - "sourceIp": true + "connectionProperties": { + "sourceIp": true }, - "terminal": true + "terminal": true } ] } @@ -131,9 +128,9 @@ ] } ], - "validateClusters": true + "validateClusters": true } ], - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "nonce": "00000001" } \ No newline at end of file diff --git a/agent/xds/testdata/secrets/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden b/agent/xds/testdata/secrets/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden deleted file mode 100644 index 95612291de707..0000000000000 --- a/agent/xds/testdata/secrets/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/api-gateway-with-http-route.latest.golden b/agent/xds/testdata/secrets/api-gateway-with-http-route.latest.golden deleted file mode 100644 index e6c25e165c65d..0000000000000 --- a/agent/xds/testdata/secrets/api-gateway-with-http-route.latest.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/api-gateway-with-multiple-inline-certificates.latest.golden b/agent/xds/testdata/secrets/api-gateway-with-multiple-inline-certificates.latest.golden deleted file mode 100644 index e6c25e165c65d..0000000000000 --- a/agent/xds/testdata/secrets/api-gateway-with-multiple-inline-certificates.latest.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden deleted file mode 100644 index 95612291de707..0000000000000 --- a/agent/xds/testdata/secrets/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-peered-upstreams-http2.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-peered-upstreams-http2.latest.golden deleted file mode 100644 index e6c25e165c65d..0000000000000 --- a/agent/xds/testdata/secrets/connect-proxy-with-peered-upstreams-http2.latest.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-peered-upstreams-listener-override.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-peered-upstreams-listener-override.latest.golden deleted file mode 100644 index 95612291de707..0000000000000 --- a/agent/xds/testdata/secrets/connect-proxy-with-peered-upstreams-listener-override.latest.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xds/testing.go b/agent/xds/testing.go index 916bbd9b50777..446f1a37a6518 100644 --- a/agent/xds/testing.go +++ b/agent/xds/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds diff --git a/agent/xds/validateupstream-test/validateupstream_test.go b/agent/xds/validateupstream-test/validateupstream_test.go index 9c57bdf81aaf2..f2810bb1c02e4 100644 --- a/agent/xds/validateupstream-test/validateupstream_test.go +++ b/agent/xds/validateupstream-test/validateupstream_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package validateupstream_test diff --git a/agent/xds/xds.go b/agent/xds/xds.go index aab5bc7aaf14c..07fe1c4731079 100644 --- a/agent/xds/xds.go +++ b/agent/xds/xds.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package xds provides an implementation of a gRPC service that exports Envoy's // xDS API for config discovery. Specifically we support the Aggregated diff --git a/agent/xds/xds_protocol_helpers_test.go b/agent/xds/xds_protocol_helpers_test.go index 655e0458f49e0..958a27474c441 100644 --- a/agent/xds/xds_protocol_helpers_test.go +++ b/agent/xds/xds_protocol_helpers_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds @@ -9,7 +9,10 @@ import ( "testing" "time" - "github.com/armon/go-metrics" + "github.com/hashicorp/consul/agent/connect" + "github.com/hashicorp/consul/agent/grpc-external/limiter" + "github.com/hashicorp/consul/envoyextensions/xdscommon" + envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" @@ -24,6 +27,8 @@ import ( envoy_upstreams_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/v3" envoy_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" + + "github.com/armon/go-metrics" "github.com/mitchellh/copystructure" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" @@ -31,15 +36,8 @@ import ( "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/wrapperspb" - "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/agent/grpc-external/limiter" "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/proxycfg-sources/catalog" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/sdk/testutil" ) @@ -73,14 +71,14 @@ func newTestSnapshot( // testing. It also implements ConnectAuthz to allow control over authorization. type testManager struct { sync.Mutex - stateChans map[structs.ServiceID]chan proxysnapshot.ProxySnapshot + stateChans map[structs.ServiceID]chan *proxycfg.ConfigSnapshot drainChans map[structs.ServiceID]chan struct{} cancels chan structs.ServiceID } func newTestManager(t *testing.T) *testManager { return &testManager{ - stateChans: map[structs.ServiceID]chan proxysnapshot.ProxySnapshot{}, + stateChans: map[structs.ServiceID]chan *proxycfg.ConfigSnapshot{}, drainChans: map[structs.ServiceID]chan struct{}{}, cancels: make(chan structs.ServiceID, 10), } @@ -90,12 +88,12 @@ func newTestManager(t *testing.T) *testManager { func (m *testManager) RegisterProxy(t *testing.T, proxyID structs.ServiceID) { m.Lock() defer m.Unlock() - m.stateChans[proxyID] = make(chan proxysnapshot.ProxySnapshot, 1) + m.stateChans[proxyID] = make(chan *proxycfg.ConfigSnapshot, 1) m.drainChans[proxyID] = make(chan struct{}) } // Deliver simulates a proxy registration -func (m *testManager) DeliverConfig(t *testing.T, proxyID structs.ServiceID, cfg proxysnapshot.ProxySnapshot) { +func (m *testManager) DeliverConfig(t *testing.T, proxyID structs.ServiceID, cfg *proxycfg.ConfigSnapshot) { t.Helper() m.Lock() defer m.Unlock() @@ -122,10 +120,7 @@ func (m *testManager) DrainStreams(proxyID structs.ServiceID) { } // Watch implements ConfigManager -func (m *testManager) Watch(id *pbresource.ID, _ string, _ string) (<-chan proxysnapshot.ProxySnapshot, - limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) { - // Create service ID - proxyID := structs.NewServiceID(id.Name, catalog.GetEnterpriseMetaFromResourceID(id)) +func (m *testManager) Watch(proxyID structs.ServiceID, _ string, _ string) (<-chan *proxycfg.ConfigSnapshot, limiter.SessionTerminatedChan, proxycfg.CancelFunc, error) { m.Lock() defer m.Unlock() @@ -233,7 +228,7 @@ func xdsNewEndpoint(ip string, port int) *envoy_endpoint_v3.LbEndpoint { return &envoy_endpoint_v3.LbEndpoint{ HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ Endpoint: &envoy_endpoint_v3.Endpoint{ - Address: response.MakeAddress(ip, port), + Address: makeAddress(ip, port), }, }, } @@ -242,7 +237,7 @@ func xdsNewEndpoint(ip string, port int) *envoy_endpoint_v3.LbEndpoint { func xdsNewEndpointWithHealth(ip string, port int, health envoy_core_v3.HealthStatus, weight int) *envoy_endpoint_v3.LbEndpoint { ep := xdsNewEndpoint(ip, port) ep.HealthStatus = health - ep.LoadBalancingWeight = response.MakeUint32Value(weight) + ep.LoadBalancingWeight = makeUint32Value(weight) return ep } @@ -302,7 +297,7 @@ func xdsNewTransportSocket( if downstream { var requireClientCertPB *wrapperspb.BoolValue if requireClientCert { - requireClientCertPB = response.MakeBoolValue(true) + requireClientCertPB = makeBoolValue(true) } tlsContext = &envoy_tls_v3.DownstreamTlsContext{ @@ -602,7 +597,7 @@ func makeTestListener(t *testing.T, snap *proxycfg.ConfigSnapshot, fixtureName s return &envoy_listener_v3.Listener{ // Envoy can't bind to port 1 Name: "public_listener:0.0.0.0:1", - Address: response.MakeAddress("0.0.0.0", 1), + Address: makeAddress("0.0.0.0", 1), TrafficDirection: envoy_core_v3.TrafficDirection_INBOUND, FilterChains: []*envoy_listener_v3.FilterChain{ { @@ -625,7 +620,7 @@ func makeTestListener(t *testing.T, snap *proxycfg.ConfigSnapshot, fixtureName s case "tcp:public_listener": return &envoy_listener_v3.Listener{ Name: "public_listener:0.0.0.0:9999", - Address: response.MakeAddress("0.0.0.0", 9999), + Address: makeAddress("0.0.0.0", 9999), TrafficDirection: envoy_core_v3.TrafficDirection_INBOUND, FilterChains: []*envoy_listener_v3.FilterChain{ { @@ -648,7 +643,7 @@ func makeTestListener(t *testing.T, snap *proxycfg.ConfigSnapshot, fixtureName s case "tcp:db": return &envoy_listener_v3.Listener{ Name: "db:127.0.0.1:9191", - Address: response.MakeAddress("127.0.0.1", 9191), + Address: makeAddress("127.0.0.1", 9191), TrafficDirection: envoy_core_v3.TrafficDirection_OUTBOUND, FilterChains: []*envoy_listener_v3.FilterChain{ { @@ -666,7 +661,7 @@ func makeTestListener(t *testing.T, snap *proxycfg.ConfigSnapshot, fixtureName s case "http2:db": return &envoy_listener_v3.Listener{ Name: "db:127.0.0.1:9191", - Address: response.MakeAddress("127.0.0.1", 9191), + Address: makeAddress("127.0.0.1", 9191), TrafficDirection: envoy_core_v3.TrafficDirection_OUTBOUND, FilterChains: []*envoy_listener_v3.FilterChain{ { @@ -694,7 +689,7 @@ func makeTestListener(t *testing.T, snap *proxycfg.ConfigSnapshot, fixtureName s case "http2:db:rds": return &envoy_listener_v3.Listener{ Name: "db:127.0.0.1:9191", - Address: response.MakeAddress("127.0.0.1", 9191), + Address: makeAddress("127.0.0.1", 9191), TrafficDirection: envoy_core_v3.TrafficDirection_OUTBOUND, FilterChains: []*envoy_listener_v3.FilterChain{ { @@ -725,7 +720,7 @@ func makeTestListener(t *testing.T, snap *proxycfg.ConfigSnapshot, fixtureName s case "http:db:rds": return &envoy_listener_v3.Listener{ Name: "db:127.0.0.1:9191", - Address: response.MakeAddress("127.0.0.1", 9191), + Address: makeAddress("127.0.0.1", 9191), TrafficDirection: envoy_core_v3.TrafficDirection_OUTBOUND, FilterChains: []*envoy_listener_v3.FilterChain{ { @@ -756,7 +751,7 @@ func makeTestListener(t *testing.T, snap *proxycfg.ConfigSnapshot, fixtureName s case "tcp:geo-cache": return &envoy_listener_v3.Listener{ Name: "prepared_query:geo-cache:127.10.10.10:8181", - Address: response.MakeAddress("127.10.10.10", 8181), + Address: makeAddress("127.10.10.10", 8181), TrafficDirection: envoy_core_v3.TrafficDirection_OUTBOUND, FilterChains: []*envoy_listener_v3.FilterChain{ { @@ -782,7 +777,7 @@ func makeTestRoute(t *testing.T, fixtureName string) *envoy_route_v3.RouteConfig case "http2:db", "http:db": return &envoy_route_v3.RouteConfiguration{ Name: "db", - ValidateClusters: response.MakeBoolValue(true), + ValidateClusters: makeBoolValue(true), VirtualHosts: []*envoy_route_v3.VirtualHost{ { Name: "db", diff --git a/agent/xds/z_xds_packages_test.go b/agent/xds/z_xds_packages_test.go index f5f0435189338..149490678cf27 100644 --- a/agent/xds/z_xds_packages_test.go +++ b/agent/xds/z_xds_packages_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xds diff --git a/agent/xdsv2/cluster_resources.go b/agent/xdsv2/cluster_resources.go deleted file mode 100644 index 5eedd1f21f378..0000000000000 --- a/agent/xdsv2/cluster_resources.go +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xdsv2 - -import ( - "errors" - "fmt" - - envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" - envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" - envoy_aggregate_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/clusters/aggregate/v3" - envoy_upstreams_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/v3" - envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" - - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" -) - -func (pr *ProxyResources) doesEnvoyClusterAlreadyExist(name string) bool { - // TODO(proxystate): consider using a map instead of [] for this kind of lookup - for _, envoyCluster := range pr.envoyResources[xdscommon.ClusterType] { - if envoyCluster.(*envoy_cluster_v3.Cluster).Name == name { - return true - } - } - return false -} - -func (pr *ProxyResources) makeXDSClusters() ([]proto.Message, error) { - clusters := make([]proto.Message, 0) - - for clusterName := range pr.proxyState.Clusters { - protoCluster, err := pr.makeClusters(clusterName) - // TODO: aggregate errors for clusters and still return any properly formed clusters. - if err != nil { - return nil, err - } - clusters = append(clusters, protoCluster...) - } - - return clusters, nil -} - -func (pr *ProxyResources) makeClusters(name string) ([]proto.Message, error) { - clusters := make([]proto.Message, 0) - proxyStateCluster, ok := pr.proxyState.Clusters[name] - if !ok { - return nil, fmt.Errorf("cluster %q not found", name) - } - - if pr.doesEnvoyClusterAlreadyExist(name) { - // don't error - return []proto.Message{}, nil - } - - switch proxyStateCluster.Group.(type) { - case *pbproxystate.Cluster_FailoverGroup: - fg := proxyStateCluster.GetFailoverGroup() - clusters, err := pr.makeEnvoyAggregateCluster(name, proxyStateCluster.Protocol, fg) - if err != nil { - return nil, err - } - for _, c := range clusters { - clusters = append(clusters, c) - } - - case *pbproxystate.Cluster_EndpointGroup: - eg := proxyStateCluster.GetEndpointGroup() - cluster, err := pr.makeEnvoyCluster(name, proxyStateCluster.Protocol, eg) - if err != nil { - return nil, err - } - clusters = append(clusters, cluster) - - default: - return nil, errors.New("cluster group type should be Endpoint Group or Failover Group") - } - return clusters, nil -} - -func (pr *ProxyResources) makeEnvoyCluster(name string, protocol string, eg *pbproxystate.EndpointGroup) (*envoy_cluster_v3.Cluster, error) { - if eg != nil { - switch t := eg.Group.(type) { - case *pbproxystate.EndpointGroup_Dynamic: - dynamic := eg.GetDynamic() - return pr.makeEnvoyDynamicCluster(name, protocol, dynamic) - case *pbproxystate.EndpointGroup_Static: - static := eg.GetStatic() - return pr.makeEnvoyStaticCluster(name, protocol, static) - case *pbproxystate.EndpointGroup_Dns: - dns := eg.GetDns() - return pr.makeEnvoyDnsCluster(name, protocol, dns) - case *pbproxystate.EndpointGroup_Passthrough: - passthrough := eg.GetPassthrough() - return pr.makeEnvoyPassthroughCluster(name, protocol, passthrough) - default: - return nil, fmt.Errorf("unsupported endpoint group type: %s", t) - } - } - return nil, fmt.Errorf("no endpoint group") -} - -func (pr *ProxyResources) makeEnvoyDynamicCluster(name string, protocol string, dynamic *pbproxystate.DynamicEndpointGroup) (*envoy_cluster_v3.Cluster, error) { - cluster := &envoy_cluster_v3.Cluster{ - Name: name, - ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_EDS}, - EdsClusterConfig: &envoy_cluster_v3.Cluster_EdsClusterConfig{ - EdsConfig: &envoy_core_v3.ConfigSource{ - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, - ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_Ads{ - Ads: &envoy_core_v3.AggregatedConfigSource{}, - }, - }, - }, - } - err := addHttpProtocolOptions(protocol, cluster) - if err != nil { - return nil, err - } - if dynamic.Config != nil { - if dynamic.Config.UseAltStatName { - cluster.AltStatName = name - } - cluster.ConnectTimeout = dynamic.Config.ConnectTimeout - if !dynamic.Config.DisablePanicThreshold { - cluster.CommonLbConfig = &envoy_cluster_v3.Cluster_CommonLbConfig{ - HealthyPanicThreshold: &envoy_type_v3.Percent{ - Value: 0, // disable panic threshold - }, - } - } - addEnvoyCircuitBreakers(dynamic.Config.CircuitBreakers, cluster) - addEnvoyOutlierDetection(dynamic.Config.OutlierDetection, cluster) - - err := addEnvoyLBToCluster(dynamic.Config, cluster) - if err != nil { - return nil, err - } - } - - if dynamic.OutboundTls != nil { - envoyTransportSocket, err := pr.makeEnvoyTransportSocket(dynamic.OutboundTls) - if err != nil { - return nil, err - } - cluster.TransportSocket = envoyTransportSocket - } - - return cluster, nil - -} - -func (pr *ProxyResources) makeEnvoyStaticCluster(name string, protocol string, static *pbproxystate.StaticEndpointGroup) (*envoy_cluster_v3.Cluster, error) { - endpointList, ok := pr.proxyState.Endpoints[name] - if !ok || endpointList == nil { - return nil, fmt.Errorf("static cluster %q is missing endpoints", name) - } - cluster := &envoy_cluster_v3.Cluster{ - Name: name, - ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_STATIC}, - LoadAssignment: makeEnvoyClusterLoadAssignment(name, endpointList.Endpoints), - } - err := addHttpProtocolOptions(protocol, cluster) - if err != nil { - return nil, err - } - - if static.Config != nil { - cluster.ConnectTimeout = static.Config.ConnectTimeout - addEnvoyCircuitBreakers(static.GetConfig().CircuitBreakers, cluster) - } - return cluster, nil -} -func (pr *ProxyResources) makeEnvoyDnsCluster(name string, protocol string, dns *pbproxystate.DNSEndpointGroup) (*envoy_cluster_v3.Cluster, error) { - return nil, nil -} -func (pr *ProxyResources) makeEnvoyPassthroughCluster(name string, protocol string, passthrough *pbproxystate.PassthroughEndpointGroup) (*envoy_cluster_v3.Cluster, error) { - cluster := &envoy_cluster_v3.Cluster{ - Name: name, - ConnectTimeout: passthrough.Config.ConnectTimeout, - LbPolicy: envoy_cluster_v3.Cluster_CLUSTER_PROVIDED, - ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_ORIGINAL_DST}, - } - if passthrough.OutboundTls != nil { - envoyTransportSocket, err := pr.makeEnvoyTransportSocket(passthrough.OutboundTls) - if err != nil { - return nil, err - } - cluster.TransportSocket = envoyTransportSocket - } - err := addHttpProtocolOptions(protocol, cluster) - if err != nil { - return nil, err - } - return cluster, nil -} - -func (pr *ProxyResources) makeEnvoyAggregateCluster(name string, protocol string, fg *pbproxystate.FailoverGroup) ([]*envoy_cluster_v3.Cluster, error) { - var clusters []*envoy_cluster_v3.Cluster - if fg != nil { - - var egNames []string - for _, eg := range fg.EndpointGroups { - cluster, err := pr.makeEnvoyCluster(name, protocol, eg) - if err != nil { - return nil, err - } - egNames = append(egNames, cluster.Name) - clusters = append(clusters, cluster) - } - aggregateClusterConfig, err := anypb.New(&envoy_aggregate_cluster_v3.ClusterConfig{ - Clusters: egNames, - }) - - if err != nil { - return nil, err - } - - c := &envoy_cluster_v3.Cluster{ - Name: name, - AltStatName: name, - ConnectTimeout: fg.Config.ConnectTimeout, - LbPolicy: envoy_cluster_v3.Cluster_CLUSTER_PROVIDED, - ClusterDiscoveryType: &envoy_cluster_v3.Cluster_ClusterType{ - ClusterType: &envoy_cluster_v3.Cluster_CustomClusterType{ - Name: "envoy.clusters.aggregate", - TypedConfig: aggregateClusterConfig, - }, - }, - } - err = addHttpProtocolOptions(protocol, c) - if err != nil { - return nil, err - } - clusters = append(clusters, c) - } - return clusters, nil -} - -func addHttpProtocolOptions(protocol string, c *envoy_cluster_v3.Cluster) error { - if !(protocol == "http2" || protocol == "grpc") { - // do not error. returning nil means it won't get set. - return nil - } - cfg := &envoy_upstreams_v3.HttpProtocolOptions{ - UpstreamProtocolOptions: &envoy_upstreams_v3.HttpProtocolOptions_ExplicitHttpConfig_{ - ExplicitHttpConfig: &envoy_upstreams_v3.HttpProtocolOptions_ExplicitHttpConfig{ - ProtocolConfig: &envoy_upstreams_v3.HttpProtocolOptions_ExplicitHttpConfig_Http2ProtocolOptions{ - Http2ProtocolOptions: &envoy_core_v3.Http2ProtocolOptions{}, - }, - }, - }, - } - any, err := anypb.New(cfg) - if err != nil { - return err - } - c.TypedExtensionProtocolOptions = map[string]*anypb.Any{ - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": any, - } - return nil -} - -// addEnvoyOutlierDetection will add outlier detection config to the cluster, and if nil, add empty OutlierDetection to -// enable it with default values -func addEnvoyOutlierDetection(outlierDetection *pbproxystate.OutlierDetection, c *envoy_cluster_v3.Cluster) { - if outlierDetection == nil { - return - } - od := &envoy_cluster_v3.OutlierDetection{ - BaseEjectionTime: outlierDetection.GetBaseEjectionTime(), - Consecutive_5Xx: outlierDetection.GetConsecutive_5Xx(), - EnforcingConsecutive_5Xx: outlierDetection.GetEnforcingConsecutive_5Xx(), - Interval: outlierDetection.GetInterval(), - MaxEjectionPercent: outlierDetection.GetMaxEjectionPercent(), - } - c.OutlierDetection = od - -} - -func addEnvoyCircuitBreakers(circuitBreakers *pbproxystate.CircuitBreakers, c *envoy_cluster_v3.Cluster) { - if circuitBreakers != nil { - if circuitBreakers.UpstreamLimits == nil { - c.CircuitBreakers = &envoy_cluster_v3.CircuitBreakers{} - return - } - threshold := &envoy_cluster_v3.CircuitBreakers_Thresholds{} - threshold.MaxConnections = circuitBreakers.UpstreamLimits.MaxConnections - threshold.MaxPendingRequests = circuitBreakers.UpstreamLimits.MaxPendingRequests - threshold.MaxRequests = circuitBreakers.UpstreamLimits.MaxConcurrentRequests - - c.CircuitBreakers = &envoy_cluster_v3.CircuitBreakers{ - Thresholds: []*envoy_cluster_v3.CircuitBreakers_Thresholds{threshold}, - } - } -} - -func addEnvoyLBToCluster(dynamicConfig *pbproxystate.DynamicEndpointGroupConfig, c *envoy_cluster_v3.Cluster) error { - if dynamicConfig == nil || dynamicConfig.LbPolicy == nil { - return nil - } - - switch d := dynamicConfig.LbPolicy.(type) { - case *pbproxystate.DynamicEndpointGroupConfig_LeastRequest: - c.LbPolicy = envoy_cluster_v3.Cluster_LEAST_REQUEST - - lb := dynamicConfig.LbPolicy.(*pbproxystate.DynamicEndpointGroupConfig_LeastRequest) - if lb.LeastRequest != nil { - c.LbConfig = &envoy_cluster_v3.Cluster_LeastRequestLbConfig_{ - LeastRequestLbConfig: &envoy_cluster_v3.Cluster_LeastRequestLbConfig{ - ChoiceCount: lb.LeastRequest.ChoiceCount, - }, - } - } - case *pbproxystate.DynamicEndpointGroupConfig_RoundRobin: - c.LbPolicy = envoy_cluster_v3.Cluster_ROUND_ROBIN - - case *pbproxystate.DynamicEndpointGroupConfig_Random: - c.LbPolicy = envoy_cluster_v3.Cluster_RANDOM - - case *pbproxystate.DynamicEndpointGroupConfig_RingHash: - c.LbPolicy = envoy_cluster_v3.Cluster_RING_HASH - - lb := dynamicConfig.LbPolicy.(*pbproxystate.DynamicEndpointGroupConfig_RingHash) - if lb.RingHash != nil { - c.LbConfig = &envoy_cluster_v3.Cluster_RingHashLbConfig_{ - RingHashLbConfig: &envoy_cluster_v3.Cluster_RingHashLbConfig{ - MinimumRingSize: lb.RingHash.MinimumRingSize, - MaximumRingSize: lb.RingHash.MaximumRingSize, - }, - } - } - case *pbproxystate.DynamicEndpointGroupConfig_Maglev: - c.LbPolicy = envoy_cluster_v3.Cluster_MAGLEV - - default: - return fmt.Errorf("unsupported load balancer policy %q for cluster %q", d, c.Name) - } - return nil -} - -// TODO(proxystate): In a future PR this will create clusters and add it to ProxyResources.proxyState -func (pr *ProxyResources) makeEnvoyClusterFromL4Destination(name string) error { - return nil -} diff --git a/agent/xdsv2/endpoint_resources.go b/agent/xdsv2/endpoint_resources.go deleted file mode 100644 index ba67364e9e0b7..0000000000000 --- a/agent/xdsv2/endpoint_resources.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xdsv2 - -import ( - envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" - envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" - "google.golang.org/protobuf/proto" -) - -func makeEnvoyLbEndpoint(endpoint *pbproxystate.Endpoint) *envoy_endpoint_v3.LbEndpoint { - hs := int32(endpoint.GetHealthStatus().Number()) - return &envoy_endpoint_v3.LbEndpoint{ - HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ - Endpoint: makeEnvoyEndpoint(endpoint), - }, - HealthStatus: envoy_core_v3.HealthStatus(hs), - LoadBalancingWeight: endpoint.GetLoadBalancingWeight(), - } -} - -func makeEnvoyEndpoint(endpoint *pbproxystate.Endpoint) *envoy_endpoint_v3.Endpoint { - var address *envoy_core_v3.Address - if endpoint.GetUnixSocket() != nil { - address = response.MakePipeAddress(endpoint.GetUnixSocket().GetPath(), 0) - } else { - address = response.MakeAddress(endpoint.GetHostPort().GetHost(), int(endpoint.GetHostPort().Port)) - } - - return &envoy_endpoint_v3.Endpoint{ - Address: address, - } -} - -func makeEnvoyClusterLoadAssignment(clusterName string, endpoints []*pbproxystate.Endpoint) *envoy_endpoint_v3.ClusterLoadAssignment { - localityLbEndpoints := &envoy_endpoint_v3.LocalityLbEndpoints{} - for _, endpoint := range endpoints { - localityLbEndpoints.LbEndpoints = append(localityLbEndpoints.LbEndpoints, makeEnvoyLbEndpoint(endpoint)) - } - return &envoy_endpoint_v3.ClusterLoadAssignment{ - ClusterName: clusterName, - Endpoints: []*envoy_endpoint_v3.LocalityLbEndpoints{localityLbEndpoints}, - } -} - -func (pr *ProxyResources) makeXDSEndpoints() ([]proto.Message, error) { - endpoints := make([]proto.Message, 0) - - for clusterName, eps := range pr.proxyState.GetEndpoints() { - if clusterName != xdscommon.LocalAppClusterName { - protoEndpoint := makeEnvoyClusterLoadAssignment(clusterName, eps.Endpoints) - endpoints = append(endpoints, protoEndpoint) - } - } - - return endpoints, nil -} diff --git a/agent/xdsv2/listener_resources.go b/agent/xdsv2/listener_resources.go deleted file mode 100644 index f3a241f0cbe31..0000000000000 --- a/agent/xdsv2/listener_resources.go +++ /dev/null @@ -1,984 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xdsv2 - -import ( - "fmt" - "sort" - "strconv" - - envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" - envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" - envoy_rbac_v3 "github.com/envoyproxy/go-control-plane/envoy/config/rbac/v3" - envoy_grpc_http1_bridge_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/grpc_http1_bridge/v3" - envoy_grpc_stats_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/grpc_stats/v3" - envoy_http_router_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/router/v3" - envoy_extensions_filters_listener_http_inspector_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/http_inspector/v3" - envoy_original_dst_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/original_dst/v3" - envoy_tls_inspector_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/tls_inspector/v3" - envoy_connection_limit_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/connection_limit/v3" - envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - envoy_network_rbac_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/rbac/v3" - envoy_sni_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/sni_cluster/v3" - envoy_tcp_proxy_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/tcp_proxy/v3" - envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" - envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" - envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/wrapperspb" - - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/lib" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" -) - -const ( - envoyNetworkFilterName = "envoy.filters.network.tcp_proxy" - envoyOriginalDestinationListenerFilterName = "envoy.filters.listener.original_dst" - envoyTLSInspectorListenerFilterName = "envoy.filters.listener.tls_inspector" - envoyHttpInspectorListenerFilterName = "envoy.filters.listener.http_inspector" - envoyHttpConnectionManagerFilterName = "envoy.filters.network.http_connection_manager" -) - -func (pr *ProxyResources) makeXDSListeners() ([]proto.Message, error) { - listeners := make([]proto.Message, 0) - - for _, l := range pr.proxyState.Listeners { - protoListener, err := pr.makeListener(l) - // TODO: aggregate errors for listeners and still return any properly formed listeners. - if err != nil { - return nil, err - } - listeners = append(listeners, protoListener) - } - return listeners, nil -} - -func (pr *ProxyResources) makeListener(listener *pbproxystate.Listener) (*envoy_listener_v3.Listener, error) { - envoyListener := &envoy_listener_v3.Listener{} - - // Listener Address - var address *envoy_core_v3.Address - switch listener.BindAddress.(type) { - case *pbproxystate.Listener_HostPort: - address = makeIpPortEnvoyAddress(listener.BindAddress.(*pbproxystate.Listener_HostPort)) - case *pbproxystate.Listener_UnixSocket: - address = makeUnixSocketEnvoyAddress(listener.BindAddress.(*pbproxystate.Listener_UnixSocket)) - default: - // This should be impossible to reach because we're using protobufs. - return nil, fmt.Errorf("invalid listener bind address type: %t", listener.BindAddress) - } - envoyListener.Address = address - - // Listener Direction - var direction envoy_core_v3.TrafficDirection - switch listener.Direction { - case pbproxystate.Direction_DIRECTION_OUTBOUND: - direction = envoy_core_v3.TrafficDirection_OUTBOUND - case pbproxystate.Direction_DIRECTION_INBOUND: - direction = envoy_core_v3.TrafficDirection_INBOUND - case pbproxystate.Direction_DIRECTION_UNSPECIFIED: - direction = envoy_core_v3.TrafficDirection_UNSPECIFIED - default: - return nil, fmt.Errorf("no direction for listener %+v", listener.Name) - } - envoyListener.TrafficDirection = direction - - // Before creating the filter chains, sort routers by match to avoid draining if the list is provided out of order. - sortRouters(listener.Routers) - - // Listener filter chains - for _, r := range listener.Routers { - filterChain, err := pr.makeEnvoyListenerFilterChain(r) - if err != nil { - return nil, fmt.Errorf("could not make filter chain: %w", err) - } - envoyListener.FilterChains = append(envoyListener.FilterChains, filterChain) - } - - if listener.DefaultRouter != nil { - defaultFilterChain, err := pr.makeEnvoyListenerFilterChain(listener.DefaultRouter) - if err != nil { - return nil, fmt.Errorf("could not make filter chain: %w", err) - } - envoyListener.DefaultFilterChain = defaultFilterChain - } - - // Envoy builtin listener filters - for _, c := range listener.Capabilities { - listenerFilter, err := makeEnvoyListenerFilter(c) - if err != nil { - return nil, fmt.Errorf("could not make listener filter: %w", err) - } - envoyListener.ListenerFilters = append(envoyListener.ListenerFilters, listenerFilter) - } - - err := addEnvoyListenerConnectionBalanceConfig(listener.BalanceConnections, envoyListener) - if err != nil { - return nil, err - } - - envoyListener.Name = listener.Name - envoyListener.Address = address - envoyListener.TrafficDirection = direction - - return envoyListener, nil -} - -func makeEnvoyConnectionLimitFilter(maxInboundConns uint64) (*envoy_listener_v3.Filter, error) { - cfg := &envoy_connection_limit_v3.ConnectionLimit{ - StatPrefix: "inbound_connection_limit", - MaxConnections: wrapperspb.UInt64(maxInboundConns), - } - - return makeEnvoyFilter("envoy.filters.network.connection_limit", cfg) -} - -func addEnvoyListenerConnectionBalanceConfig(balanceType pbproxystate.BalanceConnections, listener *envoy_listener_v3.Listener) error { - switch balanceType { - case pbproxystate.BalanceConnections_BALANCE_CONNECTIONS_DEFAULT: - // Default with no balancing. - return nil - case pbproxystate.BalanceConnections_BALANCE_CONNECTIONS_EXACT: - listener.ConnectionBalanceConfig = &envoy_listener_v3.Listener_ConnectionBalanceConfig{ - BalanceType: &envoy_listener_v3.Listener_ConnectionBalanceConfig_ExactBalance_{}, - } - return nil - default: - // This should be impossible using protobufs. - return fmt.Errorf("unsupported connection balance option: %+v", balanceType) - } -} - -func makeIpPortEnvoyAddress(address *pbproxystate.Listener_HostPort) *envoy_core_v3.Address { - return &envoy_core_v3.Address{ - Address: &envoy_core_v3.Address_SocketAddress{ - SocketAddress: &envoy_core_v3.SocketAddress{ - Address: address.HostPort.Host, - PortSpecifier: &envoy_core_v3.SocketAddress_PortValue{ - PortValue: address.HostPort.Port, - }, - }, - }, - } -} - -func makeUnixSocketEnvoyAddress(address *pbproxystate.Listener_UnixSocket) *envoy_core_v3.Address { - modeInt, err := strconv.ParseUint(address.UnixSocket.Mode, 0, 32) - if err != nil { - modeInt = 0 - } - return &envoy_core_v3.Address{ - Address: &envoy_core_v3.Address_Pipe{ - Pipe: &envoy_core_v3.Pipe{ - Path: address.UnixSocket.Path, - Mode: uint32(modeInt), - }, - }, - } -} - -func (pr *ProxyResources) makeEnvoyListenerFilterChain(router *pbproxystate.Router) (*envoy_listener_v3.FilterChain, error) { - envoyFilterChain := &envoy_listener_v3.FilterChain{} - - if router == nil { - return nil, fmt.Errorf("no router to create filter chain") - } - - // Router Match - match := makeEnvoyFilterChainMatch(router.Match) - if match != nil { - envoyFilterChain.FilterChainMatch = match - } - - // Router Destination - var envoyFilters []*envoy_listener_v3.Filter - switch router.Destination.(type) { - case *pbproxystate.Router_L4: - l4Filters, err := pr.makeEnvoyResourcesForL4Destination(router.Destination.(*pbproxystate.Router_L4)) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, l4Filters...) - case *pbproxystate.Router_L7: - l7 := router.Destination.(*pbproxystate.Router_L7) - l7Filters, err := pr.makeEnvoyResourcesForL7Destination(l7) - if err != nil { - return nil, err - } - - // Inject ALPN protocols to router's TLS if destination is L7 - if router.InboundTls != nil { - router.InboundTls.AlpnProtocols = getAlpnProtocols(l7.L7.Protocol) - } - envoyFilters = append(envoyFilters, l7Filters...) - case *pbproxystate.Router_Sni: - sniFilters, err := pr.makeEnvoyResourcesForSNIDestination(router.Destination.(*pbproxystate.Router_Sni)) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, sniFilters...) - default: - // This should be impossible using protobufs. - return nil, fmt.Errorf("unsupported destination type: %t", router.Destination) - - } - - // Router TLS - ts, err := pr.makeEnvoyTransportSocket(router.InboundTls) - if err != nil { - return nil, err - } - envoyFilterChain.TransportSocket = ts - - envoyFilterChain.Filters = envoyFilters - return envoyFilterChain, err -} - -func makeEnvoyFilterChainMatch(routerMatch *pbproxystate.Match) *envoy_listener_v3.FilterChainMatch { - var envoyFilterChainMatch *envoy_listener_v3.FilterChainMatch - if routerMatch != nil { - envoyFilterChainMatch = &envoy_listener_v3.FilterChainMatch{} - - envoyFilterChainMatch.DestinationPort = routerMatch.DestinationPort - - if len(routerMatch.ServerNames) > 0 { - var serverNames []string - for _, n := range routerMatch.ServerNames { - serverNames = append(serverNames, n) - } - envoyFilterChainMatch.ServerNames = serverNames - } - if len(routerMatch.PrefixRanges) > 0 { - sortPrefixRanges(routerMatch.PrefixRanges) - var ranges []*envoy_core_v3.CidrRange - for _, r := range routerMatch.PrefixRanges { - cidrRange := &envoy_core_v3.CidrRange{ - PrefixLen: r.PrefixLen, - AddressPrefix: r.AddressPrefix, - } - ranges = append(ranges, cidrRange) - } - envoyFilterChainMatch.PrefixRanges = ranges - } - if len(routerMatch.SourcePrefixRanges) > 0 { - var ranges []*envoy_core_v3.CidrRange - for _, r := range routerMatch.SourcePrefixRanges { - cidrRange := &envoy_core_v3.CidrRange{ - PrefixLen: r.PrefixLen, - AddressPrefix: r.AddressPrefix, - } - ranges = append(ranges, cidrRange) - } - envoyFilterChainMatch.SourcePrefixRanges = ranges - } - } - return envoyFilterChainMatch -} - -func (pr *ProxyResources) makeEnvoyResourcesForSNIDestination(sni *pbproxystate.Router_Sni) ([]*envoy_listener_v3.Filter, error) { - var envoyFilters []*envoy_listener_v3.Filter - sniFilter, err := makeEnvoyFilter("envoy.filters.network.sni_cluster", &envoy_sni_cluster_v3.SniCluster{}) - if err != nil { - return nil, err - } - tcp := &envoy_tcp_proxy_v3.TcpProxy{ - StatPrefix: sni.Sni.StatPrefix, - ClusterSpecifier: &envoy_tcp_proxy_v3.TcpProxy_Cluster{Cluster: ""}, - } - tcpFilter, err := makeEnvoyFilter(envoyNetworkFilterName, tcp) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, sniFilter, tcpFilter) - return envoyFilters, err -} - -func (pr *ProxyResources) makeEnvoyResourcesForL4Destination(l4 *pbproxystate.Router_L4) ([]*envoy_listener_v3.Filter, error) { - err := pr.makeEnvoyClusterFromL4Destination(l4.L4.Name) - if err != nil { - return nil, err - } - envoyFilters, err := makeL4Filters(l4.L4) - return envoyFilters, err -} - -func (pr *ProxyResources) makeEnvoyResourcesForL7Destination(l7 *pbproxystate.Router_L7) ([]*envoy_listener_v3.Filter, error) { - envoyFilters, err := pr.makeL7Filters(l7.L7) - if err != nil { - return nil, err - } - return envoyFilters, err -} - -func getAlpnProtocols(protocol pbproxystate.L7Protocol) []string { - var alpnProtocols []string - - switch protocol { - case pbproxystate.L7Protocol_L7_PROTOCOL_GRPC, pbproxystate.L7Protocol_L7_PROTOCOL_HTTP2: - alpnProtocols = append(alpnProtocols, "h2", "http/1.1") - case pbproxystate.L7Protocol_L7_PROTOCOL_HTTP: - alpnProtocols = append(alpnProtocols, "http/1.1") - } - - return alpnProtocols -} - -func makeL4Filters(l4 *pbproxystate.L4Destination) ([]*envoy_listener_v3.Filter, error) { - var envoyFilters []*envoy_listener_v3.Filter - if l4 != nil { - // Add rbac filter. RBAC filter needs to be added first so any - // unauthorized connections will get rejected. - // TODO(proxystate): Intentions will be added in the future. - if l4.AddEmptyIntention { - rbacFilter, err := makeEmptyRBACNetworkFilter() - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, rbacFilter) - } - - if l4.MaxInboundConnections > 0 { - connectionLimitFilter, err := makeEnvoyConnectionLimitFilter(l4.MaxInboundConnections) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, connectionLimitFilter) - } - - // Add tcp proxy filter - tcp := &envoy_tcp_proxy_v3.TcpProxy{ - ClusterSpecifier: &envoy_tcp_proxy_v3.TcpProxy_Cluster{Cluster: l4.Name}, - StatPrefix: l4.StatPrefix, - } - tcpFilter, err := makeEnvoyFilter(envoyNetworkFilterName, tcp) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, tcpFilter) - } - return envoyFilters, nil - -} - -func makeEmptyRBACNetworkFilter() (*envoy_listener_v3.Filter, error) { - cfg := &envoy_network_rbac_v3.RBAC{ - StatPrefix: "connect_authz", - Rules: &envoy_rbac_v3.RBAC{}, - } - filter, err := makeEnvoyFilter("envoy.filters.network.rbac", cfg) - if err != nil { - return nil, err - } - return filter, nil -} - -// TODO: Forward client cert details will be added as part of L7 listeners task. -func (pr *ProxyResources) makeL7Filters(l7 *pbproxystate.L7Destination) ([]*envoy_listener_v3.Filter, error) { - var envoyFilters []*envoy_listener_v3.Filter - var httpConnMgr *envoy_http_v3.HttpConnectionManager - - if l7 != nil { - // TODO: Intentions will be added in the future. - if l7.MaxInboundConnections > 0 { - connLimitFilter, err := makeEnvoyConnectionLimitFilter(l7.MaxInboundConnections) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, connLimitFilter) - } - envoyHttpRouter, err := makeEnvoyHTTPFilter("envoy.filters.http.router", &envoy_http_router_v3.Router{}) - if err != nil { - return nil, err - } - - httpConnMgr = &envoy_http_v3.HttpConnectionManager{ - StatPrefix: l7.StatPrefix, - CodecType: envoy_http_v3.HttpConnectionManager_AUTO, - HttpFilters: []*envoy_http_v3.HttpFilter{ - envoyHttpRouter, - }, - Tracing: &envoy_http_v3.HttpConnectionManager_Tracing{ - // Don't trace any requests by default unless the client application - // explicitly propagates trace headers that indicate this should be - // sampled. - RandomSampling: &envoy_type_v3.Percent{Value: 0.0}, - }, - // Explicitly enable WebSocket upgrades for all HTTP listeners - UpgradeConfigs: []*envoy_http_v3.HttpConnectionManager_UpgradeConfig{ - {UpgradeType: "websocket"}, - }, - } - - routeConfig, err := pr.makeEnvoyRoute(l7.Name) - if err != nil { - return nil, err - } - - if l7.StaticRoute { - httpConnMgr.RouteSpecifier = &envoy_http_v3.HttpConnectionManager_RouteConfig{ - RouteConfig: routeConfig, - } - } else { - // Add Envoy route under the route resource since it's not inlined. - pr.envoyResources[xdscommon.RouteType] = append(pr.envoyResources[xdscommon.RouteType], routeConfig) - - httpConnMgr.RouteSpecifier = &envoy_http_v3.HttpConnectionManager_Rds{ - Rds: &envoy_http_v3.Rds{ - RouteConfigName: l7.Name, - ConfigSource: &envoy_core_v3.ConfigSource{ - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, - ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_Ads{ - Ads: &envoy_core_v3.AggregatedConfigSource{}, - }, - }, - }, - } - } - - // Add http2 protocol options - if l7.Protocol == pbproxystate.L7Protocol_L7_PROTOCOL_HTTP2 || l7.Protocol == pbproxystate.L7Protocol_L7_PROTOCOL_GRPC { - httpConnMgr.Http2ProtocolOptions = &envoy_core_v3.Http2ProtocolOptions{} - } - - // Add grpc envoy http filters. - if l7.Protocol == pbproxystate.L7Protocol_L7_PROTOCOL_GRPC { - grpcHttp1Bridge, err := makeEnvoyHTTPFilter( - "envoy.filters.http.grpc_http1_bridge", - &envoy_grpc_http1_bridge_v3.Config{}, - ) - if err != nil { - return nil, err - } - - // In envoy 1.14.x the default value "stats_for_all_methods=true" was - // deprecated, and was changed to "false" in 1.18.x. Avoid using the - // default. TODO: we may want to expose this to users somehow easily. - grpcStatsFilter, err := makeEnvoyHTTPFilter( - "envoy.filters.http.grpc_stats", - &envoy_grpc_stats_v3.FilterConfig{ - PerMethodStatSpecifier: &envoy_grpc_stats_v3.FilterConfig_StatsForAllMethods{ - StatsForAllMethods: &wrapperspb.BoolValue{Value: true}, - }, - }, - ) - if err != nil { - return nil, err - } - - // Add grpc bridge before envoyRouter and authz, and the stats in front of that. - httpConnMgr.HttpFilters = append([]*envoy_http_v3.HttpFilter{ - grpcStatsFilter, - grpcHttp1Bridge, - }, httpConnMgr.HttpFilters...) - } - - httpFilter, err := makeEnvoyFilter(envoyHttpConnectionManagerFilterName, httpConnMgr) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, httpFilter) - } - return envoyFilters, nil -} - -func (pr *ProxyResources) makeEnvoyTLSParameters(defaultParams *pbproxystate.TLSParameters, overrideParams *pbproxystate.TLSParameters) *envoy_tls_v3.TlsParameters { - tlsParams := &envoy_tls_v3.TlsParameters{} - - if overrideParams != nil { - if overrideParams.MinVersion != pbproxystate.TLSVersion_TLS_VERSION_UNSPECIFIED { - if minVersion, ok := envoyTLSVersions[overrideParams.MinVersion]; ok { - tlsParams.TlsMinimumProtocolVersion = minVersion - } - } - if overrideParams.MaxVersion != pbproxystate.TLSVersion_TLS_VERSION_UNSPECIFIED { - if maxVersion, ok := envoyTLSVersions[overrideParams.MaxVersion]; ok { - tlsParams.TlsMaximumProtocolVersion = maxVersion - } - } - if len(overrideParams.CipherSuites) != 0 { - tlsParams.CipherSuites = marshalEnvoyTLSCipherSuiteStrings(overrideParams.CipherSuites) - } - return tlsParams - } - - if defaultParams != nil { - if defaultParams.MinVersion != pbproxystate.TLSVersion_TLS_VERSION_UNSPECIFIED { - if minVersion, ok := envoyTLSVersions[defaultParams.MinVersion]; ok { - tlsParams.TlsMinimumProtocolVersion = minVersion - } - } - if defaultParams.MaxVersion != pbproxystate.TLSVersion_TLS_VERSION_UNSPECIFIED { - if maxVersion, ok := envoyTLSVersions[defaultParams.MaxVersion]; ok { - tlsParams.TlsMaximumProtocolVersion = maxVersion - } - } - if len(defaultParams.CipherSuites) != 0 { - tlsParams.CipherSuites = marshalEnvoyTLSCipherSuiteStrings(defaultParams.CipherSuites) - } - return tlsParams - } - - return tlsParams - -} - -func (pr *ProxyResources) makeEnvoyTransportSocket(ts *pbproxystate.TransportSocket) (*envoy_core_v3.TransportSocket, error) { - if ts == nil { - return nil, nil - } - commonTLSContext := &envoy_tls_v3.CommonTlsContext{} - - // Create connection TLS. Listeners should only look at inbound TLS. - switch ts.ConnectionTls.(type) { - case *pbproxystate.TransportSocket_InboundMesh: - downstreamContext := &envoy_tls_v3.DownstreamTlsContext{} - downstreamContext.CommonTlsContext = commonTLSContext - // Set TLS Parameters. - tlsParams := pr.makeEnvoyTLSParameters(pr.proxyState.Tls.InboundTlsParameters, ts.TlsParameters) - commonTLSContext.TlsParams = tlsParams - - // Set the certificate config on the tls context. - // For inbound mesh, we need to add the identity certificate - // and the validation context for the mesh depending on the provided trust bundle names. - if pr.proxyState.Tls == nil { - // if tls is nil but connection tls is provided, then the proxy state is misconfigured - return nil, fmt.Errorf("proxyState.Tls is required to generate router's transport socket") - } - im := ts.ConnectionTls.(*pbproxystate.TransportSocket_InboundMesh).InboundMesh - leaf, ok := pr.proxyState.LeafCertificates[im.IdentityKey] - if !ok { - return nil, fmt.Errorf("failed to create transport socket: leaf certificate %q not found", im.IdentityKey) - } - err := pr.makeEnvoyCertConfig(commonTLSContext, leaf) - if err != nil { - return nil, fmt.Errorf("failed to create transport socket: %w", err) - } - - // Create validation context. - // When there's only one trust bundle name, we create a simple validation context - if len(im.ValidationContext.TrustBundlePeerNameKeys) == 1 { - peerName := im.ValidationContext.TrustBundlePeerNameKeys[0] - tb, ok := pr.proxyState.TrustBundles[peerName] - if !ok { - return nil, fmt.Errorf("failed to create transport socket: provided trust bundle name does not exist in proxystate trust bundle map: %s", peerName) - } - commonTLSContext.ValidationContextType = &envoy_tls_v3.CommonTlsContext_ValidationContext{ - ValidationContext: &envoy_tls_v3.CertificateValidationContext{ - // TODO(banks): later for L7 support we may need to configure ALPN here. - TrustedCa: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: RootPEMsAsString(tb.Roots), - }, - }, - }, - } - } else if len(im.ValidationContext.TrustBundlePeerNameKeys) > 1 { - cfg := &envoy_tls_v3.SPIFFECertValidatorConfig{ - TrustDomains: make([]*envoy_tls_v3.SPIFFECertValidatorConfig_TrustDomain, 0, len(im.ValidationContext.TrustBundlePeerNameKeys)), - } - - for _, peerName := range im.ValidationContext.TrustBundlePeerNameKeys { - // Look up the trust bundle ca in the map. - tb, ok := pr.proxyState.TrustBundles[peerName] - if !ok { - return nil, fmt.Errorf("failed to create transport socket: provided bundle name does not exist in trust bundle map: %s", peerName) - } - cfg.TrustDomains = append(cfg.TrustDomains, &envoy_tls_v3.SPIFFECertValidatorConfig_TrustDomain{ - Name: tb.TrustDomain, - TrustBundle: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: RootPEMsAsString(tb.Roots), - }, - }, - }) - } - // Sort the trust domains so the output is stable. - sortTrustDomains(cfg.TrustDomains) - - spiffeConfig, err := anypb.New(cfg) - if err != nil { - return nil, err - } - commonTLSContext.ValidationContextType = &envoy_tls_v3.CommonTlsContext_ValidationContext{ - ValidationContext: &envoy_tls_v3.CertificateValidationContext{ - CustomValidatorConfig: &envoy_core_v3.TypedExtensionConfig{ - // The typed config name is hard-coded because it is not available as a wellknown var in the control plane lib. - Name: "envoy.tls.cert_validator.spiffe", - TypedConfig: spiffeConfig, - }, - }, - } - } - // Always require client certificate - downstreamContext.RequireClientCertificate = &wrapperspb.BoolValue{Value: true} - transportSocket, err := makeTransportSocket("tls", downstreamContext) - if err != nil { - return nil, err - } - return transportSocket, nil - case *pbproxystate.TransportSocket_InboundNonMesh: - downstreamContext := &envoy_tls_v3.DownstreamTlsContext{} - downstreamContext.CommonTlsContext = commonTLSContext - // Set TLS Parameters - tlsParams := pr.makeEnvoyTLSParameters(pr.proxyState.Tls.InboundTlsParameters, ts.TlsParameters) - commonTLSContext.TlsParams = tlsParams - // For non-mesh, we don't care about validation context as currently we don't support mTLS for non-mesh connections. - nonMeshTLS := ts.ConnectionTls.(*pbproxystate.TransportSocket_InboundNonMesh).InboundNonMesh - err := pr.addNonMeshCertConfig(commonTLSContext, nonMeshTLS) - if err != nil { - return nil, fmt.Errorf("failed to create transport socket: %w", err) - } - transportSocket, err := makeTransportSocket("tls", downstreamContext) - if err != nil { - return nil, err - } - return transportSocket, nil - case *pbproxystate.TransportSocket_OutboundMesh: - upstreamContext := &envoy_tls_v3.UpstreamTlsContext{} - upstreamContext.CommonTlsContext = commonTLSContext - // Set TLS Parameters - tlsParams := pr.makeEnvoyTLSParameters(pr.proxyState.Tls.OutboundTlsParameters, ts.TlsParameters) - commonTLSContext.TlsParams = tlsParams - // For outbound mesh, we need to insert the mesh identity certificate - // and the validation context for the mesh depending on the provided trust bundle names. - if pr.proxyState.Tls == nil { - // if tls is nil but connection tls is provided, then the proxy state is misconfigured - return nil, fmt.Errorf("proxyState.Tls is required to generate router's transport socket") - } - om := ts.GetOutboundMesh() - leaf, ok := pr.proxyState.LeafCertificates[om.IdentityKey] - if !ok { - return nil, fmt.Errorf("leaf %s not found in proxyState", om.IdentityKey) - } - err := pr.makeEnvoyCertConfig(commonTLSContext, leaf) - if err != nil { - return nil, fmt.Errorf("failed to create transport socket: %w", err) - } - - // Create validation context - peerName := om.ValidationContext.TrustBundlePeerNameKey - tb, ok := pr.proxyState.TrustBundles[peerName] - if !ok { - return nil, fmt.Errorf("failed to create transport socket: provided peer name does not exist in trust bundle map: %s", peerName) - } - - var matchers []*envoy_matcher_v3.StringMatcher - if len(om.ValidationContext.SpiffeIds) > 0 { - matchers = make([]*envoy_matcher_v3.StringMatcher, 0) - for _, m := range om.ValidationContext.SpiffeIds { - matchers = append(matchers, &envoy_matcher_v3.StringMatcher{ - MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{ - Exact: m, - }, - }) - } - } - commonTLSContext.ValidationContextType = &envoy_tls_v3.CommonTlsContext_ValidationContext{ - ValidationContext: &envoy_tls_v3.CertificateValidationContext{ - // TODO(banks): later for L7 support we may need to configure ALPN here. - TrustedCa: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: RootPEMsAsString(tb.Roots), - }, - }, - MatchSubjectAltNames: matchers, - }, - } - - upstreamContext.Sni = om.Sni - transportSocket, err := makeTransportSocket("tls", upstreamContext) - if err != nil { - return nil, err - } - return transportSocket, nil - default: - return nil, nil - } - -} - -func (pr *ProxyResources) makeEnvoyCertConfig(common *envoy_tls_v3.CommonTlsContext, certificate *pbproxystate.LeafCertificate) error { - if certificate == nil { - return fmt.Errorf("no leaf certificate provided") - } - common.TlsCertificates = []*envoy_tls_v3.TlsCertificate{ - { - CertificateChain: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: lib.EnsureTrailingNewline(certificate.Cert), - }, - }, - PrivateKey: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: lib.EnsureTrailingNewline(certificate.Key), - }, - }, - }, - } - return nil -} - -func (pr *ProxyResources) makeEnvoySDSCertConfig(common *envoy_tls_v3.CommonTlsContext, certificate *pbproxystate.SDSCertificate) error { - if certificate == nil { - return fmt.Errorf("no SDS certificate provided") - } - common.TlsCertificateSdsSecretConfigs = []*envoy_tls_v3.SdsSecretConfig{ - { - Name: certificate.CertResource, - SdsConfig: &envoy_core_v3.ConfigSource{ - ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_ApiConfigSource{ - ApiConfigSource: &envoy_core_v3.ApiConfigSource{ - ApiType: envoy_core_v3.ApiConfigSource_GRPC, - TransportApiVersion: envoy_core_v3.ApiVersion_V3, - // Note ClusterNames can't be set here - that's only for REST type - // we need a full GRPC config instead. - GrpcServices: []*envoy_core_v3.GrpcService{ - { - TargetSpecifier: &envoy_core_v3.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_core_v3.GrpcService_EnvoyGrpc{ - ClusterName: certificate.ClusterName, - }, - }, - Timeout: &durationpb.Duration{Seconds: 5}, - }, - }, - }, - }, - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, - }, - }, - } - return nil -} - -func (pr *ProxyResources) addNonMeshCertConfig(common *envoy_tls_v3.CommonTlsContext, tls *pbproxystate.InboundNonMeshTLS) error { - if tls == nil { - return fmt.Errorf("no inbound non-mesh TLS provided") - } - - switch tls.Identity.(type) { - case *pbproxystate.InboundNonMeshTLS_LeafKey: - leafKey := tls.Identity.(*pbproxystate.InboundNonMeshTLS_LeafKey).LeafKey - leaf, ok := pr.proxyState.LeafCertificates[leafKey] - if !ok { - return fmt.Errorf("leaf key %s not found in leaf certificate map", leafKey) - } - common.TlsCertificates = []*envoy_tls_v3.TlsCertificate{ - { - CertificateChain: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: lib.EnsureTrailingNewline(leaf.Cert), - }, - }, - PrivateKey: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: lib.EnsureTrailingNewline(leaf.Key), - }, - }, - }, - } - case *pbproxystate.InboundNonMeshTLS_Sds: - c := tls.Identity.(*pbproxystate.InboundNonMeshTLS_Sds).Sds - common.TlsCertificateSdsSecretConfigs = []*envoy_tls_v3.SdsSecretConfig{ - { - Name: c.CertResource, - SdsConfig: &envoy_core_v3.ConfigSource{ - ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_ApiConfigSource{ - ApiConfigSource: &envoy_core_v3.ApiConfigSource{ - ApiType: envoy_core_v3.ApiConfigSource_GRPC, - TransportApiVersion: envoy_core_v3.ApiVersion_V3, - // Note ClusterNames can't be set here - that's only for REST type - // we need a full GRPC config instead. - GrpcServices: []*envoy_core_v3.GrpcService{ - { - TargetSpecifier: &envoy_core_v3.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_core_v3.GrpcService_EnvoyGrpc{ - ClusterName: c.ClusterName, - }, - }, - Timeout: &durationpb.Duration{Seconds: 5}, - }, - }, - }, - }, - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, - }, - }, - } - } - - return nil -} - -func makeTransportSocket(name string, config proto.Message) (*envoy_core_v3.TransportSocket, error) { - any, err := anypb.New(config) - if err != nil { - return nil, err - } - return &envoy_core_v3.TransportSocket{ - Name: name, - ConfigType: &envoy_core_v3.TransportSocket_TypedConfig{ - TypedConfig: any, - }, - }, nil -} - -func makeEnvoyListenerFilter(c pbproxystate.Capability) (*envoy_listener_v3.ListenerFilter, error) { - var lf proto.Message - var name string - - switch c { - case pbproxystate.Capability_CAPABILITY_TRANSPARENT: - lf = &envoy_original_dst_v3.OriginalDst{} - name = envoyOriginalDestinationListenerFilterName - case pbproxystate.Capability_CAPABILITY_L4_TLS_INSPECTION: - name = envoyTLSInspectorListenerFilterName - lf = &envoy_tls_inspector_v3.TlsInspector{} - case pbproxystate.Capability_CAPABILITY_L7_PROTOCOL_INSPECTION: - name = envoyHttpInspectorListenerFilterName - lf = &envoy_extensions_filters_listener_http_inspector_v3.HttpInspector{} - default: - return nil, fmt.Errorf("unsupported listener captability: %s", c) - } - lfAsAny, err := anypb.New(lf) - if err != nil { - return nil, err - } - - return &envoy_listener_v3.ListenerFilter{ - Name: name, - ConfigType: &envoy_listener_v3.ListenerFilter_TypedConfig{TypedConfig: lfAsAny}, - }, nil -} - -func makeEnvoyFilter(name string, cfg proto.Message) (*envoy_listener_v3.Filter, error) { - any, err := anypb.New(cfg) - if err != nil { - return nil, err - } - - return &envoy_listener_v3.Filter{ - Name: name, - ConfigType: &envoy_listener_v3.Filter_TypedConfig{TypedConfig: any}, - }, nil -} - -func makeEnvoyHTTPFilter(name string, cfg proto.Message) (*envoy_http_v3.HttpFilter, error) { - any, err := anypb.New(cfg) - if err != nil { - return nil, err - } - - return &envoy_http_v3.HttpFilter{ - Name: name, - ConfigType: &envoy_http_v3.HttpFilter_TypedConfig{TypedConfig: any}, - }, nil -} - -func RootPEMsAsString(rootPEMs []string) string { - var rootPEMsString string - for _, root := range rootPEMs { - rootPEMsString += lib.EnsureTrailingNewline(root) - } - return rootPEMsString -} - -func marshalEnvoyTLSCipherSuiteStrings(cipherSuites []pbproxystate.TLSCipherSuite) []string { - envoyTLSCipherSuiteStrings := map[pbproxystate.TLSCipherSuite]string{ - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256: "ECDHE-ECDSA-AES128-GCM-SHA256", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305: "ECDHE-ECDSA-CHACHA20-POLY1305", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256: "ECDHE-RSA-AES128-GCM-SHA256", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305: "ECDHE-RSA-CHACHA20-POLY1305", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA: "ECDHE-ECDSA-AES128-SHA", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA: "ECDHE-RSA-AES128-SHA", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES128_GCM_SHA256: "AES128-GCM-SHA256", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES128_SHA: "AES128-SHA", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384: "ECDHE-ECDSA-AES256-GCM-SHA384", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384: "ECDHE-RSA-AES256-GCM-SHA384", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA: "ECDHE-ECDSA-AES256-SHA", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA: "ECDHE-RSA-AES256-SHA", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES256_GCM_SHA384: "AES256-GCM-SHA384", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES256_SHA: "AES256-SHA", - } - - var cipherSuiteStrings []string - - for _, c := range cipherSuites { - if s, ok := envoyTLSCipherSuiteStrings[c]; ok { - cipherSuiteStrings = append(cipherSuiteStrings, s) - } - } - - return cipherSuiteStrings -} - -var envoyTLSVersions = map[pbproxystate.TLSVersion]envoy_tls_v3.TlsParameters_TlsProtocol{ - pbproxystate.TLSVersion_TLS_VERSION_AUTO: envoy_tls_v3.TlsParameters_TLS_AUTO, - pbproxystate.TLSVersion_TLS_VERSION_1_0: envoy_tls_v3.TlsParameters_TLSv1_0, - pbproxystate.TLSVersion_TLS_VERSION_1_1: envoy_tls_v3.TlsParameters_TLSv1_1, - pbproxystate.TLSVersion_TLS_VERSION_1_2: envoy_tls_v3.TlsParameters_TLSv1_2, - pbproxystate.TLSVersion_TLS_VERSION_1_3: envoy_tls_v3.TlsParameters_TLSv1_3, -} - -// Sort the trust domains so that the output is stable. -// This benefits tests but also prevents Envoy from mistakenly thinking the listener -// changed and needs to be drained only because this ordering is different. -func sortTrustDomains(trustDomains []*envoy_tls_v3.SPIFFECertValidatorConfig_TrustDomain) { - sort.Slice(trustDomains, func(i int, j int) bool { - return trustDomains[i].Name < trustDomains[j].Name - }) -} - -// sortRouters stable sorts routers with a Match to avoid draining if the list is provided out of order. -// xdsv1 used to sort the filter chains on outbound listeners, so this adds that functionality by sorting routers with matches. -func sortRouters(routers []*pbproxystate.Router) { - if routers == nil { - return - } - sort.SliceStable(routers, func(i, j int) bool { - si := "" - sj := "" - if routers[i].Match != nil { - if len(routers[i].Match.PrefixRanges) > 0 { - si += routers[i].Match.PrefixRanges[0].AddressPrefix + - "/" + routers[i].Match.PrefixRanges[0].PrefixLen.String() + - ":" + routers[i].Match.DestinationPort.String() - } - if len(routers[i].Match.ServerNames) > 0 { - si += routers[i].Match.ServerNames[0] + - ":" + routers[i].Match.DestinationPort.String() - } else { - si += routers[i].Match.DestinationPort.String() - } - } - - if routers[j].Match != nil { - if len(routers[j].Match.PrefixRanges) > 0 { - sj += routers[j].Match.PrefixRanges[0].AddressPrefix + - "/" + routers[j].Match.PrefixRanges[0].PrefixLen.String() + - ":" + routers[j].Match.DestinationPort.String() - } - if len(routers[j].Match.ServerNames) > 0 { - sj += routers[j].Match.ServerNames[0] + - ":" + routers[j].Match.DestinationPort.String() - } else { - sj += routers[j].Match.DestinationPort.String() - } - } - - return si < sj - }) -} - -func sortPrefixRanges(prefixRanges []*pbproxystate.CidrRange) { - if prefixRanges == nil { - return - } - sort.SliceStable(prefixRanges, func(i, j int) bool { - return prefixRanges[i].AddressPrefix < prefixRanges[j].AddressPrefix - }) -} diff --git a/agent/xdsv2/resources.go b/agent/xdsv2/resources.go deleted file mode 100644 index fa5f7179e6a5d..0000000000000 --- a/agent/xdsv2/resources.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xdsv2 - -import ( - "fmt" - - "github.com/hashicorp/go-hclog" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/envoyextensions/xdscommon" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" -) - -// ResourceGenerator is associated with a single gRPC stream and creates xDS -// resources for a single client. -type ResourceGenerator struct { - Logger hclog.Logger - ProxyFeatures xdscommon.SupportedProxyFeatures -} - -func NewResourceGenerator( - logger hclog.Logger, -) *ResourceGenerator { - return &ResourceGenerator{ - Logger: logger, - } -} - -type ProxyResources struct { - proxyState *proxytracker.ProxyState - envoyResources map[string][]proto.Message -} - -func (g *ResourceGenerator) AllResourcesFromIR(proxyState *proxytracker.ProxyState) (map[string][]proto.Message, error) { - pr := &ProxyResources{ - proxyState: proxyState, - envoyResources: make(map[string][]proto.Message), - } - err := pr.generateXDSResources() - if err != nil { - return nil, fmt.Errorf("failed to generate xDS resources for ProxyState: %v", err) - } - return pr.envoyResources, nil -} - -func (pr *ProxyResources) generateXDSResources() error { - listeners, err := pr.makeXDSListeners() - if err != nil { - return err - } - - pr.envoyResources[xdscommon.ListenerType] = listeners - - clusters, err := pr.makeXDSClusters() - if err != nil { - return err - } - pr.envoyResources[xdscommon.ClusterType] = clusters - - endpoints, err := pr.makeXDSEndpoints() - if err != nil { - return err - } - pr.envoyResources[xdscommon.EndpointType] = endpoints - - routes, err := pr.makeXDSRoutes() - if err != nil { - return err - } - pr.envoyResources[xdscommon.RouteType] = routes - - return nil -} diff --git a/agent/xdsv2/route_resources.go b/agent/xdsv2/route_resources.go deleted file mode 100644 index 931d48f26078b..0000000000000 --- a/agent/xdsv2/route_resources.go +++ /dev/null @@ -1,525 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xdsv2 - -import ( - "fmt" - envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" - envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" - "google.golang.org/protobuf/types/known/wrapperspb" - "strings" - - envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" - "google.golang.org/protobuf/proto" -) - -func (pr *ProxyResources) makeXDSRoutes() ([]proto.Message, error) { - routes := make([]proto.Message, 0) - - for name, r := range pr.proxyState.Routes { - protoRoute := pr.makeEnvoyRouteConfigFromProxystateRoute(name, r) - // TODO: aggregate errors for routes and still return any properly formed routes. - routes = append(routes, protoRoute) - } - - return routes, nil -} - -func (pr *ProxyResources) makeEnvoyRoute(name string) (*envoy_route_v3.RouteConfiguration, error) { - var route *envoy_route_v3.RouteConfiguration - // TODO(proxystate): This will make routes in the future. This function should distinguish between static routes - // inlined into listeners and non-static routes that should be added as top level Envoy resources. - _, ok := pr.proxyState.Routes[name] - if !ok { - // This should not happen with a valid proxy state. - return nil, fmt.Errorf("could not find route in ProxyState: %s", name) - - } - return route, nil -} - -// makeEnvoyRouteConfigFromProxystateRoute converts the proxystate representation of a Route into Envoy proto message -// form. We don't throw any errors here, since the proxystate has already been validated. -func (pr *ProxyResources) makeEnvoyRouteConfigFromProxystateRoute(name string, psRoute *pbproxystate.Route) *envoy_route_v3.RouteConfiguration { - - envoyRouteConfig := &envoy_route_v3.RouteConfiguration{ - Name: name, - // ValidateClusters defaults to true when defined statically and false - // when done via RDS. Re-set the reasonable value of true to prevent - // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), - } - - for _, vh := range psRoute.GetVirtualHosts() { - envoyRouteConfig.VirtualHosts = append(envoyRouteConfig.VirtualHosts, pr.makeEnvoyVHFromProxystateVH(vh)) - } - - return envoyRouteConfig -} - -func (pr *ProxyResources) makeEnvoyVHFromProxystateVH(psVirtualHost *pbproxystate.VirtualHost) *envoy_route_v3.VirtualHost { - envoyVirtualHost := &envoy_route_v3.VirtualHost{ - Name: psVirtualHost.Name, - Domains: psVirtualHost.GetDomains(), - } - - for _, rr := range psVirtualHost.GetRouteRules() { - envoyVirtualHost.Routes = append(envoyVirtualHost.Routes, pr.makeEnvoyRouteFromProxystateRouteRule(rr)) - } - - for _, hm := range psVirtualHost.GetHeaderMutations() { - injectEnvoyVirtualHostWithProxystateHeaderMutation(envoyVirtualHost, hm) - } - - return envoyVirtualHost -} - -func (pr *ProxyResources) makeEnvoyRouteFromProxystateRouteRule(psRouteRule *pbproxystate.RouteRule) *envoy_route_v3.Route { - envoyRouteRule := &envoy_route_v3.Route{ - Match: makeEnvoyRouteMatchFromProxystateRouteMatch(psRouteRule.GetMatch()), - Action: pr.makeEnvoyRouteActionFromProxystateRouteDestination(psRouteRule.GetDestination()), - } - - for _, hm := range psRouteRule.GetHeaderMutations() { - injectEnvoyRouteRuleWithProxystateHeaderMutation(envoyRouteRule, hm) - } - - return envoyRouteRule -} - -func makeEnvoyRouteMatchFromProxystateRouteMatch(psRouteMatch *pbproxystate.RouteMatch) *envoy_route_v3.RouteMatch { - envoyRouteMatch := &envoy_route_v3.RouteMatch{} - - switch psRouteMatch.PathMatch.GetPathMatch().(type) { - case *pbproxystate.PathMatch_Exact: - envoyRouteMatch.PathSpecifier = &envoy_route_v3.RouteMatch_Path{ - Path: psRouteMatch.PathMatch.GetExact(), - } - case *pbproxystate.PathMatch_Prefix: - envoyRouteMatch.PathSpecifier = &envoy_route_v3.RouteMatch_Prefix{ - Prefix: psRouteMatch.PathMatch.GetPrefix(), - } - case *pbproxystate.PathMatch_Regex: - envoyRouteMatch.PathSpecifier = &envoy_route_v3.RouteMatch_SafeRegex{ - SafeRegex: makeEnvoyRegexMatch(psRouteMatch.PathMatch.GetRegex()), - } - default: - // This shouldn't be possible considering the types of PathMatch - return nil - } - - if len(psRouteMatch.GetHeaderMatches()) > 0 { - envoyRouteMatch.Headers = make([]*envoy_route_v3.HeaderMatcher, 0, len(psRouteMatch.GetHeaderMatches())) - } - for _, psHM := range psRouteMatch.GetHeaderMatches() { - envoyRouteMatch.Headers = append(envoyRouteMatch.Headers, makeEnvoyHeaderMatcherFromProxystateHeaderMatch(psHM)) - } - - if len(psRouteMatch.MethodMatches) > 0 { - methodHeaderRegex := strings.Join(psRouteMatch.MethodMatches, "|") - - eh := &envoy_route_v3.HeaderMatcher{ - Name: ":method", - HeaderMatchSpecifier: &envoy_route_v3.HeaderMatcher_SafeRegexMatch{ - SafeRegexMatch: makeEnvoyRegexMatch(methodHeaderRegex), - }, - } - - envoyRouteMatch.Headers = append(envoyRouteMatch.Headers, eh) - } - - if len(psRouteMatch.GetQueryParameterMatches()) > 0 { - envoyRouteMatch.QueryParameters = make([]*envoy_route_v3.QueryParameterMatcher, 0, len(psRouteMatch.GetQueryParameterMatches())) - } - for _, psQM := range psRouteMatch.GetQueryParameterMatches() { - envoyRouteMatch.QueryParameters = append(envoyRouteMatch.QueryParameters, makeEnvoyQueryParamFromProxystateQueryMatch(psQM)) - } - - return envoyRouteMatch -} - -func makeEnvoyRegexMatch(pattern string) *envoy_matcher_v3.RegexMatcher { - return &envoy_matcher_v3.RegexMatcher{ - EngineType: &envoy_matcher_v3.RegexMatcher_GoogleRe2{ - GoogleRe2: &envoy_matcher_v3.RegexMatcher_GoogleRE2{}, - }, - Regex: pattern, - } -} - -func makeEnvoyHeaderMatcherFromProxystateHeaderMatch(psMatch *pbproxystate.HeaderMatch) *envoy_route_v3.HeaderMatcher { - envoyHeaderMatcher := &envoy_route_v3.HeaderMatcher{ - Name: psMatch.Name, - } - - switch psMatch.Match.(type) { - case *pbproxystate.HeaderMatch_Exact: - envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_ExactMatch{ - ExactMatch: psMatch.GetExact(), - } - case *pbproxystate.HeaderMatch_Regex: - envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_SafeRegexMatch{ - SafeRegexMatch: makeEnvoyRegexMatch(psMatch.GetRegex()), - } - case *pbproxystate.HeaderMatch_Prefix: - envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_PrefixMatch{ - PrefixMatch: psMatch.GetPrefix(), - } - case *pbproxystate.HeaderMatch_Suffix: - envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_SuffixMatch{ - SuffixMatch: psMatch.GetSuffix(), - } - case *pbproxystate.HeaderMatch_Present: - envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_PresentMatch{ - PresentMatch: true, - } - default: - // This shouldn't be possible considering the types of HeaderMatch - return nil - } - - if psMatch.GetInvertMatch() { - envoyHeaderMatcher.InvertMatch = true - } - - return envoyHeaderMatcher -} - -func makeEnvoyQueryParamFromProxystateQueryMatch(psMatch *pbproxystate.QueryParameterMatch) *envoy_route_v3.QueryParameterMatcher { - envoyQueryParamMatcher := &envoy_route_v3.QueryParameterMatcher{ - Name: psMatch.Name, - } - - switch psMatch.Match.(type) { - case *pbproxystate.QueryParameterMatch_Exact: - envoyQueryParamMatcher.QueryParameterMatchSpecifier = &envoy_route_v3.QueryParameterMatcher_StringMatch{ - StringMatch: &envoy_matcher_v3.StringMatcher{ - MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{ - Exact: psMatch.GetExact(), - }, - }, - } - - case *pbproxystate.QueryParameterMatch_Regex: - envoyQueryParamMatcher.QueryParameterMatchSpecifier = &envoy_route_v3.QueryParameterMatcher_StringMatch{ - StringMatch: &envoy_matcher_v3.StringMatcher{ - MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{ - SafeRegex: makeEnvoyRegexMatch(psMatch.GetRegex()), - }, - }, - } - case *pbproxystate.QueryParameterMatch_Present: - envoyQueryParamMatcher.QueryParameterMatchSpecifier = &envoy_route_v3.QueryParameterMatcher_PresentMatch{ - PresentMatch: true, - } - default: - // This shouldn't be possible considering the types of QueryMatch - return nil - } - - return envoyQueryParamMatcher -} - -// TODO (dans): Will this always be envoy_route_v3.Route_Route? -// Definitely for connect proxies this is the only option. -func (pr *ProxyResources) makeEnvoyRouteActionFromProxystateRouteDestination(psRouteDestination *pbproxystate.RouteDestination) *envoy_route_v3.Route_Route { - envoyRouteRoute := &envoy_route_v3.Route_Route{ - Route: &envoy_route_v3.RouteAction{}, - } - - switch psRouteDestination.Destination.(type) { - case *pbproxystate.RouteDestination_Cluster: - psCluster := psRouteDestination.GetCluster() - envoyRouteRoute.Route.ClusterSpecifier = &envoy_route_v3.RouteAction_Cluster{ - Cluster: psCluster.GetName(), - } - clusters, _ := pr.makeClusters(psCluster.Name) - pr.envoyResources[xdscommon.ClusterType] = append(pr.envoyResources[xdscommon.ClusterType], clusters...) - - case *pbproxystate.RouteDestination_WeightedClusters: - psWeightedClusters := psRouteDestination.GetWeightedClusters() - envoyClusters := make([]*envoy_route_v3.WeightedCluster_ClusterWeight, 0, len(psWeightedClusters.GetClusters())) - totalWeight := 0 - for _, psCluster := range psWeightedClusters.GetClusters() { - clusters, _ := pr.makeClusters(psCluster.Name) - pr.envoyResources[xdscommon.ClusterType] = append(pr.envoyResources[xdscommon.ClusterType], clusters...) - totalWeight += int(psCluster.Weight.GetValue()) - envoyClusters = append(envoyClusters, makeEnvoyClusterWeightFromProxystateWeightedCluster(psCluster)) - } - var envoyWeightScale *wrapperspb.UInt32Value - if totalWeight == 10000 { - envoyWeightScale = response.MakeUint32Value(10000) - } - - envoyRouteRoute.Route.ClusterSpecifier = &envoy_route_v3.RouteAction_WeightedClusters{ - WeightedClusters: &envoy_route_v3.WeightedCluster{ - Clusters: envoyClusters, - TotalWeight: envoyWeightScale, - }, - } - default: - // This shouldn't be possible considering the types of Destination - return nil - } - - injectEnvoyRouteActionWithProxystateDestinationConfig(envoyRouteRoute.Route, psRouteDestination.GetDestinationConfiguration()) - - if psRouteDestination.GetDestinationConfiguration() != nil { - config := psRouteDestination.GetDestinationConfiguration() - action := envoyRouteRoute.Route - - action.PrefixRewrite = config.GetPrefixRewrite() - - if config.GetTimeoutConfig().GetTimeout() != nil { - action.Timeout = config.GetTimeoutConfig().GetTimeout() - } - - if config.GetTimeoutConfig().GetTimeout() != nil { - action.Timeout = config.GetTimeoutConfig().GetTimeout() - } - - if config.GetTimeoutConfig().GetIdleTimeout() != nil { - action.IdleTimeout = config.GetTimeoutConfig().GetIdleTimeout() - } - - if config.GetRetryPolicy() != nil { - action.RetryPolicy = makeEnvoyRetryPolicyFromProxystateRetryPolicy(config.GetRetryPolicy()) - } - } - - return envoyRouteRoute -} - -func makeEnvoyClusterWeightFromProxystateWeightedCluster(cluster *pbproxystate.L7WeightedDestinationCluster) *envoy_route_v3.WeightedCluster_ClusterWeight { - envoyClusterWeight := &envoy_route_v3.WeightedCluster_ClusterWeight{ - Name: cluster.GetName(), - Weight: cluster.GetWeight(), - } - - for _, hm := range cluster.GetHeaderMutations() { - injectEnvoyClusterWeightWithProxystateHeaderMutation(envoyClusterWeight, hm) - } - - return envoyClusterWeight -} - -func injectEnvoyClusterWeightWithProxystateHeaderMutation(envoyClusterWeight *envoy_route_v3.WeightedCluster_ClusterWeight, mutation *pbproxystate.HeaderMutation) { - - mutation.GetAction() - switch mutation.GetAction().(type) { - case *pbproxystate.HeaderMutation_RequestHeaderAdd: - action := mutation.GetRequestHeaderAdd() - header := action.GetHeader() - app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - - hvo := &envoy_core_v3.HeaderValueOption{ - Header: &envoy_core_v3.HeaderValue{ - Key: header.GetKey(), - Value: header.GetValue(), - }, - Append: response.MakeBoolValue(app), - } - envoyClusterWeight.RequestHeadersToAdd = append(envoyClusterWeight.RequestHeadersToAdd, hvo) - - case *pbproxystate.HeaderMutation_RequestHeaderRemove: - action := mutation.GetRequestHeaderRemove() - envoyClusterWeight.RequestHeadersToRemove = append(envoyClusterWeight.RequestHeadersToRemove, action.GetHeaderKeys()...) - - case *pbproxystate.HeaderMutation_ResponseHeaderAdd: - action := mutation.GetResponseHeaderAdd() - header := action.GetHeader() - app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - - hvo := &envoy_core_v3.HeaderValueOption{ - Header: &envoy_core_v3.HeaderValue{ - Key: header.GetKey(), - Value: header.GetValue(), - }, - Append: response.MakeBoolValue(app), - } - envoyClusterWeight.ResponseHeadersToAdd = append(envoyClusterWeight.ResponseHeadersToAdd, hvo) - - case *pbproxystate.HeaderMutation_ResponseHeaderRemove: - action := mutation.GetResponseHeaderRemove() - envoyClusterWeight.ResponseHeadersToRemove = append(envoyClusterWeight.ResponseHeadersToRemove, action.GetHeaderKeys()...) - - default: - // This shouldn't be possible considering the types of Destination - return - } -} - -func injectEnvoyRouteActionWithProxystateDestinationConfig(envoyAction *envoy_route_v3.RouteAction, config *pbproxystate.DestinationConfiguration) { - if config == nil { - return - } - - if len(config.GetHashPolicies()) > 0 { - envoyAction.HashPolicy = make([]*envoy_route_v3.RouteAction_HashPolicy, 0, len(config.GetHashPolicies())) - } - for _, policy := range config.GetHashPolicies() { - envoyPolicy := makeEnvoyHashPolicyFromProxystateLBHashPolicy(policy) - envoyAction.HashPolicy = append(envoyAction.HashPolicy, envoyPolicy) - } - - if config.AutoHostRewrite != nil { - envoyAction.HostRewriteSpecifier = &envoy_route_v3.RouteAction_AutoHostRewrite{ - AutoHostRewrite: config.AutoHostRewrite, - } - } -} - -func makeEnvoyHashPolicyFromProxystateLBHashPolicy(psPolicy *pbproxystate.LoadBalancerHashPolicy) *envoy_route_v3.RouteAction_HashPolicy { - - switch psPolicy.GetPolicy().(type) { - case *pbproxystate.LoadBalancerHashPolicy_ConnectionProperties: - return &envoy_route_v3.RouteAction_HashPolicy{ - PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_ConnectionProperties_{ - ConnectionProperties: &envoy_route_v3.RouteAction_HashPolicy_ConnectionProperties{ - SourceIp: true, // always true - }, - }, - Terminal: psPolicy.GetConnectionProperties().GetTerminal(), - } - - case *pbproxystate.LoadBalancerHashPolicy_Header: - return &envoy_route_v3.RouteAction_HashPolicy{ - PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Header_{ - Header: &envoy_route_v3.RouteAction_HashPolicy_Header{ - HeaderName: psPolicy.GetHeader().GetName(), - }, - }, - Terminal: psPolicy.GetHeader().GetTerminal(), - } - - case *pbproxystate.LoadBalancerHashPolicy_Cookie: - cookie := &envoy_route_v3.RouteAction_HashPolicy_Cookie{ - Name: psPolicy.GetCookie().GetName(), - Path: psPolicy.GetCookie().GetPath(), - Ttl: psPolicy.GetCookie().GetTtl(), - } - - return &envoy_route_v3.RouteAction_HashPolicy{ - PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Cookie_{ - Cookie: cookie, - }, - Terminal: psPolicy.GetCookie().GetTerminal(), - } - - case *pbproxystate.LoadBalancerHashPolicy_QueryParameter: - return &envoy_route_v3.RouteAction_HashPolicy{ - PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_QueryParameter_{ - QueryParameter: &envoy_route_v3.RouteAction_HashPolicy_QueryParameter{ - Name: psPolicy.GetQueryParameter().GetName(), - }, - }, - Terminal: psPolicy.GetQueryParameter().GetTerminal(), - } - } - // This shouldn't be possible considering the types of LoadBalancerPolicy - return nil -} - -func makeEnvoyRetryPolicyFromProxystateRetryPolicy(psRetryPolicy *pbproxystate.RetryPolicy) *envoy_route_v3.RetryPolicy { - return &envoy_route_v3.RetryPolicy{ - NumRetries: psRetryPolicy.GetNumRetries(), - RetriableStatusCodes: psRetryPolicy.GetRetriableStatusCodes(), - RetryOn: psRetryPolicy.GetRetryOn(), - } -} - -func injectEnvoyRouteRuleWithProxystateHeaderMutation(envoyRouteRule *envoy_route_v3.Route, mutation *pbproxystate.HeaderMutation) { - - mutation.GetAction() - switch mutation.GetAction().(type) { - case *pbproxystate.HeaderMutation_RequestHeaderAdd: - action := mutation.GetRequestHeaderAdd() - header := action.GetHeader() - app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - - hvo := &envoy_core_v3.HeaderValueOption{ - Header: &envoy_core_v3.HeaderValue{ - Key: header.GetKey(), - Value: header.GetValue(), - }, - Append: response.MakeBoolValue(app), - } - envoyRouteRule.RequestHeadersToAdd = append(envoyRouteRule.RequestHeadersToAdd, hvo) - - case *pbproxystate.HeaderMutation_RequestHeaderRemove: - action := mutation.GetRequestHeaderRemove() - envoyRouteRule.RequestHeadersToRemove = append(envoyRouteRule.RequestHeadersToRemove, action.GetHeaderKeys()...) - - case *pbproxystate.HeaderMutation_ResponseHeaderAdd: - action := mutation.GetResponseHeaderAdd() - header := action.GetHeader() - app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - - hvo := &envoy_core_v3.HeaderValueOption{ - Header: &envoy_core_v3.HeaderValue{ - Key: header.GetKey(), - Value: header.GetValue(), - }, - Append: response.MakeBoolValue(app), - } - envoyRouteRule.ResponseHeadersToAdd = append(envoyRouteRule.ResponseHeadersToAdd, hvo) - - case *pbproxystate.HeaderMutation_ResponseHeaderRemove: - action := mutation.GetResponseHeaderRemove() - envoyRouteRule.ResponseHeadersToRemove = append(envoyRouteRule.ResponseHeadersToRemove, action.GetHeaderKeys()...) - - default: - // This shouldn't be possible considering the types of Destination - return - } -} - -func injectEnvoyVirtualHostWithProxystateHeaderMutation(envoyVirtualHost *envoy_route_v3.VirtualHost, mutation *pbproxystate.HeaderMutation) { - - mutation.GetAction() - switch mutation.GetAction().(type) { - case *pbproxystate.HeaderMutation_RequestHeaderAdd: - action := mutation.GetRequestHeaderAdd() - header := action.GetHeader() - app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - - hvo := &envoy_core_v3.HeaderValueOption{ - Header: &envoy_core_v3.HeaderValue{ - Key: header.GetKey(), - Value: header.GetValue(), - }, - Append: response.MakeBoolValue(app), - } - envoyVirtualHost.RequestHeadersToAdd = append(envoyVirtualHost.RequestHeadersToAdd, hvo) - - case *pbproxystate.HeaderMutation_RequestHeaderRemove: - action := mutation.GetRequestHeaderRemove() - envoyVirtualHost.RequestHeadersToRemove = append(envoyVirtualHost.RequestHeadersToRemove, action.GetHeaderKeys()...) - - case *pbproxystate.HeaderMutation_ResponseHeaderAdd: - action := mutation.GetResponseHeaderAdd() - header := action.GetHeader() - app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - - hvo := &envoy_core_v3.HeaderValueOption{ - Header: &envoy_core_v3.HeaderValue{ - Key: header.GetKey(), - Value: header.GetValue(), - }, - Append: response.MakeBoolValue(app), - } - envoyVirtualHost.ResponseHeadersToAdd = append(envoyVirtualHost.ResponseHeadersToAdd, hvo) - - case *pbproxystate.HeaderMutation_ResponseHeaderRemove: - action := mutation.GetResponseHeaderRemove() - envoyVirtualHost.ResponseHeadersToRemove = append(envoyVirtualHost.ResponseHeadersToRemove, action.GetHeaderKeys()...) - - default: - // This shouldn't be possible considering the types of Destination - return - } -} diff --git a/api/LICENSE b/api/LICENSE deleted file mode 100644 index 7c5baa45e1c29..0000000000000 --- a/api/LICENSE +++ /dev/null @@ -1,365 +0,0 @@ -Copyright (c) 2020 HashiCorp, Inc. - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - diff --git a/api/acl.go b/api/acl.go index 93087cd31c95f..48d2e66ee97fe 100644 --- a/api/acl.go +++ b/api/acl.go @@ -272,6 +272,13 @@ type ACLAuthMethod struct { Partition string `json:",omitempty"` } +type ACLTokenFilterOptions struct { + AuthMethod string `json:",omitempty"` + Policy string `json:",omitempty"` + Role string `json:",omitempty"` + ServiceName string `json:",omitempty"` +} + func (m *ACLAuthMethod) MarshalJSON() ([]byte, error) { type Alias ACLAuthMethod exported := &struct { @@ -895,6 +902,44 @@ func (a *ACL) TokenList(q *QueryOptions) ([]*ACLTokenListEntry, *QueryMeta, erro return entries, qm, nil } +// TokenListFiltered lists all tokens that match the given filter options. +// The listing does not contain any SecretIDs as those may only be retrieved by a call to TokenRead. +func (a *ACL) TokenListFiltered(t ACLTokenFilterOptions, q *QueryOptions) ([]*ACLTokenListEntry, *QueryMeta, error) { + r := a.c.newRequest("GET", "/v1/acl/tokens") + r.setQueryOptions(q) + + if t.AuthMethod != "" { + r.params.Set("authmethod", t.AuthMethod) + } + if t.Policy != "" { + r.params.Set("policy", t.Policy) + } + if t.Role != "" { + r.params.Set("role", t.Role) + } + if t.ServiceName != "" { + r.params.Set("servicename", t.ServiceName) + } + + rtt, resp, err := a.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var entries []*ACLTokenListEntry + if err := decodeBody(resp, &entries); err != nil { + return nil, nil, err + } + return entries, qm, nil +} + // PolicyCreate will create a new policy. It is not allowed for the policy parameters // ID field to be set as this will be generated by Consul while processing the request. func (a *ACL) PolicyCreate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *WriteMeta, error) { diff --git a/api/acl_test.go b/api/acl_test.go index f515878290cdd..d5ff37c1f75bb 100644 --- a/api/acl_test.go +++ b/api/acl_test.go @@ -553,6 +553,89 @@ func TestAPI_ACLToken_List(t *testing.T) { require.NotNil(t, token5) } +func TestAPI_ACLToken_ListFiltered(t *testing.T) { + t.Parallel() + c, s := makeACLClient(t) + defer s.Stop() + + acl := c.ACL() + s.WaitForSerfCheck(t) + + created1, _, err := acl.TokenCreate(&ACLToken{ + Description: "token1", + ServiceIdentities: []*ACLServiceIdentity{ + {ServiceName: "s1"}, + }, + }, nil) + require.NoError(t, err) + require.NotNil(t, created1) + require.NotEqual(t, "", created1.AccessorID) + require.NotEqual(t, "", created1.SecretID) + + created2, _, err := acl.TokenCreate(&ACLToken{ + Description: "token2", + ServiceIdentities: []*ACLServiceIdentity{ + {ServiceName: "s2"}, + }, + }, nil) + require.NoError(t, err) + require.NotNil(t, created2) + require.NotEqual(t, "", created2.AccessorID) + require.NotEqual(t, "", created2.SecretID) + + created3, _, err := acl.TokenCreate(&ACLToken{ + Description: "token3", + ServiceIdentities: []*ACLServiceIdentity{ + {ServiceName: "s1"}, + {ServiceName: "s2"}, + }, + }, nil) + require.NoError(t, err) + require.NotNil(t, created3) + require.NotEqual(t, "", created3.AccessorID) + require.NotEqual(t, "", created3.SecretID) + + tokens, qm, err := acl.TokenListFiltered(ACLTokenFilterOptions{ + ServiceName: "s1", + }, nil) + require.NoError(t, err) + require.NotEqual(t, 0, qm.LastIndex) + require.True(t, qm.KnownLeader) + require.Len(t, tokens, 2) + found := make([]string, 0, 2) + for _, token := range tokens { + found = append(found, token.Description) + } + require.ElementsMatch(t, []string{"token1", "token3"}, found) + + tokens, qm, err = acl.TokenListFiltered(ACLTokenFilterOptions{ + ServiceName: "s2", + }, nil) + require.NoError(t, err) + require.NotEqual(t, 0, qm.LastIndex) + require.True(t, qm.KnownLeader) + require.Len(t, tokens, 2) + found = make([]string, 0, 2) + for _, token := range tokens { + found = append(found, token.Description) + } + require.ElementsMatch(t, []string{"token2", "token3"}, found) + + tokens, qm, err = acl.TokenListFiltered(ACLTokenFilterOptions{ + ServiceName: "nothing", + }, nil) + require.NoError(t, err) + require.NotEqual(t, 0, qm.LastIndex) + require.True(t, qm.KnownLeader) + require.Empty(t, tokens) + + _, _, err = acl.TokenListFiltered(ACLTokenFilterOptions{ + ServiceName: "s", + AuthMethod: "a", + }, nil) + require.ErrorContains(t, err, "can only filter by one of") +} + func TestAPI_ACLToken_Clone(t *testing.T) { t.Parallel() c, s := makeACLClient(t) diff --git a/api/agent.go b/api/agent.go index b09ed1c1cd75d..6775edf4257ad 100644 --- a/api/agent.go +++ b/api/agent.go @@ -345,6 +345,7 @@ type AgentServiceCheck struct { Method string `json:",omitempty"` Body string `json:",omitempty"` TCP string `json:",omitempty"` + TCPUseTLS bool `json:",omitempty"` UDP string `json:",omitempty"` Status string `json:",omitempty"` Notes string `json:",omitempty"` diff --git a/api/agent_test.go b/api/agent_test.go index e6731bb29ad67..dce525ebc322c 100644 --- a/api/agent_test.go +++ b/api/agent_test.go @@ -165,21 +165,6 @@ func TestAPI_AgentMembersOpts(t *testing.T) { } require.Equal(t, 1, len(members)) - - members, err = agent.MembersOpts(MembersOpts{ - WAN: true, - Filter: `Tags["dc"] == "not-Exist"`, - }) - if err != nil { - t.Fatalf("err: %v", err) - } - require.Equal(t, 0, len(members)) - - _, err = agent.MembersOpts(MembersOpts{ - WAN: true, - Filter: `Tags["dc"] == invalid-bexpr-value`, - }) - require.ErrorContains(t, err, "Failed to create boolean expression evaluator") } func TestAPI_AgentMembers(t *testing.T) { diff --git a/api/config_entry.go b/api/config_entry.go index b59c20fd3007d..405e92ef2741e 100644 --- a/api/config_entry.go +++ b/api/config_entry.go @@ -39,12 +39,11 @@ const ( ) const ( - BuiltinAWSLambdaExtension string = "builtin/aws/lambda" - BuiltinExtAuthzExtension string = "builtin/ext-authz" - BuiltinLuaExtension string = "builtin/lua" - BuiltinOTELAccessLoggingExtension string = "builtin/otel-access-logging" - BuiltinPropertyOverrideExtension string = "builtin/property-override" - BuiltinWasmExtension string = "builtin/wasm" + BuiltinAWSLambdaExtension string = "builtin/aws/lambda" + BuiltinExtAuthzExtension string = "builtin/ext-authz" + BuiltinLuaExtension string = "builtin/lua" + BuiltinPropertyOverrideExtension string = "builtin/property-override" + BuiltinWasmExtension string = "builtin/wasm" // BuiltinValidateExtension should not be exposed directly or accepted as a valid configured // extension type, as it is only used indirectly via troubleshooting tools. It is included here // for common reference alongside other builtin extensions. @@ -315,47 +314,6 @@ type UpstreamLimits struct { MaxConcurrentRequests *int `alias:"max_concurrent_requests"` } -// RateLimits is rate limiting configuration that is applied to -// inbound traffic for a service. -// Rate limiting is a Consul enterprise feature. -type RateLimits struct { - InstanceLevel InstanceLevelRateLimits `alias:"instance_level"` -} - -// InstanceLevelRateLimits represents rate limit configuration -// that are applied per service instance. -type InstanceLevelRateLimits struct { - // RequestsPerSecond is the average number of requests per second that can be - // made without being throttled. This field is required if RequestsMaxBurst - // is set. The allowed number of requests may exceed RequestsPerSecond up to - // the value specified in RequestsMaxBurst. - // - // Internally, this is the refill rate of the token bucket used for rate limiting. - RequestsPerSecond int `alias:"requests_per_second"` - - // RequestsMaxBurst is the maximum number of requests that can be sent - // in a burst. Should be equal to or greater than RequestsPerSecond. - // If unset, defaults to RequestsPerSecond. - // - // Internally, this is the maximum size of the token bucket used for rate limiting. - RequestsMaxBurst int `alias:"requests_max_burst"` - - // Routes is a list of rate limits applied to specific routes. - // Overrides any top-level configuration. - Routes []InstanceLevelRouteRateLimits -} - -// InstanceLevelRouteRateLimits represents rate limit configuration -// applied to a route matching one of PathExact/PathPrefix/PathRegex. -type InstanceLevelRouteRateLimits struct { - PathExact string `alias:"path_exact"` - PathPrefix string `alias:"path_prefix"` - PathRegex string `alias:"path_regex"` - - RequestsPerSecond int `alias:"requests_per_second"` - RequestsMaxBurst int `alias:"requests_max_burst"` -} - type ServiceConfigEntry struct { Kind string Name string @@ -374,7 +332,6 @@ type ServiceConfigEntry struct { LocalConnectTimeoutMs int `json:",omitempty" alias:"local_connect_timeout_ms"` LocalRequestTimeoutMs int `json:",omitempty" alias:"local_request_timeout_ms"` BalanceInboundConnections string `json:",omitempty" alias:"balance_inbound_connections"` - RateLimits *RateLimits `json:",omitempty" alias:"rate_limits"` EnvoyExtensions []EnvoyExtension `json:",omitempty" alias:"envoy_extensions"` Meta map[string]string `json:",omitempty"` CreateIndex uint64 diff --git a/api/config_entry_gateways.go b/api/config_entry_gateways.go index baf274e2da027..b59f1c0621ff6 100644 --- a/api/config_entry_gateways.go +++ b/api/config_entry_gateways.go @@ -284,10 +284,6 @@ type APIGatewayListener struct { Protocol string // TLS is the TLS settings for the listener. TLS APIGatewayTLSConfiguration - // Override is the policy that overrides all other policy and route specific configuration - Override *APIGatewayPolicy `json:",omitempty"` - // Default is the policy that is the default for the listener and route, routes can override this behavior - Default *APIGatewayPolicy `json:",omitempty"` } // APIGatewayTLSConfiguration specifies the configuration of a listener’s @@ -306,39 +302,3 @@ type APIGatewayTLSConfiguration struct { // Only applicable to connections negotiated via TLS 1.2 or earlier CipherSuites []string `json:",omitempty" alias:"cipher_suites"` } - -// APIGatewayPolicy holds the policy that configures the gateway listener, this is used in the `Override` and `Default` fields of a listener -type APIGatewayPolicy struct { - // JWT holds the JWT configuration for the Listener - JWT *APIGatewayJWTRequirement `json:",omitempty"` -} - -// APIGatewayJWTRequirement holds the list of JWT providers to be verified against -type APIGatewayJWTRequirement struct { - // Providers is a list of providers to consider when verifying a JWT. - Providers []*APIGatewayJWTProvider `json:",omitempty"` -} - -// APIGatewayJWTProvider holds the provider and claim verification information -type APIGatewayJWTProvider struct { - // Name is the name of the JWT provider. There MUST be a corresponding - // "jwt-provider" config entry with this name. - Name string `json:",omitempty"` - - // VerifyClaims is a list of additional claims to verify in a JWT's payload. - VerifyClaims []*APIGatewayJWTClaimVerification `json:",omitempty" alias:"verify_claims"` -} - -// APIGatewayJWTClaimVerification holds the actual claim information to be verified -type APIGatewayJWTClaimVerification struct { - // Path is the path to the claim in the token JSON. - Path []string `json:",omitempty"` - - // Value is the expected value at the given path: - // - If the type at the path is a list then we verify - // that this value is contained in the list. - // - // - If the type at the path is a string then we verify - // that this value matches. - Value string `json:",omitempty"` -} diff --git a/api/config_entry_gateways_test.go b/api/config_entry_gateways_test.go index 7383b0ae68038..25b0a2d515c26 100644 --- a/api/config_entry_gateways_test.go +++ b/api/config_entry_gateways_test.go @@ -348,150 +348,3 @@ func TestAPI_ConfigEntries_TerminatingGateway(t *testing.T) { _, _, err = configEntries.Get(TerminatingGateway, "foo", nil) require.Error(t, err) } - -func TestAPI_ConfigEntries_APIGateway(t *testing.T) { - t.Parallel() - c, s := makeClient(t) - defer s.Stop() - - configEntries := c.ConfigEntries() - listener1 := APIGatewayListener{ - Name: "listener1", - Hostname: "host.com", - Port: 3360, - Protocol: "http", - } - - listener2 := APIGatewayListener{ - Name: "listener2", - Hostname: "host2.com", - Port: 3362, - Protocol: "http", - } - - apigw1 := &APIGatewayConfigEntry{ - Kind: APIGateway, - Name: "foo", - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - Listeners: []APIGatewayListener{listener1}, - } - - apigw2 := &APIGatewayConfigEntry{ - Kind: APIGateway, - Name: "bar", - Listeners: []APIGatewayListener{listener2}, - } - - // set it - _, wm, err := configEntries.Set(apigw1, nil) - require.NoError(t, err) - require.NotNil(t, wm) - require.NotEqual(t, 0, wm.RequestTime) - - // also set the second one - _, wm, err = configEntries.Set(apigw2, nil) - require.NoError(t, err) - require.NotNil(t, wm) - require.NotEqual(t, 0, wm.RequestTime) - - // get it - entry, qm, err := configEntries.Get(APIGateway, "foo", nil) - require.NoError(t, err) - require.NotNil(t, qm) - require.NotEqual(t, 0, qm.RequestTime) - - // verify it - readGW, ok := entry.(*APIGatewayConfigEntry) - require.True(t, ok) - require.Equal(t, apigw1.Kind, readGW.Kind) - require.Equal(t, apigw1.Name, readGW.Name) - require.Equal(t, apigw1.Meta, readGW.Meta) - require.Equal(t, apigw1.Meta, readGW.GetMeta()) - - // update it - apigw1.Listeners = []APIGatewayListener{ - listener1, - { - Name: "listener3", - Hostname: "host3.com", - Port: 3363, - Protocol: "http", - }, - } - - // CAS fail - written, _, err := configEntries.CAS(apigw1, 0, nil) - require.NoError(t, err) - require.False(t, written) - - // CAS success - written, wm, err = configEntries.CAS(apigw1, readGW.ModifyIndex, nil) - require.NoError(t, err) - require.NotNil(t, wm) - require.NotEqual(t, 0, wm.RequestTime) - require.True(t, written) - - // re-setting should not yield an error - _, wm, err = configEntries.Set(apigw1, nil) - require.NoError(t, err) - require.NotNil(t, wm) - require.NotEqual(t, 0, wm.RequestTime) - - apigw2.Listeners = []APIGatewayListener{ - listener2, - { - Name: "listener4", - Hostname: "host4.com", - Port: 3364, - Protocol: "http", - }, - } - - _, wm, err = configEntries.Set(apigw2, nil) - require.NoError(t, err) - require.NotNil(t, wm) - require.NotEqual(t, 0, wm.RequestTime) - - // list them - entries, qm, err := configEntries.List(APIGateway, nil) - require.NoError(t, err) - require.NotNil(t, qm) - require.NotEqual(t, 0, qm.RequestTime) - require.Len(t, entries, 2) - - for _, entry = range entries { - switch entry.GetName() { - case "foo": - // this also verifies that the update value was persisted and - // the updated values are seen - readGW, ok = entry.(*APIGatewayConfigEntry) - require.True(t, ok) - require.Equal(t, apigw1.Kind, readGW.Kind) - require.Equal(t, apigw1.Name, readGW.Name) - require.Len(t, readGW.Listeners, 2) - - require.Equal(t, apigw1.Listeners, readGW.Listeners) - case "bar": - readGW, ok = entry.(*APIGatewayConfigEntry) - require.True(t, ok) - require.Equal(t, apigw2.Kind, readGW.Kind) - require.Equal(t, apigw2.Name, readGW.Name) - require.Len(t, readGW.Listeners, 2) - - require.Equal(t, apigw2.Listeners, readGW.Listeners) - } - } - - // delete it - wm, err = configEntries.Delete(APIGateway, "foo", nil) - require.NoError(t, err) - require.NotNil(t, wm) - require.NotEqual(t, 0, wm.RequestTime) - - // verify deletion - _, _, err = configEntries.Get(APIGateway, "foo", nil) - require.Error(t, err) -} diff --git a/api/config_entry_routes.go b/api/config_entry_routes.go index 8df367093fe2d..cfea394535dbb 100644 --- a/api/config_entry_routes.go +++ b/api/config_entry_routes.go @@ -3,8 +3,6 @@ package api -import "time" - // TCPRouteConfigEntry -- TODO stub type TCPRouteConfigEntry struct { // Kind of the config entry. This should be set to api.TCPRoute. @@ -197,11 +195,8 @@ type HTTPQueryMatch struct { // HTTPFilters specifies a list of filters used to modify a request // before it is routed to an upstream. type HTTPFilters struct { - Headers []HTTPHeaderFilter - URLRewrite *URLRewrite - RetryFilter *RetryFilter - TimeoutFilter *TimeoutFilter - JWT *JWTFilter + Headers []HTTPHeaderFilter + URLRewrite *URLRewrite } // HTTPHeaderFilter specifies how HTTP headers should be modified. @@ -215,23 +210,6 @@ type URLRewrite struct { Path string } -type RetryFilter struct { - NumRetries *uint32 - RetryOn []string - RetryOnStatusCodes []uint32 - RetryOnConnectFailure *bool -} - -type TimeoutFilter struct { - RequestTimeout time.Duration - IdleTimeout time.Duration -} - -// JWTFilter specifies the JWT configuration for a route -type JWTFilter struct { - Providers []*APIGatewayJWTProvider `json:",omitempty"` -} - // HTTPRouteRule specifies the routing rules used to determine what upstream // service an HTTP request is routed to. type HTTPRouteRule struct { diff --git a/api/config_entry_routes_test.go b/api/config_entry_routes_test.go deleted file mode 100644 index b878612e907e4..0000000000000 --- a/api/config_entry_routes_test.go +++ /dev/null @@ -1,134 +0,0 @@ -package api - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestAPI_ConfigEntries_HTTPRoute(t *testing.T) { - t.Parallel() - c, s := makeClient(t) - defer s.Stop() - - configEntries := c.ConfigEntries() - route1 := &HTTPRouteConfigEntry{ - Kind: HTTPRoute, - Name: "route1", - } - - route2 := &HTTPRouteConfigEntry{ - Kind: HTTPRoute, - Name: "route2", - } - - // set it - _, wm, err := configEntries.Set(route1, nil) - require.NoError(t, err) - require.NotNil(t, wm) - require.NotEqual(t, 0, wm.RequestTime) - - // also set the second one - _, wm, err = configEntries.Set(route2, nil) - require.NoError(t, err) - require.NotNil(t, wm) - require.NotEqual(t, 0, wm.RequestTime) - - // get it - entry, qm, err := configEntries.Get(HTTPRoute, "route1", nil) - require.NoError(t, err) - require.NotNil(t, qm) - require.NotEqual(t, 0, qm.RequestTime) - - // verify it - readRoute, ok := entry.(*HTTPRouteConfigEntry) - require.True(t, ok) - require.Equal(t, route1.Kind, readRoute.Kind) - require.Equal(t, route1.Name, readRoute.Name) - require.Equal(t, route1.Meta, readRoute.Meta) - require.Equal(t, route1.Meta, readRoute.GetMeta()) - - // update it - route1.Rules = []HTTPRouteRule{ - { - Filters: HTTPFilters{ - URLRewrite: &URLRewrite{ - Path: "abc", - }, - }, - }, - } - - // CAS fail - written, _, err := configEntries.CAS(route1, 0, nil) - require.NoError(t, err) - require.False(t, written) - - // CAS success - written, wm, err = configEntries.CAS(route1, readRoute.ModifyIndex, nil) - require.NoError(t, err) - require.NotNil(t, wm) - require.NotEqual(t, 0, wm.RequestTime) - require.True(t, written) - - // re-setting should not yield an error - _, wm, err = configEntries.Set(route1, nil) - require.NoError(t, err) - require.NotNil(t, wm) - require.NotEqual(t, 0, wm.RequestTime) - - route2.Rules = []HTTPRouteRule{ - { - Filters: HTTPFilters{ - URLRewrite: &URLRewrite{ - Path: "def", - }, - }, - }, - } - - _, wm, err = configEntries.Set(route2, nil) - require.NoError(t, err) - require.NotNil(t, wm) - require.NotEqual(t, 0, wm.RequestTime) - - // list them - entries, qm, err := configEntries.List(HTTPRoute, nil) - require.NoError(t, err) - require.NotNil(t, qm) - require.NotEqual(t, 0, qm.RequestTime) - require.Len(t, entries, 2) - - for _, entry = range entries { - switch entry.GetName() { - case "route1": - // this also verifies that the update value was persisted and - // the updated values are seen - readRoute, ok = entry.(*HTTPRouteConfigEntry) - require.True(t, ok) - require.Equal(t, route1.Kind, readRoute.Kind) - require.Equal(t, route1.Name, readRoute.Name) - require.Len(t, readRoute.Rules, 1) - - require.Equal(t, route1.Rules, readRoute.Rules) - case "route2": - readRoute, ok = entry.(*HTTPRouteConfigEntry) - require.True(t, ok) - require.Equal(t, route2.Kind, readRoute.Kind) - require.Equal(t, route2.Name, readRoute.Name) - require.Len(t, readRoute.Rules, 1) - - require.Equal(t, route2.Rules, readRoute.Rules) - } - } - - // delete it - wm, err = configEntries.Delete(HTTPRoute, "route1", nil) - require.NoError(t, err) - require.NotNil(t, wm) - require.NotEqual(t, 0, wm.RequestTime) - - // verify deletion - _, _, err = configEntries.Get(HTTPRoute, "route1", nil) - require.Error(t, err) -} diff --git a/api/health.go b/api/health.go index 932317fdb01e3..a0230020460de 100644 --- a/api/health.go +++ b/api/health.go @@ -67,6 +67,7 @@ type HealthCheckDefinition struct { TLSServerName string TLSSkipVerify bool TCP string + TCPUseTLS bool UDP string GRPC string OSService string diff --git a/api/watch/funcs_test.go b/api/watch/funcs_test.go index 4bd79a59c14f9..91318009ceac9 100644 --- a/api/watch/funcs_test.go +++ b/api/watch/funcs_test.go @@ -1196,110 +1196,6 @@ func TestChecksWatch_Filter(t *testing.T) { } } -func TestChecksWatch_Filter_by_ServiceNameStatus(t *testing.T) { - t.Parallel() - c, s := makeClient(t) - defer s.Stop() - - s.WaitForSerfCheck(t) - - var ( - wakeups [][]*api.HealthCheck - notifyCh = make(chan struct{}) - ) - - plan := mustParse(t, `{"type":"checks", "filter":"ServiceName == bar and Status == critical"}`) - plan.Handler = func(idx uint64, raw interface{}) { - if raw == nil { - return // ignore - } - v, ok := raw.([]*api.HealthCheck) - if !ok { - return // ignore - } - wakeups = append(wakeups, v) - notifyCh <- struct{}{} - } - - var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - if err := plan.Run(s.HTTPAddr); err != nil { - t.Errorf("err: %v", err) - } - }() - defer plan.Stop() - - // Wait for first wakeup. - <-notifyCh - { - catalog := c.Catalog() - - // we don't want to find this one - reg := &api.CatalogRegistration{ - Node: "foo", - Address: "1.1.1.1", - Datacenter: "dc1", - Service: &api.AgentService{ - ID: "foo", - Service: "foo", - Tags: []string{"a"}, - }, - Check: &api.AgentCheck{ - Node: "foo", - CheckID: "foo", - Name: "foo", - Status: api.HealthPassing, - ServiceID: "foo", - }, - } - if _, err := catalog.Register(reg, nil); err != nil { - t.Fatalf("err: %v", err) - } - - // we want to find this one - reg = &api.CatalogRegistration{ - Node: "bar", - Address: "2.2.2.2", - Datacenter: "dc1", - Service: &api.AgentService{ - ID: "bar", - Service: "bar", - Tags: []string{"a", "b"}, - }, - Check: &api.AgentCheck{ - Node: "bar", - CheckID: "bar", - Name: "bar", - Status: api.HealthCritical, - ServiceID: "bar", - }, - } - if _, err := catalog.Register(reg, nil); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Wait for second wakeup. - <-notifyCh - - plan.Stop() - wg.Wait() - - require.Len(t, wakeups, 2) - - { - v := wakeups[0] - require.Len(t, v, 0) - } - { - v := wakeups[1] - require.Len(t, v, 1) - require.Equal(t, "bar", v[0].CheckID) - } -} - func TestEventWatch(t *testing.T) { t.Parallel() c, s := makeClient(t) diff --git a/buf.work.yaml b/buf.work.yaml index 5fab419b164bf..f89f53a2bd8a2 100644 --- a/buf.work.yaml +++ b/buf.work.yaml @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 version: v1 directories: diff --git a/build-support/docker/Build-Go.dockerfile b/build-support/docker/Build-Go.dockerfile index 2337a72702093..c5b3c8394ea38 100644 --- a/build-support/docker/Build-Go.dockerfile +++ b/build-support/docker/Build-Go.dockerfile @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 ARG GOLANG_VERSION=1.20.7 FROM golang:${GOLANG_VERSION} diff --git a/build-support/docker/Build-UI.dockerfile b/build-support/docker/Build-UI.dockerfile index 9d646fb6ea69c..6682458137dce 100644 --- a/build-support/docker/Build-UI.dockerfile +++ b/build-support/docker/Build-UI.dockerfile @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 FROM docker.mirror.hashicorp.services/circleci/node:16-browsers diff --git a/build-support/docker/Consul-Dev-Dbg.dockerfile b/build-support/docker/Consul-Dev-Dbg.dockerfile index 488fb053264ed..cf1ae388d1f71 100644 --- a/build-support/docker/Consul-Dev-Dbg.dockerfile +++ b/build-support/docker/Consul-Dev-Dbg.dockerfile @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 FROM consul:local EXPOSE 4000 diff --git a/build-support/docker/Consul-Dev-Multiarch.dockerfile b/build-support/docker/Consul-Dev-Multiarch.dockerfile index e35a98d5f8902..265a1804cf11a 100644 --- a/build-support/docker/Consul-Dev-Multiarch.dockerfile +++ b/build-support/docker/Consul-Dev-Multiarch.dockerfile @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 ARG CONSUL_IMAGE_VERSION=latest FROM hashicorp/consul:${CONSUL_IMAGE_VERSION} diff --git a/build-support/docker/Consul-Dev.dockerfile b/build-support/docker/Consul-Dev.dockerfile index 12f014969ab51..122bc3192a7f5 100644 --- a/build-support/docker/Consul-Dev.dockerfile +++ b/build-support/docker/Consul-Dev.dockerfile @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 ARG CONSUL_IMAGE_VERSION=latest FROM hashicorp/consul:${CONSUL_IMAGE_VERSION} diff --git a/build-support/functions/00-vars.sh b/build-support/functions/00-vars.sh index ef8433c34ebb5..2f16f8ce74cab 100644 --- a/build-support/functions/00-vars.sh +++ b/build-support/functions/00-vars.sh @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # GPG Key ID to use for publically released builds HASHICORP_GPG_KEY="348FFC4C" diff --git a/build-support/functions/10-util.sh b/build-support/functions/10-util.sh index 4bb9f35a9f381..9a47ea3722dcb 100644 --- a/build-support/functions/10-util.sh +++ b/build-support/functions/10-util.sh @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 function err { if test "${COLORIZE}" -eq 1 diff --git a/build-support/functions/20-build.sh b/build-support/functions/20-build.sh index c49ff0c592986..a2e5830196b6c 100644 --- a/build-support/functions/20-build.sh +++ b/build-support/functions/20-build.sh @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 function supported_osarch { # Arguments: diff --git a/build-support/functions/30-release.sh b/build-support/functions/30-release.sh index 26f7c1048995e..d83d9f4155039 100644 --- a/build-support/functions/30-release.sh +++ b/build-support/functions/30-release.sh @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 function tag_release { # Arguments: diff --git a/build-support/scripts/build-date.sh b/build-support/scripts/build-date.sh index 49f3851bef47c..5b52bffa26473 100755 --- a/build-support/scripts/build-date.sh +++ b/build-support/scripts/build-date.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})" readonly SCRIPT_DIR="$(dirname ${BASH_SOURCE[0]})" diff --git a/build-support/scripts/build-docker.sh b/build-support/scripts/build-docker.sh index d36196e66bfd0..2b72aa5fb0616 100755 --- a/build-support/scripts/build-docker.sh +++ b/build-support/scripts/build-docker.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})" diff --git a/build-support/scripts/check-allowed-imports.sh b/build-support/scripts/check-allowed-imports.sh deleted file mode 100755 index efba156c79377..0000000000000 --- a/build-support/scripts/check-allowed-imports.sh +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - - -readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})" -readonly SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" -readonly SOURCE_DIR="$(dirname "$(dirname "${SCRIPT_DIR}")")" -readonly FN_DIR="$(dirname "${SCRIPT_DIR}")/functions" - -source "${SCRIPT_DIR}/functions.sh" - - -set -uo pipefail - -usage() { -cat <<-EOF -Usage: ${SCRIPT_NAME} [...] - -Description: - Verifies that only the specified packages may be imported from the given module - -Options: - -h | --help Print this help text. -EOF -} - -function err_usage { - err "$1" - err "" - err "$(usage)" -} - -function main { - local module_root="" - declare -a allowed_packages=() - while test $# -gt 0 - do - case "$1" in - -h | --help ) - usage - return 0 - ;; - * ) - if test -z "$module_root" - then - module_root="$1" - else - allowed_packages+="$1" - fi - shift - esac - done - - # If we could guarantee this ran with bash 4.2+ then the final argument could - # be just ${allowed_packages[@]}. However that with older versions of bash - # in combination with set -u causes bash to emit errors about using unbound - # variables when no allowed packages have been specified (i.e. the module should - # generally be disallowed with no exceptions). This syntax is very strange - # but seems to be the prescribed workaround I found. - check_imports "$module_root" ${allowed_packages[@]+"${allowed_packages[@]}"} - return $? -} - -function check_imports { - local module_root="$1" - shift - local allowed_packages="$@" - - module_imports=$( go list -test -f '{{join .TestImports "\n"}}' ./... | grep "$module_root" | sort | uniq) - module_test_imports=$( go list -test -f '{{join .TestImports "\n"}}' ./... | grep "$module_root" | sort | uniq) - - any_error=0 - - for imp in $module_imports - do - is_import_allowed "$imp" "$module_root" $allowed_packages - allowed=$? - - if test $any_error -ne 1 - then - any_error=$allowed - fi - done - - if test $any_error -eq 1 - then - echo "Only the following direct imports are allowed from module $module_root:" - for pkg in $allowed_packages - do - echo " * $pkg" - done - fi - - return $any_error -} - -function is_import_allowed { - local pkg_import=$1 - shift - local module_root=$1 - shift - local allowed_packages="$@" - - # check if the import path is a part of the module we are restricting imports for - if test "$( go list -f '{{.Module.Path}}' $pkg_import)" != "$module_root" - then - return 0 - fi - - for pkg in $allowed_packages - do - if test "${module_root}/$pkg" == "$pkg_import" - then - return 0 - fi - done - - err "Import of package $pkg_import is not allowed" - return 1 -} - -main "$@" -exit $? \ No newline at end of file diff --git a/build-support/scripts/devtools.sh b/build-support/scripts/devtools.sh index edf4b83eae66c..82cf316cb3340 100755 --- a/build-support/scripts/devtools.sh +++ b/build-support/scripts/devtools.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})" diff --git a/build-support/scripts/envoy-library-references.sh b/build-support/scripts/envoy-library-references.sh index bca15806c7e47..7f5413bbf78f8 100644 --- a/build-support/scripts/envoy-library-references.sh +++ b/build-support/scripts/envoy-library-references.sh @@ -23,7 +23,7 @@ unset CDPATH cd "$(dirname "$0")" # build-support/scripts cd ../.. # -if [[ ! -f Makefile ]] || [[ ! -f go.mod ]]; then +if [[ ! -f GNUmakefile ]] || [[ ! -f go.mod ]]; then echo "not in root consul checkout: ${PWD}" >&2 exit 1 fi diff --git a/build-support/scripts/functions.sh b/build-support/scripts/functions.sh index 4db767f13c559..42fe385c012ed 100755 --- a/build-support/scripts/functions.sh +++ b/build-support/scripts/functions.sh @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # # NOTE: This file is meant to be sourced from other bash scripts/shells diff --git a/build-support/scripts/protobuf.sh b/build-support/scripts/protobuf.sh index 20d06c807763b..420d66d6a11bd 100755 --- a/build-support/scripts/protobuf.sh +++ b/build-support/scripts/protobuf.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})" @@ -72,10 +72,6 @@ function main { status "Generated gRPC rate limit mapping file" - generate_protoset_file - - status "Generated protoset file" - return 0 } @@ -156,11 +152,5 @@ function generate_rate_limit_mappings { } } -function generate_protoset_file { - local pkg_dir="${SOURCE_DIR}/pkg" - mkdir -p "$pkg_dir" - print_run buf build -o "${pkg_dir}/consul.protoset" -} - main "$@" exit $? diff --git a/build-support/scripts/release.sh b/build-support/scripts/release.sh index fa7e7c066d458..a8fbe84d89117 100755 --- a/build-support/scripts/release.sh +++ b/build-support/scripts/release.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})" diff --git a/build-support/scripts/version.sh b/build-support/scripts/version.sh index 2bc9998813ed1..46630636bbfca 100755 --- a/build-support/scripts/version.sh +++ b/build-support/scripts/version.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})" diff --git a/build-support/windows/Dockerfile-consul-dev-windows b/build-support/windows/Dockerfile-consul-dev-windows deleted file mode 100644 index 4e35ccb6e5eba..0000000000000 --- a/build-support/windows/Dockerfile-consul-dev-windows +++ /dev/null @@ -1,4 +0,0 @@ -ARG VERSION=1.16.0 - -FROM windows/consul:${VERSION}-local -COPY dist/ C:\\consul diff --git a/build-support/windows/Dockerfile-consul-local-windows b/build-support/windows/Dockerfile-consul-local-windows deleted file mode 100644 index 992c48c286a27..0000000000000 --- a/build-support/windows/Dockerfile-consul-local-windows +++ /dev/null @@ -1,52 +0,0 @@ -ARG VERSION=1.13.3 - -FROM windows/test-sds-server as test-sds-server -FROM docker.mirror.hashicorp.services/windows/openzipkin as openzipkin -FROM windows/consul:${VERSION} - -# Fortio binary downloaded -RUN mkdir fortio -ENV FORTIO_URL=https://github.com/fortio/fortio/releases/download/v1.33.0/fortio_win_1.33.0.zip -RUN curl %FORTIO_URL% -L -o fortio.zip -RUN tar -xf fortio.zip -C fortio - -RUN choco install openssl -yf -RUN choco install jq -yf -RUN choco install netcat -yf -RUN choco install openjdk -yf - -# Install Bats -ENV BATS_URL=https://github.com/bats-core/bats-core/archive/refs/tags/v1.7.0.zip -RUN curl %BATS_URL% -L -o bats.zip -RUN mkdir bats-core -RUN tar -xf bats.zip -C bats-core --strip-components=1 -RUN cd "C:\\Program Files\\Git\\bin" && bash.exe -c "/c/bats-core/install.sh /c/bats" - -# Install Jaeger -ENV JAEGER_URL=https://github.com/jaegertracing/jaeger/releases/download/v1.11.0/jaeger-1.11.0-windows-amd64.tar.gz -RUN curl %JAEGER_URL% -L -o jaeger.tar.gz -RUN mkdir jaeger -RUN tar -xf jaeger.tar.gz -C jaeger --strip-components=1 - -# Install Socat -ENV SOCAT_URL=https://github.com/tech128/socat-1.7.3.0-windows/archive/refs/heads/master.zip -RUN curl %SOCAT_URL% -L -o socat.zip -RUN mkdir socat -RUN tar -xf socat.zip -C socat --strip-components=1 - -# Copy test-sds-server binary and certs -COPY --from=test-sds-server ["C:/go/src/", "C:/test-sds-server/"] - -# Copy openzipkin .jar file -COPY --from=openzipkin ["C:/zipkin", "C:/zipkin"] - -EXPOSE 8300 -EXPOSE 8301 8301/udp 8302 8302/udp -EXPOSE 8500 8600 8600/udp -EXPOSE 8502 - -EXPOSE 19000 19001 19002 19003 19004 -EXPOSE 21000 21001 21002 21003 21004 -EXPOSE 5000 1234 2345 - -RUN SETX /M path "%PATH%;C:\consul;C:\fortio;C:\jaeger;C:\Program Files\Git\bin;C:\Program Files\Git\usr\bin;C:\Program Files\OpenSSL-Win64\bin;C:\bats\bin\;C:\ProgramData\chocolatey\lib\jq\tools;C:\socat" diff --git a/build-support/windows/Dockerfile-openzipkin-windows b/build-support/windows/Dockerfile-openzipkin-windows deleted file mode 100644 index b23867f0b22cf..0000000000000 --- a/build-support/windows/Dockerfile-openzipkin-windows +++ /dev/null @@ -1,12 +0,0 @@ -FROM docker.mirror.hashicorp.services/windows/openjdk:1809 - -RUN mkdir zipkin -RUN curl.exe -sSL 'https://search.maven.org/remote_content?g=io.zipkin&a=zipkin-server&v=LATEST&c=exec' -o zipkin/zipkin.jar - -EXPOSE 9410/tcp - -EXPOSE 9411/tcp - -WORKDIR /zipkin - -ENTRYPOINT ["java", "-jar", "zipkin.jar"] \ No newline at end of file diff --git a/build-support/windows/build-consul-dev-image.sh b/build-support/windows/build-consul-dev-image.sh deleted file mode 100644 index ddc5e521d11aa..0000000000000 --- a/build-support/windows/build-consul-dev-image.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - - -cd ../../ -rm -rf dist - -export GOOS=windows GOARCH=amd64 -VERSION=1.16.0 -CONSUL_BUILDDATE=$(date +"%Y-%m-%dT%H:%M:%SZ") -GIT_IMPORT=github.com/hashicorp/consul/version -GOLDFLAGS=" -X $GIT_IMPORT.Version=$VERSION -X $GIT_IMPORT.VersionPrerelease=dev -X $GIT_IMPORT.BuildDate=$CONSUL_BUILDDATE " - -go build -ldflags "$GOLDFLAGS" -o ./dist/ . - -docker build -t windows/consul:${VERSION}-dev -f build-support/windows/Dockerfile-consul-dev-windows . --build-arg VERSION=${VERSION} diff --git a/build-support/windows/build-consul-local-images.sh b/build-support/windows/build-consul-local-images.sh deleted file mode 100644 index 4a22b35706c40..0000000000000 --- a/build-support/windows/build-consul-local-images.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - - -readonly HASHICORP_DOCKER_PROXY="docker.mirror.hashicorp.services" - -# Build Consul Version 1.13.3 / 1.12.6 / 1.11.11 -VERSION=${VERSION:-"1.16.0"} -export VERSION - -# Build Windows Envoy Version 1.23.1 / 1.21.5 / 1.20.7 -ENVOY_VERSION=${ENVOY_VERSION:-"1.27.0"} -export ENVOY_VERSION - -echo "Building Images" - - -# Pull Windows Servercore image -echo " " -echo "Pull Windows Servercore image" -docker pull mcr.microsoft.com/windows/servercore:1809 -# Tag Windows Servercore image -echo " " -echo "Tag Windows Servercore image" -docker tag mcr.microsoft.com/windows/servercore:1809 "${HASHICORP_DOCKER_PROXY}/windows/servercore:1809" - - -# Pull Windows Nanoserver image -echo " " -echo "Pull Windows Nanoserver image" -docker pull mcr.microsoft.com/windows/nanoserver:1809 -# Tag Windows Nanoserver image -echo " " -echo "Tag Windows Nanoserver image" -docker tag mcr.microsoft.com/windows/nanoserver:1809 "${HASHICORP_DOCKER_PROXY}/windows/nanoserver:1809" - - -# Pull Windows OpenJDK image -echo " " -echo "Pull Windows OpenJDK image" -docker pull openjdk:windowsservercore-1809 -# Tag Windows OpenJDK image -echo " " -echo "Tag Windows OpenJDK image" -docker tag openjdk:windowsservercore-1809 "${HASHICORP_DOCKER_PROXY}/windows/openjdk:1809" - -# Pull Windows Golang image -echo " " -echo "Pull Windows Golang image" -docker pull golang:1.18.1-nanoserver-1809 -# Tag Windows Golang image -echo " " -echo "Tag Windows Golang image" -docker tag golang:1.18.1-nanoserver-1809 "${HASHICORP_DOCKER_PROXY}/windows/golang:1809" - - -# Pull Kubernetes/pause image -echo " " -echo "Pull Kubernetes/pause image" -docker pull mcr.microsoft.com/oss/kubernetes/pause:3.6 -# Tag Kubernetes/pause image -echo " " -echo "Tag Kubernetes/pause image" -docker tag mcr.microsoft.com/oss/kubernetes/pause:3.6 "${HASHICORP_DOCKER_PROXY}/windows/kubernetes/pause" - -# Pull envoy-windows image -echo " " -echo "Pull envoyproxy/envoy-windows image" -docker pull envoyproxy/envoy-windows:v${ENVOY_VERSION} -# Tag envoy-windows image -echo " " -echo "Tag envoyproxy/envoy-windows image" -docker tag envoyproxy/envoy-windows:v${ENVOY_VERSION} "${HASHICORP_DOCKER_PROXY}/windows/envoy-windows:v${ENVOY_VERSION}" - -# Build Windows Openzipkin Image -docker build -t "${HASHICORP_DOCKER_PROXY}/windows/openzipkin" -f Dockerfile-openzipkin-windows . - - -# Build Windows Test sds server Image -./build-test-sds-server-image.sh - - -# Build windows/consul:${VERSION} Image -echo " " -echo "Build windows/consul:${VERSION} Image" -docker build -t "windows/consul:${VERSION}" -f ../../Dockerfile-windows ../../ --build-arg VERSION=${VERSION} - - -# Build windows/consul:${VERSION}-local Image -echo " " -echo "Build windows/consul:${VERSION}-local Image" -docker build -t windows/consul:${VERSION}-local -f ./Dockerfile-consul-local-windows . --build-arg VERSION=${VERSION} - -echo "Building Complete!" diff --git a/build-support/windows/build-test-sds-server-image.sh b/build-support/windows/build-test-sds-server-image.sh deleted file mode 100644 index 6856c2f4394d6..0000000000000 --- a/build-support/windows/build-test-sds-server-image.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - - -cd ../../test/integration/connect/envoy - -docker build -t windows/test-sds-server -f ./Dockerfile-test-sds-server-windows test-sds-server diff --git a/build-support/windows/windows-test.md b/build-support/windows/windows-test.md deleted file mode 100644 index 5295e40757ef6..0000000000000 --- a/build-support/windows/windows-test.md +++ /dev/null @@ -1,119 +0,0 @@ -# Dockerfiles for Windows Integration Tests - -## Index - -- [About](#about-this-file) -- [Consul Windows](#consul-windows) -- [Consul Windows Local](#consul-windows-local) -- [Consul Windows Dev](#consul-windows-dev) -- [Dockerfile-openzipkin-windows](#dockerfile-openzipkin-windows) - -## About this File - -In this file you will find which Docker images that need to be pre-built to run the Envoy integration tests on Windows, as well as information on how to run each of these files individually for testing purposes. - -## Consul Windows - -The Windows/Consul:_{VERSION}_ image is built from the "Dockerfile-windows" file located at the root of the project. -To do this, the official [windows/servercore image](https://hub.docker.com/_/microsoft-windows-servercore) is used as base image. -To build the image, use the following command: - -```shell -docker build -t windows/consul -f Dockerfile-windows . --build-arg VERSION=${VERSION} -``` - -You can test the built file by running the following command: - -```shell -docker run --rm -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8500:8500 -p 8600:8600 --name consul --hostname "consul-primary-server" --network-alias "consul-primary-server" windows/consul agent -dev -datacenter "primary" -grpc-port -1 -client "0.0.0.0" -bind "0.0.0.0" -``` - -If everything works properly you should openning the browser and check the Consul UI running on: `http://localhost:8500` - -## Consul Windows Local - -The Windows/Consul:_{VERSION}_-local custom image deployed in the "Dockerfile-consul-local-windows" DockerFile is built from the selected by the shell script _build-consul-local-images.sh_. -When executing it, all the tools required to run the Windows Connect Envoy Integration Tests will be added to the image. -It is necessary that the _"windows/consul"_ image has been built first. This script also takes care of that. - -To build this image you need to run the following command on your terminal: - -```shell -./build-consul-local-images.sh -``` - -> [!NOTE] -> Shell script execution may vary depending on your terminal, we recommend using **Git Bash** for Windows. - -```shell -docker run --rm -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8500:8500 -p 8600:8600 --name consul-local --hostname "consul-primary-server" --network-alias "consul-primary-server" windows/consul:_{VERSION}_-local agent -dev -datacenter "primary" -grpc-port -1 -client "0.0.0.0" -bind "0.0.0.0" -``` - -If everything works properly you can use your browser and check the Consul UI running on: `http://localhost:8500` - -## Consul Windows Dev - -The Windows/Consul:_{VERSION}_-dev custom image deployed in the "Dockerfile-consul-dev-windows" DockerFile is generated by the shell script named _build-consul-dev-image.sh_. -When executing it, the compilation of Consul is carried out and it is saved in the _"dist"_ directory, this file is then copied to the _"windows/consul:_{VERSION}_-dev"_ image. -It is necessary that the _"windows/consul_{VERSION}_-local"_ image has been built first. - -To build this image you need to run the following command on your terminal: - -```shell -./build-consul-dev-image.sh -``` - -> [!NOTE] -> Shell script execution may vary depending on your terminal, we recommend using **Git Bash** for Windows. - -You can test the built file by running the following command: - -```shell -docker run --rm -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8500:8500 -p 8600:8600 --name consul-local --hostname "consul-primary-server" --network-alias "consul-primary-server" windows/consul:_{VERSION}_-dev agent -dev -datacenter "primary" -grpc-port -1 -client "0.0.0.0" -bind "0.0.0.0" -``` - -If everything works properly you can use your browser and check the Consul UI running on: `http://localhost:8500` - -## Dockerfile-openzipkin-windows - -Due to the unavailability of an official Openzipkin Docker image for Windows, the [openjdk Windows image](https://hub.docker.com/layers/openjdk/library/openjdk/jdk-windowsservercore-1809/images/sha256-b0cc238d2ec5fb58109a0006ff9e1bcaf66a5301f49bcb8dece9599ac5be6331) was used, where the latest self-contained executable Openzipkin .jar file is downloaded. - -To build this image you need to run the following command on your terminal: - -```shell -docker build -t openzipkin -f Dockerfile-openzipkin-windows . -``` - -You can test the built file by running the following command: - -```shell -docker run --rm --name openzipkin -``` - -If everything works as it should, you will see the zipkin logo being displayed, along with the current version and port configuration: - -```shell -:: version 2.23.18 :: commit 4b71677 :: - -20XX-XX-XX XX:XX:XX.XXX INFO [/] 1252 --- [oss-http-*:9411] c.l.a.s.Server : Serving HTTP at /[0:0:0:0:0:0:0:0]:9411 - http://127.0.0.1:9411/ -``` - -# Testing - -During development, it may be more convenient to check your work-in-progress by running only the tests which you expect to be affected by your changes, as the full test suite can take several minutes to execute. [Go's built-in test tool](https://golang.org/pkg/cmd/go/internal/test/) allows specifying a list of packages to test and the `-run` option to only include test names matching a regular expression. -The `go test -short` flag can also be used to skip slower tests. - -Examples (run from the repository root): - -- `go test -v ./connect` will run all tests in the connect package (see `./connect` folder) -- `go test -v -run TestRetryJoin ./command/agent` will run all tests in the agent package (see `./command/agent` folder) with name substring `TestRetryJoin` - -When a pull request is opened CI will run all tests and lint to verify the change. - -If you want to run the tests on Windows images you must attach the win=true flag. - -Example: - -```shell -go test -v -timeout=30m -tags integration ./test/integration/connect/envoy -run="TestEnvoy/case-badauthz" -win=true -``` diff --git a/command/acl/acl.go b/command/acl/acl.go index 745fa78175d5e..71ef8c9a06171 100644 --- a/command/acl/acl.go +++ b/command/acl/acl.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/command/acl/acl_helpers.go b/command/acl/acl_helpers.go index 3459228c61edb..b0e65d224c756 100644 --- a/command/acl/acl_helpers.go +++ b/command/acl/acl_helpers.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/command/acl/acl_test.go b/command/acl/acl_test.go index c2a46f18b0423..2095795ff00be 100644 --- a/command/acl/acl_test.go +++ b/command/acl/acl_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package acl diff --git a/command/acl/agenttokens/agent_tokens.go b/command/acl/agenttokens/agent_tokens.go index f4e0c496acf62..4e4a359ace77d 100644 --- a/command/acl/agenttokens/agent_tokens.go +++ b/command/acl/agenttokens/agent_tokens.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agenttokens diff --git a/command/acl/agenttokens/agent_tokens_test.go b/command/acl/agenttokens/agent_tokens_test.go index 84f7fa3358011..d735b66d83a37 100644 --- a/command/acl/agenttokens/agent_tokens_test.go +++ b/command/acl/agenttokens/agent_tokens_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agenttokens diff --git a/command/acl/authmethod/authmethod.go b/command/acl/authmethod/authmethod.go index 18b9e58c2633a..897498024c84e 100644 --- a/command/acl/authmethod/authmethod.go +++ b/command/acl/authmethod/authmethod.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethod diff --git a/command/acl/authmethod/create/authmethod_create.go b/command/acl/authmethod/create/authmethod_create.go index 17f328d2b8be5..912a647d41155 100644 --- a/command/acl/authmethod/create/authmethod_create.go +++ b/command/acl/authmethod/create/authmethod_create.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethodcreate diff --git a/command/acl/authmethod/create/authmethod_create_ce.go b/command/acl/authmethod/create/authmethod_create_ce.go index 5c6ad2468393f..ff2d488897eda 100644 --- a/command/acl/authmethod/create/authmethod_create_ce.go +++ b/command/acl/authmethod/create/authmethod_create_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/command/acl/authmethod/create/authmethod_create_test.go b/command/acl/authmethod/create/authmethod_create_test.go index b9392544929af..b0d6a8cfe181b 100644 --- a/command/acl/authmethod/create/authmethod_create_test.go +++ b/command/acl/authmethod/create/authmethod_create_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethodcreate diff --git a/command/acl/authmethod/delete/authmethod_delete.go b/command/acl/authmethod/delete/authmethod_delete.go index e3ccd0efdd01e..44548a5983746 100644 --- a/command/acl/authmethod/delete/authmethod_delete.go +++ b/command/acl/authmethod/delete/authmethod_delete.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethoddelete diff --git a/command/acl/authmethod/delete/authmethod_delete_test.go b/command/acl/authmethod/delete/authmethod_delete_test.go index fc513fde7ebd4..45bd3ac561cd8 100644 --- a/command/acl/authmethod/delete/authmethod_delete_test.go +++ b/command/acl/authmethod/delete/authmethod_delete_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethoddelete diff --git a/command/acl/authmethod/formatter.go b/command/acl/authmethod/formatter.go index 6a22443d58dd4..3204af910b714 100644 --- a/command/acl/authmethod/formatter.go +++ b/command/acl/authmethod/formatter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethod diff --git a/command/acl/authmethod/list/authmethod_list.go b/command/acl/authmethod/list/authmethod_list.go index cae9916c12b29..1bcf24b75a638 100644 --- a/command/acl/authmethod/list/authmethod_list.go +++ b/command/acl/authmethod/list/authmethod_list.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethodlist diff --git a/command/acl/authmethod/list/authmethod_list_test.go b/command/acl/authmethod/list/authmethod_list_test.go index cd1aa2ac767b8..9064b252cd447 100644 --- a/command/acl/authmethod/list/authmethod_list_test.go +++ b/command/acl/authmethod/list/authmethod_list_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethodlist diff --git a/command/acl/authmethod/read/authmethod_read.go b/command/acl/authmethod/read/authmethod_read.go index 72d3a6f181634..b7860ca0660d2 100644 --- a/command/acl/authmethod/read/authmethod_read.go +++ b/command/acl/authmethod/read/authmethod_read.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethodread diff --git a/command/acl/authmethod/read/authmethod_read_test.go b/command/acl/authmethod/read/authmethod_read_test.go index 20a18c76dfdae..a24c1d2e55f21 100644 --- a/command/acl/authmethod/read/authmethod_read_test.go +++ b/command/acl/authmethod/read/authmethod_read_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethodread diff --git a/command/acl/authmethod/update/authmethod_update.go b/command/acl/authmethod/update/authmethod_update.go index 1c5422e88dea2..2798e6e6da8f6 100644 --- a/command/acl/authmethod/update/authmethod_update.go +++ b/command/acl/authmethod/update/authmethod_update.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethodupdate diff --git a/command/acl/authmethod/update/authmethod_update_ce.go b/command/acl/authmethod/update/authmethod_update_ce.go index d2c10d45869ed..c1ea32042473e 100644 --- a/command/acl/authmethod/update/authmethod_update_ce.go +++ b/command/acl/authmethod/update/authmethod_update_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/command/acl/authmethod/update/authmethod_update_test.go b/command/acl/authmethod/update/authmethod_update_test.go index 87ddf2f2c0bc4..e85f270cdf699 100644 --- a/command/acl/authmethod/update/authmethod_update_test.go +++ b/command/acl/authmethod/update/authmethod_update_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package authmethodupdate diff --git a/command/acl/bindingrule/bindingrule.go b/command/acl/bindingrule/bindingrule.go index 8d23e3ee37fab..782041e1ac672 100644 --- a/command/acl/bindingrule/bindingrule.go +++ b/command/acl/bindingrule/bindingrule.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bindingrule diff --git a/command/acl/bindingrule/create/bindingrule_create.go b/command/acl/bindingrule/create/bindingrule_create.go index cdedbb744dbfd..d5253c456e79d 100644 --- a/command/acl/bindingrule/create/bindingrule_create.go +++ b/command/acl/bindingrule/create/bindingrule_create.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bindingrulecreate diff --git a/command/acl/bindingrule/create/bindingrule_create_test.go b/command/acl/bindingrule/create/bindingrule_create_test.go index 2985c41abf467..43189f784c128 100644 --- a/command/acl/bindingrule/create/bindingrule_create_test.go +++ b/command/acl/bindingrule/create/bindingrule_create_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bindingrulecreate diff --git a/command/acl/bindingrule/delete/bindingrule_delete.go b/command/acl/bindingrule/delete/bindingrule_delete.go index 3fc02d788b4b6..ffb22fc73d357 100644 --- a/command/acl/bindingrule/delete/bindingrule_delete.go +++ b/command/acl/bindingrule/delete/bindingrule_delete.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bindingruledelete diff --git a/command/acl/bindingrule/delete/bindingrule_delete_test.go b/command/acl/bindingrule/delete/bindingrule_delete_test.go index 9655fbb101a4c..abd10f8add5d7 100644 --- a/command/acl/bindingrule/delete/bindingrule_delete_test.go +++ b/command/acl/bindingrule/delete/bindingrule_delete_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bindingruledelete diff --git a/command/acl/bindingrule/formatter.go b/command/acl/bindingrule/formatter.go index 6d96f4b71b4e7..1fb1feeafcc1c 100644 --- a/command/acl/bindingrule/formatter.go +++ b/command/acl/bindingrule/formatter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bindingrule diff --git a/command/acl/bindingrule/list/bindingrule_list.go b/command/acl/bindingrule/list/bindingrule_list.go index 15f395afdf2f6..2f6529af5d08d 100644 --- a/command/acl/bindingrule/list/bindingrule_list.go +++ b/command/acl/bindingrule/list/bindingrule_list.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bindingrulelist diff --git a/command/acl/bindingrule/list/bindingrule_list_test.go b/command/acl/bindingrule/list/bindingrule_list_test.go index 22035341e4248..bbb1188f8a0f4 100644 --- a/command/acl/bindingrule/list/bindingrule_list_test.go +++ b/command/acl/bindingrule/list/bindingrule_list_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bindingrulelist diff --git a/command/acl/bindingrule/read/bindingrule_read.go b/command/acl/bindingrule/read/bindingrule_read.go index 0ff55bd4ac2b8..25858d64851f1 100644 --- a/command/acl/bindingrule/read/bindingrule_read.go +++ b/command/acl/bindingrule/read/bindingrule_read.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bindingruleread diff --git a/command/acl/bindingrule/read/bindingrule_read_test.go b/command/acl/bindingrule/read/bindingrule_read_test.go index 4a324edf23174..9e1615e003b95 100644 --- a/command/acl/bindingrule/read/bindingrule_read_test.go +++ b/command/acl/bindingrule/read/bindingrule_read_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bindingruleread diff --git a/command/acl/bindingrule/update/bindingrule_update.go b/command/acl/bindingrule/update/bindingrule_update.go index 071e2bdc01b2d..59998059f476d 100644 --- a/command/acl/bindingrule/update/bindingrule_update.go +++ b/command/acl/bindingrule/update/bindingrule_update.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bindingruleupdate diff --git a/command/acl/bindingrule/update/bindingrule_update_test.go b/command/acl/bindingrule/update/bindingrule_update_test.go index 6124e9df2dc86..2f7437edcd333 100644 --- a/command/acl/bindingrule/update/bindingrule_update_test.go +++ b/command/acl/bindingrule/update/bindingrule_update_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bindingruleupdate diff --git a/command/acl/bootstrap/bootstrap.go b/command/acl/bootstrap/bootstrap.go index 2a2bfd3716d32..2f608bbdab347 100644 --- a/command/acl/bootstrap/bootstrap.go +++ b/command/acl/bootstrap/bootstrap.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bootstrap diff --git a/command/acl/bootstrap/bootstrap_test.go b/command/acl/bootstrap/bootstrap_test.go index e9a0e8cebee2a..ef5fcf41dc7aa 100644 --- a/command/acl/bootstrap/bootstrap_test.go +++ b/command/acl/bootstrap/bootstrap_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package bootstrap diff --git a/command/acl/policy/create/policy_create.go b/command/acl/policy/create/policy_create.go index 03d836ee4ad81..131d096b1cf25 100644 --- a/command/acl/policy/create/policy_create.go +++ b/command/acl/policy/create/policy_create.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package policycreate diff --git a/command/acl/policy/create/policy_create_test.go b/command/acl/policy/create/policy_create_test.go index 953dd978ed964..94ef7ac95f53d 100644 --- a/command/acl/policy/create/policy_create_test.go +++ b/command/acl/policy/create/policy_create_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package policycreate diff --git a/command/acl/policy/delete/policy_delete.go b/command/acl/policy/delete/policy_delete.go index 63c02a47ddd2b..eb1fbfc83bccf 100644 --- a/command/acl/policy/delete/policy_delete.go +++ b/command/acl/policy/delete/policy_delete.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package policydelete diff --git a/command/acl/policy/delete/policy_delete_test.go b/command/acl/policy/delete/policy_delete_test.go index 33f121db981fa..4e0b8ffbf6278 100644 --- a/command/acl/policy/delete/policy_delete_test.go +++ b/command/acl/policy/delete/policy_delete_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package policydelete diff --git a/command/acl/policy/formatter.go b/command/acl/policy/formatter.go index dce79c3907160..1e78976412079 100644 --- a/command/acl/policy/formatter.go +++ b/command/acl/policy/formatter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package policy diff --git a/command/acl/policy/list/policy_list.go b/command/acl/policy/list/policy_list.go index 44be10d6843d9..d88f57595030f 100644 --- a/command/acl/policy/list/policy_list.go +++ b/command/acl/policy/list/policy_list.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package policylist diff --git a/command/acl/policy/list/policy_list_test.go b/command/acl/policy/list/policy_list_test.go index b0cc05b2a5cf7..d9df5cc879a54 100644 --- a/command/acl/policy/list/policy_list_test.go +++ b/command/acl/policy/list/policy_list_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package policylist diff --git a/command/acl/policy/policy.go b/command/acl/policy/policy.go index 565c672706468..7a7b80cba8ffc 100644 --- a/command/acl/policy/policy.go +++ b/command/acl/policy/policy.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package policy diff --git a/command/acl/policy/read/policy_read.go b/command/acl/policy/read/policy_read.go index 36f1e65340794..e1b6b923df094 100644 --- a/command/acl/policy/read/policy_read.go +++ b/command/acl/policy/read/policy_read.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package policyread diff --git a/command/acl/policy/read/policy_read_test.go b/command/acl/policy/read/policy_read_test.go index 70036457cebb9..08fe5d1ce96ce 100644 --- a/command/acl/policy/read/policy_read_test.go +++ b/command/acl/policy/read/policy_read_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package policyread diff --git a/command/acl/policy/update/policy_update.go b/command/acl/policy/update/policy_update.go index 60b6340736137..ec0577ebb9a22 100644 --- a/command/acl/policy/update/policy_update.go +++ b/command/acl/policy/update/policy_update.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package policyupdate diff --git a/command/acl/policy/update/policy_update_test.go b/command/acl/policy/update/policy_update_test.go index 4d77191d64332..22fa8b4c89aa4 100644 --- a/command/acl/policy/update/policy_update_test.go +++ b/command/acl/policy/update/policy_update_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package policyupdate diff --git a/command/acl/role/create/role_create.go b/command/acl/role/create/role_create.go index b951367b2c5ad..588b3a0cb6590 100644 --- a/command/acl/role/create/role_create.go +++ b/command/acl/role/create/role_create.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package rolecreate diff --git a/command/acl/role/create/role_create_test.go b/command/acl/role/create/role_create_test.go index 7094a76e6cc7c..40f15433a7bf5 100644 --- a/command/acl/role/create/role_create_test.go +++ b/command/acl/role/create/role_create_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package rolecreate diff --git a/command/acl/role/delete/role_delete.go b/command/acl/role/delete/role_delete.go index aaac306f01b2b..21dc7c0d1b45f 100644 --- a/command/acl/role/delete/role_delete.go +++ b/command/acl/role/delete/role_delete.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package roledelete diff --git a/command/acl/role/delete/role_delete_test.go b/command/acl/role/delete/role_delete_test.go index 61897ca245575..8a38cf2cfc3bc 100644 --- a/command/acl/role/delete/role_delete_test.go +++ b/command/acl/role/delete/role_delete_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package roledelete diff --git a/command/acl/role/formatter.go b/command/acl/role/formatter.go index 0dba147fab0a7..5df6085e46ac6 100644 --- a/command/acl/role/formatter.go +++ b/command/acl/role/formatter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package role diff --git a/command/acl/role/formatter_test.go b/command/acl/role/formatter_test.go index ac6be59b42e7e..cd1ba90fe9a1f 100644 --- a/command/acl/role/formatter_test.go +++ b/command/acl/role/formatter_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package role diff --git a/command/acl/role/list/role_list.go b/command/acl/role/list/role_list.go index 558419e07067a..3582f9da63c20 100644 --- a/command/acl/role/list/role_list.go +++ b/command/acl/role/list/role_list.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package rolelist diff --git a/command/acl/role/list/role_list_test.go b/command/acl/role/list/role_list_test.go index 0a94d11a109da..651ab120278c9 100644 --- a/command/acl/role/list/role_list_test.go +++ b/command/acl/role/list/role_list_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package rolelist diff --git a/command/acl/role/read/role_read.go b/command/acl/role/read/role_read.go index 027aaa80019f9..d6d06997ad13f 100644 --- a/command/acl/role/read/role_read.go +++ b/command/acl/role/read/role_read.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package roleread diff --git a/command/acl/role/read/role_read_test.go b/command/acl/role/read/role_read_test.go index bef1fab260164..c7be4cb4c0375 100644 --- a/command/acl/role/read/role_read_test.go +++ b/command/acl/role/read/role_read_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package roleread diff --git a/command/acl/role/role.go b/command/acl/role/role.go index c1da51d86401e..2ea085f763311 100644 --- a/command/acl/role/role.go +++ b/command/acl/role/role.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package role diff --git a/command/acl/role/update/role_update.go b/command/acl/role/update/role_update.go index 731bfb1726d89..c42ab7ce9e616 100644 --- a/command/acl/role/update/role_update.go +++ b/command/acl/role/update/role_update.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package roleupdate diff --git a/command/acl/role/update/role_update_test.go b/command/acl/role/update/role_update_test.go index 07c4cb2d2da43..18d6110996884 100644 --- a/command/acl/role/update/role_update_test.go +++ b/command/acl/role/update/role_update_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package roleupdate diff --git a/command/acl/token/clone/token_clone.go b/command/acl/token/clone/token_clone.go index 127fca78762cd..0f4ed2473a976 100644 --- a/command/acl/token/clone/token_clone.go +++ b/command/acl/token/clone/token_clone.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tokenclone diff --git a/command/acl/token/clone/token_clone_test.go b/command/acl/token/clone/token_clone_test.go index 7181ac0caec71..0142db7437957 100644 --- a/command/acl/token/clone/token_clone_test.go +++ b/command/acl/token/clone/token_clone_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tokenclone diff --git a/command/acl/token/create/token_create.go b/command/acl/token/create/token_create.go index 25c00df60588a..4f33562908e8f 100644 --- a/command/acl/token/create/token_create.go +++ b/command/acl/token/create/token_create.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tokencreate diff --git a/command/acl/token/create/token_create_test.go b/command/acl/token/create/token_create_test.go index b92c64b0d154a..747d9415171d9 100644 --- a/command/acl/token/create/token_create_test.go +++ b/command/acl/token/create/token_create_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tokencreate diff --git a/command/acl/token/delete/token_delete.go b/command/acl/token/delete/token_delete.go index aa9f79903bb72..378c399115367 100644 --- a/command/acl/token/delete/token_delete.go +++ b/command/acl/token/delete/token_delete.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tokendelete diff --git a/command/acl/token/delete/token_delete_test.go b/command/acl/token/delete/token_delete_test.go index 29c1fe292d605..988e4afe24dc2 100644 --- a/command/acl/token/delete/token_delete_test.go +++ b/command/acl/token/delete/token_delete_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tokendelete diff --git a/command/acl/token/formatter.go b/command/acl/token/formatter.go index 6dec483aad611..dbe1a939fcec1 100644 --- a/command/acl/token/formatter.go +++ b/command/acl/token/formatter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package token diff --git a/command/acl/token/formatter_ce_test.go b/command/acl/token/formatter_ce_test.go index 128b05b58a1b1..9faa6f4b736be 100644 --- a/command/acl/token/formatter_ce_test.go +++ b/command/acl/token/formatter_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/command/acl/token/formatter_test.go b/command/acl/token/formatter_test.go index ba4c04981d781..2a5e5414d754d 100644 --- a/command/acl/token/formatter_test.go +++ b/command/acl/token/formatter_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package token diff --git a/command/acl/token/list/token_list.go b/command/acl/token/list/token_list.go index 7f500426f3369..4d7177dddf645 100644 --- a/command/acl/token/list/token_list.go +++ b/command/acl/token/list/token_list.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tokenlist diff --git a/command/acl/token/list/token_list_test.go b/command/acl/token/list/token_list_test.go index c8586bde6b80b..0a4441c47a562 100644 --- a/command/acl/token/list/token_list_test.go +++ b/command/acl/token/list/token_list_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tokenlist diff --git a/command/acl/token/read/token_read.go b/command/acl/token/read/token_read.go index 23496135bf725..c5798a8b9b31a 100644 --- a/command/acl/token/read/token_read.go +++ b/command/acl/token/read/token_read.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tokenread diff --git a/command/acl/token/read/token_read_test.go b/command/acl/token/read/token_read_test.go index 69df72e72917b..ea2317b79fd63 100644 --- a/command/acl/token/read/token_read_test.go +++ b/command/acl/token/read/token_read_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tokenread diff --git a/command/acl/token/token.go b/command/acl/token/token.go index db3771926ccc0..e8bb0cd420b61 100644 --- a/command/acl/token/token.go +++ b/command/acl/token/token.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package token diff --git a/command/acl/token/update/token_update.go b/command/acl/token/update/token_update.go index 9d636ba215df9..915c358d48ad1 100644 --- a/command/acl/token/update/token_update.go +++ b/command/acl/token/update/token_update.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tokenupdate diff --git a/command/acl/token/update/token_update_test.go b/command/acl/token/update/token_update_test.go index 019b8554a5920..b96d95d466e8f 100644 --- a/command/acl/token/update/token_update_test.go +++ b/command/acl/token/update/token_update_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tokenupdate diff --git a/command/agent/agent.go b/command/agent/agent.go index 84515f2c94bd5..c241fa2b7bc8a 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/command/agent/agent_test.go b/command/agent/agent_test.go index 3fa5d1e1a31a5..a197c6ed44798 100644 --- a/command/agent/agent_test.go +++ b/command/agent/agent_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/command/agent/startup_logger.go b/command/agent/startup_logger.go index f324ac6c55c85..baa016a2a7b09 100644 --- a/command/agent/startup_logger.go +++ b/command/agent/startup_logger.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package agent diff --git a/command/catalog/catalog.go b/command/catalog/catalog.go index f685512060076..dbc229eb35224 100644 --- a/command/catalog/catalog.go +++ b/command/catalog/catalog.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package catalog diff --git a/command/catalog/catalog_test.go b/command/catalog/catalog_test.go index 308da9452edfe..5ff5ac40e2e3c 100644 --- a/command/catalog/catalog_test.go +++ b/command/catalog/catalog_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package catalog diff --git a/command/catalog/helpers.go b/command/catalog/helpers.go index f457d8f792ab5..1d9ad1964d3d1 100644 --- a/command/catalog/helpers.go +++ b/command/catalog/helpers.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package catalog diff --git a/command/catalog/helpers_ce.go b/command/catalog/helpers_ce.go index 51e04218872f2..5f60fd9b13122 100644 --- a/command/catalog/helpers_ce.go +++ b/command/catalog/helpers_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/command/catalog/list/dc/catalog_list_datacenters.go b/command/catalog/list/dc/catalog_list_datacenters.go index c7531c9164342..7df18e7a8b70d 100644 --- a/command/catalog/list/dc/catalog_list_datacenters.go +++ b/command/catalog/list/dc/catalog_list_datacenters.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dc diff --git a/command/catalog/list/dc/catalog_list_datacenters_test.go b/command/catalog/list/dc/catalog_list_datacenters_test.go index 68a8a8bc50552..6052db994117e 100644 --- a/command/catalog/list/dc/catalog_list_datacenters_test.go +++ b/command/catalog/list/dc/catalog_list_datacenters_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package dc diff --git a/command/catalog/list/nodes/catalog_list_nodes.go b/command/catalog/list/nodes/catalog_list_nodes.go index 1d1f3912f2255..44760182cd1be 100644 --- a/command/catalog/list/nodes/catalog_list_nodes.go +++ b/command/catalog/list/nodes/catalog_list_nodes.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package nodes diff --git a/command/catalog/list/nodes/catalog_list_nodes_test.go b/command/catalog/list/nodes/catalog_list_nodes_test.go index 59db1c666bb67..0bef492b7b779 100644 --- a/command/catalog/list/nodes/catalog_list_nodes_test.go +++ b/command/catalog/list/nodes/catalog_list_nodes_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package nodes diff --git a/command/catalog/list/services/catalog_list_services.go b/command/catalog/list/services/catalog_list_services.go index 4bbcce6532957..029c8bae94f44 100644 --- a/command/catalog/list/services/catalog_list_services.go +++ b/command/catalog/list/services/catalog_list_services.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package services diff --git a/command/catalog/list/services/catalog_list_services_test.go b/command/catalog/list/services/catalog_list_services_test.go index 905729410d95e..28c7c0652e894 100644 --- a/command/catalog/list/services/catalog_list_services_test.go +++ b/command/catalog/list/services/catalog_list_services_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package services diff --git a/command/cli/cli.go b/command/cli/cli.go index a0bb5d78ddf7b..4afaeb279f665 100644 --- a/command/cli/cli.go +++ b/command/cli/cli.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cli diff --git a/command/cli/formatting.go b/command/cli/formatting.go index fec86797b057c..11ca247e900b6 100644 --- a/command/cli/formatting.go +++ b/command/cli/formatting.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cli diff --git a/command/config/config.go b/command/config/config.go index ed54954cbeb96..e5fbe803a8dc6 100644 --- a/command/config/config.go +++ b/command/config/config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package config diff --git a/command/config/delete/config_delete.go b/command/config/delete/config_delete.go index baec168b172aa..e9a9f97c7d83f 100644 --- a/command/config/delete/config_delete.go +++ b/command/config/delete/config_delete.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package delete diff --git a/command/config/delete/config_delete_test.go b/command/config/delete/config_delete_test.go index d7d6d9226054c..66b5a47a71a22 100644 --- a/command/config/delete/config_delete_test.go +++ b/command/config/delete/config_delete_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package delete diff --git a/command/config/list/config_list.go b/command/config/list/config_list.go index 4dd469590cffd..978804a191991 100644 --- a/command/config/list/config_list.go +++ b/command/config/list/config_list.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package list diff --git a/command/config/list/config_list_test.go b/command/config/list/config_list_test.go index 3e528a062fbb3..bf188f51bd963 100644 --- a/command/config/list/config_list_test.go +++ b/command/config/list/config_list_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package list diff --git a/command/config/read/config_read.go b/command/config/read/config_read.go index d3e3828817b52..348d893738853 100644 --- a/command/config/read/config_read.go +++ b/command/config/read/config_read.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package read diff --git a/command/config/read/config_read_test.go b/command/config/read/config_read_test.go index 5fbf37885d0b6..074c0ee30d3b8 100644 --- a/command/config/read/config_read_test.go +++ b/command/config/read/config_read_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package read diff --git a/command/config/write/config_write.go b/command/config/write/config_write.go index 4edfbed3bf0ce..d6a0c188b8fa1 100644 --- a/command/config/write/config_write.go +++ b/command/config/write/config_write.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package write @@ -7,12 +7,17 @@ import ( "flag" "fmt" "io" + "time" + "github.com/hashicorp/go-multierror" "github.com/mitchellh/cli" + "github.com/mitchellh/mapstructure" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/command/config" "github.com/hashicorp/consul/command/flags" "github.com/hashicorp/consul/command/helpers" + "github.com/hashicorp/consul/lib/decode" ) func New(ui cli.Ui) *cmd { @@ -104,6 +109,67 @@ func (c *cmd) Run(args []string) int { return 0 } +// There is a 'structs' variation of this in +// agent/structs/config_entry.go:DecodeConfigEntry +func newDecodeConfigEntry(raw map[string]interface{}) (api.ConfigEntry, error) { + var entry api.ConfigEntry + + kindVal, ok := raw["Kind"] + if !ok { + kindVal, ok = raw["kind"] + } + if !ok { + return nil, fmt.Errorf("Payload does not contain a kind/Kind key at the top level") + } + + if kindStr, ok := kindVal.(string); ok { + newEntry, err := api.MakeConfigEntry(kindStr, "") + if err != nil { + return nil, err + } + entry = newEntry + } else { + return nil, fmt.Errorf("Kind value in payload is not a string") + } + + var md mapstructure.Metadata + decodeConf := &mapstructure.DecoderConfig{ + DecodeHook: mapstructure.ComposeDecodeHookFunc( + decode.HookWeakDecodeFromSlice, + decode.HookTranslateKeys, + mapstructure.StringToTimeDurationHookFunc(), + mapstructure.StringToTimeHookFunc(time.RFC3339), + ), + Metadata: &md, + Result: &entry, + WeaklyTypedInput: true, + } + + decoder, err := mapstructure.NewDecoder(decodeConf) + if err != nil { + return nil, err + } + + if err := decoder.Decode(raw); err != nil { + return nil, err + } + + for _, k := range md.Unused { + switch k { + case "kind", "Kind": + // The kind field is used to determine the target, but doesn't need + // to exist on the target. + continue + } + err = multierror.Append(err, fmt.Errorf("invalid config key %q", k)) + } + if err != nil { + return nil, err + } + + return entry, nil +} + func (c *cmd) Synopsis() string { return synopsis } diff --git a/command/config/write/config_write_test.go b/command/config/write/config_write_test.go index 15e7a47465323..3319084f4f210 100644 --- a/command/config/write/config_write_test.go +++ b/command/config/write/config_write_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package write diff --git a/command/connect/ca/ca.go b/command/connect/ca/ca.go index a5edd43dbc2e9..f85ae17d6b8af 100644 --- a/command/connect/ca/ca.go +++ b/command/connect/ca/ca.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/command/connect/ca/ca_test.go b/command/connect/ca/ca_test.go index 84ebe2873dd37..eb20f57c220db 100644 --- a/command/connect/ca/ca_test.go +++ b/command/connect/ca/ca_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/command/connect/ca/get/connect_ca_get.go b/command/connect/ca/get/connect_ca_get.go index 40b9b556a4bbf..a2a7c6cb8b48b 100644 --- a/command/connect/ca/get/connect_ca_get.go +++ b/command/connect/ca/get/connect_ca_get.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package get diff --git a/command/connect/ca/get/connect_ca_get_test.go b/command/connect/ca/get/connect_ca_get_test.go index 0e5545152c34b..7d628fb2940db 100644 --- a/command/connect/ca/get/connect_ca_get_test.go +++ b/command/connect/ca/get/connect_ca_get_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package get diff --git a/command/connect/ca/set/connect_ca_set.go b/command/connect/ca/set/connect_ca_set.go index 2c9af4ec6ea9c..ca17f3e2129a7 100644 --- a/command/connect/ca/set/connect_ca_set.go +++ b/command/connect/ca/set/connect_ca_set.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package set diff --git a/command/connect/ca/set/connect_ca_set_test.go b/command/connect/ca/set/connect_ca_set_test.go index 4193d718f0dd9..1928a7dbd43f0 100644 --- a/command/connect/ca/set/connect_ca_set_test.go +++ b/command/connect/ca/set/connect_ca_set_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package set diff --git a/command/connect/connect.go b/command/connect/connect.go index c92481a723ab0..675017291692b 100644 --- a/command/connect/connect.go +++ b/command/connect/connect.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/command/connect/connect_test.go b/command/connect/connect_test.go index 3098962dc4ef8..452207a96b656 100644 --- a/command/connect/connect_test.go +++ b/command/connect/connect_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/command/connect/envoy/bootstrap_config.go b/command/connect/envoy/bootstrap_config.go index 452d3679d6f2f..2a0e21c4d25dd 100644 --- a/command/connect/envoy/bootstrap_config.go +++ b/command/connect/envoy/bootstrap_config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package envoy diff --git a/command/connect/envoy/bootstrap_config_test.go b/command/connect/envoy/bootstrap_config_test.go index ef05786347142..86566ed80cae2 100644 --- a/command/connect/envoy/bootstrap_config_test.go +++ b/command/connect/envoy/bootstrap_config_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package envoy diff --git a/command/connect/envoy/bootstrap_tpl.go b/command/connect/envoy/bootstrap_tpl.go index 4b4bbc8db77f4..26b8e2118b1ef 100644 --- a/command/connect/envoy/bootstrap_tpl.go +++ b/command/connect/envoy/bootstrap_tpl.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package envoy @@ -8,7 +8,7 @@ package envoy type BootstrapTplArgs struct { GRPC - // ProxyCluster is the cluster name for the Envoy `node` specification and + // ProxyCluster is the cluster name for the the Envoy `node` specification and // is typically the same as the ProxyID. ProxyCluster string diff --git a/command/connect/envoy/envoy.go b/command/connect/envoy/envoy.go index 3489f1017a658..256f6fc33c1a8 100644 --- a/command/connect/envoy/envoy.go +++ b/command/connect/envoy/envoy.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package envoy @@ -38,7 +38,7 @@ func New(ui cli.Ui) *cmd { return c } -const DefaultAdminAccessLogPath = os.DevNull +const DefaultAdminAccessLogPath = "/dev/null" type cmd struct { UI cli.Ui diff --git a/command/connect/envoy/envoy_ce_test.go b/command/connect/envoy/envoy_ce_test.go index 9e97516cf5d2f..89e3fd303efe9 100644 --- a/command/connect/envoy/envoy_ce_test.go +++ b/command/connect/envoy/envoy_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/command/connect/envoy/envoy_test.go b/command/connect/envoy/envoy_test.go index 0e61eea1865ab..517108e0330c8 100644 --- a/command/connect/envoy/envoy_test.go +++ b/command/connect/envoy/envoy_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package envoy diff --git a/command/connect/envoy/exec.go b/command/connect/envoy/exec.go index 71f903c106437..ffece038f71b8 100644 --- a/command/connect/envoy/exec.go +++ b/command/connect/envoy/exec.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package envoy diff --git a/command/connect/envoy/exec_supported.go b/command/connect/envoy/exec_supported.go deleted file mode 100644 index d61cbc850781d..0000000000000 --- a/command/connect/envoy/exec_supported.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build linux || darwin || windows -// +build linux darwin windows - -package envoy - -import ( - "fmt" - "os" - "strings" -) - -func isHotRestartOption(s string) bool { - restartOpts := []string{ - "--restart-epoch", - "--hot-restart-version", - "--drain-time-s", - "--parent-shutdown-time-s", - } - for _, opt := range restartOpts { - if s == opt { - return true - } - if strings.HasPrefix(s, opt+"=") { - return true - } - } - return false -} - -func hasHotRestartOption(argSets ...[]string) bool { - for _, args := range argSets { - for _, opt := range args { - if isHotRestartOption(opt) { - return true - } - } - } - return false -} - -// execArgs returns the command and args used to execute a binary. By default it -// will return a command of os.Executable with the args unmodified. This is a shim -// for testing, and can be overridden to execute using 'go run' instead. -var execArgs = func(args ...string) (string, []string, error) { - execPath, err := os.Executable() - if err != nil { - return "", nil, err - } - - if strings.HasSuffix(execPath, "/envoy.test") { - return "", nil, fmt.Errorf("set execArgs to use 'go run' instead of doing a self-exec") - } - - return execPath, args, nil -} diff --git a/command/connect/envoy/exec_test.go b/command/connect/envoy/exec_test.go index 0dbab3c6a0357..3ffc89e2f24d8 100644 --- a/command/connect/envoy/exec_test.go +++ b/command/connect/envoy/exec_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build linux || darwin // +build linux darwin diff --git a/command/connect/envoy/exec_unix.go b/command/connect/envoy/exec_unix.go index 49d340483c5a2..d3eb0765a9f9d 100644 --- a/command/connect/envoy/exec_unix.go +++ b/command/connect/envoy/exec_unix.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build linux || darwin // +build linux darwin @@ -12,12 +12,63 @@ import ( "os" "os/exec" "path/filepath" + "strings" "syscall" "time" "golang.org/x/sys/unix" ) +// testSelfExecOverride is a way for the tests to no fork-bomb themselves by +// self-executing the whole test suite for each case recursively. It's gross but +// the least gross option I could think of. +var testSelfExecOverride string + +func isHotRestartOption(s string) bool { + restartOpts := []string{ + "--restart-epoch", + "--hot-restart-version", + "--drain-time-s", + "--parent-shutdown-time-s", + } + for _, opt := range restartOpts { + if s == opt { + return true + } + if strings.HasPrefix(s, opt+"=") { + return true + } + } + return false +} + +func hasHotRestartOption(argSets ...[]string) bool { + for _, args := range argSets { + for _, opt := range args { + if isHotRestartOption(opt) { + return true + } + } + } + return false +} + +// execArgs returns the command and args used to execute a binary. By default it +// will return a command of os.Executable with the args unmodified. This is a shim +// for testing, and can be overridden to execute using 'go run' instead. +var execArgs = func(args ...string) (string, []string, error) { + execPath, err := os.Executable() + if err != nil { + return "", nil, err + } + + if strings.HasSuffix(execPath, "/envoy.test") { + return "", nil, fmt.Errorf("set execArgs to use 'go run' instead of doing a self-exec") + } + + return execPath, args, nil +} + func makeBootstrapPipe(bootstrapJSON []byte) (string, error) { pipeFile := filepath.Join(os.TempDir(), fmt.Sprintf("envoy-%x-bootstrap.json", time.Now().UnixNano()+int64(os.Getpid()))) diff --git a/command/connect/envoy/exec_unsupported.go b/command/connect/envoy/exec_unsupported.go index 87f45ec7afb8c..c9686098983e9 100644 --- a/command/connect/envoy/exec_unsupported.go +++ b/command/connect/envoy/exec_unsupported.go @@ -1,8 +1,8 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 -//go:build !linux && !darwin && !windows -// +build !linux,!darwin,!windows +//go:build !linux && !darwin +// +build !linux,!darwin package envoy diff --git a/command/connect/envoy/exec_windows.go b/command/connect/envoy/exec_windows.go deleted file mode 100644 index cf262214ead2a..0000000000000 --- a/command/connect/envoy/exec_windows.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 -//go:build windows && !fips -// +build windows,!fips - -package envoy - -import ( - "errors" - "fmt" - "github.com/natefinch/npipe" - "os" - "os/exec" - "path/filepath" - "time" -) - -func makeBootstrapPipe(bootstrapJSON []byte) (string, error) { - pipeFile := filepath.Join(os.TempDir(), - fmt.Sprintf("envoy-%x-bootstrap.json", time.Now().UnixNano()+int64(os.Getpid()))) - - binary, args, err := execArgs("connect", "envoy", "pipe-bootstrap", pipeFile) - if err != nil { - return pipeFile, err - } - - // Dial the named pipe - pipeConn, err := npipe.Dial(pipeFile) - if err != nil { - return pipeFile, err - } - defer pipeConn.Close() - - // Start the command to connect to the named pipe - cmd := exec.Command(binary, args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Stdin = pipeConn - - // Start the command - err = cmd.Start() - if err != nil { - return pipeFile, err - } - - // Write the config - n, err := pipeConn.Write(bootstrapJSON) - if err != nil { - return pipeFile, err - } - - if n < len(bootstrapJSON) { - return pipeFile, fmt.Errorf("failed writing boostrap to child STDIN: %s", err) - } - - // We can't wait for the process since we need to exec into Envoy before it - // will be able to complete so it will be remain as a zombie until Envoy is - // killed then will be reaped by the init process (pid 0). This is all a bit - // gross but the cleanest workaround I can think of for Envoy 1.10 not - // supporting /dev/fd/ config paths any more. So we are done and leaving - // the child to run it's course without reaping it. - return pipeFile, nil -} - -func startProc(binary string, args []string) (p *os.Process, err error) { - if binary, err = exec.LookPath(binary); err == nil { - var procAttr os.ProcAttr - procAttr.Files = []*os.File{os.Stdin, - os.Stdout, os.Stderr} - p, err := os.StartProcess(binary, args, &procAttr) - if err == nil { - return p, nil - } - } - return nil, err -} - -func execEnvoy(binary string, prefixArgs, suffixArgs []string, bootstrapJSON []byte) error { - tempFile, err := makeBootstrapPipe(bootstrapJSON) - if err != nil { - os.RemoveAll(tempFile) - return err - } - // We don't defer a cleanup since we are about to Exec into Envoy which means - // defer will never fire. The child process cleans up for us in the happy - // path. - - // We default to disabling hot restart because it makes it easier to run - // multiple envoys locally for testing without them trying to share memory and - // unix sockets and complain about being different IDs. But if user is - // actually configuring hot-restart explicitly with the --restart-epoch option - // then don't disable it! - disableHotRestart := !hasHotRestartOption(prefixArgs, suffixArgs) - - // First argument needs to be the executable name. - envoyArgs := []string{} - envoyArgs = append(envoyArgs, prefixArgs...) - if disableHotRestart { - envoyArgs = append(envoyArgs, "--disable-hot-restart") - } - envoyArgs = append(envoyArgs, suffixArgs...) - envoyArgs = append(envoyArgs, "--config-path", tempFile) - - // Exec - if proc, err := startProc(binary, envoyArgs); err == nil { - proc.Wait() - } else if err != nil { - return errors.New("Failed to exec envoy: " + err.Error()) - } - - return nil -} diff --git a/command/connect/envoy/exec_windows_arm64.go b/command/connect/envoy/exec_windows_arm64.go deleted file mode 100644 index b080d7818786c..0000000000000 --- a/command/connect/envoy/exec_windows_arm64.go +++ /dev/null @@ -1,83 +0,0 @@ -//go:build fips -// +build fips - -package envoy - -import ( - "errors" - "fmt" - "os" - "os/exec" - "path/filepath" - "time" -) - -func makeBootstrapPipe(bootstrapJSON []byte) (string, error) { - tempFile := filepath.Join(os.TempDir(), - fmt.Sprintf("envoy-%x-bootstrap.json", time.Now().UnixNano()+int64(os.Getpid()))) - - f, err := os.Create(tempFile) - if err != nil { - return tempFile, err - } - - defer f.Close() - f.Write(bootstrapJSON) - f.Sync() - // We can't wait for the process since we need to exec into Envoy before it - // will be able to complete so it will be remain as a zombie until Envoy is - // killed then will be reaped by the init process (pid 0). This is all a bit - // gross but the cleanest workaround I can think of for Envoy 1.10 not - // supporting /dev/fd/ config paths any more. So we are done and leaving - // the child to run it's course without reaping it. - return tempFile, nil -} - -func startProc(binary string, args []string) (p *os.Process, err error) { - if binary, err = exec.LookPath(binary); err == nil { - var procAttr os.ProcAttr - procAttr.Files = []*os.File{os.Stdin, - os.Stdout, os.Stderr} - p, err := os.StartProcess(binary, args, &procAttr) - if err == nil { - return p, nil - } - } - return nil, err -} - -func execEnvoy(binary string, prefixArgs, suffixArgs []string, bootstrapJSON []byte) error { - tempFile, err := makeBootstrapPipe(bootstrapJSON) - if err != nil { - os.RemoveAll(tempFile) - return err - } - // We don't defer a cleanup since we are about to Exec into Envoy which means - // defer will never fire. The child process cleans up for us in the happy - // path. - - // We default to disabling hot restart because it makes it easier to run - // multiple envoys locally for testing without them trying to share memory and - // unix sockets and complain about being different IDs. But if user is - // actually configuring hot-restart explicitly with the --restart-epoch option - // then don't disable it! - disableHotRestart := !hasHotRestartOption(prefixArgs, suffixArgs) - - // First argument needs to be the executable name. - envoyArgs := []string{} - envoyArgs = append(envoyArgs, prefixArgs...) - if disableHotRestart { - envoyArgs = append(envoyArgs, "--disable-hot-restart") - } - envoyArgs = append(envoyArgs, suffixArgs...) - envoyArgs = append(envoyArgs, "--config-path", tempFile) - - // Exec - if proc, err := startProc(binary, envoyArgs); err == nil { - proc.Wait() - } else if err != nil { - return errors.New("Failed to exec envoy: " + err.Error()) - } - - return nil -} diff --git a/command/connect/envoy/flags.go b/command/connect/envoy/flags.go index 4d7994ccd45da..eed9698c72fa0 100644 --- a/command/connect/envoy/flags.go +++ b/command/connect/envoy/flags.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package envoy diff --git a/command/connect/envoy/flags_test.go b/command/connect/envoy/flags_test.go index 596c0fa1a22fb..617f852691254 100644 --- a/command/connect/envoy/flags_test.go +++ b/command/connect/envoy/flags_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package envoy diff --git a/command/connect/envoy/pipe-bootstrap/connect_envoy_pipe-bootstrap.go b/command/connect/envoy/pipe-bootstrap/connect_envoy_pipe-bootstrap.go index e6dbc33db1eb7..48cec90b8145c 100644 --- a/command/connect/envoy/pipe-bootstrap/connect_envoy_pipe-bootstrap.go +++ b/command/connect/envoy/pipe-bootstrap/connect_envoy_pipe-bootstrap.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pipebootstrap diff --git a/command/connect/envoy/pipe-bootstrap/connect_envoy_pipe-bootstrap_test.go b/command/connect/envoy/pipe-bootstrap/connect_envoy_pipe-bootstrap_test.go index 4f271b6e74039..8e8b982f61f85 100644 --- a/command/connect/envoy/pipe-bootstrap/connect_envoy_pipe-bootstrap_test.go +++ b/command/connect/envoy/pipe-bootstrap/connect_envoy_pipe-bootstrap_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pipebootstrap diff --git a/command/connect/expose/expose.go b/command/connect/expose/expose.go index 569ab46bab4a7..0fe3e3de74a67 100644 --- a/command/connect/expose/expose.go +++ b/command/connect/expose/expose.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package expose diff --git a/command/connect/expose/expose_test.go b/command/connect/expose/expose_test.go index 511a495640fb8..9db76a765e822 100644 --- a/command/connect/expose/expose_test.go +++ b/command/connect/expose/expose_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package expose diff --git a/command/connect/proxy/flag_upstreams.go b/command/connect/proxy/flag_upstreams.go index 47bbb730ae86a..21a70c9b3c6bb 100644 --- a/command/connect/proxy/flag_upstreams.go +++ b/command/connect/proxy/flag_upstreams.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/command/connect/proxy/flag_upstreams_test.go b/command/connect/proxy/flag_upstreams_test.go index 7e47a9ad7950a..42647c98396d3 100644 --- a/command/connect/proxy/flag_upstreams_test.go +++ b/command/connect/proxy/flag_upstreams_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/command/connect/proxy/proxy.go b/command/connect/proxy/proxy.go index 9b352dab5d0ce..3585d798abeec 100644 --- a/command/connect/proxy/proxy.go +++ b/command/connect/proxy/proxy.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/command/connect/proxy/proxy_test.go b/command/connect/proxy/proxy_test.go index f17b04f5f8e88..fc55eadcc9b40 100644 --- a/command/connect/proxy/proxy_test.go +++ b/command/connect/proxy/proxy_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/command/connect/proxy/register.go b/command/connect/proxy/register.go index 87d6dbb9a2d32..c3051e0f9dd1c 100644 --- a/command/connect/proxy/register.go +++ b/command/connect/proxy/register.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/command/connect/proxy/register_test.go b/command/connect/proxy/register_test.go index 823b11d23c1b2..c1845ac6256ed 100644 --- a/command/connect/proxy/register_test.go +++ b/command/connect/proxy/register_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/command/connect/redirecttraffic/redirect_traffic.go b/command/connect/redirecttraffic/redirect_traffic.go index 8a597696b7f08..5e92193f0b004 100644 --- a/command/connect/redirecttraffic/redirect_traffic.go +++ b/command/connect/redirecttraffic/redirect_traffic.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package redirecttraffic diff --git a/command/connect/redirecttraffic/redirect_traffic_test.go b/command/connect/redirecttraffic/redirect_traffic_test.go index de9b362416c2d..209cfcc35d8a2 100644 --- a/command/connect/redirecttraffic/redirect_traffic_test.go +++ b/command/connect/redirecttraffic/redirect_traffic_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package redirecttraffic diff --git a/command/debug/debug.go b/command/debug/debug.go index 291e0d79e86b8..0c3fcca57a834 100644 --- a/command/debug/debug.go +++ b/command/debug/debug.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package debug diff --git a/command/debug/debug_test.go b/command/debug/debug_test.go index 1340ed057f8d7..e916ee9e7f0de 100644 --- a/command/debug/debug_test.go +++ b/command/debug/debug_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package debug diff --git a/command/event/event.go b/command/event/event.go index 73c19b6c5f776..5882b6005f680 100644 --- a/command/event/event.go +++ b/command/event/event.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package event diff --git a/command/event/event_test.go b/command/event/event_test.go index 349cb0daa8167..b267e8920a754 100644 --- a/command/event/event_test.go +++ b/command/event/event_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package event diff --git a/command/exec/exec.go b/command/exec/exec.go index 53026a6f8c877..140cdea300eb6 100644 --- a/command/exec/exec.go +++ b/command/exec/exec.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package exec diff --git a/command/exec/exec_test.go b/command/exec/exec_test.go index d8335160f28a4..74f446d11ca71 100644 --- a/command/exec/exec_test.go +++ b/command/exec/exec_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package exec diff --git a/command/flags/config.go b/command/flags/config.go index 39c615554d676..162ffea5a22ca 100644 --- a/command/flags/config.go +++ b/command/flags/config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package flags diff --git a/command/flags/config_test.go b/command/flags/config_test.go index 1a6d69ca4b574..bc718f1dc5b91 100644 --- a/command/flags/config_test.go +++ b/command/flags/config_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package flags diff --git a/command/flags/flag_map_value.go b/command/flags/flag_map_value.go index af5fec436dd57..58afc9f5c365b 100644 --- a/command/flags/flag_map_value.go +++ b/command/flags/flag_map_value.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package flags diff --git a/command/flags/flag_map_value_test.go b/command/flags/flag_map_value_test.go index d04342a01b34d..4177f452afac1 100644 --- a/command/flags/flag_map_value_test.go +++ b/command/flags/flag_map_value_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package flags diff --git a/command/flags/flag_slice_value.go b/command/flags/flag_slice_value.go index 58428e58ce9cc..b965b76546796 100644 --- a/command/flags/flag_slice_value.go +++ b/command/flags/flag_slice_value.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package flags diff --git a/command/flags/flag_slice_value_test.go b/command/flags/flag_slice_value_test.go index 24187f3f41835..84421f0f958af 100644 --- a/command/flags/flag_slice_value_test.go +++ b/command/flags/flag_slice_value_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package flags diff --git a/command/flags/http.go b/command/flags/http.go index 16157adc8a1b5..82e59431ae71d 100644 --- a/command/flags/http.go +++ b/command/flags/http.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package flags diff --git a/command/flags/http_test.go b/command/flags/http_test.go index f8b48f80cbabc..baf4ac231c8dd 100644 --- a/command/flags/http_test.go +++ b/command/flags/http_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package flags diff --git a/command/flags/merge.go b/command/flags/merge.go index 251698e320fcf..c7a475b4b1d5e 100644 --- a/command/flags/merge.go +++ b/command/flags/merge.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package flags diff --git a/command/flags/usage.go b/command/flags/usage.go index 3583620bd9f65..245cfd67c0187 100644 --- a/command/flags/usage.go +++ b/command/flags/usage.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package flags diff --git a/command/forceleave/forceleave.go b/command/forceleave/forceleave.go index 2c9e2ceb1def8..1b3aac559f171 100644 --- a/command/forceleave/forceleave.go +++ b/command/forceleave/forceleave.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package forceleave diff --git a/command/forceleave/forceleave_test.go b/command/forceleave/forceleave_test.go index 05d490777575c..c29d2996b8124 100644 --- a/command/forceleave/forceleave_test.go +++ b/command/forceleave/forceleave_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package forceleave diff --git a/command/helpers/decode_shim.go b/command/helpers/decode_shim.go index d2a73895a57fb..20ca1faeaaa80 100644 --- a/command/helpers/decode_shim.go +++ b/command/helpers/decode_shim.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package helpers diff --git a/command/helpers/helpers.go b/command/helpers/helpers.go index bc990f76fa020..3720439df3874 100644 --- a/command/helpers/helpers.go +++ b/command/helpers/helpers.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package helpers @@ -8,14 +8,12 @@ import ( "fmt" "io" "os" - "strings" "time" - "github.com/mitchellh/mapstructure" - "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/lib/decode" "github.com/hashicorp/go-multierror" + "github.com/mitchellh/mapstructure" ) func loadFromFile(path string) (string, error) { @@ -126,19 +124,13 @@ func newDecodeConfigEntry(raw map[string]interface{}) (api.ConfigEntry, error) { } for _, k := range md.Unused { - switch { - case strings.ToLower(k) == "kind": + switch k { + case "kind", "Kind": // The kind field is used to determine the target, but doesn't need // to exist on the target. continue - - case strings.HasSuffix(strings.ToLower(k), "namespace"): - err = multierror.Append(err, fmt.Errorf("invalid config key %q, namespaces are a consul enterprise feature", k)) - case strings.Contains(strings.ToLower(k), "jwt"): - err = multierror.Append(err, fmt.Errorf("invalid config key %q, api-gateway jwt validation is a consul enterprise feature", k)) - default: - err = multierror.Append(err, fmt.Errorf("invalid config key %q", k)) } + err = multierror.Append(err, fmt.Errorf("invalid config key %q", k)) } if err != nil { return nil, err diff --git a/command/helpers/helpers_test.go b/command/helpers/helpers_test.go index 6479386747bac..8d8b2164f7e7c 100644 --- a/command/helpers/helpers_test.go +++ b/command/helpers/helpers_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package helpers diff --git a/command/info/info.go b/command/info/info.go index 5bbad23eabbed..de17a53dd0d51 100644 --- a/command/info/info.go +++ b/command/info/info.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package info diff --git a/command/info/info_test.go b/command/info/info_test.go index 0faac3acc660e..5e046df8c484e 100644 --- a/command/info/info_test.go +++ b/command/info/info_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package info diff --git a/command/intention/check/check.go b/command/intention/check/check.go index dce63c75bc068..ed8119170f476 100644 --- a/command/intention/check/check.go +++ b/command/intention/check/check.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package check diff --git a/command/intention/check/check_test.go b/command/intention/check/check_test.go index 666d44d80c552..7ecac4a92f537 100644 --- a/command/intention/check/check_test.go +++ b/command/intention/check/check_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package check diff --git a/command/intention/create/create.go b/command/intention/create/create.go index df92dfe302a2e..c1eab7b0f12ca 100644 --- a/command/intention/create/create.go +++ b/command/intention/create/create.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package create diff --git a/command/intention/create/create_test.go b/command/intention/create/create_test.go index 90250368ef2b8..e74c87c2bb674 100644 --- a/command/intention/create/create_test.go +++ b/command/intention/create/create_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package create diff --git a/command/intention/delete/delete.go b/command/intention/delete/delete.go index a58ee163e6875..b63029d91d866 100644 --- a/command/intention/delete/delete.go +++ b/command/intention/delete/delete.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package delete diff --git a/command/intention/delete/delete_test.go b/command/intention/delete/delete_test.go index 51e59c8b52db1..dedcf8ff2e7d2 100644 --- a/command/intention/delete/delete_test.go +++ b/command/intention/delete/delete_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package delete diff --git a/command/intention/format.go b/command/intention/format.go index bd202cfa5081c..8683063207585 100644 --- a/command/intention/format.go +++ b/command/intention/format.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package intention diff --git a/command/intention/get/get.go b/command/intention/get/get.go index 64dd2c8441c4d..1c2437962627c 100644 --- a/command/intention/get/get.go +++ b/command/intention/get/get.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package get diff --git a/command/intention/get/get_test.go b/command/intention/get/get_test.go index 7559a3611849d..6f6f31ee9e8bc 100644 --- a/command/intention/get/get_test.go +++ b/command/intention/get/get_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package get diff --git a/command/intention/helpers.go b/command/intention/helpers.go index abc7c21e73a14..60774da85c9f1 100644 --- a/command/intention/helpers.go +++ b/command/intention/helpers.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package intention diff --git a/command/intention/helpers_test.go b/command/intention/helpers_test.go index cd2db64c69113..11dff93b108b0 100644 --- a/command/intention/helpers_test.go +++ b/command/intention/helpers_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package intention diff --git a/command/intention/intention.go b/command/intention/intention.go index 77ba5e2f5eae8..450ec630a49e1 100644 --- a/command/intention/intention.go +++ b/command/intention/intention.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package intention diff --git a/command/intention/intention_test.go b/command/intention/intention_test.go index 3a728fc028f9d..098fecfa938e6 100644 --- a/command/intention/intention_test.go +++ b/command/intention/intention_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package intention diff --git a/command/intention/list/intention_list.go b/command/intention/list/intention_list.go index 408f9d8dcd09d..f79f454dc79cb 100644 --- a/command/intention/list/intention_list.go +++ b/command/intention/list/intention_list.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package list diff --git a/command/intention/list/intention_list_test.go b/command/intention/list/intention_list_test.go index ccd6faefe3c10..2227c1c508e35 100644 --- a/command/intention/list/intention_list_test.go +++ b/command/intention/list/intention_list_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package list diff --git a/command/intention/match/match.go b/command/intention/match/match.go index ee115a7b1ad86..b6f00d1a0e88f 100644 --- a/command/intention/match/match.go +++ b/command/intention/match/match.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package match diff --git a/command/intention/match/match_test.go b/command/intention/match/match_test.go index 6715c7eba8d3a..d2a69ceada58c 100644 --- a/command/intention/match/match_test.go +++ b/command/intention/match/match_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package match diff --git a/command/join/join.go b/command/join/join.go index f5d041ed4b4d9..074813993d6ab 100644 --- a/command/join/join.go +++ b/command/join/join.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package join diff --git a/command/join/join_test.go b/command/join/join_test.go index 828cb46b6e318..e5d43c7cdea9f 100644 --- a/command/join/join_test.go +++ b/command/join/join_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package join diff --git a/command/keygen/keygen.go b/command/keygen/keygen.go index e2907bda0c0d2..c7ab5337c02c4 100644 --- a/command/keygen/keygen.go +++ b/command/keygen/keygen.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package keygen diff --git a/command/keygen/keygen_test.go b/command/keygen/keygen_test.go index 59edb12896bd6..a78a07cfedf74 100644 --- a/command/keygen/keygen_test.go +++ b/command/keygen/keygen_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package keygen diff --git a/command/keyring/keyring.go b/command/keyring/keyring.go index 0e4756f6191f7..2f9d96f0e266f 100644 --- a/command/keyring/keyring.go +++ b/command/keyring/keyring.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package keyring diff --git a/command/keyring/keyring_test.go b/command/keyring/keyring_test.go index 68c5e7f982196..5ee1b1a8752f8 100644 --- a/command/keyring/keyring_test.go +++ b/command/keyring/keyring_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package keyring diff --git a/command/kv/del/kv_delete.go b/command/kv/del/kv_delete.go index e58e4a229661f..89bdde4508c04 100644 --- a/command/kv/del/kv_delete.go +++ b/command/kv/del/kv_delete.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package del diff --git a/command/kv/del/kv_delete_test.go b/command/kv/del/kv_delete_test.go index 254fb4aa5097e..29d9b7bb98c4b 100644 --- a/command/kv/del/kv_delete_test.go +++ b/command/kv/del/kv_delete_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package del diff --git a/command/kv/exp/kv_export.go b/command/kv/exp/kv_export.go index 2f2e835bd42d7..c14acd4424d47 100644 --- a/command/kv/exp/kv_export.go +++ b/command/kv/exp/kv_export.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package exp diff --git a/command/kv/exp/kv_export_test.go b/command/kv/exp/kv_export_test.go index 76da13dcd4e6d..96e1d469113f6 100644 --- a/command/kv/exp/kv_export_test.go +++ b/command/kv/exp/kv_export_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package exp diff --git a/command/kv/get/kv_get.go b/command/kv/get/kv_get.go index 4abf0251751e4..b53173c048633 100644 --- a/command/kv/get/kv_get.go +++ b/command/kv/get/kv_get.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package get diff --git a/command/kv/get/kv_get_test.go b/command/kv/get/kv_get_test.go index 56318586de439..92b6675b80a5b 100644 --- a/command/kv/get/kv_get_test.go +++ b/command/kv/get/kv_get_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package get diff --git a/command/kv/imp/kv_import.go b/command/kv/imp/kv_import.go index 1d91d281df846..b1e6841060e60 100644 --- a/command/kv/imp/kv_import.go +++ b/command/kv/imp/kv_import.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package imp diff --git a/command/kv/imp/kv_import_test.go b/command/kv/imp/kv_import_test.go index 6bed5684cebdf..3528c2119abb2 100644 --- a/command/kv/imp/kv_import_test.go +++ b/command/kv/imp/kv_import_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package imp diff --git a/command/kv/impexp/kvimpexp.go b/command/kv/impexp/kvimpexp.go index 0dc4b394e0687..3235439ee5394 100644 --- a/command/kv/impexp/kvimpexp.go +++ b/command/kv/impexp/kvimpexp.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package impexp diff --git a/command/kv/kv.go b/command/kv/kv.go index 86d8c258e058a..3d98b63bdba3a 100644 --- a/command/kv/kv.go +++ b/command/kv/kv.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package kv diff --git a/command/kv/kv_test.go b/command/kv/kv_test.go index 85195ee9acbac..56ee94fa7e2da 100644 --- a/command/kv/kv_test.go +++ b/command/kv/kv_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package kv diff --git a/command/kv/put/kv_put.go b/command/kv/put/kv_put.go index 5f0580ce1431c..13e6ee4b9e8e4 100644 --- a/command/kv/put/kv_put.go +++ b/command/kv/put/kv_put.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package put diff --git a/command/kv/put/kv_put_test.go b/command/kv/put/kv_put_test.go index 1f0245c8e0f21..bd07f5aab38f6 100644 --- a/command/kv/put/kv_put_test.go +++ b/command/kv/put/kv_put_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package put diff --git a/command/leave/leave.go b/command/leave/leave.go index 8d997fb83c8dd..d822b5fedc540 100644 --- a/command/leave/leave.go +++ b/command/leave/leave.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package leave diff --git a/command/leave/leave_test.go b/command/leave/leave_test.go index 317a6862b91ec..67f16fefb74a9 100644 --- a/command/leave/leave_test.go +++ b/command/leave/leave_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package leave diff --git a/command/lock/lock.go b/command/lock/lock.go index a662babe041ff..f1acfd4f90937 100644 --- a/command/lock/lock.go +++ b/command/lock/lock.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lock diff --git a/command/lock/lock_test.go b/command/lock/lock_test.go index f32de5bc5e463..d90a7c0826c9e 100644 --- a/command/lock/lock_test.go +++ b/command/lock/lock_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lock diff --git a/command/lock/util_unix.go b/command/lock/util_unix.go index d2c9bf1dd41d0..3c754560b4e12 100644 --- a/command/lock/util_unix.go +++ b/command/lock/util_unix.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !windows // +build !windows diff --git a/command/lock/util_windows.go b/command/lock/util_windows.go index 12f148fa00c1f..9a271af66d1d2 100644 --- a/command/lock/util_windows.go +++ b/command/lock/util_windows.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build windows // +build windows diff --git a/command/login/aws.go b/command/login/aws.go index e7fb6af58eeff..99230679c13d5 100644 --- a/command/login/aws.go +++ b/command/login/aws.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package login diff --git a/command/login/login.go b/command/login/login.go index 0ab5237852929..18f2762c99543 100644 --- a/command/login/login.go +++ b/command/login/login.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package login diff --git a/command/login/login_ce.go b/command/login/login_ce.go index 34f935177816a..365d89dfd5dee 100644 --- a/command/login/login_ce.go +++ b/command/login/login_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/command/login/login_test.go b/command/login/login_test.go index c3bf117676178..918e1fcbff2fd 100644 --- a/command/login/login_test.go +++ b/command/login/login_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package login diff --git a/command/logout/logout.go b/command/logout/logout.go index 35365f4469547..8ff8fb6778926 100644 --- a/command/logout/logout.go +++ b/command/logout/logout.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logout diff --git a/command/logout/logout_test.go b/command/logout/logout_test.go index 7228def746b88..1e3890bb8acb9 100644 --- a/command/logout/logout_test.go +++ b/command/logout/logout_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logout diff --git a/command/maint/maint.go b/command/maint/maint.go index 252aa1de46a73..e9d189157b1f2 100644 --- a/command/maint/maint.go +++ b/command/maint/maint.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package maint diff --git a/command/maint/maint_test.go b/command/maint/maint_test.go index eabd173a623f9..c182ecbdf3ab3 100644 --- a/command/maint/maint_test.go +++ b/command/maint/maint_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package maint diff --git a/command/members/members.go b/command/members/members.go index 7b10612643b08..9895837f6484d 100644 --- a/command/members/members.go +++ b/command/members/members.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package members diff --git a/command/members/members_test.go b/command/members/members_test.go index 76e3bbe1260d2..646c51ec6248d 100644 --- a/command/members/members_test.go +++ b/command/members/members_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package members diff --git a/command/monitor/monitor.go b/command/monitor/monitor.go index e1d0e8597d502..0703b34a05120 100644 --- a/command/monitor/monitor.go +++ b/command/monitor/monitor.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package monitor diff --git a/command/monitor/monitor_test.go b/command/monitor/monitor_test.go index e9eacdda4caf6..61abfb6c9bf07 100644 --- a/command/monitor/monitor_test.go +++ b/command/monitor/monitor_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package monitor diff --git a/command/operator/autopilot/get/operator_autopilot_get.go b/command/operator/autopilot/get/operator_autopilot_get.go index 5cc2dc351e34a..d891672782673 100644 --- a/command/operator/autopilot/get/operator_autopilot_get.go +++ b/command/operator/autopilot/get/operator_autopilot_get.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package get diff --git a/command/operator/autopilot/get/operator_autopilot_get_test.go b/command/operator/autopilot/get/operator_autopilot_get_test.go index 264706ea24452..fc5e0f12e1aeb 100644 --- a/command/operator/autopilot/get/operator_autopilot_get_test.go +++ b/command/operator/autopilot/get/operator_autopilot_get_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package get diff --git a/command/operator/autopilot/operator_autopilot.go b/command/operator/autopilot/operator_autopilot.go index d1de582fbecf9..38d51641eb593 100644 --- a/command/operator/autopilot/operator_autopilot.go +++ b/command/operator/autopilot/operator_autopilot.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autopilot diff --git a/command/operator/autopilot/operator_autopilot_test.go b/command/operator/autopilot/operator_autopilot_test.go index 9861749b172a4..9fa91f988b2fc 100644 --- a/command/operator/autopilot/operator_autopilot_test.go +++ b/command/operator/autopilot/operator_autopilot_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package autopilot diff --git a/command/operator/autopilot/set/operator_autopilot_set.go b/command/operator/autopilot/set/operator_autopilot_set.go index 6a8dd5fec9ae7..c396dd5d966c4 100644 --- a/command/operator/autopilot/set/operator_autopilot_set.go +++ b/command/operator/autopilot/set/operator_autopilot_set.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package set diff --git a/command/operator/autopilot/set/operator_autopilot_set_test.go b/command/operator/autopilot/set/operator_autopilot_set_test.go index b92e7ef4b4fd8..c8d757bdbbc73 100644 --- a/command/operator/autopilot/set/operator_autopilot_set_test.go +++ b/command/operator/autopilot/set/operator_autopilot_set_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package set diff --git a/command/operator/autopilot/state/formatter.go b/command/operator/autopilot/state/formatter.go index 11cec09c6a160..f4e42a6578ed9 100644 --- a/command/operator/autopilot/state/formatter.go +++ b/command/operator/autopilot/state/formatter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/command/operator/autopilot/state/operator_autopilot_state.go b/command/operator/autopilot/state/operator_autopilot_state.go index be85fdb3ccf18..b5fd6d0718862 100644 --- a/command/operator/autopilot/state/operator_autopilot_state.go +++ b/command/operator/autopilot/state/operator_autopilot_state.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/command/operator/autopilot/state/operator_autopilot_state_test.go b/command/operator/autopilot/state/operator_autopilot_state_test.go index adc4b65933b1f..d81abcde44f7f 100644 --- a/command/operator/autopilot/state/operator_autopilot_state_test.go +++ b/command/operator/autopilot/state/operator_autopilot_state_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package state diff --git a/command/operator/operator.go b/command/operator/operator.go index 06c8c7622e487..b66924d3cb715 100644 --- a/command/operator/operator.go +++ b/command/operator/operator.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package operator diff --git a/command/operator/operator_test.go b/command/operator/operator_test.go index d25f4fc4f8d38..822ffc52347d9 100644 --- a/command/operator/operator_test.go +++ b/command/operator/operator_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package operator diff --git a/command/operator/raft/listpeers/operator_raft_list.go b/command/operator/raft/listpeers/operator_raft_list.go index abe682c103715..29643a87cf33b 100644 --- a/command/operator/raft/listpeers/operator_raft_list.go +++ b/command/operator/raft/listpeers/operator_raft_list.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package listpeers diff --git a/command/operator/raft/listpeers/operator_raft_list_test.go b/command/operator/raft/listpeers/operator_raft_list_test.go index c29ed9d418e9c..0694e0dd10465 100644 --- a/command/operator/raft/listpeers/operator_raft_list_test.go +++ b/command/operator/raft/listpeers/operator_raft_list_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package listpeers diff --git a/command/operator/raft/operator_raft.go b/command/operator/raft/operator_raft.go index 52bcb446f9b10..42b6175e974db 100644 --- a/command/operator/raft/operator_raft.go +++ b/command/operator/raft/operator_raft.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package raft diff --git a/command/operator/raft/operator_raft_test.go b/command/operator/raft/operator_raft_test.go index cac0545fa511e..275606ab5aeca 100644 --- a/command/operator/raft/operator_raft_test.go +++ b/command/operator/raft/operator_raft_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package raft diff --git a/command/operator/raft/removepeer/operator_raft_remove.go b/command/operator/raft/removepeer/operator_raft_remove.go index 12692d4d5225f..eea10a045d9ad 100644 --- a/command/operator/raft/removepeer/operator_raft_remove.go +++ b/command/operator/raft/removepeer/operator_raft_remove.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package removepeer diff --git a/command/operator/raft/removepeer/operator_raft_remove_test.go b/command/operator/raft/removepeer/operator_raft_remove_test.go index e7647712647d8..e81fc1474a386 100644 --- a/command/operator/raft/removepeer/operator_raft_remove_test.go +++ b/command/operator/raft/removepeer/operator_raft_remove_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package removepeer diff --git a/command/operator/raft/transferleader/transfer_leader.go b/command/operator/raft/transferleader/transfer_leader.go index ebeb77dfc82c6..9e3630c056015 100644 --- a/command/operator/raft/transferleader/transfer_leader.go +++ b/command/operator/raft/transferleader/transfer_leader.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package transferleader diff --git a/command/operator/raft/transferleader/transfer_leader_test.go b/command/operator/raft/transferleader/transfer_leader_test.go index 2b56fe1d784f6..7c0fc4115dbc4 100644 --- a/command/operator/raft/transferleader/transfer_leader_test.go +++ b/command/operator/raft/transferleader/transfer_leader_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package transferleader diff --git a/command/operator/usage/instances/usage_instances.go b/command/operator/usage/instances/usage_instances.go index 83231db0a1d47..1ac90dce8d363 100644 --- a/command/operator/usage/instances/usage_instances.go +++ b/command/operator/usage/instances/usage_instances.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package instances diff --git a/command/operator/usage/instances/usage_instances_ce.go b/command/operator/usage/instances/usage_instances_ce.go index ef614edfac269..dc9511b32ce28 100644 --- a/command/operator/usage/instances/usage_instances_ce.go +++ b/command/operator/usage/instances/usage_instances_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/command/operator/usage/instances/usage_instances_ce_test.go b/command/operator/usage/instances/usage_instances_ce_test.go index a064828a45f37..478b9f42118b8 100644 --- a/command/operator/usage/instances/usage_instances_ce_test.go +++ b/command/operator/usage/instances/usage_instances_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/command/operator/usage/instances/usage_instances_test.go b/command/operator/usage/instances/usage_instances_test.go index 7dac04dd3e323..8ad38e1b0c53a 100644 --- a/command/operator/usage/instances/usage_instances_test.go +++ b/command/operator/usage/instances/usage_instances_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package instances diff --git a/command/operator/usage/usage.go b/command/operator/usage/usage.go index 6e7cde57e4bf5..3d733f8f36ffb 100644 --- a/command/operator/usage/usage.go +++ b/command/operator/usage/usage.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package usage diff --git a/command/peering/delete/delete.go b/command/peering/delete/delete.go index 039ace5391884..f4399b73ce2f4 100644 --- a/command/peering/delete/delete.go +++ b/command/peering/delete/delete.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package delete diff --git a/command/peering/delete/delete_test.go b/command/peering/delete/delete_test.go index 5aa299b78d52a..56d0d495a897c 100644 --- a/command/peering/delete/delete_test.go +++ b/command/peering/delete/delete_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package delete diff --git a/command/peering/establish/establish.go b/command/peering/establish/establish.go index 42178f149040d..ef5178eecf8aa 100644 --- a/command/peering/establish/establish.go +++ b/command/peering/establish/establish.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package establish diff --git a/command/peering/establish/establish_test.go b/command/peering/establish/establish_test.go index 25abae316bc43..515b727f78b69 100644 --- a/command/peering/establish/establish_test.go +++ b/command/peering/establish/establish_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package establish diff --git a/command/peering/generate/generate.go b/command/peering/generate/generate.go index e2122aa7aa095..26410480f517b 100644 --- a/command/peering/generate/generate.go +++ b/command/peering/generate/generate.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package generate diff --git a/command/peering/generate/generate_test.go b/command/peering/generate/generate_test.go index 863b266ed15e2..529f46aacdf6e 100644 --- a/command/peering/generate/generate_test.go +++ b/command/peering/generate/generate_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package generate diff --git a/command/peering/list/list.go b/command/peering/list/list.go index 10e85d9b582f4..87fb6bade5998 100644 --- a/command/peering/list/list.go +++ b/command/peering/list/list.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package list diff --git a/command/peering/list/list_test.go b/command/peering/list/list_test.go index 43da9684728e0..f923e6d2b7615 100644 --- a/command/peering/list/list_test.go +++ b/command/peering/list/list_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package list diff --git a/command/peering/peering.go b/command/peering/peering.go index 157dd42c63d71..2a4834e514c23 100644 --- a/command/peering/peering.go +++ b/command/peering/peering.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package peering diff --git a/command/peering/read/read.go b/command/peering/read/read.go index 8d15210fcfaa9..ddd44cb4fe8b8 100644 --- a/command/peering/read/read.go +++ b/command/peering/read/read.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package read diff --git a/command/peering/read/read_test.go b/command/peering/read/read_test.go index 90a2ac879244e..42b3544661753 100644 --- a/command/peering/read/read_test.go +++ b/command/peering/read/read_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package read diff --git a/command/registry.go b/command/registry.go index f01e3a1080416..b370f14bc872c 100644 --- a/command/registry.go +++ b/command/registry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package command diff --git a/command/registry_ce.go b/command/registry_ce.go index 7ea2f73a12f95..2a7708221022a 100644 --- a/command/registry_ce.go +++ b/command/registry_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/command/reload/reload.go b/command/reload/reload.go index 458b90cbf6a89..b0989817fdc07 100644 --- a/command/reload/reload.go +++ b/command/reload/reload.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package reload diff --git a/command/reload/reload_test.go b/command/reload/reload_test.go index 11313fb138418..d75712c539347 100644 --- a/command/reload/reload_test.go +++ b/command/reload/reload_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package reload diff --git a/command/rtt/rtt.go b/command/rtt/rtt.go index db9e3efd06be2..f7a7414511d60 100644 --- a/command/rtt/rtt.go +++ b/command/rtt/rtt.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package rtt diff --git a/command/rtt/rtt_test.go b/command/rtt/rtt_test.go index 4b0621cfe33f8..8534fc1a59bc2 100644 --- a/command/rtt/rtt_test.go +++ b/command/rtt/rtt_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package rtt diff --git a/command/services/config.go b/command/services/config.go index 1a173078d6f04..f881778956d6b 100644 --- a/command/services/config.go +++ b/command/services/config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package services diff --git a/command/services/config_test.go b/command/services/config_test.go index b8a2207fb9e86..e8770337d4d9b 100644 --- a/command/services/config_test.go +++ b/command/services/config_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package services diff --git a/command/services/deregister/deregister.go b/command/services/deregister/deregister.go index bff2c972704a8..69a4ef9437d74 100644 --- a/command/services/deregister/deregister.go +++ b/command/services/deregister/deregister.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package deregister diff --git a/command/services/deregister/deregister_test.go b/command/services/deregister/deregister_test.go index 2ee9d8de5fab5..15d9ffddb22ba 100644 --- a/command/services/deregister/deregister_test.go +++ b/command/services/deregister/deregister_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package deregister diff --git a/command/services/export/export.go b/command/services/export/export.go index 49a5756602006..637553f93e6c7 100644 --- a/command/services/export/export.go +++ b/command/services/export/export.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package export import ( diff --git a/command/services/export/export_test.go b/command/services/export/export_test.go index aa13aff63c238..6a2dfa9d67b06 100644 --- a/command/services/export/export_test.go +++ b/command/services/export/export_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package export import ( diff --git a/command/services/register/register.go b/command/services/register/register.go index 33599dda01323..6e5f7a0fcfa57 100644 --- a/command/services/register/register.go +++ b/command/services/register/register.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package register diff --git a/command/services/register/register_test.go b/command/services/register/register_test.go index 24d5f4fb87ea1..2004610cf50d0 100644 --- a/command/services/register/register_test.go +++ b/command/services/register/register_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package register diff --git a/command/services/services.go b/command/services/services.go index 521092f063ae5..9c12445def7e1 100644 --- a/command/services/services.go +++ b/command/services/services.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package services diff --git a/command/services/services_test.go b/command/services/services_test.go index a2d4b45262be5..11a31cd16dbe1 100644 --- a/command/services/services_test.go +++ b/command/services/services_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package services diff --git a/command/snapshot/inspect/formatter.go b/command/snapshot/inspect/formatter.go index 53da998b25c8b..2898bf174fb07 100644 --- a/command/snapshot/inspect/formatter.go +++ b/command/snapshot/inspect/formatter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package inspect diff --git a/command/snapshot/inspect/formatter_test.go b/command/snapshot/inspect/formatter_test.go index 48b8d1da4d966..b55ea6b972a26 100644 --- a/command/snapshot/inspect/formatter_test.go +++ b/command/snapshot/inspect/formatter_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package inspect diff --git a/command/snapshot/inspect/snapshot_inspect.go b/command/snapshot/inspect/snapshot_inspect.go index 483e937eb4810..018d3f3dec348 100644 --- a/command/snapshot/inspect/snapshot_inspect.go +++ b/command/snapshot/inspect/snapshot_inspect.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package inspect diff --git a/command/snapshot/inspect/snapshot_inspect_test.go b/command/snapshot/inspect/snapshot_inspect_test.go index 1f7ff69f1bc35..f6a7990783680 100644 --- a/command/snapshot/inspect/snapshot_inspect_test.go +++ b/command/snapshot/inspect/snapshot_inspect_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package inspect diff --git a/command/snapshot/restore/snapshot_restore.go b/command/snapshot/restore/snapshot_restore.go index aaa08a162d7a8..170e77685dc2c 100644 --- a/command/snapshot/restore/snapshot_restore.go +++ b/command/snapshot/restore/snapshot_restore.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package restore diff --git a/command/snapshot/restore/snapshot_restore_test.go b/command/snapshot/restore/snapshot_restore_test.go index 61c8b2bed0d67..076df99a6bdd6 100644 --- a/command/snapshot/restore/snapshot_restore_test.go +++ b/command/snapshot/restore/snapshot_restore_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package restore diff --git a/command/snapshot/save/snapshot_save.go b/command/snapshot/save/snapshot_save.go index 2395a4f3a0389..11569d60c519c 100644 --- a/command/snapshot/save/snapshot_save.go +++ b/command/snapshot/save/snapshot_save.go @@ -1,12 +1,15 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package save import ( "flag" "fmt" + "golang.org/x/exp/slices" "os" + "path/filepath" + "strings" "github.com/mitchellh/cli" "github.com/rboyer/safeio" @@ -23,10 +26,18 @@ func New(ui cli.Ui) *cmd { } type cmd struct { - UI cli.Ui - flags *flag.FlagSet - http *flags.HTTPFlags - help string + UI cli.Ui + flags *flag.FlagSet + http *flags.HTTPFlags + help string + appendFileNameFlag flags.StringValue +} + +func (c *cmd) getAppendFileNameFlag() *flag.FlagSet { + fs := flag.NewFlagSet("", flag.ContinueOnError) + fs.Var(&c.appendFileNameFlag, "append-filename", "Append filename flag supports the following "+ + "comma-separated arguments. 1. version, 2. dc. It appends these values to the filename provided in the command") + return fs } func (c *cmd) init() { @@ -34,6 +45,7 @@ func (c *cmd) init() { c.http = &flags.HTTPFlags{} flags.Merge(c.flags, c.http.ClientFlags()) flags.Merge(c.flags, c.http.ServerFlags()) + flags.Merge(c.flags, c.getAppendFileNameFlag()) c.help = flags.Usage(help, c.flags) } @@ -58,6 +70,47 @@ func (c *cmd) Run(args []string) int { // Create and test the HTTP client client, err := c.http.APIClient() + + appendFileNameFlags := strings.Split(c.appendFileNameFlag.String(), ",") + + if len(appendFileNameFlags) != 0 && len(c.appendFileNameFlag.String()) > 0 { + fileExt := filepath.Ext(file) + fileNameWithoutExt := strings.TrimSuffix(file, fileExt) + + if slices.Contains(appendFileNameFlags, "version") { + operatorHealthResponse, err := client.Operator().AutopilotServerHealth(nil) + if err != nil { + c.UI.Error(fmt.Sprintf("Error fetching version of Consul agent Leader: %s", err)) + return 1 + } + var version string + for _, server := range operatorHealthResponse.Servers { + if server.Leader { + version = server.Version + break + } + } + fileNameWithoutExt = fileNameWithoutExt + "-" + version + } + + if slices.Contains(appendFileNameFlags, "dc") { + agentSelfResponse, err := client.Agent().Self() + if err != nil { + c.UI.Error(fmt.Sprintf("Error connecting to Consul agent and fetching datacenter/version: %s", err)) + return 1 + } + + if config, ok := agentSelfResponse["Config"]; ok { + if datacenter, ok := config["Datacenter"]; ok { + fileNameWithoutExt = fileNameWithoutExt + "-" + datacenter.(string) + } + } + } + + //adding extension back + file = fileNameWithoutExt + fileExt + } + if err != nil { c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) return 1 diff --git a/command/snapshot/save/snapshot_save_test.go b/command/snapshot/save/snapshot_save_test.go index a95b537e94755..15f31784847f0 100644 --- a/command/snapshot/save/snapshot_save_test.go +++ b/command/snapshot/save/snapshot_save_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package save @@ -72,6 +72,71 @@ func TestSnapshotSaveCommand_Validation(t *testing.T) { } } +func TestSnapshotSaveCommandWithAppendFileNameFlag(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + a := agent.NewTestAgent(t, ``) + defer a.Shutdown() + client := a.Client() + + ui := cli.NewMockUi() + c := New(ui) + + dir := testutil.TempDir(t, "snapshot") + file := filepath.Join(dir, "backup.tgz") + args := []string{ + "-append-filename=version,dc", + "-http-addr=" + a.HTTPAddr(), + file, + } + + // We need to use the self endpoint here for ENT, which returns the product suffix (+ent) + self, err := client.Agent().Self() + require.NoError(t, err) + + cfg, ok := self["Config"] + require.True(t, ok) + + dc, ok := cfg["Datacenter"] + require.True(t, ok) + + datacenter := dc.(string) + + operatorHealth, error := client.Operator().AutopilotServerHealth(nil) + require.NoError(t, error) + + var version string + for _, server := range operatorHealth.Servers { + if server.Leader { + version = server.Version + } + } + + newFilePath := filepath.Join(dir, "backup"+"-"+version+"-"+datacenter+".tgz") + + code := c.Run(args) + if code != 0 { + t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String()) + } + + fi, err := os.Stat(newFilePath) + require.NoError(t, err) + require.Equal(t, fi.Mode(), os.FileMode(0600)) + + f, err := os.Open(newFilePath) + if err != nil { + t.Fatalf("err: %v", err) + } + defer f.Close() + + if err := client.Snapshot().Restore(nil, f); err != nil { + t.Fatalf("err: %v", err) + } +} + func TestSnapshotSaveCommand(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") diff --git a/command/snapshot/snapshot_command.go b/command/snapshot/snapshot_command.go index 2e96550e191fd..7378f5449f29d 100644 --- a/command/snapshot/snapshot_command.go +++ b/command/snapshot/snapshot_command.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package snapshot diff --git a/command/snapshot/snapshot_command_test.go b/command/snapshot/snapshot_command_test.go index d38f5cde9271b..99db9533a31d7 100644 --- a/command/snapshot/snapshot_command_test.go +++ b/command/snapshot/snapshot_command_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package snapshot diff --git a/command/tls/ca/create/tls_ca_create.go b/command/tls/ca/create/tls_ca_create.go index 43a9c249f154e..4c25f8aec7a2e 100644 --- a/command/tls/ca/create/tls_ca_create.go +++ b/command/tls/ca/create/tls_ca_create.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package create diff --git a/command/tls/ca/create/tls_ca_create_test.go b/command/tls/ca/create/tls_ca_create_test.go index aee2b69062cff..d9e837e56d7f4 100644 --- a/command/tls/ca/create/tls_ca_create_test.go +++ b/command/tls/ca/create/tls_ca_create_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package create diff --git a/command/tls/ca/tls_ca.go b/command/tls/ca/tls_ca.go index ef943a4fbfe0e..65207c0dc8ba0 100644 --- a/command/tls/ca/tls_ca.go +++ b/command/tls/ca/tls_ca.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/command/tls/ca/tls_ca_test.go b/command/tls/ca/tls_ca_test.go index d24c15665f307..74cd8de37da47 100644 --- a/command/tls/ca/tls_ca_test.go +++ b/command/tls/ca/tls_ca_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ca diff --git a/command/tls/cert/create/tls_cert_create.go b/command/tls/cert/create/tls_cert_create.go index 9e0f92173bd15..7af36bc986cd8 100644 --- a/command/tls/cert/create/tls_cert_create.go +++ b/command/tls/cert/create/tls_cert_create.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package create diff --git a/command/tls/cert/create/tls_cert_create_test.go b/command/tls/cert/create/tls_cert_create_test.go index 6e807d4a4fc71..9f9fa1385a21e 100644 --- a/command/tls/cert/create/tls_cert_create_test.go +++ b/command/tls/cert/create/tls_cert_create_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package create diff --git a/command/tls/cert/tls_cert.go b/command/tls/cert/tls_cert.go index 38551ef6c621d..17795507e4319 100644 --- a/command/tls/cert/tls_cert.go +++ b/command/tls/cert/tls_cert.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cert diff --git a/command/tls/cert/tls_cert_test.go b/command/tls/cert/tls_cert_test.go index 912ff3e58e4b2..ab5144813de61 100644 --- a/command/tls/cert/tls_cert_test.go +++ b/command/tls/cert/tls_cert_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cert diff --git a/command/tls/tls.go b/command/tls/tls.go index a25a313ed02ec..fda3c4a12331a 100644 --- a/command/tls/tls.go +++ b/command/tls/tls.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tls diff --git a/command/tls/tls_test.go b/command/tls/tls_test.go index 7bd99fd4c11c4..dd34df10fd282 100644 --- a/command/tls/tls_test.go +++ b/command/tls/tls_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tls diff --git a/command/troubleshoot/proxy/troubleshoot_proxy.go b/command/troubleshoot/proxy/troubleshoot_proxy.go index 1f513043fb17d..08928b9e5453f 100644 --- a/command/troubleshoot/proxy/troubleshoot_proxy.go +++ b/command/troubleshoot/proxy/troubleshoot_proxy.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/command/troubleshoot/troubleshoot.go b/command/troubleshoot/troubleshoot.go index 36c77ff104352..431c671ee732c 100644 --- a/command/troubleshoot/troubleshoot.go +++ b/command/troubleshoot/troubleshoot.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package troubleshoot diff --git a/command/troubleshoot/troubleshoot_test.go b/command/troubleshoot/troubleshoot_test.go index a0e3f1c06957f..9ec2f68665a36 100644 --- a/command/troubleshoot/troubleshoot_test.go +++ b/command/troubleshoot/troubleshoot_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package troubleshoot diff --git a/command/troubleshoot/upstreams/troubleshoot_upstreams.go b/command/troubleshoot/upstreams/troubleshoot_upstreams.go index 5796dac583764..19737c7353307 100644 --- a/command/troubleshoot/upstreams/troubleshoot_upstreams.go +++ b/command/troubleshoot/upstreams/troubleshoot_upstreams.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package upstreams diff --git a/command/validate/validate.go b/command/validate/validate.go index 1a9630c65f47e..a44120a89f8be 100644 --- a/command/validate/validate.go +++ b/command/validate/validate.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package validate diff --git a/command/validate/validate_test.go b/command/validate/validate_test.go index dc5b519dbe31a..fdd0c7b2f2ff6 100644 --- a/command/validate/validate_test.go +++ b/command/validate/validate_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package validate diff --git a/command/version/formatter.go b/command/version/formatter.go index 612c305a7985d..c7c16da4419bf 100644 --- a/command/version/formatter.go +++ b/command/version/formatter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package version diff --git a/command/version/formatter_test.go b/command/version/formatter_test.go index 45e4019dfb5c8..b5c0bd2482b98 100644 --- a/command/version/formatter_test.go +++ b/command/version/formatter_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package version diff --git a/command/version/version.go b/command/version/version.go index da8978c3e72f7..1c2157a8eae8a 100644 --- a/command/version/version.go +++ b/command/version/version.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package version diff --git a/command/version/version_test.go b/command/version/version_test.go index d0af11506e383..45bd4fc6ac4c2 100644 --- a/command/version/version_test.go +++ b/command/version/version_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package version diff --git a/command/watch/watch.go b/command/watch/watch.go index 205ff3fb083d7..b187fa369ab44 100644 --- a/command/watch/watch.go +++ b/command/watch/watch.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package watch diff --git a/command/watch/watch_test.go b/command/watch/watch_test.go index ba29c2731a8c0..ed830a2aa7f3c 100644 --- a/command/watch/watch_test.go +++ b/command/watch/watch_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package watch diff --git a/connect/certgen/certgen.go b/connect/certgen/certgen.go index 509e7f8df4f3b..ced3720cd81b0 100644 --- a/connect/certgen/certgen.go +++ b/connect/certgen/certgen.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // certgen: a tool for generating test certificates on disk for use as // test-fixtures and for end-to-end testing and local development. diff --git a/connect/example_test.go b/connect/example_test.go index 51571bf1818cb..666f2f09db6dd 100644 --- a/connect/example_test.go +++ b/connect/example_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/connect/proxy/config.go b/connect/proxy/config.go index 19476d48d49f5..9d5e85bf4deee 100644 --- a/connect/proxy/config.go +++ b/connect/proxy/config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/connect/proxy/config_test.go b/connect/proxy/config_test.go index a196958316816..55bd64e1b18a2 100644 --- a/connect/proxy/config_test.go +++ b/connect/proxy/config_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/connect/proxy/conn.go b/connect/proxy/conn.go index acc1a49eb4b77..2c9314642ee26 100644 --- a/connect/proxy/conn.go +++ b/connect/proxy/conn.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/connect/proxy/conn_test.go b/connect/proxy/conn_test.go index b5be7952d0ee5..95836af0d9e4f 100644 --- a/connect/proxy/conn_test.go +++ b/connect/proxy/conn_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/connect/proxy/listener.go b/connect/proxy/listener.go index fc823d2712845..97d607c751f6a 100644 --- a/connect/proxy/listener.go +++ b/connect/proxy/listener.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/connect/proxy/listener_test.go b/connect/proxy/listener_test.go index 5554ecf353a6e..9b4e573a4aa1e 100644 --- a/connect/proxy/listener_test.go +++ b/connect/proxy/listener_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/connect/proxy/proxy.go b/connect/proxy/proxy.go index c365862ad8ec7..f5e7f913460fd 100644 --- a/connect/proxy/proxy.go +++ b/connect/proxy/proxy.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/connect/proxy/proxy_test.go b/connect/proxy/proxy_test.go index 20b4cdd55efef..876a91c81a4d0 100644 --- a/connect/proxy/proxy_test.go +++ b/connect/proxy/proxy_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/connect/proxy/testing.go b/connect/proxy/testing.go index 6756f16a2567b..7f8604394af75 100644 --- a/connect/proxy/testing.go +++ b/connect/proxy/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package proxy diff --git a/connect/resolver.go b/connect/resolver.go index fa89bc36d33d8..eb68b1c123358 100644 --- a/connect/resolver.go +++ b/connect/resolver.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/connect/resolver_test.go b/connect/resolver_test.go index 3aece268b5dc3..51bc13ee28d4b 100644 --- a/connect/resolver_test.go +++ b/connect/resolver_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/connect/service.go b/connect/service.go index ea38dd59b2e53..1260b065a068c 100644 --- a/connect/service.go +++ b/connect/service.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/connect/service_test.go b/connect/service_test.go index 0f6ed51a8b458..87f522214cee2 100644 --- a/connect/service_test.go +++ b/connect/service_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/connect/testing.go b/connect/testing.go index 1017ee15f5e7d..4fe1a54f6e098 100644 --- a/connect/testing.go +++ b/connect/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/connect/tls.go b/connect/tls.go index 3d29cf48e1c0a..a0e0286bc1afb 100644 --- a/connect/tls.go +++ b/connect/tls.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect @@ -425,7 +425,7 @@ func (cfg *dynamicTLSConfig) Ready() bool { return cfg.VerifyLeafWithRoots() == nil } -// ReadyWait returns a chan that is closed when the Service becomes ready +// ReadyWait returns a chan that is closed when the the Service becomes ready // for use for the first time. Note that if the Service is ready when it is // called it returns a nil chan. Ready means that it has root and leaf // certificates configured but not that the combination is valid nor that diff --git a/connect/tls_test.go b/connect/tls_test.go index 74609b1740e35..5c96371c9443d 100644 --- a/connect/tls_test.go +++ b/connect/tls_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package connect diff --git a/docs/README.md b/docs/README.md index 0d61b30fa5778..d3483710b33bd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -40,8 +40,6 @@ Also see the [FAQ](./faq.md). 1. [Integration Tests](../test/integration/connect/envoy/README.md) 1. [Upgrade Tests](../test/integration/consul-container/test/upgrade/README.md) -1. [Remote Debugging Integration Tests](../test/integration/consul-container/test/debugging.md) -1. [Peering Common Topology Tests](../test-integ/peering_commontopo/README.md) ## Important Directories @@ -56,7 +54,7 @@ contain other important source related to Consul. * [.changelog] contains markdown files that are used by [hashicorp/go-changelog] to produce the [CHANGELOG.md]. * [build-support] contains bash functions and scripts used to automate. - development tasks. Generally these scripts are called from the [Makefile]. + development tasks. Generally these scripts are called from the [GNUmakefile]. * [grafana] contains the source for a [Grafana dashboard] that can be used to monitor Consul. @@ -67,7 +65,7 @@ contain other important source related to Consul. [hashicorp/go-changelog]: https://github.com/hashicorp/go-changelog [CHANGELOG.md]: https://github.com/hashicorp/consul/blob/main/CHANGELOG.md [build-support]: https://github.com/hashicorp/consul/tree/main/build-support -[Makefile]: https://github.com/hashicorp/consul/tree/main/Makefile +[GNUmakefile]: https://github.com/hashicorp/consul/tree/main/GNUmakefile [Grafana dashboard]: https://grafana.com/grafana/dashboards [grafana]: https://github.com/hashicorp/consul/tree/main/grafana diff --git a/docs/resources/guide.md b/docs/resources/guide.md index c19566577b720..b3f389c006a6a 100644 --- a/docs/resources/guide.md +++ b/docs/resources/guide.md @@ -61,10 +61,8 @@ func RegisterTypes(r resource.Registry) { } ``` -Update the `NewTypeRegistry` method in [`type_registry.go`] to call your -package's type registration method: - -[`type_registry.go`]: ../../agent/consul/type_registry.go +Update the `registerResources` method in [`server.go`] to call your package's +type registration method: ```Go import ( @@ -73,13 +71,15 @@ import ( // … ) -func NewTypeRegistry() resource.Registry { +func (s *Server) registerResources() { // … - foo.RegisterTypes(registry) + foo.RegisterTypes(s.typeRegistry) // … } ``` +[`server.go`]: ../../agent/consul/server.go + That should be all you need to start using your new resource type. Test it out by starting an agent in dev mode: @@ -277,9 +277,7 @@ func (barReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req c Next, register your controller with the controller manager. Another common pattern is to have your package expose a method for registering controllers, -which is called from `registerControllers` in [`server.go`]. - -[`server.go`]: ../../agent/consul/server.go +which is also called from `registerResources` in [`server.go`]. ```Go package foo @@ -292,7 +290,7 @@ func RegisterControllers(mgr *controller.Manager) { ```Go package consul -func (s *Server) registerControllers() { +func (s *Server) registerResources() { // … foo.RegisterControllers(s.controllerManager) // … diff --git a/envoyextensions/extensioncommon/basic_envoy_extender.go b/envoyextensions/extensioncommon/basic_envoy_extender.go index 86cee8f14a4e8..a99d7439fea83 100644 --- a/envoyextensions/extensioncommon/basic_envoy_extender.go +++ b/envoyextensions/extensioncommon/basic_envoy_extender.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package extensioncommon diff --git a/envoyextensions/extensioncommon/basic_extension_adapter.go b/envoyextensions/extensioncommon/basic_extension_adapter.go index 39e1e8c8363bf..fbf73f34c2983 100644 --- a/envoyextensions/extensioncommon/basic_extension_adapter.go +++ b/envoyextensions/extensioncommon/basic_extension_adapter.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package extensioncommon diff --git a/envoyextensions/extensioncommon/envoy_extender.go b/envoyextensions/extensioncommon/envoy_extender.go index 269f01acd6de4..0c8f9141c9258 100644 --- a/envoyextensions/extensioncommon/envoy_extender.go +++ b/envoyextensions/extensioncommon/envoy_extender.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package extensioncommon @@ -21,7 +21,7 @@ type EnvoyExtender interface { // Extend updates indexed xDS structures to include patches for // built-in extensions. It is responsible for applying extensions to - // the appropriate xDS resources. If any portion of this function fails, + // the the appropriate xDS resources. If any portion of this function fails, // it will attempt continue and return an error. The caller can then determine // if it is better to use a partially applied extension or error out. Extend(*xdscommon.IndexedResources, *RuntimeConfig) (*xdscommon.IndexedResources, error) diff --git a/envoyextensions/extensioncommon/envoy_extender_test.go b/envoyextensions/extensioncommon/envoy_extender_test.go index 9fe6b49aeb33b..48e338ed896f3 100644 --- a/envoyextensions/extensioncommon/envoy_extender_test.go +++ b/envoyextensions/extensioncommon/envoy_extender_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package extensioncommon import ( diff --git a/envoyextensions/extensioncommon/resources.go b/envoyextensions/extensioncommon/resources.go index c5febfb6dd30a..22c6c3ffa9ee1 100644 --- a/envoyextensions/extensioncommon/resources.go +++ b/envoyextensions/extensioncommon/resources.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package extensioncommon @@ -411,8 +411,8 @@ func getSNI(chain *envoy_listener_v3.FilterChain) string { } // GetHTTPConnectionManager returns the Envoy HttpConnectionManager filter from the list of network filters. -// It also returns the index within the list of filters where the connection manager was found in case the -// caller needs to overwrite the original filter. +// It also returns the index within the list of filters where the connection manager was found in case the caller +// needs this information. // It returns a non-nil error if the HttpConnectionManager is not found. func GetHTTPConnectionManager(filters ...*envoy_listener_v3.Filter) (*envoy_http_v3.HttpConnectionManager, int, error) { for idx, filter := range filters { @@ -491,11 +491,9 @@ func InsertHTTPFilter(filters []*envoy_listener_v3.Filter, filter *envoy_http_v3 if err != nil { return filters, errors.New("failed to insert new HTTP connection manager filter") } - filtersCopy := make([]*envoy_listener_v3.Filter, len(filters)) - copy(filtersCopy, filters) - filtersCopy[idx] = newHttpConMan + filters[idx] = newHttpConMan - return filtersCopy, nil + return filters, nil } // InsertNetworkFilter inserts the given network filter into the filter chain in the location diff --git a/envoyextensions/extensioncommon/resources_test.go b/envoyextensions/extensioncommon/resources_test.go index 477e66494ce5f..659da8770ea65 100644 --- a/envoyextensions/extensioncommon/resources_test.go +++ b/envoyextensions/extensioncommon/resources_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package extensioncommon diff --git a/envoyextensions/extensioncommon/runtime_config.go b/envoyextensions/extensioncommon/runtime_config.go index 2a5e7d60077be..a20e4ed04e646 100644 --- a/envoyextensions/extensioncommon/runtime_config.go +++ b/envoyextensions/extensioncommon/runtime_config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package extensioncommon diff --git a/envoyextensions/extensioncommon/runtime_config_test.go b/envoyextensions/extensioncommon/runtime_config_test.go index 8c4c9bed6eb69..fa2ac8df5f421 100644 --- a/envoyextensions/extensioncommon/runtime_config_test.go +++ b/envoyextensions/extensioncommon/runtime_config_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package extensioncommon diff --git a/envoyextensions/extensioncommon/upstream_envoy_extender.go b/envoyextensions/extensioncommon/upstream_envoy_extender.go index 35cebe2fa5301..135aca3f82e74 100644 --- a/envoyextensions/extensioncommon/upstream_envoy_extender.go +++ b/envoyextensions/extensioncommon/upstream_envoy_extender.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package extensioncommon diff --git a/envoyextensions/go.mod b/envoyextensions/go.mod index 5d90d18653adb..ff839c348d35d 100644 --- a/envoyextensions/go.mod +++ b/envoyextensions/go.mod @@ -2,10 +2,7 @@ module github.com/hashicorp/consul/envoyextensions go 1.20 -replace ( - github.com/hashicorp/consul/api => ../api - github.com/hashicorp/consul/sdk => ../sdk -) +replace github.com/hashicorp/consul/api => ../api require ( github.com/envoyproxy/go-control-plane v0.11.0 diff --git a/envoyextensions/go.sum b/envoyextensions/go.sum index 77c098c2c2bf5..801e497f9c47d 100644 --- a/envoyextensions/go.sum +++ b/envoyextensions/go.sum @@ -62,6 +62,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/hashicorp/consul/sdk v0.14.1 h1:ZiwE2bKb+zro68sWzZ1SgHF3kRMBZ94TwOCFRF4ylPs= +github.com/hashicorp/consul/sdk v0.14.1/go.mod h1:vFt03juSzocLRFo59NkeQHHmQa6+g7oU0pfzdI1mUhg= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= diff --git a/envoyextensions/xdscommon/envoy_versioning.go b/envoyextensions/xdscommon/envoy_versioning.go index c5f9d4798c105..393a96bf9e809 100644 --- a/envoyextensions/xdscommon/envoy_versioning.go +++ b/envoyextensions/xdscommon/envoy_versioning.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xdscommon diff --git a/envoyextensions/xdscommon/envoy_versioning_test.go b/envoyextensions/xdscommon/envoy_versioning_test.go index bc02e9c4aadc7..74d26aac1bf23 100644 --- a/envoyextensions/xdscommon/envoy_versioning_test.go +++ b/envoyextensions/xdscommon/envoy_versioning_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xdscommon @@ -151,10 +151,10 @@ func TestDetermineSupportedProxyFeaturesFromString(t *testing.T) { } */ for _, v := range []string{ + "1.23.0", "1.23.1", "1.23.2", "1.23.3", "1.23.4", "1.23.5", "1.23.6", "1.23.7", "1.23.8", "1.23.9", "1.23.10", "1.23.11", "1.23.12", "1.24.0", "1.24.1", "1.24.2", "1.24.3", "1.24.4", "1.24.5", "1.24.6", "1.24.7", "1.24.8", "1.24.9", "1.24.10", "1.25.0", "1.25.1", "1.25.2", "1.25.3", "1.25.4", "1.25.5", "1.25.6", "1.25.7", "1.25.8", "1.25.9", "1.26.0", "1.26.1", "1.26.2", "1.26.3", "1.26.4", - "1.27.0", } { cases[v] = testcase{expect: SupportedProxyFeatures{}} } diff --git a/envoyextensions/xdscommon/proxysupport.go b/envoyextensions/xdscommon/proxysupport.go index 764d967616f6d..6645405571ed2 100644 --- a/envoyextensions/xdscommon/proxysupport.go +++ b/envoyextensions/xdscommon/proxysupport.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xdscommon @@ -12,10 +12,10 @@ import "strings" // // see: https://www.consul.io/docs/connect/proxies/envoy#supported-versions var EnvoyVersions = []string{ - "1.27.0", "1.26.4", "1.25.9", "1.24.10", + "1.23.12", } // UnsupportedEnvoyVersions lists any unsupported Envoy versions (mainly minor versions) that fall diff --git a/envoyextensions/xdscommon/proxysupport_test.go b/envoyextensions/xdscommon/proxysupport_test.go index cc90b726c9d94..042ab5ad874e9 100644 --- a/envoyextensions/xdscommon/proxysupport_test.go +++ b/envoyextensions/xdscommon/proxysupport_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xdscommon diff --git a/envoyextensions/xdscommon/xdscommon.go b/envoyextensions/xdscommon/xdscommon.go index efc2c5a87dd57..30c82de9ae561 100644 --- a/envoyextensions/xdscommon/xdscommon.go +++ b/envoyextensions/xdscommon/xdscommon.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package xdscommon diff --git a/envoyextensions/xdscommon/xdscommon_test.go b/envoyextensions/xdscommon/xdscommon_test.go index 2d1aec40b54f7..5cca6e13a6192 100644 --- a/envoyextensions/xdscommon/xdscommon_test.go +++ b/envoyextensions/xdscommon/xdscommon_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package xdscommon import ( diff --git a/fixup_acl_move.sh b/fixup_acl_move.sh index ac57c8c7e9334..2dbc9c6aefe77 100644 --- a/fixup_acl_move.sh +++ b/fixup_acl_move.sh @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 GOIMPORTS=~/go/bin/goimports diff --git a/go.mod b/go.mod index 2747f4b91b5e5..db5c7052cc8b4 100644 --- a/go.mod +++ b/go.mod @@ -61,9 +61,8 @@ require ( github.com/hashicorp/go-version v1.2.1 github.com/hashicorp/golang-lru v0.5.4 github.com/hashicorp/hcl v1.0.0 - github.com/hashicorp/hcl/v2 v2.6.0 github.com/hashicorp/hcp-scada-provider v0.2.3 - github.com/hashicorp/hcp-sdk-go v0.61.0 + github.com/hashicorp/hcp-sdk-go v0.55.0 github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038 github.com/hashicorp/memberlist v0.5.0 github.com/hashicorp/raft v1.5.0 @@ -87,7 +86,6 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/mitchellh/pointerstructure v1.2.1 github.com/mitchellh/reflectwalk v1.0.2 - github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce github.com/oklog/ulid/v2 v2.1.0 github.com/olekukonko/tablewriter v0.0.4 github.com/patrickmn/go-cache v2.1.0+incompatible @@ -97,7 +95,6 @@ require ( github.com/ryanuber/columnize v2.1.2+incompatible github.com/shirou/gopsutil/v3 v3.22.8 github.com/stretchr/testify v1.8.3 - github.com/zclconf/go-cty v1.2.0 go.etcd.io/bbolt v1.3.7 go.opentelemetry.io/otel v1.16.0 go.opentelemetry.io/otel/metric v1.16.0 @@ -120,7 +117,6 @@ require ( k8s.io/api v0.26.2 k8s.io/apimachinery v0.26.2 k8s.io/client-go v0.26.2 - k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 ) require ( @@ -140,9 +136,6 @@ require ( github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/DataDog/datadog-go v4.8.2+incompatible // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/agext/levenshtein v1.2.1 // indirect - github.com/apparentlymart/go-textseg v1.0.0 // indirect - github.com/apparentlymart/go-textseg/v12 v12.0.0 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect github.com/benbjohnson/immutable v0.4.0 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -212,7 +205,6 @@ require ( github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-wordwrap v1.0.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect @@ -244,7 +236,6 @@ require ( github.com/tklauser/numcpus v0.4.0 // indirect github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 // indirect github.com/vmware/govmomi v0.18.0 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect go.mongodb.org/mongo-driver v1.11.0 // indirect go.opencensus.io v0.24.0 // indirect @@ -259,12 +250,12 @@ require ( google.golang.org/appengine v1.6.7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.66.2 // indirect - gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/resty.v1 v1.12.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/klog/v2 v2.90.1 // indirect k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect + k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect diff --git a/go.sum b/go.sum index 92213557b7159..a2c02795985c6 100644 --- a/go.sum +++ b/go.sum @@ -111,8 +111,6 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14= github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw= -github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8= -github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -120,11 +118,6 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/aliyun/alibaba-cloud-sdk-go v1.62.156 h1:K4N91T1+RlSlx+t2dujeDviy4ehSGVjEltluDgmeHS4= github.com/aliyun/alibaba-cloud-sdk-go v1.62.156/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= -github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= -github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= -github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbjdL7GzRt3F8NvfJ0= -github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= @@ -319,7 +312,6 @@ github.com/go-ozzo/ozzo-validation v3.6.0+incompatible/go.mod h1:gsEKFIVnabGBt6m github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= @@ -375,7 +367,6 @@ github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71 github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -561,12 +552,10 @@ github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+l github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/hcl/v2 v2.6.0 h1:3krZOfGY6SziUXa6H9PJU6TyohHn7I+ARYnhbeNBz+o= -github.com/hashicorp/hcl/v2 v2.6.0/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY= github.com/hashicorp/hcp-scada-provider v0.2.3 h1:AarYR+/Pcv+cMvPdAlb92uOBmZfEH6ny4+DT+4NY2VQ= github.com/hashicorp/hcp-scada-provider v0.2.3/go.mod h1:ZFTgGwkzNv99PLQjTsulzaCplCzOTBh0IUQsPKzrQFo= -github.com/hashicorp/hcp-sdk-go v0.61.0 h1:x4hJ8SlLI5WCE8Uzcu4q5jfdOEz/hFxfUkhAdoFdzSg= -github.com/hashicorp/hcp-sdk-go v0.61.0/go.mod h1:xP7wmWAmdMxs/7+ovH3jZn+MCDhHRj50Rn+m7JIY3Ck= +github.com/hashicorp/hcp-sdk-go v0.55.0 h1:T4sQtgQfQJOD0uucT4hS+GZI1FmoHAQMADj277W++xw= +github.com/hashicorp/hcp-sdk-go v0.55.0/go.mod h1:hZqky4HEzsKwvLOt4QJlZUrjeQmb4UCZUhDP2HyQFfc= github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038 h1:n9J0rwVWXDpNd5iZnwY7w4WZyq53/rROeI7OVvLW8Ok= github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -664,8 +653,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= -github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/linode/linodego v0.7.1/go.mod h1:ga11n3ivecUrPCHN0rANxKmfWBJVkOXfLMZinAbj2sY= github.com/linode/linodego v0.10.0 h1:AMdb82HVgY8o3mjBXJcUv9B+fnJjfDMn2rNRGbX+jvM= @@ -723,8 +710,6 @@ github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go. github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.14.0 h1:/x0XQ6h+3U3nAyk1yx+bHPURrKa9sVVvYbuqZ7pIAtI= github.com/mitchellh/go-testing-interface v1.14.0/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= -github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452 h1:hOY53G+kBFhbYFpRVxHl5eS7laP6B1+Cq+Z9Dry1iMU= github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= @@ -754,8 +739,6 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce h1:TqjP/BTDrwN7zP9xyXVuLsMBXYMt6LLYi55PlrIcq8U= -github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:ifHPsLndGGzvgzcaXUvzmt6LxKT4pJ+uzEhtnMt+f7A= github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2 h1:BQ1HW7hr4IVovMwWg0E0PYcyW8CzqDcVmaew9cujU4s= github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -862,7 +845,6 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUt github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil/v3 v3.22.8 h1:a4s3hXogo5mE2PfdfJIonDbstO/P+9JszdfhAHSzD9Y= github.com/shirou/gopsutil/v3 v3.22.8/go.mod h1:s648gW4IywYzUfE/KjXxUsqrqx/T2xO5VqOXxONeRfI= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= @@ -887,7 +869,6 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -929,7 +910,6 @@ github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVK github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmware/govmomi v0.18.0 h1:f7QxSmP7meCtoAmiKZogvVbLInT+CZx6Px6K5rYsJZo= github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -937,8 +917,6 @@ github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+ github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= @@ -950,8 +928,6 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zclconf/go-cty v1.2.0 h1:sPHsy7ADcIZQP3vILvTjrh74ZA175TFP5vqiNK1UmlI= -github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= @@ -996,7 +972,6 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1058,7 +1033,6 @@ golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1161,7 +1135,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1485,8 +1458,6 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc= gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= diff --git a/grafana/README.md b/grafana/README.md index 2e8b2b588b75d..b3dec68183a9d 100644 --- a/grafana/README.md +++ b/grafana/README.md @@ -9,7 +9,3 @@ The page for publishing this dashboard is https://grafana.com/grafana/dashboards - Click "share" and export for external publishing - Login to Grafana via the team account (message a manager) - Publish as a new version, including change notes. - -### Grafana dashboard for consul-k8s (control plane) - -A grafana dashboard for monitoring consul-k8s (control plane) can also be found in this directory: `consul-k8s-control-plane-monitoring.json`. This dashboard has not been published to https://grafana.com. diff --git a/grafana/consul-k8s-control-plane-monitoring.json b/grafana/consul-k8s-control-plane-monitoring.json deleted file mode 100644 index e84fe8c6b9637..0000000000000 --- a/grafana/consul-k8s-control-plane-monitoring.json +++ /dev/null @@ -1,3467 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 1, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 16, - "panels": [], - "title": "Cluster Status", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 6, - "x": 0, - "y": 1 - }, - "id": 10, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "last" - ], - "fields": "", - "limit": 1, - "values": true - }, - "textMode": "auto" - }, - "pluginVersion": "9.5.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "exemplar": false, - "expr": "consul_consul_server_0_members_servers{pod=\"consul-server-0\"}", - "hide": false, - "instant": true, - "legendFormat": "__auto", - "range": false, - "refId": "A" - } - ], - "title": "Number of Consul Servers", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "No data in agentless mode", - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 6, - "y": 1 - }, - "id": 29, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "last" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.5.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "exemplar": false, - "expr": "count(kube_pod_container_resource_limits{pod=~\"consul-client-.*\", container=\"consul\", resource=\"memory\"})", - "hide": false, - "instant": true, - "legendFormat": "__auto", - "range": false, - "refId": "A" - } - ], - "title": "Number of Consul Clients (No data in agentless mode)", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "Must be 1", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 10, - "x": 14, - "y": 1 - }, - "id": 12, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "exemplar": false, - "expr": "sum({__name__=~\".+server_isLeader\"})", - "instant": false, - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Number of Leader (1: Healthy)", - "type": "timeseries" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 9 - }, - "id": 40, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 10 - }, - "id": 22, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "builder", - "expr": "consul_raft_leader_lastContact{quantile=\"0.5\"}", - "legendFormat": "__auto", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "consul_raft_leader_lastContact{quantile=\"0.99\"}", - "hide": false, - "legendFormat": "__auto", - "range": true, - "refId": "B" - } - ], - "title": "Raft Leader LastContact 99th and 50th (ms)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "Use consul.raft.rpc.appendEntries to understand how long it takes a follower node to process newly received Raft logs from the leader. Like consul.raft.commitTime, increases in this metric can indicate higher load on your Consul servers, and come with a risk of stale data. Since this metric is exposed within each follower, you should aggregate it as both an average (to track overall load on your Raft servers) and a percentile (to watch for outlier nodes).", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 10 - }, - "id": 18, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "consul_raft_rpc_appendEntries{quantile=\"0.99\"}", - "legendFormat": "__auto", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "consul_raft_rpc_appendEntries{quantile=\"0.5\"}", - "hide": false, - "legendFormat": "__auto", - "range": true, - "refId": "B" - } - ], - "title": "Follower Append Entries Latency 99th and 50th (ms)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 18 - }, - "id": 20, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "consul_raft_commitTime{quantile=\"0.99\"}", - "legendFormat": "__auto", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "consul_raft_commitTime{quantile=\"0.5\"}", - "hide": false, - "legendFormat": "__auto", - "range": true, - "refId": "B" - } - ], - "title": "Leader Raft Commit Latency 99th and 50th (ms)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 18 - }, - "id": 46, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(consul_raft_fsm_apply_sum[5m])\n/\nrate(consul_raft_fsm_apply_count[5m])", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Average Raft FSM Apply Latency per 5 minutes (ms)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 26 - }, - "id": 47, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "sum(rate(consul_raft_apply[5m]))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Raft Apply Rate per 5 minutes", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "An approximate measurement of the proportion of time the main Raft goroutine is busy and unavailable to accept new work.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 26 - }, - "id": 41, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "builder", - "expr": "consul_raft_thread_main_saturation{pod=~\"consul-server-.*\",quantile=\"0.9\"}", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Raft thread main saturation (percentage)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "An approximate measurement of the proportion of time the FSM Raft goroutine is busy and unavailable to accept new work.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 34 - }, - "id": 42, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "builder", - "expr": "consul_raft_thread_fsm_saturation{pod=~\"consul-server-.*\", quantile=\"0.9\"}", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Raft thread FSM saturation (percentage)", - "type": "timeseries" - } - ], - "title": "Raft", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 43, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "Measures the time spent updating the raft store from the serf member information.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 44, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(consul_leader_reconcile_sum{pod=~\"consul-server-.*\"}[5m])\n/ \nrate(consul_leader_reconcile_count{pod=~\"consul-server-.*\"}[5m])", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Average latency of leader reconcile per 5 minutes (ms)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "Increments whenever a Consul server becomes a leader.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 45, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "sum(consul_raft_state_leader{pod=~\"consul-server-.*\"})", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Count of a new leader elected [so far] (increasing only)", - "type": "timeseries" - } - ], - "title": "Leadership Changes", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 11 - }, - "id": 14, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 15, - "x": 0, - "y": 12 - }, - "id": 6, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "builder", - "expr": "rate(container_cpu_usage_seconds_total{container=\"consul\", pod=~\"consul-server-.*\"}[5m])", - "hide": false, - "legendFormat": "__auto", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "builder", - "expr": "kube_pod_container_resource_limits{resource=\"cpu\", container=\"consul\"}", - "hide": true, - "legendFormat": "__auto", - "range": true, - "refId": "B" - } - ], - "title": "CPU Usage in Seconds (Consul servers)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "All consul servers have the same limit", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 9, - "x": 15, - "y": 12 - }, - "id": 4, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "9.5.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "builder", - "exemplar": false, - "expr": "kube_pod_container_resource_limits{resource=\"cpu\", pod=\"consul-server-0\"}", - "instant": true, - "legendFormat": "__auto", - "range": false, - "refId": "A" - } - ], - "title": "CPU Limit in Seconds (Consul Servers)", - "type": "gauge" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 15, - "x": 0, - "y": 20 - }, - "id": 2, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "builder", - "expr": "container_memory_working_set_bytes{container=\"consul\", pod=~\"consul-server-.*\"}", - "hide": false, - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Memory Usage (Consul servers)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "All consul servers have the same limit", - "fieldConfig": { - "defaults": { - "color": { - "mode": "continuous-BlYlRd" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 9, - "x": 15, - "y": 20 - }, - "id": 8, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "9.5.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "exemplar": false, - "expr": "kube_pod_container_resource_limits{resource=\"memory\", pod=\"consul-server-0\"}", - "instant": true, - "legendFormat": "__auto", - "range": false, - "refId": "A" - } - ], - "title": "Memory Limit (Consul Servers)", - "type": "gauge" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 15, - "x": 0, - "y": 28 - }, - "id": 48, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "sum(rate(container_network_receive_bytes_total{pod=~\"consul-server-.*\"}[5m])) by (pod)", - "hide": false, - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Received bytes total per 5 minutes (Consul servers)", - "type": "timeseries" - } - ], - "title": "Resource Utilization (Consul Servers)", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 12 - }, - "id": 24, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 15, - "x": 0, - "y": 13 - }, - "id": 26, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(container_cpu_usage_seconds_total{container=\"consul\", pod=~\"consul-client-.*\"}[5m])", - "hide": false, - "legendFormat": "__auto", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "builder", - "expr": "kube_pod_container_resource_limits{resource=\"cpu\", container=\"consul\"}", - "hide": true, - "legendFormat": "__auto", - "range": true, - "refId": "B" - } - ], - "title": "CPU Usage in Seconds (Consul Clients)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "All consul clients have the same limit", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 9, - "x": 15, - "y": 13 - }, - "id": 28, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "9.5.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "exemplar": false, - "expr": "max(kube_pod_container_resource_limits{resource=\"cpu\", pod=~\"consul-client-.*\"})", - "instant": true, - "legendFormat": "__auto", - "range": false, - "refId": "A" - } - ], - "title": "CPU Limit in Seconds (Consul Clients)", - "type": "gauge" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 15, - "x": 0, - "y": 21 - }, - "id": 23, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{container=\"consul\", pod=~\"consul-client-.*\"}", - "hide": false, - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Memory Usage (Consul clients)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "All consul servers have the same limit", - "fieldConfig": { - "defaults": { - "color": { - "mode": "continuous-BlYlRd" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 9, - "x": 15, - "y": 21 - }, - "id": 25, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "9.5.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "exemplar": false, - "expr": "max(kube_pod_container_resource_limits{resource=\"memory\", pod=~\"consul-client-.*\"})", - "instant": true, - "legendFormat": "__auto", - "range": false, - "refId": "A" - } - ], - "title": "Memory Limit (Consul Clients)", - "type": "gauge" - } - ], - "title": "Resource Utilization (Consul Clients) - N/A in agentless mode", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 13 - }, - "id": 54, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 15, - "x": 0, - "y": 17 - }, - "id": 55, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(container_cpu_usage_seconds_total{pod=~\".*-connect-injector-.*\",container=\"sidecar-injector\"}[5m])", - "hide": false, - "legendFormat": "__auto", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "builder", - "expr": "kube_pod_container_resource_limits{resource=\"cpu\", container=\"consul\"}", - "hide": true, - "legendFormat": "__auto", - "range": true, - "refId": "B" - } - ], - "title": "CPU Usage in Seconds (Connect Injector)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "All consul servers have the same limit", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 9, - "x": 15, - "y": 17 - }, - "id": 56, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "9.5.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "exemplar": false, - "expr": "max(kube_pod_container_resource_limits{resource=\"cpu\", container=\"sidecar-injector\"})", - "instant": true, - "legendFormat": "__auto", - "range": false, - "refId": "A" - } - ], - "title": "CPU Limit in Seconds (Connect Injector)", - "type": "gauge" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 15, - "x": 0, - "y": 25 - }, - "id": 59, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{pod=~\".*-connect-injector-.*\",container=\"sidecar-injector\"}", - "hide": false, - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Memory Usage (Connect Injector)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "All consul servers have the same limit", - "fieldConfig": { - "defaults": { - "color": { - "mode": "continuous-BlYlRd" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 9, - "x": 15, - "y": 25 - }, - "id": 58, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "9.5.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "exemplar": false, - "expr": "max(kube_pod_container_resource_limits{resource=\"memory\", container=\"sidecar-injector\"})", - "instant": true, - "legendFormat": "__auto", - "range": false, - "refId": "A" - } - ], - "title": "Memory Limit (Connect Injector)", - "type": "gauge" - } - ], - "title": "Resource Utilization (Connect Injector)", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 30, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 15 - }, - "id": 31, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "sum(rate(consul_catalog_register_count{pod=~\"consul-server-.*\"}[5m]))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Catalog Register Count per 5 minutes", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 15 - }, - "id": 34, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(consul_catalog_register_sum{pod=~\"consul-server-.*\"}[5m])\n/\nrate(consul_catalog_register_count{pod=~\"consul-server-.*\"}[5m])", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Average latency of catalog register per 5 minutes (ms)", - "type": "timeseries" - } - ], - "title": "Feature: Catalog", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 15 - }, - "id": 49, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 16 - }, - "id": 50, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "sum(rate(consul_acl_ResolveToken_count{pod=~\"consul-server-.*\"}[5m]))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "ACL Token Resolve Count per 5 minutes", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 16 - }, - "id": 51, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(consul_acl_ResolveToken_sum{pod=~\"consul-server-.*\"}[5m])/rate(consul_acl_ResolveToken_count{pod=~\"consul-server-.*\"}[5m])", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Average latency of resolving ACL token per 5 minutes (ms)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 24 - }, - "id": 52, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(consul_acl_token_cache_hit{pod=~\"consul-server-.*\"}[5m])", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Rate of ACL token cache hit per 5 minutes", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 24 - }, - "id": 53, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(consul_acl_token_cache_miss{pod=~\"consul-server-.*\"}[5m])", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Rate of ACL token cache miss per 5 minutes", - "type": "timeseries" - } - ], - "title": "ACL", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 16 - }, - "id": 33, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "Increments whenever a Consul agent in client mode makes an RPC request to a Consul server", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 14 - }, - "id": 37, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(consul_client_rpc{namespace=\"consul\"}[5m])", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Rate of RPC requests per 5 minutes - client side ", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "Increments when a server accepts an RPC connection.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 14 - }, - "id": 36, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(consul_rpc_accept_conn{namespace=\"consul\",pod=~\"consul-server-.*\"}[5m])", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "RPC Accept Connection Count Rate per 5 minutes - server side", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "Increments whenever a Consul agent in client mode makes an RPC request to a Consul server and fails.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 22 - }, - "id": 39, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(consul_client_rpc_failed{namespace=\"consul\"}[5m])", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Rate of Failed RPC requests per 5 minutes - client side ", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "Increments when a server receives a Consul-related RPC request.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 22 - }, - "id": 32, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(consul_rpc_request{namespace=\"consul\",pod=~\"consul-server-.*\"}[5m])", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Rate of RPC requests per 5 minutes - server side", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "Increments whenever a Consul agent in client mode makes an RPC request to a Consul server gets rate limited by that agent's limits configuration.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 30 - }, - "id": 38, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(consul_client_rpc_exceeded{namespace=\"consul\"}[5m])", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Rate of Exceeded RPC requests per 5 minutes - client side ", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "description": "Increments when a server returns an error from an RPC request.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 30 - }, - "id": 35, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "editorMode": "code", - "expr": "rate(consul_rpc_request_error{namespace=\"consul\",pod=~\"consul-server-.*\"}[5m])", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Error rate of RPC requests per 5 minutes - server side", - "type": "timeseries" - } - ], - "title": "RPC", - "type": "row" - } - ], - "refresh": "30s", - "revision": 1, - "schemaVersion": 38, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-30m", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Consul K8s monitoring (control plane)", - "version": 2, - "weekStart": "" -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/run_test.go b/internal/catalog/catalogtest/run_test.go index 7e4d56aa90af1..7c17052d8246d 100644 --- a/internal/catalog/catalogtest/run_test.go +++ b/internal/catalog/catalogtest/run_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package catalogtest import ( @@ -40,8 +37,3 @@ func TestControllers_Integration(t *testing.T) { client := runInMemResourceServiceAndControllers(t, catalog.DefaultControllerDependencies()) RunCatalogV1Alpha1IntegrationTest(t, client) } - -func TestControllers_Lifecycle(t *testing.T) { - client := runInMemResourceServiceAndControllers(t, catalog.DefaultControllerDependencies()) - RunCatalogV1Alpha1LifecycleIntegrationTest(t, client) -} diff --git a/internal/catalog/catalogtest/test_integration_v1alpha1.go b/internal/catalog/catalogtest/test_integration_v1alpha1.go index e034502c4503d..8a7f4cd9a2488 100644 --- a/internal/catalog/catalogtest/test_integration_v1alpha1.go +++ b/internal/catalog/catalogtest/test_integration_v1alpha1.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package catalogtest import ( @@ -701,7 +698,6 @@ func expectedGRPCApiServiceEndpoints(t *testing.T, c *rtest.Client) *pbcatalog.S } func verifyServiceEndpoints(t *testing.T, c *rtest.Client, id *pbresource.ID, expected *pbcatalog.ServiceEndpoints) { - t.Helper() c.WaitForResourceState(t, id, func(t rtest.T, res *pbresource.Resource) { var actual pbcatalog.ServiceEndpoints err := res.Data.UnmarshalTo(&actual) diff --git a/internal/catalog/catalogtest/test_lifecycle_v1alpha1.go b/internal/catalog/catalogtest/test_lifecycle_v1alpha1.go deleted file mode 100644 index 55e9d2bbe28fc..0000000000000 --- a/internal/catalog/catalogtest/test_lifecycle_v1alpha1.go +++ /dev/null @@ -1,709 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package catalogtest - -import ( - "testing" - - "github.com/hashicorp/consul/internal/catalog" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" -) - -// RunCatalogV1Alpha1LifecycleIntegrationTest intends to excercise functionality of -// managing catalog resources over their normal lifecycle where they will be modified -// several times, change state etc. -func RunCatalogV1Alpha1LifecycleIntegrationTest(t *testing.T, client pbresource.ResourceServiceClient) { - t.Helper() - - testutil.RunStep(t, "node-lifecycle", func(t *testing.T) { - RunCatalogV1Alpha1NodeLifecycleIntegrationTest(t, client) - }) - - testutil.RunStep(t, "workload-lifecycle", func(t *testing.T) { - RunCatalogV1Alpha1WorkloadLifecycleIntegrationTest(t, client) - }) - - testutil.RunStep(t, "endpoints-lifecycle", func(t *testing.T) { - RunCatalogV1Alpha1EndpointsLifecycleIntegrationTest(t, client) - }) -} - -// RunCatalogV1Alpha1NodeLifecycleIntegrationTest verifies correct functionality of -// the node-health controller. This test will exercise the following behaviors: -// -// * Creating a Node without associated HealthStatuses will mark the node as passing -// * Associating a HealthStatus with a Node will cause recomputation of the Health -// * Changing HealthStatus to a worse health will cause recomputation of the Health -// * Changing HealthStatus to a better health will cause recomputation of the Health -// * Deletion of associated HealthStatuses will recompute the Health (back to passing) -// * Deletion of the node will cause deletion of associated health statuses -func RunCatalogV1Alpha1NodeLifecycleIntegrationTest(t *testing.T, client pbresource.ResourceServiceClient) { - c := rtest.NewClient(client) - - nodeName := "test-lifecycle" - nodeHealthName := "test-lifecycle-node-status" - - // initial node creation - node := rtest.Resource(catalog.NodeV1Alpha1Type, nodeName). - WithData(t, &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{ - {Host: "172.16.2.3"}, - {Host: "198.18.2.3", External: true}, - }, - }). - Write(t, c) - - // wait for the node health controller to mark the node as healthy - c.WaitForStatusCondition(t, node.Id, - catalog.NodeHealthStatusKey, - catalog.NodeHealthConditions[pbcatalog.Health_HEALTH_PASSING]) - - // Its easy enough to simply repeatedly set the health status and it proves - // that going both from better to worse health and worse to better all - // happen as expected. We leave the health in a warning state to allow for - // the subsequent health status deletion to cause the health to go back - // to passing. - healthChanges := []pbcatalog.Health{ - pbcatalog.Health_HEALTH_PASSING, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_MAINTENANCE, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_PASSING, - pbcatalog.Health_HEALTH_WARNING, - } - - // This will be set within the loop and used afterwards to delete the health status - var nodeHealth *pbresource.Resource - - // Iterate through the various desired health statuses, updating - // a HealthStatus resource owned by the node and waiting for - // reconciliation at each point - for _, health := range healthChanges { - // update the health check - nodeHealth = setHealthStatus(t, c, node.Id, nodeHealthName, health) - - // wait for reconciliation to kick in and put the node into the right - // health status. - c.WaitForStatusCondition(t, node.Id, - catalog.NodeHealthStatusKey, - catalog.NodeHealthConditions[health]) - } - - // now delete the health status and ensure things go back to passing - c.MustDelete(t, nodeHealth.Id) - - // wait for the node health controller to mark the node as healthy - c.WaitForStatusCondition(t, node.Id, - catalog.NodeHealthStatusKey, - catalog.NodeHealthConditions[pbcatalog.Health_HEALTH_PASSING]) - - // Add the health status back once more, the actual status doesn't matter. - // It just must be owned by the node so that we can show cascading - // deletions of owned health statuses working. - healthStatus := setHealthStatus(t, c, node.Id, nodeHealthName, pbcatalog.Health_HEALTH_CRITICAL) - - // Delete the node and wait for the health status to be deleted. - c.MustDelete(t, node.Id) - c.WaitForDeletion(t, healthStatus.Id) -} - -// RunCatalogV1Alpha1WorkloadLifecycleIntegrationTest verifies correct functionality of -// the workload-health controller. This test will exercise the following behaviors: -// -// - Associating a workload with a node causes recomputation of the health and takes -// into account the nodes health -// - Modifying the workloads associated node causes health recomputation and takes into -// account the new nodes health -// - Removal of the node association causes recomputation of health and for no node health -// to be taken into account. -// - Creating a workload without associated health statuses or node association will -// be marked passing -// - Creating a workload without associated health statuses but with a node will -// inherit its health from the node. -// - Changing HealthStatus to a worse health will cause recompuation of the Health -// - Changing HealthStatus to a better health will cause recompuation of the Health -// - Overall health is computed as the worst health amongst the nodes health and all -// of the workloads associated HealthStatuses -// - Deletion of the workload will cause deletion of all associated health statuses. -func RunCatalogV1Alpha1WorkloadLifecycleIntegrationTest(t *testing.T, client pbresource.ResourceServiceClient) { - c := rtest.NewClient(client) - testutil.RunStep(t, "nodeless-workload", func(t *testing.T) { - runV1Alpha1NodelessWorkloadLifecycleIntegrationTest(t, c) - }) - - testutil.RunStep(t, "node-associated-workload", func(t *testing.T) { - runV1Alpha1NodeAssociatedWorkloadLifecycleIntegrationTest(t, c) - }) -} - -// runV1Alpha1NodelessWorkloadLifecycleIntegrationTest verifies correct functionality of -// the workload-health controller for workloads without node associations. In particular -// the following behaviors are being tested -// -// - Creating a workload without associated health statuses or node association will -// be marked passing -// - Changing HealthStatus to a worse health will cause recompuation of the Health -// - Changing HealthStatus to a better health will cause recompuation of the Health -// - Deletion of associated HealthStatus for a nodeless workload will be set back to passing -// - Deletion of the workload will cause deletion of all associated health statuses. -func runV1Alpha1NodelessWorkloadLifecycleIntegrationTest(t *testing.T, c *rtest.Client) { - workloadName := "test-lifecycle-workload" - workloadHealthName := "test-lifecycle-workload-status" - - // create a workload without a node association or health statuses yet - workload := rtest.Resource(catalog.WorkloadV1Alpha1Type, workloadName). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "198.18.9.8"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Identity: "test-lifecycle", - }). - Write(t, c) - - // wait for the workload health controller to mark the workload as healthy - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadHealthConditions[pbcatalog.Health_HEALTH_PASSING]) - - // We may not need to iterate through all of these states but its easy - // enough and quick enough to do so. The general rationale is that we - // should move through changing the workloads associated health status - // in this progression. We can prove that moving from better to worse - // health or worse to better both function correctly. - healthChanges := []pbcatalog.Health{ - pbcatalog.Health_HEALTH_PASSING, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_MAINTENANCE, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_PASSING, - pbcatalog.Health_HEALTH_WARNING, - } - - var workloadHealth *pbresource.Resource - // Iterate through the various desired health statuses, updating - // a HealthStatus resource owned by the workload and waiting for - // reconciliation at each point - for _, health := range healthChanges { - // update the health status - workloadHealth = setHealthStatus(t, c, workload.Id, workloadHealthName, health) - - // wait for reconciliation to kick in and put the workload into - // the right health status. - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadHealthConditions[health]) - } - - // Now delete the health status, things should go back to passing status - c.MustDelete(t, workloadHealth.Id) - - // ensure the workloads health went back to passing - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadHealthConditions[pbcatalog.Health_HEALTH_PASSING]) - - // Reset the workload health. The actual health is irrelevant, we just want it - // to exist to provde that Health Statuses get deleted along with the workload - // when its deleted. - workloadHealth = setHealthStatus(t, c, workload.Id, workloadHealthName, pbcatalog.Health_HEALTH_WARNING) - - // Delete the workload and wait for the HealthStatus to also be deleted - c.MustDelete(t, workload.Id) - c.WaitForDeletion(t, workloadHealth.Id) -} - -// runV1Alpha1NodeAssociatedWorkloadLifecycleIntegrationTest verifies correct functionality of -// the workload-health controller. This test will exercise the following behaviors: -// -// - Associating a workload with a node causes recomputation of the health and takes -// into account the nodes health -// - Modifying the workloads associated node causes health recomputation and takes into -// account the new nodes health -// - Removal of the node association causes recomputation of health and for no node health -// to be taken into account. -// - Creating a workload without associated health statuses but with a node will -// inherit its health from the node. -// - Overall health is computed as the worst health amongst the nodes health and all -// of the workloads associated HealthStatuses -func runV1Alpha1NodeAssociatedWorkloadLifecycleIntegrationTest(t *testing.T, c *rtest.Client) { - workloadName := "test-lifecycle" - workloadHealthName := "test-lifecycle" - nodeName1 := "test-lifecycle-1" - nodeName2 := "test-lifecycle-2" - nodeHealthName1 := "test-lifecycle-node-1" - nodeHealthName2 := "test-lifecycle-node-2" - - // Insert a some nodes to link the workloads to at various points throughout the test - node1 := rtest.Resource(catalog.NodeV1Alpha1Type, nodeName1). - WithData(t, &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{{Host: "172.17.9.10"}}, - }). - Write(t, c) - node2 := rtest.Resource(catalog.NodeV1Alpha1Type, nodeName2). - WithData(t, &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{{Host: "172.17.9.11"}}, - }). - Write(t, c) - - // Set some non-passing health statuses for those nodes. Using non-passing will make - // it easy to see that changing a passing workloads node association appropriately - // impacts the overall workload health. - setHealthStatus(t, c, node1.Id, nodeHealthName1, pbcatalog.Health_HEALTH_CRITICAL) - setHealthStatus(t, c, node2.Id, nodeHealthName2, pbcatalog.Health_HEALTH_WARNING) - - // Add the workload but don't immediately associate with any node. - workload := rtest.Resource(catalog.WorkloadV1Alpha1Type, workloadName). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "198.18.9.8"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Identity: "test-lifecycle", - }). - Write(t, c) - - // wait for the workload health controller to mark the workload as healthy - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadHealthConditions[pbcatalog.Health_HEALTH_PASSING]) - - // now modify the workload to associate it with node 1 (currently with CRITICAL health) - workload = rtest.ResourceID(workload.Id). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "198.18.9.8"}}, - Ports: map[string]*pbcatalog.WorkloadPort{"http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - Identity: "test-lifecycle", - // this is the only difference from the previous write - NodeName: node1.Id.Name, - }). - Write(t, c) - - // wait for the workload health controller to mark the workload as critical (due to node 1 having critical health) - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadAndNodeHealthConditions[pbcatalog.Health_HEALTH_PASSING][pbcatalog.Health_HEALTH_CRITICAL]) - - // Now reassociate the workload with node 2. This should cause recalculation of its health into the warning state - workload = rtest.ResourceID(workload.Id). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "198.18.9.8"}}, - Ports: map[string]*pbcatalog.WorkloadPort{"http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - Identity: "test-lifecycle", - // this is the only difference from the previous write - NodeName: node2.Id.Name, - }). - Write(t, c) - - // Wait for the workload health controller to mark the workload as warning (due to node 2 having warning health) - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadAndNodeHealthConditions[pbcatalog.Health_HEALTH_PASSING][pbcatalog.Health_HEALTH_WARNING]) - - // Delete the node, this should cause the health to be recalculated as critical because the node association - // is broken. - c.MustDelete(t, node2.Id) - - // Wait for the workload health controller to mark the workload as critical due to the missing node - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadAndNodeHealthConditions[pbcatalog.Health_HEALTH_PASSING][pbcatalog.Health_HEALTH_CRITICAL]) - - // Now fixup the node association to point at node 1 - workload = rtest.ResourceID(workload.Id). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "198.18.9.8"}}, - Ports: map[string]*pbcatalog.WorkloadPort{"http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - Identity: "test-lifecycle", - // this is the only difference from the previous write - NodeName: node1.Id.Name, - }). - Write(t, c) - - // Also set node 1 health down to WARNING - setHealthStatus(t, c, node1.Id, nodeHealthName1, pbcatalog.Health_HEALTH_WARNING) - - // Wait for the workload health controller to mark the workload as warning (due to node 1 having warning health now) - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadAndNodeHealthConditions[pbcatalog.Health_HEALTH_PASSING][pbcatalog.Health_HEALTH_WARNING]) - - // Now add a critical workload health check to ensure that both node and workload health are accounted for. - setHealthStatus(t, c, workload.Id, workloadHealthName, pbcatalog.Health_HEALTH_CRITICAL) - - // Wait for the workload health to be recomputed and put into the critical status. - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadAndNodeHealthConditions[pbcatalog.Health_HEALTH_CRITICAL][pbcatalog.Health_HEALTH_WARNING]) - - // Reset the workloads health to passing. We expect the overall health to go back to warning - setHealthStatus(t, c, workload.Id, workloadHealthName, pbcatalog.Health_HEALTH_PASSING) - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadAndNodeHealthConditions[pbcatalog.Health_HEALTH_PASSING][pbcatalog.Health_HEALTH_WARNING]) - - // Remove the node association and wait for the health to go back to passing - workload = rtest.ResourceID(workload.Id). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "198.18.9.8"}}, - Ports: map[string]*pbcatalog.WorkloadPort{"http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - Identity: "test-lifecycle", - }). - Write(t, c) - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadHealthConditions[pbcatalog.Health_HEALTH_PASSING]) -} - -// RunCatalogV1Alpha1EndpointsLifecycleIntegrationTest verifies the correct functionality of -// the endpoints controller. This test will exercise the following behaviors: -// -// * Services without a selector get marked with status indicating their endpoints are unmanaged -// * Services with a selector get marked with status indicating their endpoints are managed -// * Deleting a service will delete the associated endpoints (regardless of them being managed or not) -// * Moving from managed to unmanaged endpoints will delete the managed endpoints -// * Moving from unmanaged to managed endpoints will overwrite any previous endpoints. -// * A service with a selector that matches no workloads will still have the endpoints object written. -// * Adding ports to a service will recalculate the endpoints -// * Removing ports from a service will recalculate the endpoints -// * Changing the workload will recalculate the endpoints (ports, addresses, or health) -func RunCatalogV1Alpha1EndpointsLifecycleIntegrationTest(t *testing.T, client pbresource.ResourceServiceClient) { - c := rtest.NewClient(client) - serviceName := "test-lifecycle" - - // Create the service without a selector. We should not see endpoints generated but we should see the - // status updated to note endpoints are not being managed. - service := rtest.Resource(catalog.ServiceV1Alpha1Type, serviceName). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{{TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - }). - Write(t, c) - - // Wait to ensure the status is updated accordingly - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionUnmanaged) - - // Verify that no endpoints were created. - endpointsID := rtest.Resource(catalog.ServiceEndpointsV1Alpha1Type, serviceName).ID() - c.RequireResourceNotFound(t, endpointsID) - - // Add some empty endpoints (type validations enforce that they are owned by the service) - rtest.ResourceID(endpointsID). - WithData(t, &pbcatalog.ServiceEndpoints{}). - WithOwner(service.Id). - Write(t, c) - - // Now delete the service and ensure that they are cleaned up. - c.MustDelete(t, service.Id) - c.WaitForDeletion(t, endpointsID) - - // Add some workloads to eventually select by the service - - // api-1 has all ports (http, grpc and mesh). It also has a mixture of Addresses - // that select individual ports and one that selects all ports implicitly - api1 := rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-1"). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - {Host: "::1", Ports: []string{"grpc"}}, - {Host: "127.0.0.2", Ports: []string{"http"}}, - {Host: "172.17.1.1", Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - Identity: "api", - }). - Write(t, c) - - // api-2 has only grpc and mesh ports. It also has a mixture of Addresses that - // select individual ports and one that selects all ports implicitly - api2 := rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-2"). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - {Host: "::1", Ports: []string{"grpc"}}, - {Host: "172.17.1.2", Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - Identity: "api", - }). - Write(t, c) - - // api-3 has the mesh and HTTP ports. It also has a mixture of Addresses that - // select individual ports and one that selects all ports. - api3 := rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-3"). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - {Host: "172.17.1.3", Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Identity: "api", - }). - Write(t, c) - - // Now create a service with unmanaged endpoints again - service = rtest.Resource(catalog.ServiceV1Alpha1Type, serviceName). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{{TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - }). - Write(t, c) - - // Inject the endpoints resource. We want to prove that transition from unmanaged to - // managed endpoints results in overwriting of the old endpoints - rtest.ResourceID(endpointsID). - WithData(t, &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "198.18.1.1", External: true}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 443, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - }, - }). - WithOwner(service.Id). - Write(t, c) - - // Wait to ensure the status is updated accordingly - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionUnmanaged) - - // Now move the service to having managed endpoints - service = rtest.ResourceID(service.Id). - WithData(t, &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"bar"}}, - Ports: []*pbcatalog.ServicePort{{TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - }). - Write(t, c) - - // Verify that this status is updated to show this service as having managed endpoints - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionManaged) - - // Verify that the service endpoints are created. In this case they will be empty - verifyServiceEndpoints(t, c, endpointsID, &pbcatalog.ServiceEndpoints{}) - - // Rewrite the service to select the API workloads - just select the singular port for now - service = rtest.ResourceID(service.Id). - WithData(t, &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{{TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - }). - Write(t, c) - - // Wait for the status to be updated. The condition itself will remain unchanged but we are waiting for - // the generations to match to know that the endpoints would have been regenerated - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionManaged) - - // ensure that api-1 and api-3 are selected but api-2 is excluded due to not having the desired port - verifyServiceEndpoints(t, c, endpointsID, &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: api1.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"http"}}, - {Host: "127.0.0.2", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - { - TargetRef: api3.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - }, - }) - - // Rewrite the service to select the API workloads - changing from selecting the HTTP port to the gRPC port - service = rtest.ResourceID(service.Id). - WithData(t, &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{{TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}}, - }). - Write(t, c) - - // Wait for the status to be updated. The condition itself will remain unchanged but we are waiting for - // the generations to match to know that the endpoints would have been regenerated - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionManaged) - - // Check that the endpoints were generated as expected - verifyServiceEndpoints(t, c, endpointsID, &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: api1.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"grpc"}}, - {Host: "::1", Ports: []string{"grpc"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - { - TargetRef: api2.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"grpc"}}, - {Host: "::1", Ports: []string{"grpc"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - }, - }) - - // Update the service to change the ports used. This should result in the workload being removed - // from the endpoints - rtest.ResourceID(api2.Id). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - {Host: "::1", Ports: []string{"http"}}, - {Host: "172.17.1.2", Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Identity: "api", - }). - Write(t, c) - - // Verify that api-2 was removed from the service endpoints as it no longer has a grpc port - verifyServiceEndpoints(t, c, endpointsID, &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: api1.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"grpc"}}, - {Host: "::1", Ports: []string{"grpc"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - }, - }) - - // Remove the ::1 address from workload api1 which should result in recomputing endpoints - rtest.ResourceID(api1.Id). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - {Host: "172.17.1.1", Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - Identity: "api", - }). - Write(t, c) - - // Verify that api-1 had its addresses modified appropriately - verifyServiceEndpoints(t, c, endpointsID, &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: api1.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"grpc"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - }, - }) - - // Add a failing health status to the api1 workload to force recomputation of endpoints - setHealthStatus(t, c, api1.Id, "api-failed", pbcatalog.Health_HEALTH_CRITICAL) - - // Verify that api-1 within the endpoints has the expected health - verifyServiceEndpoints(t, c, endpointsID, &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: api1.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"grpc"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - }, - }, - }) - - // Move the service to being unmanaged. We should see the ServiceEndpoints being removed. - service = rtest.ResourceID(service.Id). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{{TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}}, - }). - Write(t, c) - - // Wait for the endpoints controller to inform us that the endpoints are not being managed - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionUnmanaged) - // Ensure that the managed endpoints were deleted - c.WaitForDeletion(t, endpointsID) - - // Put the service back into managed mode. - service = rtest.ResourceID(service.Id). - WithData(t, &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{{TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}}, - }). - Write(t, c) - - // Wait for the service endpoints to be regenerated - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionManaged) - c.RequireResourceExists(t, endpointsID) - - // Now delete the service and ensure that the endpoints eventually are deleted as well - c.MustDelete(t, service.Id) - c.WaitForDeletion(t, endpointsID) - -} - -func setHealthStatus(t *testing.T, client *rtest.Client, owner *pbresource.ID, name string, health pbcatalog.Health) *pbresource.Resource { - return rtest.Resource(catalog.HealthStatusV1Alpha1Type, name). - WithData(t, &pbcatalog.HealthStatus{ - Type: "synthetic", - Status: health, - }). - WithOwner(owner). - Write(t, client) -} diff --git a/internal/catalog/exports.go b/internal/catalog/exports.go index 566c2e2b6edf1..61247091be1cf 100644 --- a/internal/catalog/exports.go +++ b/internal/catalog/exports.go @@ -1,22 +1,15 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package catalog import ( "github.com/hashicorp/consul/internal/catalog/internal/controllers" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/endpoints" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/failover" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/nodehealth" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/workloadhealth" - "github.com/hashicorp/consul/internal/catalog/internal/mappers/failovermapper" "github.com/hashicorp/consul/internal/catalog/internal/mappers/nodemapper" "github.com/hashicorp/consul/internal/catalog/internal/mappers/selectiontracker" "github.com/hashicorp/consul/internal/catalog/internal/types" "github.com/hashicorp/consul/internal/controller" "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" ) var ( @@ -36,7 +29,6 @@ var ( HealthStatusKind = types.HealthStatusKind HealthChecksKind = types.HealthChecksKind DNSPolicyKind = types.DNSPolicyKind - FailoverPolicyKind = types.FailoverPolicyKind // Resource Types for the v1alpha1 version. @@ -48,43 +40,6 @@ var ( HealthStatusV1Alpha1Type = types.HealthStatusV1Alpha1Type HealthChecksV1Alpha1Type = types.HealthChecksV1Alpha1Type DNSPolicyV1Alpha1Type = types.DNSPolicyV1Alpha1Type - FailoverPolicyV1Alpha1Type = types.FailoverPolicyV1Alpha1Type - - // Resource Types for the latest version. - - WorkloadType = types.WorkloadType - ServiceType = types.ServiceType - ServiceEndpointsType = types.ServiceEndpointsType - VirtualIPsType = types.VirtualIPsType - NodeType = types.NodeType - HealthStatusType = types.HealthStatusType - HealthChecksType = types.HealthChecksType - DNSPolicyType = types.DNSPolicyType - FailoverPolicyType = types.FailoverPolicyType - - // Controller Statuses - NodeHealthStatusKey = nodehealth.StatusKey - NodeHealthStatusConditionHealthy = nodehealth.StatusConditionHealthy - NodeHealthConditions = nodehealth.Conditions - - WorkloadHealthStatusKey = workloadhealth.StatusKey - WorkloadHealthStatusConditionHealthy = workloadhealth.StatusConditionHealthy - WorkloadHealthConditions = workloadhealth.WorkloadConditions - WorkloadAndNodeHealthConditions = workloadhealth.NodeAndWorkloadConditions - - EndpointsStatusKey = endpoints.StatusKey - EndpointsStatusConditionEndpointsManaged = endpoints.StatusConditionEndpointsManaged - EndpointsStatusConditionManaged = endpoints.ConditionManaged - EndpointsStatusConditionUnmanaged = endpoints.ConditionUnmanaged - - FailoverStatusKey = failover.StatusKey - FailoverStatusConditionAccepted = failover.StatusConditionAccepted - FailoverStatusConditionAcceptedOKReason = failover.OKReason - FailoverStatusConditionAcceptedMissingServiceReason = failover.MissingServiceReason - FailoverStatusConditionAcceptedUnknownPortReason = failover.UnknownPortReason - FailoverStatusConditionAcceptedMissingDestinationServiceReason = failover.MissingDestinationServiceReason - FailoverStatusConditionAcceptedUnknownDestinationPortReason = failover.UnknownDestinationPortReason - FailoverStatusConditionAcceptedUsingMeshDestinationPortReason = failover.UsingMeshDestinationPortReason ) // RegisterTypes adds all resource types within the "catalog" API group @@ -99,7 +54,6 @@ func DefaultControllerDependencies() ControllerDependencies { return ControllerDependencies{ WorkloadHealthNodeMapper: nodemapper.New(), EndpointsWorkloadMapper: selectiontracker.New(), - FailoverMapper: failovermapper.New(), } } @@ -108,21 +62,3 @@ func DefaultControllerDependencies() ControllerDependencies { func RegisterControllers(mgr *controller.Manager, deps ControllerDependencies) { controllers.Register(mgr, deps) } - -// SimplifyFailoverPolicy fully populates the PortConfigs map and clears the -// Configs map using the provided Service. -func SimplifyFailoverPolicy(svc *pbcatalog.Service, failover *pbcatalog.FailoverPolicy) *pbcatalog.FailoverPolicy { - return types.SimplifyFailoverPolicy(svc, failover) -} - -// FailoverPolicyMapper maintains the bidirectional tracking relationship of a -// FailoverPolicy to the Services related to it. -type FailoverPolicyMapper interface { - TrackFailover(failover *resource.DecodedResource[*pbcatalog.FailoverPolicy]) - UntrackFailover(failoverID *pbresource.ID) - FailoverIDsByService(svcID *pbresource.ID) []*pbresource.ID -} - -func NewFailoverPolicyMapper() FailoverPolicyMapper { - return failovermapper.New() -} diff --git a/internal/catalog/internal/controllers/endpoints/controller.go b/internal/catalog/internal/controllers/endpoints/controller.go index af10d40d3baa9..1be2a3fd2fadc 100644 --- a/internal/catalog/internal/controllers/endpoints/controller.go +++ b/internal/catalog/internal/controllers/endpoints/controller.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package endpoints diff --git a/internal/catalog/internal/controllers/endpoints/controller_test.go b/internal/catalog/internal/controllers/endpoints/controller_test.go index 646bb288d3533..ff53509057a2c 100644 --- a/internal/catalog/internal/controllers/endpoints/controller_test.go +++ b/internal/catalog/internal/controllers/endpoints/controller_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package endpoints import ( diff --git a/internal/catalog/internal/controllers/endpoints/reconciliation_data.go b/internal/catalog/internal/controllers/endpoints/reconciliation_data.go index 0194d471b0c24..f00ac1595a217 100644 --- a/internal/catalog/internal/controllers/endpoints/reconciliation_data.go +++ b/internal/catalog/internal/controllers/endpoints/reconciliation_data.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package endpoints import ( diff --git a/internal/catalog/internal/controllers/endpoints/reconciliation_data_test.go b/internal/catalog/internal/controllers/endpoints/reconciliation_data_test.go index b16223827069d..c0c83deda98d6 100644 --- a/internal/catalog/internal/controllers/endpoints/reconciliation_data_test.go +++ b/internal/catalog/internal/controllers/endpoints/reconciliation_data_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package endpoints import ( diff --git a/internal/catalog/internal/controllers/endpoints/status.go b/internal/catalog/internal/controllers/endpoints/status.go index 75066978361ca..5388a0fda9126 100644 --- a/internal/catalog/internal/controllers/endpoints/status.go +++ b/internal/catalog/internal/controllers/endpoints/status.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package endpoints diff --git a/internal/catalog/internal/controllers/failover/controller.go b/internal/catalog/internal/controllers/failover/controller.go deleted file mode 100644 index 9accb62aa4478..0000000000000 --- a/internal/catalog/internal/controllers/failover/controller.go +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package failover - -import ( - "context" - - "github.com/hashicorp/consul/internal/catalog/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// FailoverMapper tracks the relationship between a FailoverPolicy an a Service -// it references whether due to name-alignment or from a reference in a -// FailoverDestination leg. -type FailoverMapper interface { - // TrackFailover extracts all Service references from the provided - // FailoverPolicy and indexes them so that MapService can turn Service - // events into FailoverPolicy events properly. - TrackFailover(failover *resource.DecodedResource[*pbcatalog.FailoverPolicy]) - - // UntrackFailover forgets the links inserted by TrackFailover for the - // provided FailoverPolicyID. - UntrackFailover(failoverID *pbresource.ID) - - // MapService will take a Service resource and return controller requests - // for all FailoverPolicies associated with the Service. - MapService(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) -} - -func FailoverPolicyController(mapper FailoverMapper) controller.Controller { - if mapper == nil { - panic("No FailoverMapper was provided to the FailoverPolicyController constructor") - } - return controller.ForType(types.FailoverPolicyType). - WithWatch(types.ServiceType, mapper.MapService). - WithReconciler(newFailoverPolicyReconciler(mapper)) -} - -type failoverPolicyReconciler struct { - mapper FailoverMapper -} - -func newFailoverPolicyReconciler(mapper FailoverMapper) *failoverPolicyReconciler { - return &failoverPolicyReconciler{ - mapper: mapper, - } -} - -func (r *failoverPolicyReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { - // The runtime is passed by value so replacing it here for the remainder of this - // reconciliation request processing will not affect future invocations. - rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", StatusKey) - - rt.Logger.Trace("reconciling failover policy") - - failoverPolicyID := req.ID - - failoverPolicy, err := getFailoverPolicy(ctx, rt, failoverPolicyID) - if err != nil { - rt.Logger.Error("error retrieving failover policy", "error", err) - return err - } - if failoverPolicy == nil { - r.mapper.UntrackFailover(failoverPolicyID) - - // Either the failover policy was deleted, or it doesn't exist but an - // update to a Service came through and we can ignore it. - return nil - } - - r.mapper.TrackFailover(failoverPolicy) - - // FailoverPolicy is name-aligned with the Service it controls. - serviceID := &pbresource.ID{ - Type: types.ServiceType, - Tenancy: failoverPolicyID.Tenancy, - Name: failoverPolicyID.Name, - } - - service, err := getService(ctx, rt, serviceID) - if err != nil { - rt.Logger.Error("error retrieving corresponding service", "error", err) - return err - } - destServices := make(map[resource.ReferenceKey]*resource.DecodedResource[*pbcatalog.Service]) - if service != nil { - destServices[resource.NewReferenceKey(serviceID)] = service - } - - // Denorm the ports and stuff. After this we have no empty ports. - if service != nil { - failoverPolicy.Data = types.SimplifyFailoverPolicy( - service.Data, - failoverPolicy.Data, - ) - } - - // Fetch services. - for _, dest := range failoverPolicy.Data.GetUnderlyingDestinations() { - if dest.Ref == nil || !isServiceType(dest.Ref.Type) || dest.Ref.Section != "" { - continue // invalid, not possible due to validation hook - } - - key := resource.NewReferenceKey(dest.Ref) - - if _, ok := destServices[key]; ok { - continue - } - - destID := resource.IDFromReference(dest.Ref) - - destService, err := getService(ctx, rt, destID) - if err != nil { - rt.Logger.Error("error retrieving destination service", "service", key, "error", err) - return err - } - - if destService != nil { - destServices[key] = destService - } - } - - newStatus := computeNewStatus(failoverPolicy, service, destServices) - - if resource.EqualStatus(failoverPolicy.Resource.Status[StatusKey], newStatus, false) { - rt.Logger.Trace("resource's failover policy status is unchanged", - "conditions", newStatus.Conditions) - return nil - } - - _, err = rt.Client.WriteStatus(ctx, &pbresource.WriteStatusRequest{ - Id: failoverPolicy.Resource.Id, - Key: StatusKey, - Status: newStatus, - }) - - if err != nil { - rt.Logger.Error("error encountered when attempting to update the resource's failover policy status", "error", err) - return err - } - - rt.Logger.Trace("resource's failover policy status was updated", - "conditions", newStatus.Conditions) - return nil -} - -func getFailoverPolicy(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*resource.DecodedResource[*pbcatalog.FailoverPolicy], error) { - return resource.GetDecodedResource[*pbcatalog.FailoverPolicy](ctx, rt.Client, id) -} - -func getService(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*resource.DecodedResource[*pbcatalog.Service], error) { - return resource.GetDecodedResource[*pbcatalog.Service](ctx, rt.Client, id) -} - -func computeNewStatus( - failoverPolicy *resource.DecodedResource[*pbcatalog.FailoverPolicy], - service *resource.DecodedResource[*pbcatalog.Service], - destServices map[resource.ReferenceKey]*resource.DecodedResource[*pbcatalog.Service], -) *pbresource.Status { - if service == nil { - return &pbresource.Status{ - ObservedGeneration: failoverPolicy.Resource.Generation, - Conditions: []*pbresource.Condition{ - ConditionMissingService, - }, - } - } - - allowedPortProtocols := make(map[string]pbcatalog.Protocol) - for _, port := range service.Data.Ports { - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - continue // skip - } - allowedPortProtocols[port.TargetPort] = port.Protocol - } - - var conditions []*pbresource.Condition - - if failoverPolicy.Data.Config != nil { - for _, dest := range failoverPolicy.Data.Config.Destinations { - // We know from validation that a Ref must be set, and the type it - // points to is a Service. - // - // Rather than do additional validation, just do a quick - // belt-and-suspenders check-and-skip if something looks weird. - if dest.Ref == nil || !isServiceType(dest.Ref.Type) { - continue - } - - if cond := serviceHasPort(dest, destServices); cond != nil { - conditions = append(conditions, cond) - } - } - // TODO: validate that referenced sameness groups exist - } - - for port, pc := range failoverPolicy.Data.PortConfigs { - if _, ok := allowedPortProtocols[port]; !ok { - conditions = append(conditions, ConditionUnknownPort(port)) - } - - for _, dest := range pc.Destinations { - // We know from validation that a Ref must be set, and the type it - // points to is a Service. - // - // Rather than do additional validation, just do a quick - // belt-and-suspenders check-and-skip if something looks weird. - if dest.Ref == nil || !isServiceType(dest.Ref.Type) { - continue - } - - if cond := serviceHasPort(dest, destServices); cond != nil { - conditions = append(conditions, cond) - } - } - - // TODO: validate that referenced sameness groups exist - } - - if len(conditions) > 0 { - return &pbresource.Status{ - ObservedGeneration: failoverPolicy.Resource.Generation, - Conditions: conditions, - } - } - - return &pbresource.Status{ - ObservedGeneration: failoverPolicy.Resource.Generation, - Conditions: []*pbresource.Condition{ - ConditionOK, - }, - } -} - -func serviceHasPort( - dest *pbcatalog.FailoverDestination, - destServices map[resource.ReferenceKey]*resource.DecodedResource[*pbcatalog.Service], -) *pbresource.Condition { - key := resource.NewReferenceKey(dest.Ref) - destService, ok := destServices[key] - if !ok { - return ConditionMissingDestinationService(dest.Ref) - } - - found := false - mesh := false - for _, port := range destService.Data.Ports { - if port.TargetPort == dest.Port { - found = true - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - mesh = true - } - break - } - } - - if !found { - return ConditionUnknownDestinationPort(dest.Ref, dest.Port) - } else if mesh { - return ConditionUsingMeshDestinationPort(dest.Ref, dest.Port) - } - - return nil -} - -func isServiceType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, types.ServiceType): - return true - } - return false -} diff --git a/internal/catalog/internal/controllers/failover/controller_test.go b/internal/catalog/internal/controllers/failover/controller_test.go deleted file mode 100644 index de42844ae6b2d..0000000000000 --- a/internal/catalog/internal/controllers/failover/controller_test.go +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package failover - -import ( - "context" - "testing" - - "github.com/stretchr/testify/suite" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog/internal/mappers/failovermapper" - "github.com/hashicorp/consul/internal/catalog/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - "github.com/hashicorp/consul/sdk/testutil" -) - -type controllerSuite struct { - suite.Suite - - ctx context.Context - client *rtest.Client - rt controller.Runtime - - failoverMapper FailoverMapper - - ctl failoverPolicyReconciler -} - -func (suite *controllerSuite) SetupTest() { - suite.ctx = testutil.TestContext(suite.T()) - client := svctest.RunResourceService(suite.T(), types.Register) - suite.rt = controller.Runtime{ - Client: client, - Logger: testutil.Logger(suite.T()), - } - suite.client = rtest.NewClient(client) - - suite.failoverMapper = failovermapper.New() -} - -func (suite *controllerSuite) TestController() { - // This test's purpose is to exercise the controller in a halfway realistic - // way, verifying the event triggers work in the live code. - - // Run the controller manager - mgr := controller.NewManager(suite.client, suite.rt.Logger) - mgr.Register(FailoverPolicyController(suite.failoverMapper)) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - // Create an advance pointer to some services. - apiServiceRef := resource.Reference(rtest.Resource(types.ServiceType, "api").ID(), "") - otherServiceRef := resource.Reference(rtest.Resource(types.ServiceType, "other").ID(), "") - - // create a failover without any services - failoverData := &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: apiServiceRef, - }}, - }, - } - failover := rtest.Resource(types.FailoverPolicyType, "api"). - WithData(suite.T(), failoverData). - Write(suite.T(), suite.client) - - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionMissingService) - - // Provide the service. - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{{ - TargetPort: "http", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }}, - } - _ = rtest.Resource(types.ServiceType, "api"). - WithData(suite.T(), apiServiceData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionOK) - - // Update the failover to reference an unknown port - failoverData = &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: apiServiceRef, - Port: "http", - }}, - }, - "admin": { - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: apiServiceRef, - Port: "admin", - }}, - }, - }, - } - _ = rtest.Resource(types.FailoverPolicyType, "api"). - WithData(suite.T(), failoverData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionUnknownPort("admin")) - - // update the service to fix the stray reference, but point to a mesh port - apiServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "http", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "admin", - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - } - _ = rtest.Resource(types.ServiceType, "api"). - WithData(suite.T(), apiServiceData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionUsingMeshDestinationPort(apiServiceRef, "admin")) - - // update the service to fix the stray reference to not be a mesh port - apiServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "http", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "admin", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - _ = rtest.Resource(types.ServiceType, "api"). - WithData(suite.T(), apiServiceData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionOK) - - // change failover leg to point to missing service - failoverData = &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: apiServiceRef, - Port: "http", - }}, - }, - "admin": { - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: otherServiceRef, - Port: "admin", - }}, - }, - }, - } - _ = rtest.Resource(types.FailoverPolicyType, "api"). - WithData(suite.T(), failoverData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionMissingDestinationService(otherServiceRef)) - - // Create the missing service, but forget the port. - otherServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"other-"}}, - Ports: []*pbcatalog.ServicePort{{ - TargetPort: "http", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }}, - } - _ = rtest.Resource(types.ServiceType, "other"). - WithData(suite.T(), otherServiceData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionUnknownDestinationPort(otherServiceRef, "admin")) - - // fix the destination leg's port - otherServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"other-"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "http", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "admin", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - _ = rtest.Resource(types.ServiceType, "other"). - WithData(suite.T(), otherServiceData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionOK) - - // Update the two services to use differnet port names so the easy path doesn't work - apiServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "foo", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "bar", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - _ = rtest.Resource(types.ServiceType, "api"). - WithData(suite.T(), apiServiceData). - Write(suite.T(), suite.client) - - otherServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"other-"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "foo", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "baz", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - _ = rtest.Resource(types.ServiceType, "other"). - WithData(suite.T(), otherServiceData). - Write(suite.T(), suite.client) - - failoverData = &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: otherServiceRef, - }}, - }, - } - failover = rtest.Resource(types.FailoverPolicyType, "api"). - WithData(suite.T(), failoverData). - Write(suite.T(), suite.client) - - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionUnknownDestinationPort(otherServiceRef, "bar")) - - // and fix it the silly way by removing it from api+failover - apiServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "foo", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - _ = rtest.Resource(types.ServiceType, "api"). - WithData(suite.T(), apiServiceData). - Write(suite.T(), suite.client) - - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionOK) -} - -func TestFailoverController(t *testing.T) { - suite.Run(t, new(controllerSuite)) -} diff --git a/internal/catalog/internal/controllers/failover/status.go b/internal/catalog/internal/controllers/failover/status.go deleted file mode 100644 index b2801c41ed93e..0000000000000 --- a/internal/catalog/internal/controllers/failover/status.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package failover - -import ( - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - StatusKey = "consul.io/failover-policy" - StatusConditionAccepted = "accepted" - - OKReason = "Ok" - OKMessage = "failover policy was accepted" - - MissingServiceReason = "MissingService" - MissingServiceMessage = "service for failover policy does not exist" - - UnknownPortReason = "UnknownPort" - UnknownPortMessagePrefix = "port is not defined on service: " - - MissingDestinationServiceReason = "MissingDestinationService" - MissingDestinationServiceMessagePrefix = "destination service for failover policy does not exist: " - - UnknownDestinationPortReason = "UnknownDestinationPort" - UnknownDestinationPortMessagePrefix = "port is not defined on destination service: " - - UsingMeshDestinationPortReason = "UsingMeshDestinationPort" - UsingMeshDestinationPortMessagePrefix = "port is a special unroutable mesh port on destination service: " -) - -var ( - ConditionOK = &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_TRUE, - Reason: OKReason, - Message: OKMessage, - } - - ConditionMissingService = &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: MissingServiceReason, - Message: MissingServiceMessage, - } -) - -func ConditionUnknownPort(port string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: UnknownPortReason, - Message: UnknownPortMessagePrefix + port, - } -} - -func ConditionMissingDestinationService(ref *pbresource.Reference) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: MissingDestinationServiceReason, - Message: MissingDestinationServiceMessagePrefix + resource.ReferenceToString(ref), - } -} - -func ConditionUnknownDestinationPort(ref *pbresource.Reference, port string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: UnknownDestinationPortReason, - Message: UnknownDestinationPortMessagePrefix + port + " on " + resource.ReferenceToString(ref), - } -} - -func ConditionUsingMeshDestinationPort(ref *pbresource.Reference, port string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: UnknownDestinationPortReason, - Message: UnknownDestinationPortMessagePrefix + port + " on " + resource.ReferenceToString(ref), - } -} diff --git a/internal/catalog/internal/controllers/nodehealth/controller.go b/internal/catalog/internal/controllers/nodehealth/controller.go index 362ac1578c813..4e3aff9993ba1 100644 --- a/internal/catalog/internal/controllers/nodehealth/controller.go +++ b/internal/catalog/internal/controllers/nodehealth/controller.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package nodehealth diff --git a/internal/catalog/internal/controllers/nodehealth/controller_test.go b/internal/catalog/internal/controllers/nodehealth/controller_test.go index 9723dabf93206..8150fe0bdda3a 100644 --- a/internal/catalog/internal/controllers/nodehealth/controller_test.go +++ b/internal/catalog/internal/controllers/nodehealth/controller_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package nodehealth diff --git a/internal/catalog/internal/controllers/nodehealth/status.go b/internal/catalog/internal/controllers/nodehealth/status.go index d3cf0d8a8dc1e..14a3151484b59 100644 --- a/internal/catalog/internal/controllers/nodehealth/status.go +++ b/internal/catalog/internal/controllers/nodehealth/status.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package nodehealth diff --git a/internal/catalog/internal/controllers/register.go b/internal/catalog/internal/controllers/register.go index df1f7c88c7b2e..5f7fc631a543b 100644 --- a/internal/catalog/internal/controllers/register.go +++ b/internal/catalog/internal/controllers/register.go @@ -1,11 +1,10 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package controllers import ( "github.com/hashicorp/consul/internal/catalog/internal/controllers/endpoints" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/failover" "github.com/hashicorp/consul/internal/catalog/internal/controllers/nodehealth" "github.com/hashicorp/consul/internal/catalog/internal/controllers/workloadhealth" "github.com/hashicorp/consul/internal/controller" @@ -14,12 +13,10 @@ import ( type Dependencies struct { WorkloadHealthNodeMapper workloadhealth.NodeMapper EndpointsWorkloadMapper endpoints.WorkloadMapper - FailoverMapper failover.FailoverMapper } func Register(mgr *controller.Manager, deps Dependencies) { mgr.Register(nodehealth.NodeHealthController()) mgr.Register(workloadhealth.WorkloadHealthController(deps.WorkloadHealthNodeMapper)) mgr.Register(endpoints.ServiceEndpointsController(deps.EndpointsWorkloadMapper)) - mgr.Register(failover.FailoverPolicyController(deps.FailoverMapper)) } diff --git a/internal/catalog/internal/controllers/workloadhealth/controller.go b/internal/catalog/internal/controllers/workloadhealth/controller.go index d8a33c9222360..77009697bcd7e 100644 --- a/internal/catalog/internal/controllers/workloadhealth/controller.go +++ b/internal/catalog/internal/controllers/workloadhealth/controller.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package workloadhealth import ( diff --git a/internal/catalog/internal/controllers/workloadhealth/controller_test.go b/internal/catalog/internal/controllers/workloadhealth/controller_test.go index 1afb06243a6e2..29d93f088d453 100644 --- a/internal/catalog/internal/controllers/workloadhealth/controller_test.go +++ b/internal/catalog/internal/controllers/workloadhealth/controller_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package workloadhealth diff --git a/internal/catalog/internal/controllers/workloadhealth/status.go b/internal/catalog/internal/controllers/workloadhealth/status.go index f7bf000da2735..05cc989ddd934 100644 --- a/internal/catalog/internal/controllers/workloadhealth/status.go +++ b/internal/catalog/internal/controllers/workloadhealth/status.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package workloadhealth import ( diff --git a/internal/catalog/internal/mappers/failovermapper/failover_mapper.go b/internal/catalog/internal/mappers/failovermapper/failover_mapper.go deleted file mode 100644 index 4ae6776cb66ce..0000000000000 --- a/internal/catalog/internal/mappers/failovermapper/failover_mapper.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package failovermapper - -import ( - "context" - - "github.com/hashicorp/consul/internal/catalog/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// Mapper tracks the relationship between a FailoverPolicy an a Service it -// references whether due to name-alignment or from a reference in a -// FailoverDestination leg. -type Mapper struct { - b *bimapper.Mapper -} - -// New creates a new Mapper. -func New() *Mapper { - return &Mapper{ - b: bimapper.New(types.FailoverPolicyType, types.ServiceType), - } -} - -// TrackFailover extracts all Service references from the provided -// FailoverPolicy and indexes them so that MapService can turn Service events -// into FailoverPolicy events properly. -func (m *Mapper) TrackFailover(failover *resource.DecodedResource[*pbcatalog.FailoverPolicy]) { - destRefs := failover.Data.GetUnderlyingDestinationRefs() - destRefs = append(destRefs, &pbresource.Reference{ - Type: types.ServiceType, - Tenancy: failover.Resource.Id.Tenancy, - Name: failover.Resource.Id.Name, - }) - m.trackFailover(failover.Resource.Id, destRefs) -} - -func (m *Mapper) trackFailover(failover *pbresource.ID, services []*pbresource.Reference) { - var servicesAsIDsOrRefs []resource.ReferenceOrID - for _, s := range services { - servicesAsIDsOrRefs = append(servicesAsIDsOrRefs, s) - } - m.b.TrackItem(failover, servicesAsIDsOrRefs) -} - -// UntrackFailover forgets the links inserted by TrackFailover for the provided -// FailoverPolicyID. -func (m *Mapper) UntrackFailover(failoverID *pbresource.ID) { - m.b.UntrackItem(failoverID) -} - -func (m *Mapper) MapService(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - return m.b.MapLink(ctx, rt, res) -} - -func (m *Mapper) FailoverIDsByService(svcID *pbresource.ID) []*pbresource.ID { - return m.b.ItemsForLink(svcID) -} diff --git a/internal/catalog/internal/mappers/failovermapper/failover_mapper_test.go b/internal/catalog/internal/mappers/failovermapper/failover_mapper_test.go deleted file mode 100644 index 048f444eca61d..0000000000000 --- a/internal/catalog/internal/mappers/failovermapper/failover_mapper_test.go +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package failovermapper - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/catalog/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestMapper_Tracking(t *testing.T) { - registry := resource.NewRegistry() - types.Register(registry) - - // Create an advance pointer to some services. - randoSvc := rtest.Resource(types.ServiceType, "rando"). - WithData(t, &pbcatalog.Service{}). - Build() - rtest.ValidateAndNormalize(t, registry, randoSvc) - - apiSvc := rtest.Resource(types.ServiceType, "api"). - WithData(t, &pbcatalog.Service{}). - Build() - rtest.ValidateAndNormalize(t, registry, apiSvc) - - fooSvc := rtest.Resource(types.ServiceType, "foo"). - WithData(t, &pbcatalog.Service{}). - Build() - rtest.ValidateAndNormalize(t, registry, fooSvc) - - barSvc := rtest.Resource(types.ServiceType, "bar"). - WithData(t, &pbcatalog.Service{}). - Build() - rtest.ValidateAndNormalize(t, registry, barSvc) - - wwwSvc := rtest.Resource(types.ServiceType, "www"). - WithData(t, &pbcatalog.Service{}). - Build() - rtest.ValidateAndNormalize(t, registry, wwwSvc) - - fail1 := rtest.Resource(types.FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(types.ServiceType, "foo")}, - {Ref: newRef(types.ServiceType, "bar")}, - }, - }, - }). - Build() - rtest.ValidateAndNormalize(t, registry, fail1) - failDec1 := rtest.MustDecode[*pbcatalog.FailoverPolicy](t, fail1) - - fail2 := rtest.Resource(types.FailoverPolicyType, "www"). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(types.ServiceType, "www"), Datacenter: "dc2"}, - {Ref: newRef(types.ServiceType, "foo")}, - }, - }, - }). - Build() - rtest.ValidateAndNormalize(t, registry, fail2) - failDec2 := rtest.MustDecode[*pbcatalog.FailoverPolicy](t, fail2) - - fail1_updated := rtest.Resource(types.FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(types.ServiceType, "bar")}, - }, - }, - }). - Build() - rtest.ValidateAndNormalize(t, registry, fail1_updated) - failDec1_updated := rtest.MustDecode[*pbcatalog.FailoverPolicy](t, fail1_updated) - - m := New() - - // Nothing tracked yet so we assume nothing. - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc) - requireServicesTracked(t, m, fooSvc) - requireServicesTracked(t, m, barSvc) - requireServicesTracked(t, m, wwwSvc) - - // no-ops - m.UntrackFailover(fail1.Id) - - // still nothing - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc) - requireServicesTracked(t, m, fooSvc) - requireServicesTracked(t, m, barSvc) - requireServicesTracked(t, m, wwwSvc) - - // Actually insert some data. - m.TrackFailover(failDec1) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc, fail1.Id) - requireServicesTracked(t, m, fooSvc, fail1.Id) - requireServicesTracked(t, m, barSvc, fail1.Id) - requireServicesTracked(t, m, wwwSvc) - - // track it again, no change - m.TrackFailover(failDec1) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc, fail1.Id) - requireServicesTracked(t, m, fooSvc, fail1.Id) - requireServicesTracked(t, m, barSvc, fail1.Id) - requireServicesTracked(t, m, wwwSvc) - - // track new one that overlaps slightly - m.TrackFailover(failDec2) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc, fail1.Id) - requireServicesTracked(t, m, fooSvc, fail1.Id, fail2.Id) - requireServicesTracked(t, m, barSvc, fail1.Id) - requireServicesTracked(t, m, wwwSvc, fail2.Id) - - // update the original to change it - m.TrackFailover(failDec1_updated) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc, fail1.Id) - requireServicesTracked(t, m, fooSvc, fail2.Id) - requireServicesTracked(t, m, barSvc, fail1.Id) - requireServicesTracked(t, m, wwwSvc, fail2.Id) - - // delete the original - m.UntrackFailover(fail1.Id) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc) - requireServicesTracked(t, m, fooSvc, fail2.Id) - requireServicesTracked(t, m, barSvc) - requireServicesTracked(t, m, wwwSvc, fail2.Id) - - // delete the other one - m.UntrackFailover(fail2.Id) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc) - requireServicesTracked(t, m, fooSvc) - requireServicesTracked(t, m, barSvc) - requireServicesTracked(t, m, wwwSvc) -} - -func requireServicesTracked(t *testing.T, mapper *Mapper, svc *pbresource.Resource, failovers ...*pbresource.ID) { - t.Helper() - - reqs, err := mapper.MapService( - context.Background(), - controller.Runtime{}, - svc, - ) - require.NoError(t, err) - - require.Len(t, reqs, len(failovers)) - - for _, failover := range failovers { - prototest.AssertContainsElement(t, reqs, controller.Request{ID: failover}) - } -} - -func newRef(typ *pbresource.Type, name string) *pbresource.Reference { - return rtest.Resource(typ, name).Reference("") -} - -func defaultTenancy() *pbresource.Tenancy { - return &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - } -} diff --git a/internal/catalog/internal/mappers/nodemapper/node_mapper.go b/internal/catalog/internal/mappers/nodemapper/node_mapper.go index 11e575f307521..8eea26dd08ca1 100644 --- a/internal/catalog/internal/mappers/nodemapper/node_mapper.go +++ b/internal/catalog/internal/mappers/nodemapper/node_mapper.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package nodemapper import ( diff --git a/internal/catalog/internal/mappers/nodemapper/node_mapper_test.go b/internal/catalog/internal/mappers/nodemapper/node_mapper_test.go index 763e192ebf165..acfe67cf6b106 100644 --- a/internal/catalog/internal/mappers/nodemapper/node_mapper_test.go +++ b/internal/catalog/internal/mappers/nodemapper/node_mapper_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package nodemapper import ( diff --git a/internal/catalog/internal/mappers/selectiontracker/selection_tracker.go b/internal/catalog/internal/mappers/selectiontracker/selection_tracker.go index 3cfe0489dd3f6..3bf229bff65eb 100644 --- a/internal/catalog/internal/mappers/selectiontracker/selection_tracker.go +++ b/internal/catalog/internal/mappers/selectiontracker/selection_tracker.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package selectiontracker diff --git a/internal/catalog/internal/mappers/selectiontracker/selection_tracker_test.go b/internal/catalog/internal/mappers/selectiontracker/selection_tracker_test.go index be4f7121d3217..75fa0967c94b3 100644 --- a/internal/catalog/internal/mappers/selectiontracker/selection_tracker_test.go +++ b/internal/catalog/internal/mappers/selectiontracker/selection_tracker_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package selectiontracker import ( diff --git a/internal/catalog/internal/types/dns_policy.go b/internal/catalog/internal/types/dns_policy.go index d2b6001b5dbc2..4c3456027667c 100644 --- a/internal/catalog/internal/types/dns_policy.go +++ b/internal/catalog/internal/types/dns_policy.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/catalog/internal/types/dns_policy_test.go b/internal/catalog/internal/types/dns_policy_test.go index 93ee628041974..b4c2da3c78aad 100644 --- a/internal/catalog/internal/types/dns_policy_test.go +++ b/internal/catalog/internal/types/dns_policy_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/catalog/internal/types/errors.go b/internal/catalog/internal/types/errors.go index 3b331a9a6302c..6f0b44c1b3787 100644 --- a/internal/catalog/internal/types/errors.go +++ b/internal/catalog/internal/types/errors.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/catalog/internal/types/errors_test.go b/internal/catalog/internal/types/errors_test.go index 08f227166aa22..7a8157727350c 100644 --- a/internal/catalog/internal/types/errors_test.go +++ b/internal/catalog/internal/types/errors_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/catalog/internal/types/failover_policy.go b/internal/catalog/internal/types/failover_policy.go deleted file mode 100644 index 03993d707c9d0..0000000000000 --- a/internal/catalog/internal/types/failover_policy.go +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "fmt" - - "github.com/hashicorp/go-multierror" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - FailoverPolicyKind = "FailoverPolicy" -) - -var ( - FailoverPolicyV1Alpha1Type = &pbresource.Type{ - Group: GroupName, - GroupVersion: VersionV1Alpha1, - Kind: FailoverPolicyKind, - } - - FailoverPolicyType = FailoverPolicyV1Alpha1Type -) - -func RegisterFailoverPolicy(r resource.Registry) { - r.Register(resource.Registration{ - Type: FailoverPolicyV1Alpha1Type, - Proto: &pbcatalog.FailoverPolicy{}, - Mutate: MutateFailoverPolicy, - Validate: ValidateFailoverPolicy, - }) -} - -func MutateFailoverPolicy(res *pbresource.Resource) error { - var failover pbcatalog.FailoverPolicy - - if err := res.Data.UnmarshalTo(&failover); err != nil { - return resource.NewErrDataParse(&failover, err) - } - - changed := false - - // Handle eliding empty configs. - if failover.Config != nil && failover.Config.IsEmpty() { - failover.Config = nil - changed = true - } - for port, pc := range failover.PortConfigs { - if pc.IsEmpty() { - delete(failover.PortConfigs, port) - changed = true - } - } - if len(failover.PortConfigs) == 0 { - failover.PortConfigs = nil - changed = true - } - - // TODO(rb): normalize dest ref tenancies - - if !changed { - return nil - } - - return res.Data.MarshalFrom(&failover) -} - -func ValidateFailoverPolicy(res *pbresource.Resource) error { - var failover pbcatalog.FailoverPolicy - - if err := res.Data.UnmarshalTo(&failover); err != nil { - return resource.NewErrDataParse(&failover, err) - } - - var merr error - - 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 failover.Config != nil { - for _, err := range validateFailoverConfig(failover.Config, false) { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "config", - Wrapped: err, - }) - } - } - - for portName, pc := range failover.PortConfigs { - if portNameErr := validatePortName(portName); portNameErr != nil { - merr = multierror.Append(merr, resource.ErrInvalidMapKey{ - Map: "port_configs", - Key: portName, - Wrapped: portNameErr, - }) - } - - for _, err := range validateFailoverConfig(pc, true) { - merr = multierror.Append(merr, resource.ErrInvalidMapValue{ - Map: "port_configs", - Key: portName, - Wrapped: err, - }) - } - - // TODO: should sameness group be a ref once that's a resource? - } - - return merr -} - -func validateFailoverConfig(config *pbcatalog.FailoverConfig, ported bool) []error { - var errs []error - - if (len(config.Destinations) > 0) == (config.SamenessGroup != "") { - errs = append(errs, resource.ErrInvalidField{ - Name: "destinations", - Wrapped: fmt.Errorf("exactly one of destinations or sameness_group should be set"), - }) - } - for i, dest := range config.Destinations { - for _, err := range validateFailoverPolicyDestination(dest, ported) { - errs = append(errs, resource.ErrInvalidListElement{ - Name: "destinations", - Index: i, - Wrapped: err, - }) - } - } - - switch config.Mode { - case pbcatalog.FailoverMode_FAILOVER_MODE_UNSPECIFIED: - // means pbcatalog.FailoverMode_FAILOVER_MODE_SEQUENTIAL - case pbcatalog.FailoverMode_FAILOVER_MODE_SEQUENTIAL: - case pbcatalog.FailoverMode_FAILOVER_MODE_ORDER_BY_LOCALITY: - default: - errs = append(errs, resource.ErrInvalidField{ - Name: "mode", - Wrapped: fmt.Errorf("not a supported enum value: %v", config.Mode), - }) - } - - // TODO: validate sameness group requirements - - return errs -} - -func validateFailoverPolicyDestination(dest *pbcatalog.FailoverDestination, ported bool) []error { - var errs []error - if dest.Ref == nil { - errs = append(errs, resource.ErrInvalidField{ - Name: "ref", - Wrapped: resource.ErrMissing, - }) - } else if !resource.EqualType(dest.Ref.Type, ServiceType) { - errs = append(errs, resource.ErrInvalidField{ - Name: "ref", - Wrapped: resource.ErrInvalidReferenceType{ - AllowedType: ServiceType, - }, - }) - } else if dest.Ref.Section != "" { - errs = append(errs, resource.ErrInvalidField{ - Name: "ref", - Wrapped: resource.ErrInvalidField{ - Name: "section", - Wrapped: errors.New("section not supported for failover policy dest refs"), - }, - }) - } - - // NOTE: Destinations here cannot define ports. Port equality is - // assumed and will be reconciled. - if dest.Port != "" { - if ported { - if portNameErr := validatePortName(dest.Port); portNameErr != nil { - errs = append(errs, resource.ErrInvalidField{ - Name: "port", - Wrapped: portNameErr, - }) - } - } else { - errs = append(errs, resource.ErrInvalidField{ - Name: "port", - Wrapped: fmt.Errorf("ports cannot be specified explicitly for the general failover section since it relies upon port alignment"), - }) - } - } - - hasPeer := false - if dest.Ref != nil { - hasPeer = dest.Ref.Tenancy.PeerName != "local" - } - - if hasPeer && dest.Datacenter != "" { - errs = append(errs, resource.ErrInvalidField{ - Name: "datacenter", - Wrapped: fmt.Errorf("ref.tenancy.peer_name and datacenter are mutually exclusive fields"), - }) - } - - return errs -} - -// SimplifyFailoverPolicy fully populates the PortConfigs map and clears the -// Configs map using the provided Service. -func SimplifyFailoverPolicy(svc *pbcatalog.Service, failover *pbcatalog.FailoverPolicy) *pbcatalog.FailoverPolicy { - if failover == nil { - panic("failover is required") - } - if svc == nil { - panic("service is required") - } - - // Copy so we can edit it. - dup := proto.Clone(failover) - failover = dup.(*pbcatalog.FailoverPolicy) - - if failover.PortConfigs == nil { - failover.PortConfigs = make(map[string]*pbcatalog.FailoverConfig) - } - - for _, port := range svc.Ports { - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - continue // skip - } - - if pc, ok := failover.PortConfigs[port.TargetPort]; ok { - for i, dest := range pc.Destinations { - // Assume port alignment. - if dest.Port == "" { - dest.Port = port.TargetPort - pc.Destinations[i] = dest - } - } - continue - } - - if failover.Config != nil { - // Duplicate because each port will get this uniquely. - pc2 := proto.Clone(failover.Config).(*pbcatalog.FailoverConfig) - for _, dest := range pc2.Destinations { - dest.Port = port.TargetPort - } - failover.PortConfigs[port.TargetPort] = pc2 - } - } - - if failover.Config != nil { - failover.Config = nil - } - - return failover -} diff --git a/internal/catalog/internal/types/failover_policy_test.go b/internal/catalog/internal/types/failover_policy_test.go deleted file mode 100644 index d80e9b2f880e7..0000000000000 --- a/internal/catalog/internal/types/failover_policy_test.go +++ /dev/null @@ -1,599 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestMutateFailoverPolicy(t *testing.T) { - type testcase struct { - failover *pbcatalog.FailoverPolicy - expect *pbcatalog.FailoverPolicy - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(FailoverPolicyType, "api"). - WithData(t, tc.failover). - Build() - - err := MutateFailoverPolicy(res) - - got := resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, res) - - if tc.expectErr == "" { - require.NoError(t, err) - prototest.AssertDeepEqual(t, tc.expect, got.Data) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - "empty-1": { - failover: &pbcatalog.FailoverPolicy{}, - expect: &pbcatalog.FailoverPolicy{}, - }, - "empty-config-1": { - failover: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{}, - }, - expect: &pbcatalog.FailoverPolicy{}, - }, - "empty-config-2": { - failover: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: make([]*pbcatalog.FailoverDestination, 0), - }, - }, - expect: &pbcatalog.FailoverPolicy{}, - }, - "empty-map-1": { - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: make(map[string]*pbcatalog.FailoverConfig), - }, - expect: &pbcatalog.FailoverPolicy{}, - }, - "empty-map-config-1": { - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": {}, - }, - }, - expect: &pbcatalog.FailoverPolicy{}, - }, - "empty-map-config-2": { - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: make([]*pbcatalog.FailoverDestination, 0), - }, - }, - }, - expect: &pbcatalog.FailoverPolicy{}, - }, - "normal": { - failover: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Mode: pbcatalog.FailoverMode_FAILOVER_MODE_SEQUENTIAL, - Regions: []string{"foo", "bar"}, - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "a")}, - {Ref: newRef(ServiceType, "b")}, - }, - }, - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "foo")}, - {Ref: newRef(ServiceType, "bar")}, - }, - }, - "admin": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "y")}, - {Ref: newRef(ServiceType, "z")}, - }, - }, - }, - }, - expect: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Mode: pbcatalog.FailoverMode_FAILOVER_MODE_SEQUENTIAL, - Regions: []string{"foo", "bar"}, - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "a")}, - {Ref: newRef(ServiceType, "b")}, - }, - }, - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "foo")}, - {Ref: newRef(ServiceType, "bar")}, - }, - }, - "admin": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "y")}, - {Ref: newRef(ServiceType, "z")}, - }, - }, - }, - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestValidateFailoverPolicy(t *testing.T) { - type configTestcase struct { - config *pbcatalog.FailoverConfig - expectErr string - } - - type testcase struct { - failover *pbcatalog.FailoverPolicy - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(FailoverPolicyType, "api"). - WithData(t, tc.failover). - Build() - - require.NoError(t, MutateFailoverPolicy(res)) - - // Verify that mutate didn't actually change the object. - got := resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, res) - prototest.AssertDeepEqual(t, tc.failover, got.Data) - - err := ValidateFailoverPolicy(res) - - // Verify that validate didn't actually change the object. - got = resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, res) - prototest.AssertDeepEqual(t, tc.failover, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - configCases := map[string]configTestcase{ - "dest with sameness": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "api-backup")}, - }, - SamenessGroup: "blah", - }, - expectErr: `invalid "destinations" field: exactly one of destinations or sameness_group should be set`, - }, - "dest without sameness": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "api-backup")}, - }, - }, - }, - "sameness without dest": { - config: &pbcatalog.FailoverConfig{ - SamenessGroup: "blah", - }, - }, - "mode: invalid": { - config: &pbcatalog.FailoverConfig{ - Mode: 99, - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "api-backup")}, - }, - }, - expectErr: `invalid "mode" field: not a supported enum value: 99`, - }, - "dest: no ref": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {}, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "ref" field: missing required field`, - }, - "dest: non-service ref": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(WorkloadType, "api-backup")}, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "ref" field: reference must have type catalog.v1alpha1.Service`, - }, - "dest: ref with section": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: resourcetest.Resource(ServiceType, "api").Reference("blah")}, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "ref" field: invalid "section" field: section not supported for failover policy dest refs`, - }, - "dest: ref peer and datacenter": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRefWithPeer(ServiceType, "api", "peer1"), Datacenter: "dc2"}, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "datacenter" field: ref.tenancy.peer_name and datacenter are mutually exclusive fields`, - }, - "dest: ref peer without datacenter": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRefWithPeer(ServiceType, "api", "peer1")}, - }, - }, - }, - "dest: ref datacenter without peer": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "api"), Datacenter: "dc2"}, - }, - }, - }, - } - - cases := map[string]testcase{ - // emptiness - "empty": { - failover: &pbcatalog.FailoverPolicy{}, - expectErr: `invalid "config" field: at least one of config or port_configs must be set`, - }, - "non-empty: one port config but no plain config": { - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "api-backup")}, - }, - }, - }, - }, - }, - "non-empty: some plain config but no port configs": { - failover: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "api-backup")}, - }, - }, - }, - }, - // plain config - "plain config: bad dest: any port name": { - failover: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "api-backup"), Port: "web"}, - }, - }, - }, - expectErr: `invalid "config" field: invalid element at index 0 of list "destinations": invalid "port" field: ports cannot be specified explicitly for the general failover section since it relies upon port alignment`, - }, - // ported config - "ported config: bad dest: invalid port name": { - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "api-backup"), Port: "$bad$"}, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid element at index 0 of list "destinations": invalid "port" field: value must match regex: ^[a-z0-9]([a-z0-9\-_]*[a-z0-9])?$`, - }, - "ported config: bad ported in map": { - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "$bad$": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(ServiceType, "api-backup"), Port: "http"}, - }, - }, - }, - }, - expectErr: `map port_configs contains an invalid key - "$bad$": value must match regex: ^[a-z0-9]([a-z0-9\-_]*[a-z0-9])?$`, - }, - } - - maybeWrap := func(wrapPrefix, base string) string { - if base != "" { - return wrapPrefix + base - } - return "" - } - - for name, tc := range configCases { - cases["plain config: "+name] = testcase{ - failover: &pbcatalog.FailoverPolicy{ - Config: proto.Clone(tc.config).(*pbcatalog.FailoverConfig), - }, - expectErr: maybeWrap(`invalid "config" field: `, tc.expectErr), - } - - cases["ported config: "+name] = testcase{ - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": proto.Clone(tc.config).(*pbcatalog.FailoverConfig), - }, - }, - expectErr: maybeWrap(`invalid value of key "http" within port_configs: `, tc.expectErr), - } - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestSimplifyFailoverPolicy(t *testing.T) { - registry := resource.NewRegistry() - Register(registry) - - type testcase struct { - svc *pbresource.Resource - failover *pbresource.Resource - expect *pbresource.Resource - } - run := func(t *testing.T, tc testcase) { - // Ensure we only use valid inputs. - resourcetest.ValidateAndNormalize(t, registry, tc.svc) - resourcetest.ValidateAndNormalize(t, registry, tc.failover) - resourcetest.ValidateAndNormalize(t, registry, tc.expect) - - svc := resourcetest.MustDecode[*pbcatalog.Service](t, tc.svc) - failover := resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, tc.failover) - expect := resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, tc.expect) - - inputFailoverCopy := proto.Clone(failover.Data).(*pbcatalog.FailoverPolicy) - - got := SimplifyFailoverPolicy(svc.Data, failover.Data) - prototest.AssertDeepEqual(t, expect.Data, got) - - // verify input was not altered - prototest.AssertDeepEqual(t, inputFailoverCopy, failover.Data) - } - - newPort := func(name string, virtualPort uint32, protocol pbcatalog.Protocol) *pbcatalog.ServicePort { - return &pbcatalog.ServicePort{ - VirtualPort: virtualPort, - TargetPort: name, - Protocol: protocol, - } - } - - cases := map[string]testcase{ - "implicit with mesh port skipping": { - svc: resourcetest.Resource(ServiceType, "api"). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - newPort("mesh", 21001, pbcatalog.Protocol_PROTOCOL_MESH), - newPort("http", 8080, pbcatalog.Protocol_PROTOCOL_HTTP), - }, - }). - Build(), - failover: resourcetest.Resource(FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(ServiceType, "api-backup"), - }, - }, - }, - }). - Build(), - expect: resourcetest.Resource(FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(ServiceType, "api-backup"), - Port: "http", // port defaulted - }, - }, - }, - }, - }). - Build(), - }, - "explicit with port aligned defaulting": { - svc: resourcetest.Resource(ServiceType, "api"). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - newPort("mesh", 9999, pbcatalog.Protocol_PROTOCOL_MESH), - newPort("http", 8080, pbcatalog.Protocol_PROTOCOL_HTTP), - newPort("rest", 8282, pbcatalog.Protocol_PROTOCOL_HTTP2), - }, - }). - Build(), - failover: resourcetest.Resource(FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(ServiceType, "api-backup"), - Port: "www", - }, - { - Ref: newRef(ServiceType, "api-double-backup"), - }, - }, - }, - }, - }). - Build(), - expect: resourcetest.Resource(FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(ServiceType, "api-backup"), - Port: "www", - }, - { - Ref: newRef(ServiceType, "api-double-backup"), - Port: "http", // port defaulted - }, - }, - }, - }, - }). - Build(), - }, - "implicit port explosion": { - svc: resourcetest.Resource(ServiceType, "api"). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - newPort("http", 8080, pbcatalog.Protocol_PROTOCOL_HTTP), - newPort("rest", 8282, pbcatalog.Protocol_PROTOCOL_HTTP2), - }, - }). - Build(), - failover: resourcetest.Resource(FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(ServiceType, "api-backup"), - }, - { - Ref: newRef(ServiceType, "api-double-backup"), - }, - }, - }, - }). - Build(), - expect: resourcetest.Resource(FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(ServiceType, "api-backup"), - Port: "http", - }, - { - Ref: newRef(ServiceType, "api-double-backup"), - Port: "http", - }, - }, - }, - "rest": { - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(ServiceType, "api-backup"), - Port: "rest", - }, - { - Ref: newRef(ServiceType, "api-double-backup"), - Port: "rest", - }, - }, - }, - }, - }). - Build(), - }, - "mixed port explosion with skip": { - svc: resourcetest.Resource(ServiceType, "api"). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - newPort("http", 8080, pbcatalog.Protocol_PROTOCOL_HTTP), - newPort("rest", 8282, pbcatalog.Protocol_PROTOCOL_HTTP2), - }, - }). - Build(), - failover: resourcetest.Resource(FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(ServiceType, "api-backup"), - }, - { - Ref: newRef(ServiceType, "api-double-backup"), - }, - }, - }, - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "rest": { - Mode: pbcatalog.FailoverMode_FAILOVER_MODE_ORDER_BY_LOCALITY, - Regions: []string{"us", "eu"}, - SamenessGroup: "sameweb", - }, - }, - }). - Build(), - expect: resourcetest.Resource(FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(ServiceType, "api-backup"), - Port: "http", - }, - { - Ref: newRef(ServiceType, "api-double-backup"), - Port: "http", - }, - }, - }, - "rest": { - Mode: pbcatalog.FailoverMode_FAILOVER_MODE_ORDER_BY_LOCALITY, - Regions: []string{"us", "eu"}, - SamenessGroup: "sameweb", - }, - }, - }). - Build(), - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func newRef(typ *pbresource.Type, name string) *pbresource.Reference { - return resourcetest.Resource(typ, name).Reference("") -} - -func newRefWithPeer(typ *pbresource.Type, name string, peer string) *pbresource.Reference { - ref := newRef(typ, name) - ref.Tenancy.PeerName = peer - return ref -} diff --git a/internal/catalog/internal/types/health_checks.go b/internal/catalog/internal/types/health_checks.go index f22f9bea97f8a..7df200ec28eb3 100644 --- a/internal/catalog/internal/types/health_checks.go +++ b/internal/catalog/internal/types/health_checks.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/catalog/internal/types/health_checks_test.go b/internal/catalog/internal/types/health_checks_test.go index 8ae722959e60c..12c13d3c1a228 100644 --- a/internal/catalog/internal/types/health_checks_test.go +++ b/internal/catalog/internal/types/health_checks_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/catalog/internal/types/health_status.go b/internal/catalog/internal/types/health_status.go index 29c4094f9a0a4..5e5a659475d8c 100644 --- a/internal/catalog/internal/types/health_status.go +++ b/internal/catalog/internal/types/health_status.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/catalog/internal/types/health_status_test.go b/internal/catalog/internal/types/health_status_test.go index d504b64b76a24..be9d30d501151 100644 --- a/internal/catalog/internal/types/health_status_test.go +++ b/internal/catalog/internal/types/health_status_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/catalog/internal/types/node.go b/internal/catalog/internal/types/node.go index 2d9bc6e821d15..0d2c795abaa5c 100644 --- a/internal/catalog/internal/types/node.go +++ b/internal/catalog/internal/types/node.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/catalog/internal/types/node_test.go b/internal/catalog/internal/types/node_test.go index 4f3ca2c0a5986..93e5ecea329a2 100644 --- a/internal/catalog/internal/types/node_test.go +++ b/internal/catalog/internal/types/node_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/catalog/internal/types/service.go b/internal/catalog/internal/types/service.go index 91c0c732e2e8e..27e13530e5f3f 100644 --- a/internal/catalog/internal/types/service.go +++ b/internal/catalog/internal/types/service.go @@ -1,16 +1,15 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types import ( "math" - "github.com/hashicorp/go-multierror" - "github.com/hashicorp/consul/internal/resource" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/go-multierror" ) const ( @@ -88,17 +87,6 @@ func ValidateService(res *pbresource.Resource) error { }) } - if protoErr := validateProtocol(port.Protocol); protoErr != nil { - err = multierror.Append(err, resource.ErrInvalidListElement{ - Name: "ports", - Index: idx, - Wrapped: resource.ErrInvalidField{ - Name: "protocol", - Wrapped: protoErr, - }, - }) - } - // validate the virtual port is within the allowed range - 0 is allowed // to signify that no virtual port should be used and the port will not // be available for transparent proxying within the mesh. diff --git a/internal/catalog/internal/types/service_endpoints.go b/internal/catalog/internal/types/service_endpoints.go index a8a591ef26e27..8c3d1cf109561 100644 --- a/internal/catalog/internal/types/service_endpoints.go +++ b/internal/catalog/internal/types/service_endpoints.go @@ -1,16 +1,15 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types import ( "math" - "github.com/hashicorp/go-multierror" - "github.com/hashicorp/consul/internal/resource" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/go-multierror" ) const ( @@ -45,16 +44,6 @@ func MutateServiceEndpoints(res *pbresource.Resource) error { } } - return nil -} - -func ValidateServiceEndpoints(res *pbresource.Resource) error { - var svcEndpoints pbcatalog.ServiceEndpoints - - if err := res.Data.UnmarshalTo(&svcEndpoints); err != nil { - return resource.NewErrDataParse(&svcEndpoints, err) - } - var err error if !resource.EqualType(res.Owner.Type, ServiceV1Alpha1Type) { err = multierror.Append(err, resource.ErrOwnerTypeInvalid{ @@ -65,7 +54,6 @@ func ValidateServiceEndpoints(res *pbresource.Resource) error { if !resource.EqualTenancy(res.Owner.Tenancy, res.Id.Tenancy) { err = multierror.Append(err, resource.ErrOwnerTenantInvalid{ - ResourceType: ServiceEndpointsV1Alpha1Type, ResourceTenancy: res.Id.Tenancy, OwnerTenancy: res.Owner.Tenancy, }) @@ -81,6 +69,17 @@ func ValidateServiceEndpoints(res *pbresource.Resource) error { }) } + return err +} + +func ValidateServiceEndpoints(res *pbresource.Resource) error { + var svcEndpoints pbcatalog.ServiceEndpoints + + if err := res.Data.UnmarshalTo(&svcEndpoints); err != nil { + return resource.NewErrDataParse(&svcEndpoints, err) + } + + var err error for idx, endpoint := range svcEndpoints.Endpoints { if endpointErr := validateEndpoint(endpoint, res); endpointErr != nil { err = multierror.Append(err, resource.ErrInvalidListElement{ @@ -129,13 +128,6 @@ func validateEndpoint(endpoint *pbcatalog.Endpoint, res *pbresource.Resource) er }) } - if healthErr := validateHealth(endpoint.HealthStatus); healthErr != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "health_status", - Wrapped: healthErr, - }) - } - // Validate the endpoints ports for portName, port := range endpoint.Ports { // Port names must be DNS labels @@ -147,17 +139,6 @@ func validateEndpoint(endpoint *pbcatalog.Endpoint, res *pbresource.Resource) er }) } - if protoErr := validateProtocol(port.Protocol); protoErr != nil { - err = multierror.Append(err, resource.ErrInvalidMapValue{ - Map: "ports", - Key: portName, - Wrapped: resource.ErrInvalidField{ - Name: "protocol", - Wrapped: protoErr, - }, - }) - } - // As the physical port is the real port the endpoint will be bound to // it must be in the standard 1-65535 range. if port.Port < 1 || port.Port > math.MaxUint16 { @@ -165,7 +146,7 @@ func validateEndpoint(endpoint *pbcatalog.Endpoint, res *pbresource.Resource) er Map: "ports", Key: portName, Wrapped: resource.ErrInvalidField{ - Name: "physical_port", + Name: "phsical_port", Wrapped: errInvalidPhysicalPort, }, }) diff --git a/internal/catalog/internal/types/service_endpoints_test.go b/internal/catalog/internal/types/service_endpoints_test.go index 9b45d7d2ca639..bd902d6246838 100644 --- a/internal/catalog/internal/types/service_endpoints_test.go +++ b/internal/catalog/internal/types/service_endpoints_test.go @@ -1,17 +1,17 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types import ( "testing" - "github.com/stretchr/testify/require" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/known/anypb" ) var ( @@ -20,13 +20,22 @@ var ( Namespace: "default", PeerName: "local", } +) - badEndpointTenancy = &pbresource.Tenancy{ - Partition: "default", - Namespace: "bad", - PeerName: "local", +func createServiceEndpointsResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource { + res := &pbresource.Resource{ + Id: &pbresource.ID{ + Type: ServiceEndpointsType, + Tenancy: defaultEndpointTenancy, + Name: "test-service", + }, } -) + + var err error + res.Data, err = anypb.New(data) + require.NoError(t, err) + return res +} func TestValidateServiceEndpoints_Ok(t *testing.T) { data := &pbcatalog.ServiceEndpoints{ @@ -53,14 +62,8 @@ func TestValidateServiceEndpoints_Ok(t *testing.T) { }, } - res := rtest.Resource(ServiceEndpointsType, "test-service"). - WithData(t, data). - Build() + res := createServiceEndpointsResource(t, data) - // fill in owner automatically - require.NoError(t, MutateServiceEndpoints(res)) - - // Now validate that everything is good. err := ValidateServiceEndpoints(res) require.NoError(t, err) } @@ -70,7 +73,7 @@ func TestValidateServiceEndpoints_ParseError(t *testing.T) { // to cause the error we are expecting data := &pbcatalog.IP{Address: "198.18.0.1"} - res := rtest.Resource(ServiceEndpointsType, "test-service").WithData(t, data).Build() + res := createServiceEndpointsResource(t, data) err := ValidateServiceEndpoints(res) require.Error(t, err) @@ -101,7 +104,6 @@ func TestValidateServiceEndpoints_EndpointInvalid(t *testing.T) { } type testCase struct { - owner *pbresource.ID modify func(*pbcatalog.Endpoint) validateErr func(t *testing.T, err error) } @@ -131,20 +133,6 @@ func TestValidateServiceEndpoints_EndpointInvalid(t *testing.T) { require.ErrorIs(t, err, resource.ErrEmpty) }, }, - "invalid-health-status": { - modify: func(endpoint *pbcatalog.Endpoint) { - endpoint.Ports["foo"] = &pbcatalog.WorkloadPort{ - Port: 42, - } - endpoint.HealthStatus = 99 - }, - validateErr: func(t *testing.T, err error) { - rtest.RequireError(t, err, resource.ErrInvalidField{ - Name: "health_status", - Wrapped: resource.NewConstError("not a supported enum value: 99"), - }) - }, - }, "invalid-port-name": { modify: func(endpoint *pbcatalog.Endpoint) { endpoint.Ports[""] = &pbcatalog.WorkloadPort{ @@ -152,29 +140,11 @@ func TestValidateServiceEndpoints_EndpointInvalid(t *testing.T) { } }, validateErr: func(t *testing.T, err error) { - rtest.RequireError(t, err, resource.ErrInvalidMapKey{ - Map: "ports", - Key: "", - Wrapped: resource.ErrEmpty, - }) - }, - }, - "invalid-port-protocol": { - modify: func(endpoint *pbcatalog.Endpoint) { - endpoint.Ports["foo"] = &pbcatalog.WorkloadPort{ - Port: 42, - Protocol: 99, - } - }, - validateErr: func(t *testing.T, err error) { - rtest.RequireError(t, err, resource.ErrInvalidMapValue{ - Map: "ports", - Key: "foo", - Wrapped: resource.ErrInvalidField{ - Name: "protocol", - Wrapped: resource.NewConstError("not a supported enum value: 99"), - }, - }) + var mapErr resource.ErrInvalidMapKey + require.ErrorAs(t, err, &mapErr) + require.Equal(t, "ports", mapErr.Map) + require.Equal(t, "", mapErr.Key) + require.Equal(t, resource.ErrEmpty, mapErr.Wrapped) }, }, "port-0": { @@ -193,50 +163,18 @@ func TestValidateServiceEndpoints_EndpointInvalid(t *testing.T) { require.ErrorIs(t, err, errInvalidPhysicalPort) }, }, - "invalid-owner": { - owner: &pbresource.ID{ - Type: DNSPolicyType, - Tenancy: badEndpointTenancy, - Name: "wrong", - }, - validateErr: func(t *testing.T, err error) { - rtest.RequireError(t, err, resource.ErrOwnerTypeInvalid{ - ResourceType: ServiceEndpointsType, - OwnerType: DNSPolicyType}) - rtest.RequireError(t, err, resource.ErrOwnerTenantInvalid{ - ResourceType: ServiceEndpointsType, - ResourceTenancy: defaultEndpointTenancy, - OwnerTenancy: badEndpointTenancy, - }) - rtest.RequireError(t, err, resource.ErrInvalidField{ - Name: "name", - Wrapped: errInvalidEndpointsOwnerName{ - Name: "test-service", - OwnerName: "wrong"}, - }) - }, - }, } for name, tcase := range cases { t.Run(name, func(t *testing.T) { - endpoint := genData() - if tcase.modify != nil { - tcase.modify(endpoint) - } + data := genData() + tcase.modify(data) - data := &pbcatalog.ServiceEndpoints{ + res := createServiceEndpointsResource(t, &pbcatalog.ServiceEndpoints{ Endpoints: []*pbcatalog.Endpoint{ - endpoint, + data, }, - } - res := rtest.Resource(ServiceEndpointsType, "test-service"). - WithOwner(tcase.owner). - WithData(t, data). - Build() - - // Run the mututation to setup defaults - require.NoError(t, MutateServiceEndpoints(res)) + }) err := ValidateServiceEndpoints(res) require.Error(t, err) @@ -244,13 +182,3 @@ func TestValidateServiceEndpoints_EndpointInvalid(t *testing.T) { }) } } - -func TestMutateServiceEndpoints_PopulateOwner(t *testing.T) { - res := rtest.Resource(ServiceEndpointsType, "test-service").Build() - - require.NoError(t, MutateServiceEndpoints(res)) - require.NotNil(t, res.Owner) - require.True(t, resource.EqualType(res.Owner.Type, ServiceType)) - require.True(t, resource.EqualTenancy(res.Owner.Tenancy, defaultEndpointTenancy)) - require.Equal(t, res.Owner.Name, res.Id.Name) -} diff --git a/internal/catalog/internal/types/service_test.go b/internal/catalog/internal/types/service_test.go index 4f53a5c0a62bb..1a0a035d91613 100644 --- a/internal/catalog/internal/types/service_test.go +++ b/internal/catalog/internal/types/service_test.go @@ -1,18 +1,17 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types import ( "testing" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/known/anypb" - "github.com/hashicorp/consul/internal/resource" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/known/anypb" ) func createServiceResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource { @@ -172,37 +171,6 @@ func TestValidateService_VirtualPortReused(t *testing.T) { require.EqualValues(t, 42, actual.Value) } -func TestValidateService_InvalidPortProtocol(t *testing.T) { - data := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "foo", - Protocol: 99, - }, - }, - } - - res := createServiceResource(t, data) - - err := ValidateService(res) - - expected := resource.ErrInvalidListElement{ - Name: "ports", - Index: 0, - Wrapped: resource.ErrInvalidField{ - Name: "protocol", - Wrapped: resource.NewConstError("not a supported enum value: 99"), - }, - } - - var actual resource.ErrInvalidListElement - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - func TestValidateService_VirtualPortInvalid(t *testing.T) { data := &pbcatalog.Service{ Workloads: &pbcatalog.WorkloadSelector{ diff --git a/internal/catalog/internal/types/types.go b/internal/catalog/internal/types/types.go index 4d64f2137cc8f..6ab3730bb2936 100644 --- a/internal/catalog/internal/types/types.go +++ b/internal/catalog/internal/types/types.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types @@ -22,5 +22,4 @@ func Register(r resource.Registry) { RegisterHealthChecks(r) RegisterDNSPolicy(r) RegisterVirtualIPs(r) - RegisterFailoverPolicy(r) } diff --git a/internal/catalog/internal/types/types_test.go b/internal/catalog/internal/types/types_test.go index e63fd044eae6c..d40fc42dd07ca 100644 --- a/internal/catalog/internal/types/types_test.go +++ b/internal/catalog/internal/types/types_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/catalog/internal/types/validators.go b/internal/catalog/internal/types/validators.go index 94691107f9347..e9fc08562784b 100644 --- a/internal/catalog/internal/types/validators.go +++ b/internal/catalog/internal/types/validators.go @@ -1,20 +1,18 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types import ( - "fmt" "net" "regexp" "strings" - "github.com/hashicorp/go-multierror" - "google.golang.org/protobuf/proto" - "github.com/hashicorp/consul/internal/resource" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/go-multierror" + "google.golang.org/protobuf/proto" ) const ( @@ -137,19 +135,6 @@ func validatePortName(name string) error { return nil } -func validateProtocol(protocol pbcatalog.Protocol) error { - switch protocol { - case pbcatalog.Protocol_PROTOCOL_TCP, - pbcatalog.Protocol_PROTOCOL_HTTP, - pbcatalog.Protocol_PROTOCOL_HTTP2, - pbcatalog.Protocol_PROTOCOL_GRPC, - pbcatalog.Protocol_PROTOCOL_MESH: - return nil - default: - return resource.NewConstError(fmt.Sprintf("not a supported enum value: %v", protocol)) - } -} - // validateWorkloadAddress will validate the WorkloadAddress type. This involves validating // the Host within the workload address and the ports references. For ports references we // ensure that values in the addresses ports array are present in the set of map keys. @@ -222,16 +207,3 @@ func validateReference(allowedType *pbresource.Type, allowedTenancy *pbresource. return err } - -func validateHealth(health pbcatalog.Health) error { - switch health { - case pbcatalog.Health_HEALTH_ANY, - pbcatalog.Health_HEALTH_PASSING, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_MAINTENANCE: - return nil - default: - return resource.NewConstError(fmt.Sprintf("not a supported enum value: %v", health)) - } -} diff --git a/internal/catalog/internal/types/validators_test.go b/internal/catalog/internal/types/validators_test.go index a3790e9f9e051..cd3a12c5c0740 100644 --- a/internal/catalog/internal/types/validators_test.go +++ b/internal/catalog/internal/types/validators_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types @@ -8,12 +8,11 @@ import ( "strings" "testing" - "github.com/hashicorp/go-multierror" - "github.com/stretchr/testify/require" - "github.com/hashicorp/consul/internal/resource" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/go-multierror" + "github.com/stretchr/testify/require" ) func TestIsValidDNSLabel(t *testing.T) { diff --git a/internal/catalog/internal/types/virtual_ips.go b/internal/catalog/internal/types/virtual_ips.go index 73cb4855d42c2..a27f08df0a77e 100644 --- a/internal/catalog/internal/types/virtual_ips.go +++ b/internal/catalog/internal/types/virtual_ips.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/catalog/internal/types/virtual_ips_test.go b/internal/catalog/internal/types/virtual_ips_test.go index 16edac73ce32c..76d55e7ecd745 100644 --- a/internal/catalog/internal/types/virtual_ips_test.go +++ b/internal/catalog/internal/types/virtual_ips_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/catalog/internal/types/workload.go b/internal/catalog/internal/types/workload.go index b26506d175e4f..a0dc7142d1e09 100644 --- a/internal/catalog/internal/types/workload.go +++ b/internal/catalog/internal/types/workload.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types @@ -7,11 +7,10 @@ import ( "math" "sort" - "github.com/hashicorp/go-multierror" - "github.com/hashicorp/consul/internal/resource" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/go-multierror" ) const ( @@ -77,17 +76,6 @@ func ValidateWorkload(res *pbresource.Resource) error { }) } - if protoErr := validateProtocol(port.Protocol); protoErr != nil { - err = multierror.Append(err, resource.ErrInvalidMapValue{ - Map: "ports", - Key: portName, - Wrapped: resource.ErrInvalidField{ - Name: "protocol", - Wrapped: protoErr, - }, - }) - } - // Collect the list of mesh ports if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { meshPorts = append(meshPorts, portName) diff --git a/internal/catalog/internal/types/workload_test.go b/internal/catalog/internal/types/workload_test.go index 6763fba54c976..03662472f2254 100644 --- a/internal/catalog/internal/types/workload_test.go +++ b/internal/catalog/internal/types/workload_test.go @@ -1,18 +1,17 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types import ( "testing" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/known/anypb" - "github.com/hashicorp/consul/internal/resource" pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/known/anypb" ) func createWorkloadResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource { @@ -228,30 +227,6 @@ func TestValidateWorkload_InvalidPortName(t *testing.T) { require.Equal(t, expected, actual) } -func TestValidateWorkload_InvalidPortProtocol(t *testing.T) { - data := validWorkload() - data.Ports["foo"] = &pbcatalog.WorkloadPort{ - Port: 42, - Protocol: 99, - } - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - expected := resource.ErrInvalidMapValue{ - Map: "ports", - Key: "foo", - Wrapped: resource.ErrInvalidField{ - Name: "protocol", - Wrapped: resource.NewConstError("not a supported enum value: 99"), - }, - } - var actual resource.ErrInvalidMapValue - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - func TestValidateWorkload_Port0(t *testing.T) { data := validWorkload() data.Ports["bar"] = &pbcatalog.WorkloadPort{Port: 0} diff --git a/internal/controller/api.go b/internal/controller/api.go index 5c2fc2e782717..8f5d873368b5d 100644 --- a/internal/controller/api.go +++ b/internal/controller/api.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package controller @@ -11,7 +11,6 @@ import ( "github.com/hashicorp/go-hclog" - "github.com/hashicorp/consul/agent/consul/controller/queue" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/proto-public/pbresource" ) @@ -47,21 +46,6 @@ func (c Controller) WithWatch(watchedType *pbresource.Type, mapper DependencyMap return c } -// WithCustomWatch adds a custom watch on the given dependency to the controller. Custom mapper -// will be called to map events produced by source to the controller's watched type. -func (c Controller) WithCustomWatch(source *Source, mapper CustomDependencyMapper) Controller { - if source == nil { - panic("source must not be nil") - } - - if mapper == nil { - panic("mapper must not be nil") - } - - c.customWatches = append(c.customWatches, customWatch{source, mapper}) - return c -} - // WithLogger changes the controller's logger. func (c Controller) WithLogger(logger hclog.Logger) Controller { if logger == nil { @@ -123,14 +107,13 @@ func (c Controller) backoff() (time.Duration, time.Duration) { // Use the builder methods in this package (starting with ForType) to construct // a controller, and then pass it to a Manager to be executed. type Controller struct { - managedType *pbresource.Type - reconciler Reconciler - logger hclog.Logger - watches []watch - customWatches []customWatch - baseBackoff time.Duration - maxBackoff time.Duration - placement Placement + managedType *pbresource.Type + reconciler Reconciler + logger hclog.Logger + watches []watch + baseBackoff time.Duration + maxBackoff time.Duration + placement Placement } type watch struct { @@ -138,45 +121,6 @@ type watch struct { mapper DependencyMapper } -// Watch is responsible for watching for custom events from source and adding them to -// the event queue. -func (s *Source) Watch(ctx context.Context, add func(e Event)) error { - for { - select { - case <-ctx.Done(): - return nil - case evt, ok := <-s.Source: - if !ok { - return nil - } - add(evt) - } - } -} - -// Source is used as a generic source of events. This can be used when events aren't coming from resources -// stored by the resource API. -type Source struct { - Source <-chan Event -} - -// Event captures an event in the system which the API can choose to respond to. -type Event struct { - Obj queue.ItemType -} - -// Key returns a string that will be used to de-duplicate items in the queue. -func (e Event) Key() string { - return e.Obj.Key() -} - -// customWatch represent a Watch on a custom Event source and a Mapper to map said -// Events into Requests that the controller can respond to. -type customWatch struct { - source *Source - mapper CustomDependencyMapper -} - // Request represents a request to reconcile the resource with the given ID. type Request struct { // ID of the resource that needs to be reconciled. diff --git a/internal/controller/api_test.go b/internal/controller/api_test.go index 40d3ec99bebdb..e80a2d7d7133e 100644 --- a/internal/controller/api_test.go +++ b/internal/controller/api_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package controller_test @@ -25,20 +25,9 @@ func TestController_API(t *testing.T) { rec := newTestReconciler() client := svctest.RunResourceService(t, demo.RegisterTypes) - concertsChan := make(chan controller.Event) - defer close(concertsChan) - concertSource := &controller.Source{Source: concertsChan} - concertMapper := func(ctx context.Context, rt controller.Runtime, event controller.Event) ([]controller.Request, error) { - artistID := event.Obj.(*Concert).artistID - var requests []controller.Request - requests = append(requests, controller.Request{ID: artistID}) - return requests, nil - } - ctrl := controller. ForType(demo.TypeV2Artist). WithWatch(demo.TypeV2Album, controller.MapOwner). - WithCustomWatch(concertSource, concertMapper). WithBackoff(10*time.Millisecond, 100*time.Millisecond). WithReconciler(rec) @@ -80,32 +69,6 @@ func TestController_API(t *testing.T) { prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) }) - t.Run("custom watched resource type", func(t *testing.T) { - res, err := demo.GenerateV2Artist() - require.NoError(t, err) - - rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - - req := rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - - rec.expectNoRequest(t, 500*time.Millisecond) - - concertsChan <- controller.Event{Obj: &Concert{name: "test-concert", artistID: rsp.Resource.Id}} - - watchedReq := rec.wait(t) - prototest.AssertDeepEqual(t, req.ID, watchedReq.ID) - - otherArtist, err := demo.GenerateV2Artist() - require.NoError(t, err) - - concertsChan <- controller.Event{Obj: &Concert{name: "test-concert", artistID: otherArtist.Id}} - - watchedReq = rec.wait(t) - prototest.AssertDeepEqual(t, otherArtist.Id, watchedReq.ID) - }) - t.Run("error retries", func(t *testing.T) { rec.failNext(errors.New("KABOOM")) @@ -303,12 +266,3 @@ func testContext(t *testing.T) context.Context { return ctx } - -type Concert struct { - name string - artistID *pbresource.ID -} - -func (c Concert) Key() string { - return c.name -} diff --git a/internal/controller/controller.go b/internal/controller/controller.go index ac901d355b6e3..54d5c57386a32 100644 --- a/internal/controller/controller.go +++ b/internal/controller/controller.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package controller @@ -40,39 +40,20 @@ func (c *controllerRunner) run(ctx context.Context) error { }) }) - for _, w := range c.ctrl.watches { + for _, watch := range c.ctrl.watches { + watch := watch mapQueue := runQueue[mapperRequest](groupCtx, c.ctrl) - watcher := w + // Watched Type Events → Mapper Queue group.Go(func() error { - return c.watch(groupCtx, watcher.watchedType, func(res *pbresource.Resource) { + return c.watch(groupCtx, watch.watchedType, func(res *pbresource.Resource) { mapQueue.Add(mapperRequest{res: res}) }) }) // Mapper Queue → Mapper → Reconciliation Queue group.Go(func() error { - return c.runMapper(groupCtx, watcher, mapQueue, recQueue, func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error) { - return watcher.mapper(ctx, runtime, itemType.(mapperRequest).res) - }) - }) - } - - for _, cw := range c.ctrl.customWatches { - customMapQueue := runQueue[Event](groupCtx, c.ctrl) - watcher := cw - // Custom Events → Mapper Queue - group.Go(func() error { - return watcher.source.Watch(groupCtx, func(e Event) { - customMapQueue.Add(e) - }) - }) - - // Mapper Queue → Mapper → Reconciliation Queue - group.Go(func() error { - return c.runCustomMapper(groupCtx, watcher, customMapQueue, recQueue, func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error) { - return watcher.mapper(ctx, runtime, itemType.(Event)) - }) + return c.runMapper(groupCtx, watch, mapQueue, recQueue) }) } @@ -90,7 +71,7 @@ func runQueue[T queue.ItemType](ctx context.Context, ctrl Controller) queue.Work } func (c *controllerRunner) watch(ctx context.Context, typ *pbresource.Type, add func(*pbresource.Resource)) error { - wl, err := c.client.WatchList(ctx, &pbresource.WatchListRequest{ + watch, err := c.client.WatchList(ctx, &pbresource.WatchListRequest{ Type: typ, Tenancy: &pbresource.Tenancy{ Partition: storage.Wildcard, @@ -104,7 +85,7 @@ func (c *controllerRunner) watch(ctx context.Context, typ *pbresource.Type, add } for { - event, err := wl.Recv() + event, err := watch.Recv() if err != nil { c.logger.Warn("error received from watch", "error", err) return err @@ -118,7 +99,6 @@ func (c *controllerRunner) runMapper( w watch, from queue.WorkQueue[mapperRequest], to queue.WorkQueue[Request], - mapper func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error), ) error { logger := c.logger.With("watched_resource_type", resource.ToGVK(w.watchedType)) @@ -128,36 +108,27 @@ func (c *controllerRunner) runMapper( return nil } - if err := c.doMap(ctx, mapper, to, item, logger); err != nil { + var reqs []Request + err := c.handlePanic(func() error { + var err error + reqs, err = w.mapper(ctx, c.runtime(), item.res) + return err + }) + if err != nil { from.AddRateLimited(item) from.Done(item) continue } - from.Forget(item) - from.Done(item) - } -} - -func (c *controllerRunner) runCustomMapper( - ctx context.Context, - cw customWatch, - from queue.WorkQueue[Event], - to queue.WorkQueue[Request], - mapper func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error), -) error { - logger := c.logger.With("watched_event", cw.source) - - for { - item, shutdown := from.Get() - if shutdown { - return nil - } - - if err := c.doMap(ctx, mapper, to, item, logger); err != nil { - from.AddRateLimited(item) - from.Done(item) - continue + for _, r := range reqs { + if !resource.EqualType(r.ID.Type, c.ctrl.managedType) { + logger.Error("dependency mapper returned request for a resource of the wrong type", + "type_expected", resource.ToGVK(c.ctrl.managedType), + "type_got", resource.ToGVK(r.ID.Type), + ) + continue + } + to.Add(r) } from.Forget(item) @@ -165,29 +136,6 @@ func (c *controllerRunner) runCustomMapper( } } -func (c *controllerRunner) doMap(ctx context.Context, mapper func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error), to queue.WorkQueue[Request], item queue.ItemType, logger hclog.Logger) error { - var reqs []Request - if err := c.handlePanic(func() error { - var err error - reqs, err = mapper(ctx, c.runtime(), item) - return err - }); err != nil { - return err - } - - for _, r := range reqs { - if !resource.EqualType(r.ID.Type, c.ctrl.managedType) { - logger.Error("dependency mapper returned request for a resource of the wrong type", - "type_expected", resource.ToGVK(c.ctrl.managedType), - "type_got", resource.ToGVK(r.ID.Type), - ) - continue - } - to.Add(r) - } - return nil -} - func (c *controllerRunner) runReconciler(ctx context.Context, queue queue.WorkQueue[Request]) error { for { req, shutdown := queue.Get() diff --git a/internal/controller/dependency_mappers.go b/internal/controller/dependency_mappers.go index 1ac331ffafdd4..c054c4369e94a 100644 --- a/internal/controller/dependency_mappers.go +++ b/internal/controller/dependency_mappers.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package controller import ( @@ -18,14 +15,6 @@ type DependencyMapper func( res *pbresource.Resource, ) ([]Request, error) -// CustomDependencyMapper is called when an Event occurs to determine which of the -// controller's managed resources need to be reconciled. -type CustomDependencyMapper func( - ctx context.Context, - rt Runtime, - event Event, -) ([]Request, error) - // MapOwner implements a DependencyMapper that returns the updated resource's owner. func MapOwner(_ context.Context, _ Runtime, res *pbresource.Resource) ([]Request, error) { var reqs []Request diff --git a/internal/controller/dependency_mappers_test.go b/internal/controller/dependency_mappers_test.go index b9956cdb71f48..b5300bfb9ac98 100644 --- a/internal/controller/dependency_mappers_test.go +++ b/internal/controller/dependency_mappers_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package controller import ( diff --git a/internal/controller/doc.go b/internal/controller/doc.go index db7d944e932e8..28953791525c1 100644 --- a/internal/controller/doc.go +++ b/internal/controller/doc.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package controller provides an API for implementing control loops on top of // Consul resources. It is heavily inspired by [Kubebuilder] and the Kubernetes diff --git a/internal/controller/lease.go b/internal/controller/lease.go index 596bd2546bce7..2cb00d133019c 100644 --- a/internal/controller/lease.go +++ b/internal/controller/lease.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package controller // Lease is used to ensure controllers are run as singletons (i.e. one leader- diff --git a/internal/controller/manager.go b/internal/controller/manager.go index 1e7e910210616..92c5829c581ec 100644 --- a/internal/controller/manager.go +++ b/internal/controller/manager.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package controller import ( diff --git a/internal/controller/supervisor.go b/internal/controller/supervisor.go index 4abb841f60e0f..5983ff4c4b7b0 100644 --- a/internal/controller/supervisor.go +++ b/internal/controller/supervisor.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package controller import ( diff --git a/internal/controller/supervisor_test.go b/internal/controller/supervisor_test.go index e455565d88b76..1792b8b95c21d 100644 --- a/internal/controller/supervisor_test.go +++ b/internal/controller/supervisor_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package controller import ( diff --git a/internal/go-sso/oidcauth/auth.go b/internal/go-sso/oidcauth/auth.go index a2f35763a3d0e..c50940780e77d 100644 --- a/internal/go-sso/oidcauth/auth.go +++ b/internal/go-sso/oidcauth/auth.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // package oidcauth bundles up an opinionated approach to authentication using // both the OIDC authorization code workflow and simple JWT decoding (via diff --git a/internal/go-sso/oidcauth/config.go b/internal/go-sso/oidcauth/config.go index 84bbac9e0cbe5..3d51aff19f9be 100644 --- a/internal/go-sso/oidcauth/config.go +++ b/internal/go-sso/oidcauth/config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package oidcauth diff --git a/internal/go-sso/oidcauth/config_test.go b/internal/go-sso/oidcauth/config_test.go index c72a69e0845f0..0ef4abcd69e53 100644 --- a/internal/go-sso/oidcauth/config_test.go +++ b/internal/go-sso/oidcauth/config_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package oidcauth diff --git a/internal/go-sso/oidcauth/internal/strutil/util.go b/internal/go-sso/oidcauth/internal/strutil/util.go index 9cdc0b1acb1c1..50cd24c324913 100644 --- a/internal/go-sso/oidcauth/internal/strutil/util.go +++ b/internal/go-sso/oidcauth/internal/strutil/util.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package strutil diff --git a/internal/go-sso/oidcauth/internal/strutil/util_test.go b/internal/go-sso/oidcauth/internal/strutil/util_test.go index 06d76a6c69d51..2e3fd1919acac 100644 --- a/internal/go-sso/oidcauth/internal/strutil/util_test.go +++ b/internal/go-sso/oidcauth/internal/strutil/util_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package strutil diff --git a/internal/go-sso/oidcauth/jwt.go b/internal/go-sso/oidcauth/jwt.go index fbb6a31669c8e..0695a60c5527f 100644 --- a/internal/go-sso/oidcauth/jwt.go +++ b/internal/go-sso/oidcauth/jwt.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package oidcauth diff --git a/internal/go-sso/oidcauth/jwt_test.go b/internal/go-sso/oidcauth/jwt_test.go index 621fb6660b537..9a8d9cf07ed19 100644 --- a/internal/go-sso/oidcauth/jwt_test.go +++ b/internal/go-sso/oidcauth/jwt_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package oidcauth diff --git a/internal/go-sso/oidcauth/oidc.go b/internal/go-sso/oidcauth/oidc.go index df00dfcc25f60..dbbf22582abf1 100644 --- a/internal/go-sso/oidcauth/oidc.go +++ b/internal/go-sso/oidcauth/oidc.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package oidcauth diff --git a/internal/go-sso/oidcauth/oidc_test.go b/internal/go-sso/oidcauth/oidc_test.go index 48de99b641812..288c704d08386 100644 --- a/internal/go-sso/oidcauth/oidc_test.go +++ b/internal/go-sso/oidcauth/oidc_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package oidcauth diff --git a/internal/go-sso/oidcauth/oidcauthtest/testing.go b/internal/go-sso/oidcauth/oidcauthtest/testing.go index 0956673c05156..432bcae333e45 100644 --- a/internal/go-sso/oidcauth/oidcauthtest/testing.go +++ b/internal/go-sso/oidcauth/oidcauthtest/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // package oidcauthtest exposes tools to assist in writing unit tests of OIDC // and JWT authentication workflows. diff --git a/internal/go-sso/oidcauth/oidcjwt.go b/internal/go-sso/oidcauth/oidcjwt.go index 14a6b4def2ad4..fec78dae232ee 100644 --- a/internal/go-sso/oidcauth/oidcjwt.go +++ b/internal/go-sso/oidcauth/oidcjwt.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package oidcauth diff --git a/internal/go-sso/oidcauth/oidcjwt_test.go b/internal/go-sso/oidcauth/oidcjwt_test.go index 49574856332a5..e1bd0cd919b2e 100644 --- a/internal/go-sso/oidcauth/oidcjwt_test.go +++ b/internal/go-sso/oidcauth/oidcjwt_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package oidcauth diff --git a/internal/go-sso/oidcauth/util.go b/internal/go-sso/oidcauth/util.go index 709798dee6353..06cc9054b89c9 100644 --- a/internal/go-sso/oidcauth/util.go +++ b/internal/go-sso/oidcauth/util.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package oidcauth diff --git a/internal/go-sso/oidcauth/util_test.go b/internal/go-sso/oidcauth/util_test.go index 6cf8bae1b3bd4..1bef6d51c6ae4 100644 --- a/internal/go-sso/oidcauth/util_test.go +++ b/internal/go-sso/oidcauth/util_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package oidcauth diff --git a/internal/mesh/exports.go b/internal/mesh/exports.go index 6a6f97221f303..753c10a7ba935 100644 --- a/internal/mesh/exports.go +++ b/internal/mesh/exports.go @@ -1,11 +1,9 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package mesh import ( - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers" "github.com/hashicorp/consul/internal/mesh/internal/types" "github.com/hashicorp/consul/internal/resource" ) @@ -19,39 +17,13 @@ var ( // Resource Kind Names. - ProxyConfigurationKind = types.ProxyConfigurationKind - UpstreamsKind = types.UpstreamsKind - UpstreamsConfigurationKind = types.UpstreamsConfigurationKind - ProxyStateKind = types.ProxyStateTemplateKind - HTTPRouteKind = types.HTTPRouteKind - GRPCRouteKind = types.GRPCRouteKind - TCPRouteKind = types.TCPRouteKind - DestinationPolicyKind = types.DestinationPolicyKind - ComputedRoutesKind = types.ComputedRoutesKind + ProxyConfigurationKind = types.ProxyConfigurationKind + UpstreamsKind = types.UpstreamsKind // Resource Types for the v1alpha1 version. - ProxyConfigurationV1Alpha1Type = types.ProxyConfigurationV1Alpha1Type - UpstreamsV1Alpha1Type = types.UpstreamsV1Alpha1Type - UpstreamsConfigurationV1Alpha1Type = types.UpstreamsConfigurationV1Alpha1Type - ProxyStateTemplateConfigurationV1Alpha1Type = types.ProxyStateTemplateV1Alpha1Type - HTTPRouteV1Alpha1Type = types.HTTPRouteV1Alpha1Type - GRPCRouteV1Alpha1Type = types.GRPCRouteV1Alpha1Type - TCPRouteV1Alpha1Type = types.TCPRouteV1Alpha1Type - DestinationPolicyV1Alpha1Type = types.DestinationPolicyV1Alpha1Type - ComputedRoutesV1Alpha1Type = types.ComputedRoutesV1Alpha1Type - - // Resource Types for the latest version. - - ProxyConfigurationType = types.ProxyConfigurationType - UpstreamsType = types.UpstreamsType - UpstreamsConfigurationType = types.UpstreamsConfigurationType - ProxyStateTemplateConfigurationType = types.ProxyStateTemplateType - HTTPRouteType = types.HTTPRouteType - GRPCRouteType = types.GRPCRouteType - TCPRouteType = types.TCPRouteType - DestinationPolicyType = types.DestinationPolicyType - ComputedRoutesType = types.ComputedRoutesType + ProxyConfigurationV1Alpha1Type = types.ProxyConfigurationV1Alpha1Type + UpstreamsV1Alpha1Type = types.UpstreamsV1Alpha1Type ) // RegisterTypes adds all resource types within the "catalog" API group @@ -59,11 +31,3 @@ var ( func RegisterTypes(r resource.Registry) { types.Register(r) } - -// RegisterControllers registers controllers for the mesh types with -// the given controller Manager. -func RegisterControllers(mgr *controller.Manager, deps ControllerDependencies) { - controllers.Register(mgr, deps) -} - -type ControllerDependencies = controllers.Dependencies diff --git a/internal/mesh/internal/controllers/register.go b/internal/mesh/internal/controllers/register.go deleted file mode 100644 index adfdd5c8afc09..0000000000000 --- a/internal/mesh/internal/controllers/register.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package controllers - -import ( - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/xds" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" -) - -type Dependencies struct { - TrustBundleFetcher xds.TrustBundleFetcher - ProxyUpdater xds.ProxyUpdater -} - -func Register(mgr *controller.Manager, deps Dependencies) { - mapper := bimapper.New(types.ProxyStateTemplateType, catalog.ServiceEndpointsType) - mgr.Register(xds.Controller(mapper, deps.ProxyUpdater, deps.TrustBundleFetcher)) -} diff --git a/internal/mesh/internal/controllers/xds/controller.go b/internal/mesh/internal/controllers/xds/controller.go deleted file mode 100644 index 04afeecc50c45..0000000000000 --- a/internal/mesh/internal/controllers/xds/controller.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "context" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/xds/status" - "github.com/hashicorp/consul/internal/mesh/internal/types" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ControllerName = "consul.io/xds-controller" - -func Controller(mapper *bimapper.Mapper, updater ProxyUpdater, fetcher TrustBundleFetcher) controller.Controller { - if mapper == nil || updater == nil || fetcher == nil { - panic("mapper, updater and fetcher are required") - } - - return controller.ForType(types.ProxyStateTemplateType). - WithWatch(catalog.ServiceEndpointsType, mapper.MapLink). - WithCustomWatch(proxySource(updater), proxyMapper). - WithPlacement(controller.PlacementEachServer). - WithReconciler(&xdsReconciler{bimapper: mapper, updater: updater, fetchTrustBundle: fetcher}) -} - -type xdsReconciler struct { - bimapper *bimapper.Mapper - updater ProxyUpdater - fetchTrustBundle TrustBundleFetcher -} - -type TrustBundleFetcher func() (*pbproxystate.TrustBundle, error) - -// ProxyUpdater is an interface that defines the ability to push proxy updates to the updater -// and also check its connectivity to the server. -type ProxyUpdater interface { - // PushChange allows pushing a computed ProxyState to xds for xds resource generation to send to a proxy. - PushChange(id *pbresource.ID, snapshot proxysnapshot.ProxySnapshot) error - - // ProxyConnectedToServer returns whether this id is connected to this server. - ProxyConnectedToServer(id *pbresource.ID) bool - - // EventChannel returns a channel of events that are consumed by the Custom Watcher. - EventChannel() chan controller.Event -} - -func (r *xdsReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { - rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", ControllerName) - - rt.Logger.Trace("reconciling proxy state template", "id", req.ID) - - // Get the ProxyStateTemplate. - proxyStateTemplate, err := getProxyStateTemplate(ctx, rt, req.ID) - if err != nil { - rt.Logger.Error("error reading proxy state template", "error", err) - return err - } - - if proxyStateTemplate == nil || proxyStateTemplate.Template == nil || !r.updater.ProxyConnectedToServer(req.ID) { - rt.Logger.Trace("proxy state template has been deleted or this controller is not responsible for this proxy state template", "id", req.ID) - - // If the proxy state was deleted, we should remove references to it in the mapper. - r.bimapper.UntrackItem(req.ID) - - return nil - } - - var ( - statusCondition *pbresource.Condition - pstResource *pbresource.Resource - ) - pstResource = proxyStateTemplate.Resource - - // Initialize the ProxyState endpoints map. - if proxyStateTemplate.Template.ProxyState == nil { - rt.Logger.Error("proxy state was missing from proxy state template") - // Set the status. - statusCondition = status.ConditionRejectedNilProxyState(status.KeyFromID(req.ID)) - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - - return err - } - - // TODO: Fetch trust bundles for all peers when peering is supported. - trustBundle, err := r.fetchTrustBundle() - if err != nil { - rt.Logger.Error("error fetching root trust bundle", "error", err) - // Set the status. - statusCondition = status.ConditionRejectedTrustBundleFetchFailed(status.KeyFromID(req.ID)) - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - return err - } - - if proxyStateTemplate.Template.ProxyState.TrustBundles == nil { - proxyStateTemplate.Template.ProxyState.TrustBundles = make(map[string]*pbproxystate.TrustBundle) - } - // TODO: Figure out the correct key for the default trust bundle. - proxyStateTemplate.Template.ProxyState.TrustBundles["local"] = trustBundle - - if proxyStateTemplate.Template.ProxyState.Endpoints == nil { - proxyStateTemplate.Template.ProxyState.Endpoints = make(map[string]*pbproxystate.Endpoints) - } - - // Iterate through the endpoint references. - // For endpoints, the controller should: - // 1. Resolve ServiceEndpoint references - // 2. Translate them into pbproxystate.Endpoints - // 3. Add the pbproxystate.Endpoints to the ProxyState endpoints map. - // 4. Track relationships between ProxyState and ServiceEndpoints, such that we can look up ServiceEndpoints and - // figure out which ProxyStates are associated with it (for mapping watches) and vice versa (for looking up - // references). The bimapper package is useful for tracking these relationships. - endpointReferencesMap := proxyStateTemplate.Template.RequiredEndpoints - var endpointsInProxyStateTemplate []resource.ReferenceOrID - for xdsClusterName, endpointRef := range endpointReferencesMap { - - // Step 1: Resolve the reference by looking up the ServiceEndpoints. - // serviceEndpoints will not be nil unless there is an error. - serviceEndpoints, err := getServiceEndpoints(ctx, rt, endpointRef.Id) - if err != nil { - rt.Logger.Error("error reading service endpoint", "id", endpointRef.Id, "error", err) - // Set the status. - statusCondition = status.ConditionRejectedErrorReadingEndpoints(status.KeyFromID(endpointRef.Id), err.Error()) - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - - return err - } - - // Step 2: Translate it into pbproxystate.Endpoints. - psEndpoints, err := generateProxyStateEndpoints(serviceEndpoints, endpointRef.Port) - if err != nil { - rt.Logger.Error("error translating service endpoints to proxy state endpoints", "endpoint", endpointRef.Id, "error", err) - - // Set the status. - statusCondition = status.ConditionRejectedCreatingProxyStateEndpoints(status.KeyFromID(endpointRef.Id), err.Error()) - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - - return err - } - - // Step 3: Add the endpoints to ProxyState. - proxyStateTemplate.Template.ProxyState.Endpoints[xdsClusterName] = psEndpoints - - // Track all the endpoints that are used by this ProxyStateTemplate, so we can use this for step 4. - endpointResourceRef := resource.Reference(endpointRef.Id, "") - endpointsInProxyStateTemplate = append(endpointsInProxyStateTemplate, endpointResourceRef) - - } - - // Step 4: Track relationships between ProxyStateTemplates and ServiceEndpoints. - r.bimapper.TrackItem(req.ID, endpointsInProxyStateTemplate) - - computedProxyState := proxyStateTemplate.Template.ProxyState - - err = r.updater.PushChange(req.ID, &proxytracker.ProxyState{ProxyState: computedProxyState}) - if err != nil { - // Set the status. - statusCondition = status.ConditionRejectedPushChangeFailed(status.KeyFromID(req.ID)) - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - return err - } - - // Set the status. - statusCondition = status.ConditionAccepted() - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - return nil -} - -func resourceIdToReference(id *pbresource.ID) *pbresource.Reference { - ref := &pbresource.Reference{ - Name: id.GetName(), - Type: id.GetType(), - Tenancy: id.GetTenancy(), - } - return ref -} diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go deleted file mode 100644 index 627615d54e713..0000000000000 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ /dev/null @@ -1,736 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/xds/status" - "github.com/hashicorp/consul/internal/mesh/internal/types" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" -) - -type xdsControllerTestSuite struct { - suite.Suite - - ctx context.Context - client *resourcetest.Client - runtime controller.Runtime - - ctl *xdsReconciler - mapper *bimapper.Mapper - updater *mockUpdater - fetcher TrustBundleFetcher - - fooProxyStateTemplate *pbresource.Resource - barProxyStateTemplate *pbresource.Resource - barEndpointRefs map[string]*pbproxystate.EndpointRef - fooEndpointRefs map[string]*pbproxystate.EndpointRef - fooEndpoints *pbresource.Resource - fooService *pbresource.Resource - fooBarEndpoints *pbresource.Resource - fooBarService *pbresource.Resource - expectedFooProxyStateEndpoints map[string]*pbproxystate.Endpoints - expectedBarProxyStateEndpoints map[string]*pbproxystate.Endpoints - expectedTrustBundle map[string]*pbproxystate.TrustBundle -} - -func (suite *xdsControllerTestSuite) SetupTest() { - suite.ctx = testutil.TestContext(suite.T()) - resourceClient := svctest.RunResourceService(suite.T(), types.Register, catalog.RegisterTypes) - suite.runtime = controller.Runtime{Client: resourceClient, Logger: testutil.Logger(suite.T())} - suite.client = resourcetest.NewClient(resourceClient) - suite.fetcher = mockFetcher - - suite.mapper = bimapper.New(types.ProxyStateTemplateType, catalog.ServiceEndpointsType) - suite.updater = newMockUpdater() - - suite.ctl = &xdsReconciler{ - bimapper: suite.mapper, - updater: suite.updater, - fetchTrustBundle: suite.fetcher, - } -} - -func mockFetcher() (*pbproxystate.TrustBundle, error) { - var bundle pbproxystate.TrustBundle - bundle = pbproxystate.TrustBundle{ - TrustDomain: "some-trust-domain", - Roots: []string{"some-root", "some-other-root"}, - } - return &bundle, nil -} - -// This test ensures when a ProxyState is deleted, it is no longer tracked in the mapper. -func (suite *xdsControllerTestSuite) TestReconcile_NoProxyStateTemplate() { - // Track the id of a non-existent ProxyStateTemplate. - proxyStateTemplateId := resourcetest.Resource(types.ProxyStateTemplateType, "not-found").ID() - suite.mapper.TrackItem(proxyStateTemplateId, []resource.ReferenceOrID{}) - - // Run the reconcile, and since no ProxyStateTemplate is stored, this simulates a deletion. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: proxyStateTemplateId, - }) - require.NoError(suite.T(), err) - - // Assert that nothing is tracked in the mapper. - require.True(suite.T(), suite.mapper.IsEmpty()) -} - -// This test ensures if the controller was previously tracking a ProxyStateTemplate, and now that proxy has -// disconnected from this server, it's ignored and removed from the mapper. -func (suite *xdsControllerTestSuite) TestReconcile_RemoveTrackingProxiesNotConnectedToServer() { - // Store the initial ProxyStateTemplate and track it in the mapper. - proxyStateTemplate := resourcetest.Resource(types.ProxyStateTemplateType, "test"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{}). - Write(suite.T(), suite.client) - - suite.mapper.TrackItem(proxyStateTemplate.Id, []resource.ReferenceOrID{}) - - // Simulate the proxy disconnecting from this server. The resource still exists, but this proxy might be connected - // to a different server now, so we no longer need to track it. - suite.updater.notConnected = true - - // Run the reconcile. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: proxyStateTemplate.Id, - }) - require.NoError(suite.T(), err) - - // Assert that nothing is tracked in the mapper. - require.True(suite.T(), suite.mapper.IsEmpty()) -} - -// This test sets up the updater to return an error when calling PushChange, and ensures the status is set -// correctly. -func (suite *xdsControllerTestSuite) TestReconcile_PushChangeError() { - // Have the mock simulate an error from the PushChange call. - suite.updater.pushChangeError = true - - // Setup a happy path scenario. - suite.setupFooProxyStateTemplateAndEndpoints() - - // Run the reconcile. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: suite.fooProxyStateTemplate.Id, - }) - require.Error(suite.T(), err) - - // Assert on the status reflecting endpoint not found. - suite.client.RequireStatusCondition(suite.T(), suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionRejectedPushChangeFailed(status.KeyFromID(suite.fooProxyStateTemplate.Id))) -} - -// This test sets up a ProxyStateTemplate that references a ServiceEndpoints that doesn't exist, and ensures the -// status is correct. -func (suite *xdsControllerTestSuite) TestReconcile_MissingEndpoint() { - // Set fooProxyStateTemplate with a reference to fooEndpoints, without storing fooEndpoints so the controller should - // notice it's missing. - fooEndpointsId := resourcetest.Resource(catalog.ServiceEndpointsType, "foo-service").ID() - fooRequiredEndpoints := make(map[string]*pbproxystate.EndpointRef) - fooRequiredEndpoints["test-cluster-1"] = &pbproxystate.EndpointRef{ - Id: fooEndpointsId, - Port: "mesh", - } - - fooProxyStateTemplate := resourcetest.Resource(types.ProxyStateTemplateType, "foo-pst"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{ - RequiredEndpoints: fooRequiredEndpoints, - ProxyState: &pbmesh.ProxyState{}, - }). - Write(suite.T(), suite.client) - - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireResourceExists(r, fooProxyStateTemplate.Id) - }) - - // Run the reconcile. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: fooProxyStateTemplate.Id, - }) - require.Error(suite.T(), err) - - // Assert on the status reflecting endpoint not found. - suite.client.RequireStatusCondition(suite.T(), fooProxyStateTemplate.Id, ControllerName, status.ConditionRejectedErrorReadingEndpoints(status.KeyFromID(fooEndpointsId), "rpc error: code = NotFound desc = resource not found")) -} - -// This test sets up a ProxyStateTemplate that references a ServiceEndpoints that can't be read correctly, and -// checks the status is correct. -func (suite *xdsControllerTestSuite) TestReconcile_ReadEndpointError() { - badID := &pbresource.ID{ - Type: &pbresource.Type{ - Group: "not", - Kind: "found", - GroupVersion: "vfake", - }, - Tenancy: &pbresource.Tenancy{Namespace: "default", Partition: "default", PeerName: "local"}, - } - fooRequiredEndpoints := make(map[string]*pbproxystate.EndpointRef) - fooRequiredEndpoints["test-cluster-1"] = &pbproxystate.EndpointRef{ - Id: badID, - Port: "mesh", - } - - fooProxyStateTemplate := resourcetest.Resource(types.ProxyStateTemplateType, "foo-pst"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{ - RequiredEndpoints: fooRequiredEndpoints, - ProxyState: &pbmesh.ProxyState{}, - }). - Write(suite.T(), suite.client) - - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireResourceExists(r, fooProxyStateTemplate.Id) - }) - - // Run the reconcile. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: fooProxyStateTemplate.Id, - }) - 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 is required")) -} - -// This test is a happy path creation test to make sure pbproxystate.Endpoints are created in the computed -// pbmesh.ProxyState from the RequiredEndpoints references. More specific translations between endpoint references -// and pbproxystate.Endpoints are unit tested in endpoint_builder.go. -func (suite *xdsControllerTestSuite) TestReconcile_ProxyStateTemplateComputesEndpoints() { - // Set up fooEndpoints and fooProxyStateTemplate with a reference to fooEndpoints and store them in the state store. - // This setup saves expected values in the suite so it can be asserted against later. - suite.setupFooProxyStateTemplateAndEndpoints() - - // Run the reconcile. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: suite.fooProxyStateTemplate.Id, - }) - require.NoError(suite.T(), err) - - // Assert on the status. - suite.client.RequireStatusCondition(suite.T(), suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - - // Assert that the endpoints computed in the controller matches the expected endpoints. - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - prototest.AssertDeepEqual(suite.T(), suite.expectedFooProxyStateEndpoints, actualEndpoints) -} - -func (suite *xdsControllerTestSuite) TestReconcile_ProxyStateTemplateSetsTrustBundles() { - // This test is a happy path creation test to make sure pbproxystate.Template.TrustBundles are created in the computed - // pbmesh.ProxyState from the TrustBundleFetcher. - suite.setupFooProxyStateTemplateAndEndpoints() - - // Run the reconcile. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: suite.fooProxyStateTemplate.Id, - }) - require.NoError(suite.T(), err) - - // Assert on the status. - suite.client.RequireStatusCondition(suite.T(), suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - - // Assert that the endpoints computed in the controller matches the expected endpoints. - actualTrustBundle := suite.updater.GetTrustBundle(suite.fooProxyStateTemplate.Id.Name) - prototest.AssertDeepEqual(suite.T(), suite.expectedTrustBundle, actualTrustBundle) -} - -// This test is a happy path creation test that calls reconcile multiple times with a more complex setup. This -// scenario is trickier to test in the controller test because the end computation of the xds controller is not -// stored in the state store. So this test ensures that between multiple reconciles the correct ProxyStates are -// computed for each ProxyStateTemplate. -func (suite *xdsControllerTestSuite) TestReconcile_MultipleProxyStateTemplatesComputesMultipleEndpoints() { - // Set up fooProxyStateTemplate and barProxyStateTemplate and their associated resources and store them. Resources - // and expected results are stored in the suite to assert against. - suite.setupFooBarProxyStateTemplateAndEndpoints() - - // Reconcile the fooProxyStateTemplate. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: suite.fooProxyStateTemplate.Id, - }) - require.NoError(suite.T(), err) - - // Assert on the status. - suite.client.RequireStatusCondition(suite.T(), suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - - // Assert that the endpoints computed in the controller matches the expected endpoints. - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - prototest.AssertDeepEqual(suite.T(), suite.expectedFooProxyStateEndpoints, actualEndpoints) - - // Reconcile the barProxyStateTemplate. - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: suite.barProxyStateTemplate.Id, - }) - require.NoError(suite.T(), err) - - // Assert on the status. - suite.client.RequireStatusCondition(suite.T(), suite.barProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - - // Assert that the endpoints computed in the controller matches the expected endpoints. - actualBarEndpoints := suite.updater.GetEndpoints(suite.barProxyStateTemplate.Id.Name) - prototest.AssertDeepEqual(suite.T(), suite.expectedBarProxyStateEndpoints, actualBarEndpoints) -} - -// Sets up a full controller, and tests that reconciles are getting triggered for the events it should. -func (suite *xdsControllerTestSuite) TestController_ComputeAddUpdateEndpoints() { - // Run the controller manager. - mgr := controller.NewManager(suite.client, suite.runtime.Logger) - mgr.Register(Controller(suite.mapper, suite.updater, suite.fetcher)) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - // Set up fooEndpoints and fooProxyStateTemplate with a reference to fooEndpoints. These need to be stored - // because the controller reconcile looks them up. - suite.setupFooProxyStateTemplateAndEndpoints() - - // Assert that the expected ProxyState matches the actual ProxyState that PushChange was called with. This needs to - // be in a retry block unlike the Reconcile tests because the controller triggers asynchronously. - retry.Run(suite.T(), func(r *retry.R) { - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - // Assert on the status. - suite.client.RequireStatusCondition(r, suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - // Assert that the endpoints computed in the controller matches the expected endpoints. - prototest.AssertDeepEqual(r, suite.expectedFooProxyStateEndpoints, actualEndpoints) - }) - - // Now, update the endpoint to be unhealthy. This will ensure the controller is getting triggered on changes to this - // endpoint that it should be tracking, even when the ProxyStateTemplate does not change. - resourcetest.Resource(catalog.ServiceEndpointsType, "foo-service"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.1.1.1", - Ports: []string{"mesh"}, - }, - { - Host: "10.2.2.2", - Ports: []string{"mesh"}, - }, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - }, - }}). - WithOwner(suite.fooService.Id). - Write(suite.T(), suite.client) - - // Wait for the endpoint to be written. - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireVersionChanged(suite.T(), suite.fooEndpoints.Id, suite.fooEndpoints.Version) - }) - - // Update the expected endpoints to also have unhealthy status. - suite.expectedFooProxyStateEndpoints["test-cluster-1"].Endpoints[0].HealthStatus = pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - suite.expectedFooProxyStateEndpoints["test-cluster-1"].Endpoints[1].HealthStatus = pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - - retry.Run(suite.T(), func(r *retry.R) { - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - // Assert on the status. - suite.client.RequireStatusCondition(suite.T(), suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - // Assert that the endpoints computed in the controller matches the expected endpoints. - prototest.AssertDeepEqual(r, suite.expectedFooProxyStateEndpoints, actualEndpoints) - }) - - // Now add a new endpoint reference and endpoint to the fooProxyStateTemplate. This will ensure that the controller - // now tracks the newly added endpoint. - secondService := resourcetest.Resource(catalog.ServiceType, "second-service"). - WithData(suite.T(), &pbcatalog.Service{}). - Write(suite.T(), suite.client) - - secondEndpoints := resourcetest.Resource(catalog.ServiceEndpointsType, "second-service"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.5.5.5", - Ports: []string{"mesh"}, - }, - { - Host: "10.6.6.6", - Ports: []string{"mesh"}, - }, - }, - }, - }}). - WithOwner(secondService.Id). - Write(suite.T(), suite.client) - - // Update the endpoint references on the fooProxyStateTemplate. - suite.fooEndpointRefs["test-cluster-2"] = &pbproxystate.EndpointRef{ - Id: secondEndpoints.Id, - Port: "mesh", - } - oldVersion := suite.fooProxyStateTemplate.Version - fooProxyStateTemplate := resourcetest.Resource(types.ProxyStateTemplateType, "foo-pst"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{ - RequiredEndpoints: suite.fooEndpointRefs, - ProxyState: &pbmesh.ProxyState{}, - }). - Write(suite.T(), suite.client) - - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireVersionChanged(r, fooProxyStateTemplate.Id, oldVersion) - }) - - // Update the expected endpoints with this new endpoints. - suite.expectedFooProxyStateEndpoints["test-cluster-2"] = &pbproxystate.Endpoints{ - Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.5.5.5", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.6.6.6", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }, - } - - retry.Run(suite.T(), func(r *retry.R) { - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - // Assert on the status. - suite.client.RequireStatusCondition(suite.T(), suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - // Assert that the endpoints computed in the controller matches the expected endpoints. - prototest.AssertDeepEqual(r, suite.expectedFooProxyStateEndpoints, actualEndpoints) - }) - -} - -// Sets up a full controller, and tests that reconciles are getting triggered for the events it should. -func (suite *xdsControllerTestSuite) TestController_ComputeEndpointForProxyConnections() { - // Run the controller manager. - mgr := controller.NewManager(suite.client, suite.runtime.Logger) - - mgr.Register(Controller(suite.mapper, suite.updater, suite.fetcher)) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - // Set up fooEndpoints and fooProxyStateTemplate with a reference to fooEndpoints. These need to be stored - // because the controller reconcile looks them up. - suite.setupFooProxyStateTemplateAndEndpoints() - - // Assert that the expected ProxyState matches the actual ProxyState that PushChange was called with. This needs to - // be in a retry block unlike the Reconcile tests because the controller triggers asynchronously. - retry.Run(suite.T(), func(r *retry.R) { - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - // Assert on the status. - suite.client.RequireStatusCondition(r, suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - // Assert that the endpoints computed in the controller matches the expected endpoints. - prototest.AssertDeepEqual(r, suite.expectedFooProxyStateEndpoints, actualEndpoints) - }) - - eventChannel := suite.updater.EventChannel() - eventChannel <- controller.Event{Obj: &proxytracker.ProxyConnection{ProxyID: suite.fooProxyStateTemplate.Id}} - - // Wait for the proxy state template to be re-evaluated. - proxyStateTemp := suite.client.WaitForNewVersion(suite.T(), suite.fooProxyStateTemplate.Id, suite.fooProxyStateTemplate.Version) - require.NotNil(suite.T(), proxyStateTemp) -} - -// Setup: fooProxyStateTemplate with an EndpointsRef to fooEndpoints -// Saves all related resources to the suite so they can be modified if needed. -func (suite *xdsControllerTestSuite) setupFooProxyStateTemplateAndEndpoints() { - fooService := resourcetest.Resource(catalog.ServiceType, "foo-service"). - WithData(suite.T(), &pbcatalog.Service{}). - Write(suite.T(), suite.client) - - fooEndpoints := resourcetest.Resource(catalog.ServiceEndpointsType, "foo-service"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.1.1.1", - Ports: []string{"mesh"}, - }, - { - Host: "10.2.2.2", - Ports: []string{"mesh"}, - }, - }, - }, - }}). - WithOwner(fooService.Id). - Write(suite.T(), suite.client) - - fooRequiredEndpoints := make(map[string]*pbproxystate.EndpointRef) - fooRequiredEndpoints["test-cluster-1"] = &pbproxystate.EndpointRef{ - Id: fooEndpoints.Id, - Port: "mesh", - } - - fooProxyStateTemplate := resourcetest.Resource(types.ProxyStateTemplateType, "foo-pst"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{ - RequiredEndpoints: fooRequiredEndpoints, - ProxyState: &pbmesh.ProxyState{}, - }). - Write(suite.T(), suite.client) - - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireResourceExists(r, fooProxyStateTemplate.Id) - }) - - expectedFooProxyStateEndpoints := map[string]*pbproxystate.Endpoints{ - "test-cluster-1": {Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.1.1.1", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.2.2.2", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }}, - } - - expectedTrustBundle := map[string]*pbproxystate.TrustBundle{ - "local": { - TrustDomain: "some-trust-domain", - Roots: []string{"some-root", "some-other-root"}, - }, - } - - suite.fooService = fooService - suite.fooEndpoints = fooEndpoints - suite.fooEndpointRefs = fooRequiredEndpoints - suite.fooProxyStateTemplate = fooProxyStateTemplate - suite.expectedFooProxyStateEndpoints = expectedFooProxyStateEndpoints - suite.expectedTrustBundle = expectedTrustBundle -} - -// Setup: -// - fooProxyStateTemplate with an EndpointsRef to fooEndpoints and fooBarEndpoints. -// - barProxyStateTemplate with an EndpointsRef to fooBarEndpoints. -// -// Saves all related resources to the suite so they can be modified if needed. -func (suite *xdsControllerTestSuite) setupFooBarProxyStateTemplateAndEndpoints() { - fooService := resourcetest.Resource(catalog.ServiceType, "foo-service"). - WithData(suite.T(), &pbcatalog.Service{}). - Write(suite.T(), suite.client) - - fooEndpoints := resourcetest.Resource(catalog.ServiceEndpointsType, "foo-service"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.1.1.1", - Ports: []string{"mesh"}, - }, - { - Host: "10.2.2.2", - Ports: []string{"mesh"}, - }, - }, - }, - }}). - WithOwner(fooService.Id). - Write(suite.T(), suite.client) - - fooBarService := resourcetest.Resource(catalog.ServiceType, "foo-bar-service"). - WithData(suite.T(), &pbcatalog.Service{}). - Write(suite.T(), suite.client) - - fooBarEndpoints := resourcetest.Resource(catalog.ServiceEndpointsType, "foo-bar-service"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.3.3.3", - Ports: []string{"mesh"}, - }, - { - Host: "10.4.4.4", - Ports: []string{"mesh"}, - }, - }, - }, - }}). - WithOwner(fooBarService.Id). - Write(suite.T(), suite.client) - - fooRequiredEndpoints := make(map[string]*pbproxystate.EndpointRef) - fooRequiredEndpoints["test-cluster-1"] = &pbproxystate.EndpointRef{ - Id: fooEndpoints.Id, - Port: "mesh", - } - fooRequiredEndpoints["test-cluster-2"] = &pbproxystate.EndpointRef{ - Id: fooBarEndpoints.Id, - Port: "mesh", - } - - barRequiredEndpoints := make(map[string]*pbproxystate.EndpointRef) - barRequiredEndpoints["test-cluster-1"] = &pbproxystate.EndpointRef{ - Id: fooBarEndpoints.Id, - // Sidecar proxy controller will usually set mesh port here. - Port: "mesh", - } - - fooProxyStateTemplate := resourcetest.Resource(types.ProxyStateTemplateType, "foo-pst"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{ - // Contains the foo and foobar endpoints. - RequiredEndpoints: fooRequiredEndpoints, - ProxyState: &pbmesh.ProxyState{}, - }). - Write(suite.T(), suite.client) - - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireResourceExists(r, fooProxyStateTemplate.Id) - }) - - barProxyStateTemplate := resourcetest.Resource(types.ProxyStateTemplateType, "bar-pst"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{ - // Contains the foobar endpoint. - RequiredEndpoints: barRequiredEndpoints, - ProxyState: &pbmesh.ProxyState{}, - }). - Write(suite.T(), suite.client) - - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireResourceExists(r, barProxyStateTemplate.Id) - }) - - expectedFooProxyStateEndpoints := map[string]*pbproxystate.Endpoints{ - "test-cluster-1": {Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.1.1.1", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.2.2.2", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }}, - "test-cluster-2": {Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.3.3.3", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.4.4.4", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }}, - } - - expectedBarProxyStateEndpoints := map[string]*pbproxystate.Endpoints{ - "test-cluster-1": {Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.3.3.3", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.4.4.4", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }}, - } - - suite.fooProxyStateTemplate = fooProxyStateTemplate - suite.barProxyStateTemplate = barProxyStateTemplate - suite.barEndpointRefs = barRequiredEndpoints - suite.fooEndpointRefs = fooRequiredEndpoints - suite.fooEndpoints = fooEndpoints - suite.fooService = fooService - suite.fooBarEndpoints = fooBarEndpoints - suite.fooBarService = fooBarService - suite.expectedFooProxyStateEndpoints = expectedFooProxyStateEndpoints - suite.expectedBarProxyStateEndpoints = expectedBarProxyStateEndpoints -} - -func TestXdsController(t *testing.T) { - suite.Run(t, new(xdsControllerTestSuite)) -} diff --git a/internal/mesh/internal/controllers/xds/endpoint_builder.go b/internal/mesh/internal/controllers/xds/endpoint_builder.go deleted file mode 100644 index 715dd2544bed6..0000000000000 --- a/internal/mesh/internal/controllers/xds/endpoint_builder.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "fmt" - "net" - - "golang.org/x/exp/slices" - - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" -) - -func generateProxyStateEndpoints(serviceEndpoints *ServiceEndpointsData, portName string) (*pbproxystate.Endpoints, error) { - var psEndpoints []*pbproxystate.Endpoint - - if serviceEndpoints.Endpoints == nil || serviceEndpoints.Resource == nil { - return nil, fmt.Errorf("service endpoints requires both endpoints and resource") - } - eps := serviceEndpoints.Endpoints.GetEndpoints() - - for _, ep := range eps { - for _, addr := range ep.Addresses { - // Check if the address is using the portName name this proxy state endpoints is for. If it does, create the - // endpoint. - if slices.Contains(addr.Ports, portName) { - // Lookup the portName number from the portName name. - wlPort, ok := ep.Ports[portName] - if !ok { - // This should never happen, as it should be validated by the ServiceEndpoints controller. - return nil, fmt.Errorf("could not find portName %q in endpoint %s", portName, serviceEndpoints.Resource.Id) - } - portNum := wlPort.Port - - psEndpoint, err := createProxyStateEndpoint(addr.Host, portNum, ep.HealthStatus) - if err != nil { - return nil, err - } - psEndpoints = append(psEndpoints, psEndpoint) - } - } - } - - return &pbproxystate.Endpoints{Endpoints: psEndpoints}, nil -} - -func createProxyStateEndpoint(host string, port uint32, health pbcatalog.Health) (*pbproxystate.Endpoint, error) { - addr := net.ParseIP(host) - if addr == nil { - return nil, fmt.Errorf("host is not an ip") - } - - psEndpoint := &pbproxystate.Endpoint{ - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: host, - Port: port, - }, - }, - HealthStatus: endpointHealth(health), - // TODO(xds): Weight will be added later. More information is potentially needed in the reference. - } - return psEndpoint, nil -} - -func endpointHealth(catalogHealth pbcatalog.Health) pbproxystate.HealthStatus { - health := pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY - - if catalogHealth == pbcatalog.Health_HEALTH_CRITICAL { - health = pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - } - return health -} diff --git a/internal/mesh/internal/controllers/xds/endpoint_builder_test.go b/internal/mesh/internal/controllers/xds/endpoint_builder_test.go deleted file mode 100644 index 3340014e0625d..0000000000000 --- a/internal/mesh/internal/controllers/xds/endpoint_builder_test.go +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestMakeProxyStateEndpointsFromServiceEndpoints(t *testing.T) { - type test struct { - name string - serviceEndpointsData *ServiceEndpointsData - portName string - expErr string - expectedProxyStateEndpoints *pbproxystate.Endpoints - } - cases := []test{ - { - name: "endpoints with passing health", - serviceEndpointsData: serviceEndpointsData("passing"), - portName: "mesh", - expectedProxyStateEndpoints: &pbproxystate.Endpoints{ - Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.1.1.1", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.2.2.2", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.3.3.3", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }, - }, - }, - { - name: "endpoints with critical health", - serviceEndpointsData: serviceEndpointsData("critical"), - portName: "mesh", - expectedProxyStateEndpoints: &pbproxystate.Endpoints{ - Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.1.1.1", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.2.2.2", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.3.3.3", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY, - }, - }, - }, - }, - { - name: "endpoints with any health are considered healthy", - serviceEndpointsData: serviceEndpointsData("any"), - portName: "mesh", - expectedProxyStateEndpoints: &pbproxystate.Endpoints{ - Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.1.1.1", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.2.2.2", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.3.3.3", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }, - }, - }, - { - name: "endpoints with missing ports returns an error", - serviceEndpointsData: serviceEndpointsData("missing port lookup"), - portName: "mesh", - expErr: "could not find portName", - }, - { - name: "nil endpoints returns an error", - serviceEndpointsData: serviceEndpointsData("nil endpoints"), - portName: "mesh", - expErr: "service endpoints requires both endpoints and resource", - }, - { - name: "nil resource returns an error", - serviceEndpointsData: serviceEndpointsData("nil resource"), - portName: "mesh", - expErr: "service endpoints requires both endpoints and resource", - }, - { - name: "portName doesn't exist in endpoints results in empty endpoints", - serviceEndpointsData: serviceEndpointsData("passing"), - portName: "does-not-exist", - expectedProxyStateEndpoints: &pbproxystate.Endpoints{ - Endpoints: []*pbproxystate.Endpoint{}, - }, - }, - } - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - actualEndpoints, err := generateProxyStateEndpoints(tc.serviceEndpointsData, tc.portName) - if tc.expErr != "" { - require.ErrorContains(t, err, tc.expErr) - } else { - prototest.AssertDeepEqual(t, tc.expectedProxyStateEndpoints, actualEndpoints) - } - }) - } -} - -func serviceEndpointsData(variation string) *ServiceEndpointsData { - r := resourcetest.Resource(catalog.ServiceEndpointsType, "test").Build() - eps := &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.1.1.1", - Ports: []string{"mesh"}, - }, - { - Host: "10.2.2.2", - Ports: []string{"mesh"}, - }, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.3.3.3", - Ports: []string{"mesh"}, - }, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - }, - } - - switch variation { - case "passing": - case "critical": - eps.Endpoints[0].HealthStatus = pbcatalog.Health_HEALTH_CRITICAL - eps.Endpoints[1].HealthStatus = pbcatalog.Health_HEALTH_CRITICAL - case "any": - eps.Endpoints[0].HealthStatus = pbcatalog.Health_HEALTH_ANY - eps.Endpoints[1].HealthStatus = pbcatalog.Health_HEALTH_ANY - case "missing port lookup": - delete(eps.Endpoints[0].Ports, "mesh") - case "nil endpoints": - eps = nil - case "nil resource": - r = nil - } - - return &ServiceEndpointsData{ - Resource: r, - Endpoints: eps, - } -} diff --git a/internal/mesh/internal/controllers/xds/mock_updater.go b/internal/mesh/internal/controllers/xds/mock_updater.go deleted file mode 100644 index f17a388e8e8b8..0000000000000 --- a/internal/mesh/internal/controllers/xds/mock_updater.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "fmt" - "sync" - - "github.com/hashicorp/consul/internal/controller" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" - "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// mockUpdater mocks the updater functions, and stores ProxyStates from calls to PushChange, so we can assert it was -// computed correctly in the controller. -type mockUpdater struct { - lock sync.Mutex - // latestPs is a map from a ProxyStateTemplate's id.Name in string form to the last computed ProxyState for that - // ProxyStateTemplate. - latestPs map[string]proxysnapshot.ProxySnapshot - notConnected bool - pushChangeError bool - eventChan chan controller.Event -} - -func newMockUpdater() *mockUpdater { - return &mockUpdater{ - latestPs: make(map[string]proxysnapshot.ProxySnapshot), - } -} - -func (m *mockUpdater) SetPushChangeErrorTrue() { - m.lock.Lock() - defer m.lock.Unlock() - m.pushChangeError = true -} - -func (m *mockUpdater) SetProxyAsNotConnected() { - m.lock.Lock() - defer m.lock.Unlock() - m.notConnected = true -} - -func (m *mockUpdater) PushChange(id *pbresource.ID, snapshot proxysnapshot.ProxySnapshot) error { - m.lock.Lock() - defer m.lock.Unlock() - if m.pushChangeError { - return fmt.Errorf("mock push change error") - } else { - m.setUnsafe(id.Name, snapshot.(*proxytracker.ProxyState)) - } - return nil -} - -func (m *mockUpdater) ProxyConnectedToServer(_ *pbresource.ID) bool { - m.lock.Lock() - defer m.lock.Unlock() - if m.notConnected { - return false - } - return true -} - -func (m *mockUpdater) EventChannel() chan controller.Event { - if m.eventChan == nil { - m.eventChan = make(chan controller.Event) - } - return m.eventChan -} - -func (p *mockUpdater) Get(name string) *proxytracker.ProxyState { - p.lock.Lock() - defer p.lock.Unlock() - ps, ok := p.latestPs[name] - if ok { - return ps.(*proxytracker.ProxyState) - } - return nil -} - -func (p *mockUpdater) GetEndpoints(name string) map[string]*pbproxystate.Endpoints { - p.lock.Lock() - defer p.lock.Unlock() - ps, ok := p.latestPs[name] - if ok { - return ps.(*proxytracker.ProxyState).Endpoints - } - return nil -} - -func (p *mockUpdater) GetTrustBundle(name string) map[string]*pbproxystate.TrustBundle { - p.lock.Lock() - defer p.lock.Unlock() - ps, ok := p.latestPs[name] - if ok { - return ps.(*proxytracker.ProxyState).TrustBundles - } - return nil -} - -func (p *mockUpdater) Set(name string, ps *proxytracker.ProxyState) { - p.lock.Lock() - defer p.lock.Unlock() - p.setUnsafe(name, ps) -} - -func (p *mockUpdater) setUnsafe(name string, ps *proxytracker.ProxyState) { - p.latestPs[name] = ps -} diff --git a/internal/mesh/internal/controllers/xds/proxy_tracker_watch.go b/internal/mesh/internal/controllers/xds/proxy_tracker_watch.go deleted file mode 100644 index 419a200a9104a..0000000000000 --- a/internal/mesh/internal/controllers/xds/proxy_tracker_watch.go +++ /dev/null @@ -1,21 +0,0 @@ -package xds - -import ( - "context" - "fmt" - - "github.com/hashicorp/consul/internal/controller" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" -) - -func proxySource(updater ProxyUpdater) *controller.Source { - return &controller.Source{Source: updater.EventChannel()} -} - -func proxyMapper(ctx context.Context, rt controller.Runtime, event controller.Event) ([]controller.Request, error) { - connection, ok := event.Obj.(*proxytracker.ProxyConnection) - if !ok { - return nil, fmt.Errorf("expected event to be of type *proxytracker.ProxyConnection but was %+v", event) - } - return []controller.Request{{ID: connection.ProxyID}}, nil -} diff --git a/internal/mesh/internal/controllers/xds/reconciliation_data.go b/internal/mesh/internal/controllers/xds/reconciliation_data.go deleted file mode 100644 index a4aae8fdc43f0..0000000000000 --- a/internal/mesh/internal/controllers/xds/reconciliation_data.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "context" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type ServiceEndpointsData struct { - Resource *pbresource.Resource - Endpoints *pbcatalog.ServiceEndpoints -} - -type ProxyStateTemplateData struct { - Resource *pbresource.Resource - Template *pbmesh.ProxyStateTemplate -} - -// getServiceEndpoints will return a non-nil &ServiceEndpointsData unless there is an error. -func getServiceEndpoints(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*ServiceEndpointsData, error) { - rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: id}) - if err != nil { - return nil, err - } - - var se pbcatalog.ServiceEndpoints - err = rsp.Resource.Data.UnmarshalTo(&se) - if err != nil { - return nil, resource.NewErrDataParse(&se, err) - } - - return &ServiceEndpointsData{Resource: rsp.Resource, Endpoints: &se}, nil -} - -func getProxyStateTemplate(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*ProxyStateTemplateData, error) { - rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: id}) - switch { - case status.Code(err) == codes.NotFound: - return nil, nil - case err != nil: - return nil, err - } - - var pst pbmesh.ProxyStateTemplate - err = rsp.Resource.Data.UnmarshalTo(&pst) - if err != nil { - return nil, resource.NewErrDataParse(&pst, err) - } - - return &ProxyStateTemplateData{Resource: rsp.Resource, Template: &pst}, nil -} diff --git a/internal/mesh/internal/controllers/xds/status/status.go b/internal/mesh/internal/controllers/xds/status/status.go deleted file mode 100644 index 0aff944f5495f..0000000000000 --- a/internal/mesh/internal/controllers/xds/status/status.go +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package status - -import ( - "context" - "fmt" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - StatusConditionProxyStateAccepted = "ProxyStateAccepted" - StatusReasonNilProxyState = "ProxyStateNil" - StatusReasonProxyStateReferencesComputed = "ProxyStateReferencesComputed" - StatusReasonEndpointNotRead = "ProxyStateEndpointReferenceReadError" - StatusReasonCreatingProxyStateEndpointsFailed = "ProxyStateEndpointsNotComputed" - StatusReasonPushChangeFailed = "ProxyStatePushChangeFailed" - StatusReasonTrustBundleFetchFailed = "ProxyStateTrustBundleFetchFailed" -) - -func KeyFromID(id *pbresource.ID) string { - return fmt.Sprintf("%s/%s/%s", - resource.ToGVK(id.Type), - resource.TenancyToString(id.Tenancy), - id.Name) -} - -func ConditionAccepted() *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_TRUE, - Reason: StatusReasonProxyStateReferencesComputed, - Message: fmt.Sprintf("proxy state was computed and pushed."), - } -} -func ConditionRejectedNilProxyState(pstRef string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonNilProxyState, - Message: fmt.Sprintf("nil proxy state is not valid %q.", pstRef), - } -} -func ConditionRejectedErrorReadingEndpoints(endpointRef string, err string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonEndpointNotRead, - Message: fmt.Sprintf("error reading referenced service endpoints %q: %s", endpointRef, err), - } -} -func ConditionRejectedCreatingProxyStateEndpoints(endpointRef string, err string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonCreatingProxyStateEndpointsFailed, - Message: fmt.Sprintf("could not create proxy state endpoints from service endpoints %q: %s", endpointRef, err), - } -} -func ConditionRejectedPushChangeFailed(pstRef string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonPushChangeFailed, - Message: fmt.Sprintf("failed to push change for proxy state template %q", pstRef), - } -} -func ConditionRejectedTrustBundleFetchFailed(pstRef string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonTrustBundleFetchFailed, - Message: fmt.Sprintf("failed to fetch trust bundle for proxy state template %q", pstRef), - } -} - -// WriteStatusIfChanged updates the ProxyStateTemplate status if it has changed. -func WriteStatusIfChanged(ctx context.Context, rt controller.Runtime, res *pbresource.Resource, condition *pbresource.Condition) { - newStatus := &pbresource.Status{ - ObservedGeneration: res.Generation, - Conditions: []*pbresource.Condition{ - condition, - }, - } - // If the status is unchanged then we should return and avoid the unnecessary write - const controllerName = "consul.io/xds-controller" - if resource.EqualStatus(res.Status[controllerName], newStatus, false) { - return - } else { - _, err := rt.Client.WriteStatus(ctx, &pbresource.WriteStatusRequest{ - Id: res.Id, - Key: controllerName, - Status: newStatus, - }) - - if err != nil { - rt.Logger.Error("error updating the proxy state template status", "error", err, "proxyStateTeamplate", res.Id) - } - } -} diff --git a/internal/mesh/internal/types/computed_routes.go b/internal/mesh/internal/types/computed_routes.go deleted file mode 100644 index c43627c896c45..0000000000000 --- a/internal/mesh/internal/types/computed_routes.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - ComputedRoutesKind = "ComputedRoutes" -) - -var ( - ComputedRoutesV1Alpha1Type = &pbresource.Type{ - Group: GroupName, - GroupVersion: VersionV1Alpha1, - Kind: ComputedRoutesKind, - } - - ComputedRoutesType = ComputedRoutesV1Alpha1Type -) - -func RegisterComputedRoutes(r resource.Registry) { - r.Register(resource.Registration{ - Type: ComputedRoutesV1Alpha1Type, - Proto: &pbmesh.ComputedRoutes{}, - Validate: ValidateComputedRoutes, - }) -} - -func ValidateComputedRoutes(res *pbresource.Resource) error { - var config pbmesh.ComputedRoutes - - if err := res.Data.UnmarshalTo(&config); err != nil { - return resource.NewErrDataParse(&config, err) - } - - var merr error - - if len(config.PortedConfigs) == 0 { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "ported_configs", - Wrapped: resource.ErrEmpty, - }) - } - - // TODO(rb): do more elaborate validation - - for port, pmc := range config.PortedConfigs { - wrapErr := func(err error) error { - return resource.ErrInvalidMapValue{ - Map: "ported_configs", - Key: port, - Wrapped: err, - } - } - if pmc.Config == nil { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "config", - Wrapped: resource.ErrEmpty, - })) - } - if len(pmc.Targets) == 0 { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "targets", - Wrapped: resource.ErrEmpty, - })) - } - } - - return merr -} diff --git a/internal/mesh/internal/types/computed_routes_test.go b/internal/mesh/internal/types/computed_routes_test.go deleted file mode 100644 index 46b2f890a71e5..0000000000000 --- a/internal/mesh/internal/types/computed_routes_test.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestValidateComputedRoutes(t *testing.T) { - type testcase struct { - routes *pbmesh.ComputedRoutes - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(ComputedRoutesType, "api"). - WithData(t, tc.routes). - Build() - - err := ValidateComputedRoutes(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.ComputedRoutes](t, res) - prototest.AssertDeepEqual(t, tc.routes, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - "empty": { - routes: &pbmesh.ComputedRoutes{}, - expectErr: `invalid "ported_configs" field: cannot be empty`, - }, - "empty config": { - routes: &pbmesh.ComputedRoutes{ - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: nil, - Targets: map[string]*pbmesh.BackendTargetDetails{ - "foo": {}, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within ported_configs: invalid "config" field: cannot be empty`, - }, - "empty targets": { - routes: &pbmesh.ComputedRoutes{ - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.InterpretedTCPRoute{}, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within ported_configs: invalid "targets" field: cannot be empty`, - }, - "valid": { - routes: &pbmesh.ComputedRoutes{ - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.InterpretedTCPRoute{}, - }, - Targets: map[string]*pbmesh.BackendTargetDetails{ - "foo": {}, - }, - }, - }, - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/mesh/internal/types/decoded.go b/internal/mesh/internal/types/decoded.go deleted file mode 100644 index 90ce21233327e..0000000000000 --- a/internal/mesh/internal/types/decoded.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" -) - -type ( - DecodedHTTPRoute = resource.DecodedResource[*pbmesh.HTTPRoute] - DecodedGRPCRoute = resource.DecodedResource[*pbmesh.GRPCRoute] - DecodedTCPRoute = resource.DecodedResource[*pbmesh.TCPRoute] - DecodedDestinationPolicy = resource.DecodedResource[*pbmesh.DestinationPolicy] - DecodedComputedRoutes = resource.DecodedResource[*pbmesh.ComputedRoutes] - DecodedFailoverPolicy = resource.DecodedResource[*pbcatalog.FailoverPolicy] - DecodedService = resource.DecodedResource[*pbcatalog.Service] -) diff --git a/internal/mesh/internal/types/destination_policy.go b/internal/mesh/internal/types/destination_policy.go deleted file mode 100644 index 1c1cbd57d2e13..0000000000000 --- a/internal/mesh/internal/types/destination_policy.go +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "fmt" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - DestinationPolicyKind = "DestinationPolicy" -) - -var ( - DestinationPolicyV1Alpha1Type = &pbresource.Type{ - Group: GroupName, - GroupVersion: VersionV1Alpha1, - Kind: DestinationPolicyKind, - } - - DestinationPolicyType = DestinationPolicyV1Alpha1Type -) - -func RegisterDestinationPolicy(r resource.Registry) { - r.Register(resource.Registration{ - Type: DestinationPolicyV1Alpha1Type, - Proto: &pbmesh.DestinationPolicy{}, - Validate: ValidateDestinationPolicy, - }) -} - -func ValidateDestinationPolicy(res *pbresource.Resource) error { - var policy pbmesh.DestinationPolicy - - if err := res.Data.UnmarshalTo(&policy); err != nil { - return resource.NewErrDataParse(&policy, err) - } - - var merr error - - if len(policy.PortConfigs) == 0 { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "port_configs", - Wrapped: resource.ErrEmpty, - }) - } - - for port, pc := range policy.PortConfigs { - wrapErr := func(err error) error { - return resource.ErrInvalidMapValue{ - Map: "port_configs", - Key: port, - Wrapped: err, - } - } - - if dur := pc.ConnectTimeout.AsDuration(); dur < 0 { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "connect_timeout", - Wrapped: fmt.Errorf("'%v', must be >= 0", dur), - })) - } - if dur := pc.RequestTimeout.AsDuration(); dur < 0 { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "request_timeout", - Wrapped: fmt.Errorf("'%v', must be >= 0", dur), - })) - } - - if pc.LoadBalancer != nil { - lb := pc.LoadBalancer - wrapLBErr := func(err error) error { - return wrapErr(resource.ErrInvalidField{ - Name: "load_balancer", - Wrapped: err, - }) - } - - switch lb.Policy { - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_UNSPECIFIED: - // means just do the default - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RANDOM: - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_ROUND_ROBIN: - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST: - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV: - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH: - default: - merr = multierror.Append(merr, wrapLBErr(resource.ErrInvalidField{ - Name: "policy", - Wrapped: fmt.Errorf("not a supported enum value: %v", lb.Policy), - })) - } - - if lb.Policy != pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH && lb.Config != nil { - if _, ok := lb.Config.(*pbmesh.LoadBalancer_RingHashConfig); ok { - merr = multierror.Append(merr, wrapLBErr(resource.ErrInvalidField{ - Name: "config", - Wrapped: fmt.Errorf("ring_hash_config specified for incompatible load balancing policy %q", lb.Policy), - })) - } - } - - if lb.Policy != pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST && lb.Config != nil { - if _, ok := lb.Config.(*pbmesh.LoadBalancer_LeastRequestConfig); ok { - merr = multierror.Append(merr, wrapLBErr(resource.ErrInvalidField{ - Name: "config", - Wrapped: fmt.Errorf("least_request_config specified for incompatible load balancing policy %q", lb.Policy), - })) - } - } - - if !lb.Policy.IsHashBased() && len(lb.HashPolicies) > 0 { - merr = multierror.Append(merr, wrapLBErr(resource.ErrInvalidField{ - Name: "hash_policies", - Wrapped: fmt.Errorf("hash_policies specified for non-hash-based policy %q", lb.Policy), - })) - } - - LOOP: - for i, hp := range lb.HashPolicies { - wrapHPErr := func(err error) error { - return wrapLBErr(resource.ErrInvalidListElement{ - Name: "hash_policies", - Index: i, - Wrapped: err, - }) - } - - var hasField bool - switch hp.Field { - case pbmesh.HashPolicyField_HASH_POLICY_FIELD_UNSPECIFIED: - case pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER, - pbmesh.HashPolicyField_HASH_POLICY_FIELD_COOKIE, - pbmesh.HashPolicyField_HASH_POLICY_FIELD_QUERY_PARAMETER: - hasField = true - default: - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "field", - Wrapped: fmt.Errorf("not a supported enum value: %v", hp.Field), - })) - continue LOOP // no need to keep validating - } - - if hp.SourceIp { - if hasField { - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "field", - Wrapped: fmt.Errorf("a single hash policy cannot hash both a source address and a %q", hp.Field), - })) - } - if hp.FieldValue != "" { - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "field_value", - Wrapped: errors.New("cannot be specified when hashing source_ip"), - })) - } - } - - if hasField && hp.FieldValue == "" { - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "field_value", - Wrapped: fmt.Errorf("field %q was specified without a field_value", hp.Field), - })) - } - if hp.FieldValue != "" && !hasField { - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "field", - Wrapped: resource.ErrMissing, - })) - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "field_value", - Wrapped: errors.New("requires a field to apply to"), - })) - } - if hp.CookieConfig != nil { - if hp.Field != pbmesh.HashPolicyField_HASH_POLICY_FIELD_COOKIE { - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "cookie_config", - Wrapped: fmt.Errorf("incompatible with field %q", hp.Field), - })) - } - if hp.CookieConfig.Session && hp.CookieConfig.Ttl.AsDuration() != 0 { - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "cookie_config", - Wrapped: resource.ErrInvalidField{ - Name: "ttl", - Wrapped: fmt.Errorf("a session cookie cannot have an associated TTL"), - }, - })) - } - } - } - } - - if pc.LocalityPrioritization != nil { - lp := pc.LocalityPrioritization - wrapLPErr := func(err error) error { - return wrapErr(resource.ErrInvalidField{ - Name: "locality_prioritization", - Wrapped: err, - }) - } - - switch lp.Mode { - case pbmesh.LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED: - // means pbmesh.LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_NONE - case pbmesh.LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_NONE: - case pbmesh.LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_FAILOVER: - default: - merr = multierror.Append(merr, wrapLPErr(resource.ErrInvalidField{ - Name: "mode", - Wrapped: fmt.Errorf("not a supported enum value: %v", lp.Mode), - })) - } - } - } - - return merr -} diff --git a/internal/mesh/internal/types/destination_policy_test.go b/internal/mesh/internal/types/destination_policy_test.go deleted file mode 100644 index 960c42aedea2a..0000000000000 --- a/internal/mesh/internal/types/destination_policy_test.go +++ /dev/null @@ -1,510 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/durationpb" - - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestValidateDestinationPolicy(t *testing.T) { - type testcase struct { - policy *pbmesh.DestinationPolicy - expectErr string - expectErrs []string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(DestinationPolicyType, "api"). - WithData(t, tc.policy). - Build() - - err := ValidateDestinationPolicy(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.DestinationPolicy](t, res) - prototest.AssertDeepEqual(t, tc.policy, got.Data) - - if tc.expectErr != "" && len(tc.expectErrs) > 0 { - t.Fatalf("cannot test singular and list errors at the same time") - } - - if tc.expectErr == "" && len(tc.expectErrs) == 0 { - require.NoError(t, err) - } else if tc.expectErr != "" { - testutil.RequireErrorContains(t, err, tc.expectErr) - } else { - for _, expectErr := range tc.expectErrs { - testutil.RequireErrorContains(t, err, expectErr) - } - } - } - - cases := map[string]testcase{ - // emptiness - "empty": { - policy: &pbmesh.DestinationPolicy{}, - expectErr: `invalid "port_configs" field: cannot be empty`, - }, - "good connect timeout": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - }, - }, - }, - }, - "bad connect timeout": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(-55 * time.Second), - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "connect_timeout" field: '-55s', must be >= 0`, - }, - "good request timeout": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - RequestTimeout: durationpb.New(55 * time.Second), - }, - }, - }, - }, - "bad request timeout": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - RequestTimeout: durationpb.New(-55 * time.Second), - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "request_timeout" field: '-55s', must be >= 0`, - }, - // load balancer - "lbpolicy: missing enum": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{}, - }, - }, - }, - }, - "lbpolicy: bad enum": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: 99, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid "policy" field: not a supported enum value: 99`, - }, - "lbpolicy: supported": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RANDOM, - }, - }, - }, - }, - }, - "lbpolicy: bad for least request config": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH, - Config: &pbmesh.LoadBalancer_LeastRequestConfig{ - LeastRequestConfig: &pbmesh.LeastRequestConfig{ - ChoiceCount: 10, - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid "config" field: least_request_config specified for incompatible load balancing policy "LOAD_BALANCER_POLICY_RING_HASH"`, - }, - "lbpolicy: bad for ring hash config": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST, - Config: &pbmesh.LoadBalancer_RingHashConfig{ - RingHashConfig: &pbmesh.RingHashConfig{ - MinimumRingSize: 1024, - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid "config" field: ring_hash_config specified for incompatible load balancing policy "LOAD_BALANCER_POLICY_LEAST_REQUEST"`, - }, - "lbpolicy: good for least request config": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST, - Config: &pbmesh.LoadBalancer_LeastRequestConfig{ - LeastRequestConfig: &pbmesh.LeastRequestConfig{ - ChoiceCount: 10, - }, - }, - }, - }, - }, - }, - }, - "lbpolicy: good for ring hash config": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH, - Config: &pbmesh.LoadBalancer_RingHashConfig{ - RingHashConfig: &pbmesh.RingHashConfig{ - MinimumRingSize: 1024, - }, - }, - }, - }, - }, - }, - }, - "lbpolicy: empty policy with hash policy": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - HashPolicies: []*pbmesh.HashPolicy{ - {SourceIp: true}, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid "hash_policies" field: hash_policies specified for non-hash-based policy "LOAD_BALANCER_POLICY_UNSPECIFIED"`, - }, - "lbconfig: cookie config with header policy": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER, - FieldValue: "x-user-id", - CookieConfig: &pbmesh.CookieConfig{ - Ttl: durationpb.New(10 * time.Second), - Path: "/root", - }, - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "cookie_config" field: incompatible with field "HASH_POLICY_FIELD_HEADER"`, - }, - "lbconfig: cannot generate session cookie with ttl": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_COOKIE, - FieldValue: "good-cookie", - CookieConfig: &pbmesh.CookieConfig{ - Session: true, - Ttl: durationpb.New(10 * time.Second), - }, - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "cookie_config" field: invalid "ttl" field: a session cookie cannot have an associated TTL`, - }, - "lbconfig: valid cookie policy": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_COOKIE, - FieldValue: "good-cookie", - CookieConfig: &pbmesh.CookieConfig{ - Ttl: durationpb.New(10 * time.Second), - Path: "/oven", - }, - }, - }, - }, - }, - }, - }, - }, - "lbconfig: bad match field": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: 99, - FieldValue: "X-Consul-Token", - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field" field: not a supported enum value: 99`, - }, - "lbconfig: supported match field": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER, - FieldValue: "X-Consul-Token", - }, - }, - }, - }, - }, - }, - }, - "lbconfig: missing match field": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - FieldValue: "X-Consul-Token", - }, - }, - }, - }, - }, - }, - expectErrs: []string{ - `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field" field: missing required field`, - `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field_value" field: requires a field to apply to`, - }, - }, - "lbconfig: cannot match on source address and custom field": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER, - SourceIp: true, - }, - }, - }, - }, - }, - }, - expectErrs: []string{ - `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field" field: a single hash policy cannot hash both a source address and a "HASH_POLICY_FIELD_HEADER"`, - `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field_value" field: field "HASH_POLICY_FIELD_HEADER" was specified without a field_value`, - }, - }, - "lbconfig: matchvalue not compatible with source address": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - FieldValue: "X-Consul-Token", - SourceIp: true, - }, - }, - }, - }, - }, - }, - expectErrs: []string{ - `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field_value" field: cannot be specified when hashing source_ip`, - `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field_value" field: requires a field to apply to`, - }, - }, - "lbconfig: field without match value": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER, - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field_value" field: field "HASH_POLICY_FIELD_HEADER" was specified without a field_value`, - }, - "lbconfig: matchvalue without field": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - FieldValue: "my-cookie", - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field_value" field: requires a field to apply to`, - }, - "lbconfig: ring hash kitchen sink": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH, - Config: &pbmesh.LoadBalancer_RingHashConfig{ - RingHashConfig: &pbmesh.RingHashConfig{ - MaximumRingSize: 10, - MinimumRingSize: 2, - }, - }, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_COOKIE, - FieldValue: "my-cookie", - }, - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER, - FieldValue: "alt-header", - Terminal: true, - }, - }, - }, - }, - }, - }, - }, - "lbconfig: least request kitchen sink": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST, - Config: &pbmesh.LoadBalancer_LeastRequestConfig{ - LeastRequestConfig: &pbmesh.LeastRequestConfig{ - ChoiceCount: 10, - }, - }, - }, - }, - }, - }, - }, - "locality: good mode": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - LocalityPrioritization: &pbmesh.LocalityPrioritization{ - Mode: pbmesh.LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_FAILOVER, - }, - }, - }, - }, - }, - "locality: unset mode": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - LocalityPrioritization: &pbmesh.LocalityPrioritization{ - Mode: pbmesh.LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED, - }, - }, - }, - }, - }, - "locality: bad mode": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - LocalityPrioritization: &pbmesh.LocalityPrioritization{ - Mode: 99, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "locality_prioritization" field: invalid "mode" field: not a supported enum value: 99`, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/mesh/internal/types/grpc_route.go b/internal/mesh/internal/types/grpc_route.go deleted file mode 100644 index 0d6c8df07f4e8..0000000000000 --- a/internal/mesh/internal/types/grpc_route.go +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "fmt" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - GRPCRouteKind = "GRPCRoute" -) - -var ( - GRPCRouteV1Alpha1Type = &pbresource.Type{ - Group: GroupName, - GroupVersion: VersionV1Alpha1, - Kind: GRPCRouteKind, - } - - GRPCRouteType = GRPCRouteV1Alpha1Type -) - -func RegisterGRPCRoute(r resource.Registry) { - r.Register(resource.Registration{ - Type: GRPCRouteV1Alpha1Type, - Proto: &pbmesh.GRPCRoute{}, - // TODO(rb): normalize parent/backend ref tenancies in a Mutate hook - Validate: ValidateGRPCRoute, - }) -} - -func ValidateGRPCRoute(res *pbresource.Resource) error { - var route pbmesh.GRPCRoute - - if err := res.Data.UnmarshalTo(&route); err != nil { - return resource.NewErrDataParse(&route, err) - } - - var merr error - if err := validateParentRefs(route.ParentRefs); err != nil { - merr = multierror.Append(merr, err) - } - - if len(route.Hostnames) > 0 { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "hostnames", - Wrapped: errors.New("should not populate hostnames"), - }) - } - - for i, rule := range route.Rules { - wrapRuleErr := func(err error) error { - return resource.ErrInvalidListElement{ - Name: "rules", - Index: i, - Wrapped: err, - } - } - - for j, match := range rule.Matches { - wrapMatchErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "matches", - Index: j, - Wrapped: err, - }) - } - - if match.Method != nil { - switch match.Method.Type { - case pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_UNSPECIFIED: - merr = multierror.Append(merr, wrapMatchErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: resource.ErrMissing, - }, - )) - case pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT: - case pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_REGEX: - default: - merr = multierror.Append(merr, wrapMatchErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: fmt.Errorf("not a supported enum value: %v", match.Method.Type), - }, - )) - } - if match.Method.Service == "" && match.Method.Method == "" { - merr = multierror.Append(merr, wrapMatchErr( - resource.ErrInvalidField{ - Name: "service", - Wrapped: errors.New("at least one of \"service\" or \"method\" must be set"), - }, - )) - } - } - - for k, header := range match.Headers { - wrapMatchHeaderErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "headers", - Index: k, - Wrapped: err, - }) - } - - if err := validateHeaderMatchType(header.Type); err != nil { - merr = multierror.Append(merr, wrapMatchHeaderErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: err, - }), - ) - } - - if header.Name == "" { - merr = multierror.Append(merr, wrapMatchHeaderErr( - resource.ErrInvalidField{ - Name: "name", - Wrapped: resource.ErrMissing, - }), - ) - } - } - } - - for j, filter := range rule.Filters { - wrapFilterErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "filters", - Index: j, - Wrapped: err, - }) - } - set := 0 - if filter.RequestHeaderModifier != nil { - set++ - } - if filter.ResponseHeaderModifier != nil { - set++ - } - if filter.UrlRewrite != nil { - set++ - if filter.UrlRewrite.PathPrefix == "" { - merr = multierror.Append(merr, wrapFilterErr( - resource.ErrInvalidField{ - Name: "url_rewrite", - Wrapped: resource.ErrInvalidField{ - Name: "path_prefix", - Wrapped: errors.New("field should not be empty if enclosing section is set"), - }, - }, - )) - } - } - if set != 1 { - merr = multierror.Append(merr, wrapFilterErr( - errors.New("exactly one of request_header_modifier, response_header_modifier, or url_rewrite is required"), - )) - } - } - - if len(rule.BackendRefs) == 0 { - /* - BackendRefs (optional)¶ - - BackendRefs defines API objects where matching requests should be - sent. If unspecified, the rule performs no forwarding. If - unspecified and no filters are specified that would result in a - response being sent, a 404 error code is returned. - */ - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "backend_refs", - Wrapped: resource.ErrEmpty, - }, - )) - } - for j, hbref := range rule.BackendRefs { - wrapBackendRefErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "backend_refs", - Index: j, - Wrapped: err, - }) - } - for _, err := range validateBackendRef(hbref.BackendRef) { - merr = multierror.Append(merr, wrapBackendRefErr( - resource.ErrInvalidField{ - Name: "backend_ref", - Wrapped: err, - }, - )) - } - - if len(hbref.Filters) > 0 { - merr = multierror.Append(merr, wrapBackendRefErr( - resource.ErrInvalidField{ - Name: "filters", - Wrapped: errors.New("filters are not supported at this level yet"), - }, - )) - } - } - - if rule.Timeouts != nil { - for _, err := range validateHTTPTimeouts(rule.Timeouts) { - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "timeouts", - Wrapped: err, - }, - )) - } - } - if rule.Retries != nil { - for _, err := range validateHTTPRetries(rule.Retries) { - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "retries", - Wrapped: err, - }, - )) - } - } - } - - return merr -} diff --git a/internal/mesh/internal/types/grpc_route_test.go b/internal/mesh/internal/types/grpc_route_test.go deleted file mode 100644 index e9abc118c6546..0000000000000 --- a/internal/mesh/internal/types/grpc_route_test.go +++ /dev/null @@ -1,523 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestValidateGRPCRoute(t *testing.T) { - type testcase struct { - route *pbmesh.GRPCRoute - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(GRPCRouteType, "api"). - WithData(t, tc.route). - Build() - - err := ValidateGRPCRoute(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.GRPCRoute](t, res) - prototest.AssertDeepEqual(t, tc.route, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - "hostnames not supported for services": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Hostnames: []string{"foo.local"}, - }, - expectErr: `invalid "hostnames" field: should not populate hostnames`, - }, - "no rules": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - }, - }, - "rules with no matches": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "rules with matches that are empty": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - // none - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "method match with no type is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Service: "foo", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "type" field: missing required field`, - }, - "method match with unknown type is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Type: 99, - Service: "foo", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "type" field: not a supported enum value: 99`, - }, - "method match with no service nor method is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Type: pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT, - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "service" field: at least one of "service" or "method" must be set`, - }, - "method match is good (1)": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Type: pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT, - Service: "foo", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "method match is good (2)": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Type: pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT, - Method: "bar", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "method match is good (3)": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Type: pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT, - Service: "foo", - Method: "bar", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "header match with no type is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Headers: []*pbmesh.GRPCHeaderMatch{{ - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "headers": invalid "type" field: missing required field`, - }, - "header match with unknown type is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Headers: []*pbmesh.GRPCHeaderMatch{{ - Type: 99, - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "headers": invalid "type" field: not a supported enum value: 99`, - }, - "header match with no name is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Headers: []*pbmesh.GRPCHeaderMatch{{ - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - }}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "headers": invalid "name" field: missing required field`, - }, - "header match is good": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Headers: []*pbmesh.GRPCHeaderMatch{{ - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter empty is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - // none - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter req header mod is ok": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter resp header mod is ok": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter rewrite header mod missing path prefix": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": invalid "url_rewrite" field: invalid "path_prefix" field: field should not be empty if enclosing section is set`, - }, - "filter rewrite header mod is ok": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter req+resp header mod is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter req+rewrite header mod is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter resp+rewrite header mod is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter req+resp+rewrite header mod is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "backend ref with filters is unsupported": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - Filters: []*pbmesh.GRPCRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "backend_refs": invalid "filters" field: filters are not supported at this level yet`, - }, - "nil backend ref": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - BackendRefs: []*pbmesh.GRPCBackendRef{nil}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "backend_refs": invalid "backend_ref" field: missing required field`, - }, - } - - // Add common timeouts test cases. - for name, timeoutsTC := range getXRouteTimeoutsTestCases() { - cases["timeouts: "+name] = testcase{ - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Timeouts: timeoutsTC.timeouts, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: timeoutsTC.expectErr, - } - } - - // Add common retries test cases. - for name, retriesTC := range getXRouteRetriesTestCases() { - cases["retries: "+name] = testcase{ - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Retries: retriesTC.retries, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: retriesTC.expectErr, - } - } - - // Add common parent refs test cases. - for name, parentTC := range getXRouteParentRefTestCases() { - cases["parent-ref: "+name] = testcase{ - route: &pbmesh.GRPCRoute{ - ParentRefs: parentTC.refs, - }, - expectErr: parentTC.expectErr, - } - } - // add common backend ref test cases. - for name, backendTC := range getXRouteBackendRefTestCases() { - var refs []*pbmesh.GRPCBackendRef - for _, br := range backendTC.refs { - refs = append(refs, &pbmesh.GRPCBackendRef{ - BackendRef: br, - }) - } - cases["backend-ref: "+name] = testcase{ - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{ - {BackendRefs: refs}, - }, - }, - expectErr: backendTC.expectErr, - } - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/mesh/internal/types/http_route.go b/internal/mesh/internal/types/http_route.go deleted file mode 100644 index d348091a7e92f..0000000000000 --- a/internal/mesh/internal/types/http_route.go +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "fmt" - "net/http" - "strings" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - HTTPRouteKind = "HTTPRoute" -) - -var ( - HTTPRouteV1Alpha1Type = &pbresource.Type{ - Group: GroupName, - GroupVersion: VersionV1Alpha1, - Kind: HTTPRouteKind, - } - - HTTPRouteType = HTTPRouteV1Alpha1Type -) - -func RegisterHTTPRoute(r resource.Registry) { - r.Register(resource.Registration{ - Type: HTTPRouteV1Alpha1Type, - Proto: &pbmesh.HTTPRoute{}, - Mutate: MutateHTTPRoute, - Validate: ValidateHTTPRoute, - }) -} - -func MutateHTTPRoute(res *pbresource.Resource) error { - var route pbmesh.HTTPRoute - - if err := res.Data.UnmarshalTo(&route); err != nil { - return resource.NewErrDataParse(&route, err) - } - - changed := false - - for _, rule := range route.Rules { - for _, match := range rule.Matches { - if match.Method != "" { - norm := strings.ToUpper(match.Method) - if match.Method != norm { - match.Method = norm - changed = true - } - } - } - } - - // TODO(rb): normalize parent/backend ref tenancies - - if !changed { - return nil - } - - return res.Data.MarshalFrom(&route) -} - -func ValidateHTTPRoute(res *pbresource.Resource) error { - var route pbmesh.HTTPRoute - - if err := res.Data.UnmarshalTo(&route); err != nil { - return resource.NewErrDataParse(&route, err) - } - - var merr error - if err := validateParentRefs(route.ParentRefs); err != nil { - merr = multierror.Append(merr, err) - } - - if len(route.Hostnames) > 0 { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "hostnames", - Wrapped: errors.New("should not populate hostnames"), - }) - } - - for i, rule := range route.Rules { - wrapRuleErr := func(err error) error { - return resource.ErrInvalidListElement{ - Name: "rules", - Index: i, - Wrapped: err, - } - } - - for j, match := range rule.Matches { - wrapMatchErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "matches", - Index: j, - Wrapped: err, - }) - } - - if match.Path != nil { - wrapMatchPathErr := func(err error) error { - return wrapMatchErr(resource.ErrInvalidField{ - Name: "path", - Wrapped: err, - }) - } - switch match.Path.Type { - case pbmesh.PathMatchType_PATH_MATCH_TYPE_UNSPECIFIED: - merr = multierror.Append(merr, wrapMatchPathErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: resource.ErrMissing, - }, - )) - case pbmesh.PathMatchType_PATH_MATCH_TYPE_EXACT: - if !strings.HasPrefix(match.Path.Value, "/") { - merr = multierror.Append(merr, wrapMatchPathErr( - resource.ErrInvalidField{ - Name: "value", - Wrapped: fmt.Errorf("exact patch value does not start with '/': %q", match.Path.Value), - }, - )) - } - case pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX: - if !strings.HasPrefix(match.Path.Value, "/") { - merr = multierror.Append(merr, wrapMatchPathErr( - resource.ErrInvalidField{ - Name: "value", - Wrapped: fmt.Errorf("prefix patch value does not start with '/': %q", match.Path.Value), - }, - )) - } - default: - merr = multierror.Append(merr, wrapMatchPathErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: fmt.Errorf("not a supported enum value: %v", match.Path.Type), - }, - )) - } - } - - for k, hdr := range match.Headers { - wrapMatchHeaderErr := func(err error) error { - return wrapMatchErr(resource.ErrInvalidListElement{ - Name: "headers", - Index: k, - Wrapped: err, - }) - } - - if err := validateHeaderMatchType(hdr.Type); err != nil { - merr = multierror.Append(merr, wrapMatchHeaderErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: err, - }), - ) - } - - if hdr.Name == "" { - merr = multierror.Append(merr, wrapMatchHeaderErr( - resource.ErrInvalidField{ - Name: "name", - Wrapped: resource.ErrMissing, - }), - ) - } - } - - for k, qm := range match.QueryParams { - wrapMatchParamErr := func(err error) error { - return wrapMatchErr(resource.ErrInvalidListElement{ - Name: "query_params", - Index: k, - Wrapped: err, - }) - } - - switch qm.Type { - case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_UNSPECIFIED: - merr = multierror.Append(merr, wrapMatchParamErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: resource.ErrMissing, - }), - ) - case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT: - case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_REGEX: - case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_PRESENT: - default: - merr = multierror.Append(merr, wrapMatchParamErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: fmt.Errorf("not a supported enum value: %v", qm.Type), - }, - )) - } - - if qm.Name == "" { - merr = multierror.Append(merr, wrapMatchParamErr( - resource.ErrInvalidField{ - Name: "name", - Wrapped: resource.ErrMissing, - }), - ) - } - } - - if match.Method != "" && !isValidHTTPMethod(match.Method) { - merr = multierror.Append(merr, wrapMatchErr( - resource.ErrInvalidField{ - Name: "method", - Wrapped: fmt.Errorf("not a valid http method: %q", match.Method), - }, - )) - } - } - - for j, filter := range rule.Filters { - wrapFilterErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "filters", - Index: j, - Wrapped: err, - }) - } - set := 0 - if filter.RequestHeaderModifier != nil { - set++ - } - if filter.ResponseHeaderModifier != nil { - set++ - } - if filter.UrlRewrite != nil { - set++ - if filter.UrlRewrite.PathPrefix == "" { - merr = multierror.Append(merr, wrapFilterErr( - resource.ErrInvalidField{ - Name: "url_rewrite", - Wrapped: resource.ErrInvalidField{ - Name: "path_prefix", - Wrapped: errors.New("field should not be empty if enclosing section is set"), - }, - }, - )) - } - } - if set != 1 { - merr = multierror.Append(merr, wrapFilterErr( - errors.New("exactly one of request_header_modifier, response_header_modifier, or url_rewrite is required"), - )) - } - } - - if len(rule.BackendRefs) == 0 { - /* - BackendRefs (optional)¶ - - BackendRefs defines API objects where matching requests should be - sent. If unspecified, the rule performs no forwarding. If - unspecified and no filters are specified that would result in a - response being sent, a 404 error code is returned. - */ - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "backend_refs", - Wrapped: resource.ErrEmpty, - }, - )) - } - for j, hbref := range rule.BackendRefs { - wrapBackendRefErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "backend_refs", - Index: j, - Wrapped: err, - }) - } - - for _, err := range validateBackendRef(hbref.BackendRef) { - merr = multierror.Append(merr, wrapBackendRefErr( - resource.ErrInvalidField{ - Name: "backend_ref", - Wrapped: err, - }, - )) - } - - if len(hbref.Filters) > 0 { - merr = multierror.Append(merr, wrapBackendRefErr( - resource.ErrInvalidField{ - Name: "filters", - Wrapped: errors.New("filters are not supported at this level yet"), - }, - )) - } - } - - if rule.Timeouts != nil { - for _, err := range validateHTTPTimeouts(rule.Timeouts) { - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "timeouts", - Wrapped: err, - }, - )) - } - } - if rule.Retries != nil { - for _, err := range validateHTTPRetries(rule.Retries) { - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "retries", - Wrapped: err, - }, - )) - } - } - } - - return merr -} - -func isValidHTTPMethod(method string) bool { - switch method { - case http.MethodGet, - http.MethodHead, - http.MethodPost, - http.MethodPut, - http.MethodPatch, - http.MethodDelete, - http.MethodConnect, - http.MethodOptions, - http.MethodTrace: - return true - default: - return false - } -} diff --git a/internal/mesh/internal/types/http_route_test.go b/internal/mesh/internal/types/http_route_test.go deleted file mode 100644 index 0f4626aa7094a..0000000000000 --- a/internal/mesh/internal/types/http_route_test.go +++ /dev/null @@ -1,980 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/durationpb" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestMutateHTTPRoute(t *testing.T) { - type testcase struct { - route *pbmesh.HTTPRoute - expect *pbmesh.HTTPRoute - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(HTTPRouteType, "api"). - WithData(t, tc.route). - Build() - - err := MutateHTTPRoute(res) - - got := resourcetest.MustDecode[*pbmesh.HTTPRoute](t, res) - - if tc.expectErr == "" { - require.NoError(t, err) - - if tc.expect == nil { - tc.expect = proto.Clone(tc.route).(*pbmesh.HTTPRoute) - } - - prototest.AssertDeepEqual(t, tc.expect, got.Data) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - "no-rules": { - route: &pbmesh.HTTPRoute{}, - }, - "rules-with-no-matches": { - route: &pbmesh.HTTPRoute{ - Rules: []*pbmesh.HTTPRouteRule{{ - // none - }}, - }, - }, - "rules-with-matches-no-methods": { - route: &pbmesh.HTTPRoute{ - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/foo", - }, - }}, - }}, - }, - }, - "rules-with-matches-methods-uppercase": { - route: &pbmesh.HTTPRoute{ - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{ - { - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/foo", - }, - Method: "GET", - }, - { - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/bar", - }, - Method: "POST", - }, - }, - }}, - }, - }, - "rules-with-matches-methods-lowercase": { - route: &pbmesh.HTTPRoute{ - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{ - { - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/foo", - }, - Method: "get", - }, - { - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/bar", - }, - Method: "post", - }, - }, - }}, - }, - expect: &pbmesh.HTTPRoute{ - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{ - { - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/foo", - }, - Method: "GET", - }, - { - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/bar", - }, - Method: "POST", - }, - }, - }}, - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestValidateHTTPRoute(t *testing.T) { - type testcase struct { - route *pbmesh.HTTPRoute - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(HTTPRouteType, "api"). - WithData(t, tc.route). - Build() - - err := MutateHTTPRoute(res) - require.NoError(t, err) - - err = ValidateHTTPRoute(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.HTTPRoute](t, res) - prototest.AssertDeepEqual(t, tc.route, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - "hostnames not supported for services": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Hostnames: []string{"foo.local"}, - }, - expectErr: `invalid "hostnames" field: should not populate hostnames`, - }, - "no rules": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - }, - }, - "rules with no matches": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "rules with matches that are empty": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - // none - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "path match with no type is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Value: "/foo", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "path" field: invalid "type" field: missing required field`, - }, - "path match with unknown type is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: 99, - Value: "/foo", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "path" field: invalid "type" field: not a supported enum value: 99`, - }, - "exact path match with no leading slash is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_EXACT, - Value: "foo", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "path" field: invalid "value" field: exact patch value does not start with '/': "foo"`, - }, - "prefix path match with no leading slash is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "foo", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "path" field: invalid "value" field: prefix patch value does not start with '/': "foo"`, - }, - "exact path match with leading slash is good": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_EXACT, - Value: "/foo", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "prefix path match with leading slash is good": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/foo", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "header match with no type is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Headers: []*pbmesh.HTTPHeaderMatch{{ - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid element at index 0 of list "headers": invalid "type" field: missing required field`, - }, - "header match with unknown type is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Headers: []*pbmesh.HTTPHeaderMatch{{ - Type: 99, - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid element at index 0 of list "headers": invalid "type" field: not a supported enum value: 99`, - }, - "header match with no name is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Headers: []*pbmesh.HTTPHeaderMatch{{ - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid element at index 0 of list "headers": invalid "name" field: missing required field`, - }, - "header match is good": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Headers: []*pbmesh.HTTPHeaderMatch{{ - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "queryparam match with no type is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - QueryParams: []*pbmesh.HTTPQueryParamMatch{{ - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid element at index 0 of list "query_params": invalid "type" field: missing required field`, - }, - "queryparam match with unknown type is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - QueryParams: []*pbmesh.HTTPQueryParamMatch{{ - Type: 99, - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid element at index 0 of list "query_params": invalid "type" field: not a supported enum value: 99`, - }, - "queryparam match with no name is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - QueryParams: []*pbmesh.HTTPQueryParamMatch{{ - Type: pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT, - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid element at index 0 of list "query_params": invalid "name" field: missing required field`, - }, - "queryparam match is good": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - QueryParams: []*pbmesh.HTTPQueryParamMatch{{ - Type: pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT, - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "method match is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Method: "BOB", - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "method" field: not a valid http method: "BOB"`, - }, - "method match is good": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Method: "DELETE", - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter empty is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - // none - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter req header mod is ok": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter resp header mod is ok": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter rewrite header mod missing path prefix": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": invalid "url_rewrite" field: invalid "path_prefix" field: field should not be empty if enclosing section is set`, - }, - "filter rewrite header mod is ok": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter req+resp header mod is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter req+rewrite header mod is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter resp+rewrite header mod is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter req+resp+rewrite header mod is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "backend ref with filters is unsupported": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - Filters: []*pbmesh.HTTPRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "backend_refs": invalid "filters" field: filters are not supported at this level yet`, - }, - "nil backend ref": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{nil}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "backend_refs": invalid "backend_ref" field: missing required field`, - }, - } - - // Add common timeouts test cases. - for name, timeoutsTC := range getXRouteTimeoutsTestCases() { - cases["timeouts: "+name] = testcase{ - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Timeouts: timeoutsTC.timeouts, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: timeoutsTC.expectErr, - } - } - - // Add common retries test cases. - for name, retriesTC := range getXRouteRetriesTestCases() { - cases["retries: "+name] = testcase{ - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Retries: retriesTC.retries, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(catalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: retriesTC.expectErr, - } - } - - // Add common parent refs test cases. - for name, parentTC := range getXRouteParentRefTestCases() { - cases["parent-ref: "+name] = testcase{ - route: &pbmesh.HTTPRoute{ - ParentRefs: parentTC.refs, - }, - expectErr: parentTC.expectErr, - } - } - // add common backend ref test cases. - for name, backendTC := range getXRouteBackendRefTestCases() { - var refs []*pbmesh.HTTPBackendRef - for _, br := range backendTC.refs { - refs = append(refs, &pbmesh.HTTPBackendRef{ - BackendRef: br, - }) - } - cases["backend-ref: "+name] = testcase{ - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{ - {BackendRefs: refs}, - }, - }, - expectErr: backendTC.expectErr, - } - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -type xRouteParentRefTestcase struct { - refs []*pbmesh.ParentReference - expectErr string -} - -func getXRouteParentRefTestCases() map[string]xRouteParentRefTestcase { - return map[string]xRouteParentRefTestcase{ - "no parent refs": { - expectErr: `invalid "parent_refs" field: cannot be empty`, - }, - "parent ref with nil ref": { - refs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "api", ""), - { - Ref: nil, - Port: "http", - }, - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "ref" field: missing required field`, - }, - "parent ref with bad type ref": { - refs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "api", ""), - newParentRef(catalog.WorkloadType, "api", ""), - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "ref" field: reference must have type catalog.v1alpha1.Service`, - }, - "parent ref with section": { - refs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "api", ""), - { - Ref: resourcetest.Resource(catalog.ServiceType, "web").Reference("section2"), - Port: "http", - }, - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "ref" field: invalid "section" field: section not supported for service parent refs`, - }, - "duplicate exact parents": { - refs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "api", "http"), - newParentRef(catalog.ServiceType, "api", "http"), - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "ref" field: parent ref "catalog.v1alpha1.Service/default.local.default/api" for port "http" exists twice`, - }, - "duplicate wild parents": { - refs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "api", ""), - newParentRef(catalog.ServiceType, "api", ""), - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "ref" field: parent ref "catalog.v1alpha1.Service/default.local.default/api" for wildcard port exists twice`, - }, - "duplicate parents via exact+wild overlap": { - refs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "api", "http"), - newParentRef(catalog.ServiceType, "api", ""), - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "ref" field: parent ref "catalog.v1alpha1.Service/default.local.default/api" for ports [http] covered by wildcard port already`, - }, - "duplicate parents via exact+wild overlap (reversed)": { - refs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "api", ""), - newParentRef(catalog.ServiceType, "api", "http"), - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "ref" field: parent ref "catalog.v1alpha1.Service/default.local.default/api" for port "http" covered by wildcard port already`, - }, - "good single parent ref": { - refs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "api", "http"), - }, - }, - "good muliple parent refs": { - refs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "api", "http"), - newParentRef(catalog.ServiceType, "web", ""), - }, - }, - } -} - -type xRouteBackendRefTestcase struct { - refs []*pbmesh.BackendReference - expectErr string -} - -func getXRouteBackendRefTestCases() map[string]xRouteBackendRefTestcase { - return map[string]xRouteBackendRefTestcase{ - "no backend refs": { - expectErr: `invalid "backend_refs" field: cannot be empty`, - }, - "backend ref with nil ref": { - refs: []*pbmesh.BackendReference{ - newBackendRef(catalog.ServiceType, "api", ""), - { - Ref: nil, - Port: "http", - }, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 1 of list "backend_refs": invalid "backend_ref" field: invalid "ref" field: missing required field`, - }, - "backend ref with bad type ref": { - refs: []*pbmesh.BackendReference{ - newBackendRef(catalog.ServiceType, "api", ""), - newBackendRef(catalog.WorkloadType, "api", ""), - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 1 of list "backend_refs": invalid "backend_ref" field: invalid "ref" field: reference must have type catalog.v1alpha1.Service`, - }, - "backend ref with section": { - refs: []*pbmesh.BackendReference{ - newBackendRef(catalog.ServiceType, "api", ""), - { - Ref: resourcetest.Resource(catalog.ServiceType, "web").Reference("section2"), - Port: "http", - }, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 1 of list "backend_refs": invalid "backend_ref" field: invalid "ref" field: invalid "section" field: section not supported for service backend refs`, - }, - "backend ref with datacenter": { - refs: []*pbmesh.BackendReference{ - newBackendRef(catalog.ServiceType, "api", ""), - { - Ref: newRef(catalog.ServiceType, "db"), - Port: "http", - Datacenter: "dc2", - }, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 1 of list "backend_refs": invalid "backend_ref" field: invalid "datacenter" field: datacenter is not yet supported on backend refs`, - }, - "good backend ref": { - refs: []*pbmesh.BackendReference{ - newBackendRef(catalog.ServiceType, "api", ""), - { - Ref: newRef(catalog.ServiceType, "db"), - Port: "http", - }, - }, - }, - } -} - -type xRouteTimeoutsTestcase struct { - timeouts *pbmesh.HTTPRouteTimeouts - expectErr string -} - -func getXRouteTimeoutsTestCases() map[string]xRouteTimeoutsTestcase { - return map[string]xRouteTimeoutsTestcase{ - "bad request": { - timeouts: &pbmesh.HTTPRouteTimeouts{ - Request: durationpb.New(-1 * time.Second), - }, - expectErr: `invalid element at index 0 of list "rules": invalid "timeouts" field: invalid "request" field: timeout cannot be negative: -1s`, - }, - "bad backend request": { - timeouts: &pbmesh.HTTPRouteTimeouts{ - BackendRequest: durationpb.New(-1 * time.Second), - }, - expectErr: `invalid element at index 0 of list "rules": invalid "timeouts" field: invalid "backend_request" field: timeout cannot be negative: -1s`, - }, - "bad idle": { - timeouts: &pbmesh.HTTPRouteTimeouts{ - Idle: durationpb.New(-1 * time.Second), - }, - expectErr: `invalid element at index 0 of list "rules": invalid "timeouts" field: invalid "idle" field: timeout cannot be negative: -1s`, - }, - "good all": { - timeouts: &pbmesh.HTTPRouteTimeouts{ - Request: durationpb.New(1 * time.Second), - BackendRequest: durationpb.New(2 * time.Second), - Idle: durationpb.New(3 * time.Second), - }, - }, - } -} - -type xRouteRetriesTestcase struct { - retries *pbmesh.HTTPRouteRetries - expectErr string -} - -func getXRouteRetriesTestCases() map[string]xRouteRetriesTestcase { - return map[string]xRouteRetriesTestcase{ - "bad number": { - retries: &pbmesh.HTTPRouteRetries{ - Number: -5, - }, - expectErr: `invalid element at index 0 of list "rules": invalid "retries" field: invalid "number" field: cannot be negative: -5`, - }, - "bad conditions": { - retries: &pbmesh.HTTPRouteRetries{ - OnConditions: []string{"garbage"}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid "retries" field: invalid element at index 0 of list "on_conditions": not a valid retry condition: "garbage"`, - }, - "good all": { - retries: &pbmesh.HTTPRouteRetries{ - Number: 5, - OnConditions: []string{"internal"}, - }, - }, - } -} - -func newRef(typ *pbresource.Type, name string) *pbresource.Reference { - return resourcetest.Resource(typ, name).Reference("") -} - -func newBackendRef(typ *pbresource.Type, name, port string) *pbmesh.BackendReference { - return &pbmesh.BackendReference{ - Ref: newRef(typ, name), - Port: port, - } -} - -func newParentRef(typ *pbresource.Type, name, port string) *pbmesh.ParentReference { - return &pbmesh.ParentReference{ - Ref: newRef(typ, name), - Port: port, - } -} diff --git a/internal/mesh/internal/types/proxy_configuration.go b/internal/mesh/internal/types/proxy_configuration.go index e85a00494f0f9..9205dc81b132a 100644 --- a/internal/mesh/internal/types/proxy_configuration.go +++ b/internal/mesh/internal/types/proxy_configuration.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types @@ -16,7 +16,7 @@ const ( var ( ProxyConfigurationV1Alpha1Type = &pbresource.Type{ Group: GroupName, - GroupVersion: VersionV1Alpha1, + GroupVersion: CurrentVersion, Kind: ProxyConfigurationKind, } @@ -25,9 +25,8 @@ var ( func RegisterProxyConfiguration(r resource.Registry) { r.Register(resource.Registration{ - Type: ProxyConfigurationV1Alpha1Type, - Proto: &pbmesh.ProxyConfiguration{}, - // TODO(rb): add validation for proxy configuration + Type: ProxyConfigurationV1Alpha1Type, + Proto: &pbmesh.ProxyConfiguration{}, Validate: nil, }) } diff --git a/internal/mesh/internal/types/proxy_state_template.go b/internal/mesh/internal/types/proxy_state_template.go deleted file mode 100644 index 526e0e48cb5af..0000000000000 --- a/internal/mesh/internal/types/proxy_state_template.go +++ /dev/null @@ -1,62 +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" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - ProxyStateTemplateKind = "ProxyStateTemplate" -) - -var ( - ProxyStateTemplateV1Alpha1Type = &pbresource.Type{ - Group: GroupName, - GroupVersion: VersionV1Alpha1, - Kind: ProxyStateTemplateKind, - } - - ProxyStateTemplateType = ProxyStateTemplateV1Alpha1Type -) - -func RegisterProxyStateTemplate(r resource.Registry) { - r.Register(resource.Registration{ - Type: ProxyStateTemplateV1Alpha1Type, - Proto: &pbmesh.ProxyStateTemplate{}, - Validate: nil, - ACLs: &resource.ACLHooks{ - Read: func(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID) error { - // Check service:read and operator:read permissions. - // If service:read is not allowed, check operator:read. We want to allow both as this - // resource is mostly useful for debuggability and we want to cover - // the most cases that serve that purpose. - serviceReadErr := authorizer.ToAllowAuthorizer().ServiceReadAllowed(id.Name, authzContext) - operatorReadErr := authorizer.ToAllowAuthorizer().OperatorReadAllowed(authzContext) - - switch { - case serviceReadErr != nil: - return serviceReadErr - case operatorReadErr != nil: - return operatorReadErr - } - - return nil - }, - Write: func(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, p *pbresource.Resource) error { - // Require operator:write only for "break-glass" scenarios as this resource should be mostly - // managed by a controller. - return authorizer.ToAllowAuthorizer().OperatorWriteAllowed(authzContext) - }, - List: func(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext) error { - // No-op List permission as we want to default to filtering resources - // from the list using the Read enforcement. - return nil - }, - }, - }) -} diff --git a/internal/mesh/internal/types/tcp_route.go b/internal/mesh/internal/types/tcp_route.go deleted file mode 100644 index c7a6ccf874303..0000000000000 --- a/internal/mesh/internal/types/tcp_route.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - TCPRouteKind = "TCPRoute" -) - -var ( - TCPRouteV1Alpha1Type = &pbresource.Type{ - Group: GroupName, - GroupVersion: VersionV1Alpha1, - Kind: TCPRouteKind, - } - - TCPRouteType = TCPRouteV1Alpha1Type -) - -func RegisterTCPRoute(r resource.Registry) { - r.Register(resource.Registration{ - Type: TCPRouteV1Alpha1Type, - Proto: &pbmesh.TCPRoute{}, - // TODO(rb): normalize parent/backend ref tenancies in a Mutate hook - Validate: ValidateTCPRoute, - }) -} - -func ValidateTCPRoute(res *pbresource.Resource) error { - var route pbmesh.TCPRoute - - if err := res.Data.UnmarshalTo(&route); err != nil { - return resource.NewErrDataParse(&route, err) - } - - var merr error - - if err := validateParentRefs(route.ParentRefs); err != nil { - merr = multierror.Append(merr, err) - } - - for i, rule := range route.Rules { - wrapRuleErr := func(err error) error { - return resource.ErrInvalidListElement{ - Name: "rules", - Index: i, - Wrapped: err, - } - } - - if len(rule.BackendRefs) == 0 { - /* - BackendRefs (optional)¶ - - BackendRefs defines API objects where matching requests should be - sent. If unspecified, the rule performs no forwarding. If - unspecified and no filters are specified that would result in a - response being sent, a 404 error code is returned. - */ - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "backend_refs", - Wrapped: resource.ErrEmpty, - }, - )) - } - for j, hbref := range rule.BackendRefs { - wrapBackendRefErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "backend_refs", - Index: j, - Wrapped: err, - }) - } - for _, err := range validateBackendRef(hbref.BackendRef) { - merr = multierror.Append(merr, wrapBackendRefErr( - resource.ErrInvalidField{ - Name: "backend_ref", - Wrapped: err, - }, - )) - } - } - } - - return merr -} diff --git a/internal/mesh/internal/types/tcp_route_test.go b/internal/mesh/internal/types/tcp_route_test.go deleted file mode 100644 index 2619a06a3ac28..0000000000000 --- a/internal/mesh/internal/types/tcp_route_test.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestValidateTCPRoute(t *testing.T) { - type testcase struct { - route *pbmesh.TCPRoute - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(TCPRouteType, "api"). - WithData(t, tc.route). - Build() - - err := ValidateTCPRoute(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.TCPRoute](t, res) - prototest.AssertDeepEqual(t, tc.route, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{} - - // Add common parent refs test cases. - for name, parentTC := range getXRouteParentRefTestCases() { - cases["parent-ref: "+name] = testcase{ - route: &pbmesh.TCPRoute{ - ParentRefs: parentTC.refs, - }, - expectErr: parentTC.expectErr, - } - } - // add common backend ref test cases. - for name, backendTC := range getXRouteBackendRefTestCases() { - var refs []*pbmesh.TCPBackendRef - for _, br := range backendTC.refs { - refs = append(refs, &pbmesh.TCPBackendRef{ - BackendRef: br, - }) - } - cases["backend-ref: "+name] = testcase{ - route: &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(catalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.TCPRouteRule{ - {BackendRefs: refs}, - }, - }, - expectErr: backendTC.expectErr, - } - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/mesh/internal/types/types.go b/internal/mesh/internal/types/types.go index 3b800f36d7dc1..3eeb69bd101c2 100644 --- a/internal/mesh/internal/types/types.go +++ b/internal/mesh/internal/types/types.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types @@ -16,11 +16,4 @@ const ( func Register(r resource.Registry) { RegisterProxyConfiguration(r) RegisterUpstreams(r) - RegisterUpstreamsConfiguration(r) - RegisterProxyStateTemplate(r) - RegisterHTTPRoute(r) - RegisterTCPRoute(r) - RegisterGRPCRoute(r) - RegisterDestinationPolicy(r) - RegisterComputedRoutes(r) } diff --git a/internal/mesh/internal/types/types_test.go b/internal/mesh/internal/types/types_test.go index b481a75d0ad55..4324e87078301 100644 --- a/internal/mesh/internal/types/types_test.go +++ b/internal/mesh/internal/types/types_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/internal/mesh/internal/types/upstreams.go b/internal/mesh/internal/types/upstreams.go index f96e40d1ff41b..54fd14b098d55 100644 --- a/internal/mesh/internal/types/upstreams.go +++ b/internal/mesh/internal/types/upstreams.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types @@ -16,7 +16,7 @@ const ( var ( UpstreamsV1Alpha1Type = &pbresource.Type{ Group: GroupName, - GroupVersion: VersionV1Alpha1, + GroupVersion: CurrentVersion, Kind: UpstreamsKind, } diff --git a/internal/mesh/internal/types/upstreams_configuration.go b/internal/mesh/internal/types/upstreams_configuration.go deleted file mode 100644 index ae7ba0d5b0736..0000000000000 --- a/internal/mesh/internal/types/upstreams_configuration.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - UpstreamsConfigurationKind = "UpstreamsConfiguration" -) - -var ( - UpstreamsConfigurationV1Alpha1Type = &pbresource.Type{ - Group: GroupName, - GroupVersion: VersionV1Alpha1, - Kind: UpstreamsConfigurationKind, - } - - UpstreamsConfigurationType = UpstreamsConfigurationV1Alpha1Type -) - -func RegisterUpstreamsConfiguration(r resource.Registry) { - r.Register(resource.Registration{ - Type: UpstreamsConfigurationV1Alpha1Type, - Proto: &pbmesh.UpstreamsConfiguration{}, - Validate: nil, - }) -} diff --git a/internal/mesh/internal/types/util.go b/internal/mesh/internal/types/util.go deleted file mode 100644 index 5a0e45d0201e7..0000000000000 --- a/internal/mesh/internal/types/util.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func IsRouteType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, HTTPRouteType), - resource.EqualType(typ, GRPCRouteType), - resource.EqualType(typ, TCPRouteType): - return true - } - return false -} - -func IsFailoverPolicyType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, catalog.FailoverPolicyType): - return true - } - return false -} - -func IsDestinationPolicyType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, DestinationPolicyType): - return true - } - return false -} - -func IsServiceType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, catalog.ServiceType): - return true - } - return false -} - -func IsComputedRoutesType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, ComputedRoutesType): - return true - } - return false -} diff --git a/internal/mesh/internal/types/xroute.go b/internal/mesh/internal/types/xroute.go deleted file mode 100644 index 572e7f53138b6..0000000000000 --- a/internal/mesh/internal/types/xroute.go +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "fmt" - - "github.com/hashicorp/go-multierror" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" -) - -type XRouteData interface { - proto.Message - XRouteWithRefs -} - -type XRouteWithRefs interface { - GetParentRefs() []*pbmesh.ParentReference - GetUnderlyingBackendRefs() []*pbmesh.BackendReference -} - -type portedRefKey struct { - Key resource.ReferenceKey - Port string -} - -func validateParentRefs(parentRefs []*pbmesh.ParentReference) error { - var merr error - if len(parentRefs) == 0 { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "parent_refs", - Wrapped: resource.ErrEmpty, - }) - } - - var ( - seen = make(map[portedRefKey]struct{}) - seenAny = make(map[resource.ReferenceKey][]string) - ) - for i, parent := range parentRefs { - wrapErr := func(err error) error { - return resource.ErrInvalidListElement{ - Name: "parent_refs", - Index: i, - Wrapped: err, - } - } - if parent.Ref == nil { - merr = multierror.Append(merr, wrapErr( - resource.ErrInvalidField{ - Name: "ref", - Wrapped: resource.ErrMissing, - }, - )) - } else { - if !IsServiceType(parent.Ref.Type) { - merr = multierror.Append(merr, wrapErr( - resource.ErrInvalidField{ - Name: "ref", - Wrapped: resource.ErrInvalidReferenceType{ - AllowedType: catalog.ServiceType, - }, - }, - )) - } - if parent.Ref.Section != "" { - merr = multierror.Append(merr, wrapErr( - resource.ErrInvalidField{ - Name: "ref", - Wrapped: resource.ErrInvalidField{ - Name: "section", - Wrapped: errors.New("section not supported for service parent refs"), - }, - }, - )) - } - - prk := portedRefKey{ - Key: resource.NewReferenceKey(parent.Ref), - Port: parent.Port, - } - - _, portExist := seen[prk] - - if parent.Port == "" { - coveredPorts, exactExists := seenAny[prk.Key] - - if portExist { // check for duplicate wild - merr = multierror.Append(merr, wrapErr( - resource.ErrInvalidField{ - Name: "ref", - Wrapped: fmt.Errorf( - "parent ref %q for wildcard port exists twice", - resource.ReferenceToString(parent.Ref), - ), - }, - )) - } else if exactExists { // check for existing exact - merr = multierror.Append(merr, wrapErr( - resource.ErrInvalidField{ - Name: "ref", - Wrapped: fmt.Errorf( - "parent ref %q for ports %v covered by wildcard port already", - resource.ReferenceToString(parent.Ref), - coveredPorts, - ), - }, - )) - } else { - seen[prk] = struct{}{} - } - - } else { - prkWild := prk - prkWild.Port = "" - _, wildExist := seen[prkWild] - - if portExist { // check for duplicate exact - merr = multierror.Append(merr, wrapErr( - resource.ErrInvalidField{ - Name: "ref", - Wrapped: fmt.Errorf( - "parent ref %q for port %q exists twice", - resource.ReferenceToString(parent.Ref), - parent.Port, - ), - }, - )) - } else if wildExist { // check for existing wild - merr = multierror.Append(merr, wrapErr( - resource.ErrInvalidField{ - Name: "ref", - Wrapped: fmt.Errorf( - "parent ref %q for port %q covered by wildcard port already", - resource.ReferenceToString(parent.Ref), - parent.Port, - ), - }, - )) - } else { - seen[prk] = struct{}{} - seenAny[prk.Key] = append(seenAny[prk.Key], parent.Port) - } - } - } - } - - return merr -} - -func validateBackendRef(backendRef *pbmesh.BackendReference) []error { - var errs []error - if backendRef == nil { - errs = append(errs, resource.ErrMissing) - - } else if backendRef.Ref == nil { - errs = append(errs, resource.ErrInvalidField{ - Name: "ref", - Wrapped: resource.ErrMissing, - }) - - } else { - if !IsServiceType(backendRef.Ref.Type) { - errs = append(errs, resource.ErrInvalidField{ - Name: "ref", - Wrapped: resource.ErrInvalidReferenceType{ - AllowedType: catalog.ServiceType, - }, - }) - } - - if backendRef.Ref.Section != "" { - errs = append(errs, resource.ErrInvalidField{ - Name: "ref", - Wrapped: resource.ErrInvalidField{ - Name: "section", - Wrapped: errors.New("section not supported for service backend refs"), - }, - }) - } - - if backendRef.Datacenter != "" { - errs = append(errs, resource.ErrInvalidField{ - Name: "datacenter", - Wrapped: errors.New("datacenter is not yet supported on backend refs"), - }) - } - } - return errs -} - -func validateHeaderMatchType(typ pbmesh.HeaderMatchType) error { - switch typ { - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_UNSPECIFIED: - return resource.ErrMissing - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT: - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_REGEX: - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_PRESENT: - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_PREFIX: - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_SUFFIX: - default: - return fmt.Errorf("not a supported enum value: %v", typ) - } - return nil -} - -func validateHTTPTimeouts(timeouts *pbmesh.HTTPRouteTimeouts) []error { - if timeouts == nil { - return nil - } - - var errs []error - - if timeouts.Request != nil { - val := timeouts.Request.AsDuration() - if val < 0 { - errs = append(errs, resource.ErrInvalidField{ - Name: "request", - Wrapped: fmt.Errorf("timeout cannot be negative: %v", val), - }) - } - } - if timeouts.BackendRequest != nil { - val := timeouts.BackendRequest.AsDuration() - if val < 0 { - errs = append(errs, resource.ErrInvalidField{ - Name: "backend_request", - Wrapped: fmt.Errorf("timeout cannot be negative: %v", val), - }) - } - } - if timeouts.Idle != nil { - val := timeouts.Idle.AsDuration() - if val < 0 { - errs = append(errs, resource.ErrInvalidField{ - Name: "idle", - Wrapped: fmt.Errorf("timeout cannot be negative: %v", val), - }) - } - } - - return errs -} - -func validateHTTPRetries(retries *pbmesh.HTTPRouteRetries) []error { - if retries == nil { - return nil - } - - var errs []error - - if retries.Number < 0 { - errs = append(errs, resource.ErrInvalidField{ - Name: "number", - Wrapped: fmt.Errorf("cannot be negative: %v", retries.Number), - }) - } - - for i, condition := range retries.OnConditions { - if !isValidRetryCondition(condition) { - errs = append(errs, resource.ErrInvalidListElement{ - Name: "on_conditions", - Index: i, - Wrapped: fmt.Errorf("not a valid retry condition: %q", condition), - }) - } - } - - return errs -} - -func isValidRetryCondition(retryOn string) bool { - switch retryOn { - case "5xx", - "gateway-error", - "reset", - "connect-failure", - "envoy-ratelimited", - "retriable-4xx", - "refused-stream", - "cancelled", - "deadline-exceeded", - "internal", - "resource-exhausted", - "unavailable": - return true - default: - return false - } -} diff --git a/internal/mesh/proxy-snapshot/proxy_snapshot.go b/internal/mesh/proxy-snapshot/proxy_snapshot.go deleted file mode 100644 index 40763f568c17f..0000000000000 --- a/internal/mesh/proxy-snapshot/proxy_snapshot.go +++ /dev/null @@ -1,17 +0,0 @@ -package proxysnapshot - -import "github.com/hashicorp/consul/acl" - -// ProxySnapshot is an abstraction that allows interchangeability between -// Catalog V1 ConfigSnapshot and Catalog V2 ProxyState. -type ProxySnapshot interface { - AllowEmptyListeners() bool - AllowEmptyRoutes() bool - AllowEmptyClusters() bool - Authorize(authz acl.Authorizer) error - LoggerName() string -} - -// CancelFunc is a type for a returned function that can be called to cancel a -// watch. -type CancelFunc func() diff --git a/internal/mesh/proxy-tracker/mock_SessionLimiter.go b/internal/mesh/proxy-tracker/mock_SessionLimiter.go deleted file mode 100644 index 32375dbdc3862..0000000000000 --- a/internal/mesh/proxy-tracker/mock_SessionLimiter.go +++ /dev/null @@ -1,53 +0,0 @@ -// Code generated by mockery v2.33.1. DO NOT EDIT. - -package proxytracker - -import ( - limiter "github.com/hashicorp/consul/agent/grpc-external/limiter" - mock "github.com/stretchr/testify/mock" -) - -// MockSessionLimiter is an autogenerated mock type for the SessionLimiter type -type MockSessionLimiter struct { - mock.Mock -} - -// BeginSession provides a mock function with given fields: -func (_m *MockSessionLimiter) BeginSession() (limiter.Session, error) { - ret := _m.Called() - - var r0 limiter.Session - var r1 error - if rf, ok := ret.Get(0).(func() (limiter.Session, error)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() limiter.Session); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(limiter.Session) - } - } - - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NewMockSessionLimiter creates a new instance of MockSessionLimiter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewMockSessionLimiter(t interface { - mock.TestingT - Cleanup(func()) -}) *MockSessionLimiter { - mock := &MockSessionLimiter{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/internal/mesh/proxy-tracker/proxy_state_exports.go b/internal/mesh/proxy-tracker/proxy_state_exports.go deleted file mode 100644 index 59c4e1070f10c..0000000000000 --- a/internal/mesh/proxy-tracker/proxy_state_exports.go +++ /dev/null @@ -1,42 +0,0 @@ -package proxytracker - -import ( - "github.com/hashicorp/consul/acl" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" -) - -// ProxyState is an implementation of the ProxySnapshot interface for pbmesh.ProxyState. -// It is a simple wrapper around pbmesh.ProxyState so that it can be used -// by the ProxyWatcher interface in XDS processing. This struct is necessary -// because pbmesh.ProxyState is a proto definition and there were complications -// adding these functions directly to that proto definition. -type ProxyState struct { - *pbmesh.ProxyState -} - -// TODO(proxystate): need to modify ProxyState to carry a type/kind (connect proxy, mesh gateway, etc.) -// for sidecar proxies, all Allow* functions -// should return false, but for different gateways we'd need to add it to IR. - -func (p *ProxyState) AllowEmptyListeners() bool { - return false -} - -func (p *ProxyState) AllowEmptyRoutes() bool { - return false -} - -func (p *ProxyState) AllowEmptyClusters() bool { - return false -} - -func (p *ProxyState) Authorize(authz acl.Authorizer) error { - // TODO(proxystate): we'll need to implement this once identity policy is implemented - - // Authed OK! - return nil -} - -func (p *ProxyState) LoggerName() string { - return "" -} diff --git a/internal/mesh/proxy-tracker/proxy_tracker.go b/internal/mesh/proxy-tracker/proxy_tracker.go deleted file mode 100644 index a40353aaf6998..0000000000000 --- a/internal/mesh/proxy-tracker/proxy_tracker.go +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxytracker - -import ( - "errors" - "fmt" - "sync" - - "github.com/hashicorp/go-hclog" - - "github.com/hashicorp/consul/agent/grpc-external/limiter" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/types" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// ProxyConnection implements the queue.ItemType interface so that it can be used in a controller.Event. -// It is sent on the newProxyConnectionCh channel. -// TODO(ProxyState): needs to support tenancy in the future. -type ProxyConnection struct { - ProxyID *pbresource.ID -} - -// Key is current resourceID.Name. -func (e *ProxyConnection) Key() string { - return e.ProxyID.GetName() -} - -// proxyWatchData is a handle on all of the relevant bits that is created by calling Watch(). -// It is meant to be stored in the proxies cache by proxyID so that watches can be notified -// when the ProxyState for that proxyID has changed. -type proxyWatchData struct { - // notifyCh is the channel that the watcher receives updates from ProxyTracker. - notifyCh chan proxysnapshot.ProxySnapshot - // state is the current/last updated ProxyState for a given proxy. - state proxysnapshot.ProxySnapshot - // token is the ACL token provided by the watcher. - token string - // nodeName is the node where the given proxy resides. - nodeName string -} - -type ProxyTrackerConfig struct { - // logger will be used to write log messages. - Logger hclog.Logger - - // sessionLimiter is used to enforce xDS concurrency limits. - SessionLimiter SessionLimiter -} - -// ProxyTracker implements the Watcher and Updater interfaces. The Watcher is used by the xds server to add a new proxy -// to this server, and get back a channel for updates. The Updater is used by the ProxyState controller running on the -// server to push ProxyState updates to the notify channel. -type ProxyTracker struct { - config ProxyTrackerConfig - // proxies is a cache of the proxies connected to this server and configuration information for each one. - proxies map[resource.ReferenceKey]*proxyWatchData - // newProxyConnectionCh is the channel that the "updater" retains to receive messages from ProxyTracker that a new - // proxy has connected to ProxyTracker and a signal the "updater" should call PushChanges with a new state. - newProxyConnectionCh chan controller.Event - // shutdownCh is a channel that closes when ProxyTracker is shutdown. ShutdownChannel is never written to, only closed to - // indicate a shutdown has been initiated. - shutdownCh chan struct{} - // mu is a mutex that is used internally for locking when reading and modifying ProxyTracker state, namely the proxies map. - mu sync.Mutex -} - -// NewProxyTracker returns a ProxyTracker instance given a configuration. -func NewProxyTracker(cfg ProxyTrackerConfig) *ProxyTracker { - return &ProxyTracker{ - config: cfg, - proxies: make(map[resource.ReferenceKey]*proxyWatchData), - // buffering this channel since ProxyTracker will be registering watches for all proxies. - // using the buffer will limit errors related to controller and the proxy are both running - // but the controllers listening function is not blocking on the particular receive line. - // This channel is meant to error when the controller is "not ready" which means up and alive. - // This buffer will try to reduce false negatives and limit unnecessary erroring. - newProxyConnectionCh: make(chan controller.Event, 1000), - shutdownCh: make(chan struct{}), - } -} - -// Watch connects a proxy with ProxyTracker and returns the consumer a channel to receive updates, -// a channel to notify of xDS terminated session, and a cancel function to cancel the watch. -func (pt *ProxyTracker) Watch(proxyID *pbresource.ID, - nodeName string, token string) (<-chan proxysnapshot.ProxySnapshot, - limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) { - pt.config.Logger.Trace("watch initiated", "proxyID", proxyID, "nodeName", nodeName) - if err := pt.validateWatchArgs(proxyID, nodeName); err != nil { - pt.config.Logger.Error("args failed validation", err) - return nil, nil, nil, err - } - // Begin a session with the xDS session concurrency limiter. - // - // See: https://github.com/hashicorp/consul/issues/15753 - session, err := pt.config.SessionLimiter.BeginSession() - if err != nil { - pt.config.Logger.Error("failed to begin session with xDS session concurrency limiter", err) - return nil, nil, nil, err - } - - // This buffering is crucial otherwise we'd block immediately trying to - // deliver the current snapshot below if we already have one. - - proxyStateChan := make(chan proxysnapshot.ProxySnapshot, 1) - watchData := &proxyWatchData{ - notifyCh: proxyStateChan, - state: nil, - token: token, - nodeName: nodeName, - } - - proxyReferenceKey := resource.NewReferenceKey(proxyID) - cancel := func() { - pt.mu.Lock() - defer pt.mu.Unlock() - pt.cancelWatchLocked(proxyReferenceKey, proxyStateChan, session) - } - - pt.mu.Lock() - defer pt.mu.Unlock() - - pt.proxies[proxyReferenceKey] = watchData - - //Send an event to the controller - err = pt.notifyNewProxyChannel(proxyID) - if err != nil { - pt.config.Logger.Error("failed to notify controller of new proxy connection", err) - pt.cancelWatchLocked(proxyReferenceKey, watchData.notifyCh, session) - return nil, nil, nil, err - } - pt.config.Logger.Trace("controller notified of watch created", "proxyID", proxyID, "nodeName", nodeName) - - return proxyStateChan, session.Terminated(), cancel, nil -} - -// notifyNewProxyChannel attempts to send a message to newProxyConnectionCh and will return an error if there's no receiver. -// This will handle conditions where a proxy is connected but there's no controller for some reason to receive the event. -// This will error back to the proxy's Watch call and will cause the proxy call Watch again to retry connection until the controller -// is available. -func (pt *ProxyTracker) notifyNewProxyChannel(proxyID *pbresource.ID) error { - controllerEvent := controller.Event{ - Obj: &ProxyConnection{ - ProxyID: proxyID, - }, - } - select { - case pt.newProxyConnectionCh <- controllerEvent: - return nil - // using default here to return errors is only safe when we have a large buffer. - // the receiver is on a loop to read from the channel. If the sequence of - // sender blocks on the channel and then the receiver blocks on the channel is not - // aligned, then extraneous errors could be returned to the proxy that are just - // false negatives and the controller could be up and healthy. - default: - return fmt.Errorf("failed to notify the controller of the proxy connecting") - } -} - -// cancelWatchLocked does the following: -// - deletes the key from the proxies array. -// - ends the session with xDS session limiter. -// - closes the proxy state channel assigned to the proxy. -// This function assumes the state lock is already held. -func (pt *ProxyTracker) cancelWatchLocked(proxyReferenceKey resource.ReferenceKey, proxyStateChan chan proxysnapshot.ProxySnapshot, session limiter.Session) { - delete(pt.proxies, proxyReferenceKey) - session.End() - close(proxyStateChan) - pt.config.Logger.Trace("watch cancelled", "proxyReferenceKey", proxyReferenceKey) -} - -// validateWatchArgs checks the proxyIDand nodeName passed to Watch -// and returns an error if the args are not properly constructed. -func (pt *ProxyTracker) validateWatchArgs(proxyID *pbresource.ID, - nodeName string) error { - if proxyID == nil { - return errors.New("proxyID is required") - } else if proxyID.GetType().GetKind() != types.ProxyStateTemplateType.Kind { - return fmt.Errorf("proxyID must be a %s", types.ProxyStateTemplateType.GetKind()) - } else if nodeName == "" { - return errors.New("nodeName is required") - } - - return nil -} - -// PushChange allows pushing a computed ProxyState to xds for xds resource generation to send to a proxy. -func (pt *ProxyTracker) PushChange(proxyID *pbresource.ID, proxyState proxysnapshot.ProxySnapshot) error { - pt.config.Logger.Trace("push change called for proxy", "proxyID", proxyID) - proxyReferenceKey := resource.NewReferenceKey(proxyID) - pt.mu.Lock() - defer pt.mu.Unlock() - if data, ok := pt.proxies[proxyReferenceKey]; ok { - data.state = proxyState - - pt.deliverLatest(proxyID, proxyState, data.notifyCh) - } else { - return errors.New("proxyState change could not be sent because proxy is not connected") - } - - return nil -} - -func (pt *ProxyTracker) deliverLatest(proxyID *pbresource.ID, proxyState proxysnapshot.ProxySnapshot, ch chan proxysnapshot.ProxySnapshot) { - pt.config.Logger.Trace("delivering latest proxy snapshot to proxy", "proxyID", proxyID) - // Send if chan is empty - select { - case ch <- proxyState: - return - default: - } - - // Not empty, drain the chan of older snapshots and redeliver. For now we only - // use 1-buffered chans but this will still work if we change that later. -OUTER: - for { - select { - case <-ch: - continue - default: - break OUTER - } - } - - // Now send again - select { - case ch <- proxyState: - return - default: - // This should not be possible since we should be the only sender, enforced - // by m.mu but error and drop the update rather than panic. - pt.config.Logger.Error("failed to deliver proxyState to proxy", - "proxy", proxyID.String(), - ) - } -} - -// EventChannel returns an event channel that sends controller events when a proxy connects to a server. -func (pt *ProxyTracker) EventChannel() chan controller.Event { - return pt.newProxyConnectionCh -} - -// ShutdownChannel returns a channel that closes when ProxyTracker is shutdown. ShutdownChannel is never written to, only closed to -// indicate a shutdown has been initiated. -func (pt *ProxyTracker) ShutdownChannel() chan struct{} { - return pt.shutdownCh -} - -// ProxyConnectedToServer returns whether this id is connected to this server. -func (pt *ProxyTracker) ProxyConnectedToServer(proxyID *pbresource.ID) bool { - pt.mu.Lock() - defer pt.mu.Unlock() - proxyReferenceKey := resource.NewReferenceKey(proxyID) - _, ok := pt.proxies[proxyReferenceKey] - return ok -} - -// Shutdown removes all state and close all channels. -func (pt *ProxyTracker) Shutdown() { - pt.config.Logger.Info("proxy tracker shutdown initiated") - pt.mu.Lock() - defer pt.mu.Unlock() - - // Close all current watchers first - for proxyID, watchData := range pt.proxies { - close(watchData.notifyCh) - delete(pt.proxies, proxyID) - } - - close(pt.newProxyConnectionCh) - close(pt.shutdownCh) -} - -//go:generate mockery --name SessionLimiter --inpackage -type SessionLimiter interface { - BeginSession() (limiter.Session, error) -} diff --git a/internal/mesh/proxy-tracker/proxy_tracker_test.go b/internal/mesh/proxy-tracker/proxy_tracker_test.go deleted file mode 100644 index 09e5be13ac524..0000000000000 --- a/internal/mesh/proxy-tracker/proxy_tracker_test.go +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxytracker - -import ( - "errors" - "fmt" - "testing" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/agent/grpc-external/limiter" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestProxyTracker_Watch(t *testing.T) { - resourceID := resourcetest.Resource(types.ProxyStateTemplateType, "test").ID() - proxyReferenceKey := resource.NewReferenceKey(resourceID) - lim := NewMockSessionLimiter(t) - session1 := newMockSession(t) - session1TermCh := make(limiter.SessionTerminatedChan) - session1.On("Terminated").Return(session1TermCh) - session1.On("End").Return() - lim.On("BeginSession").Return(session1, nil) - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - // Watch() - proxyStateChan, _, cancelFunc, err := pt.Watch(resourceID, "node 1", "token") - require.NoError(t, err) - - // ensure New Proxy Connection message is sent - newProxyMsg := <-pt.EventChannel() - require.Equal(t, resourceID.Name, newProxyMsg.Obj.Key()) - - // watchData is stored in the proxies array with a nil state - watchData, ok := pt.proxies[proxyReferenceKey] - require.True(t, ok) - require.NotNil(t, watchData) - require.Nil(t, watchData.state) - - // calling cancelFunc does the following: - // - closes the proxy state channel - // - and removes the map entry for the proxy - // - session is ended - cancelFunc() - - // read channel to see if there is data and it is open. - receivedState, channelOpen := <-proxyStateChan - require.Nil(t, receivedState) - require.False(t, channelOpen) - - // key is removed from proxies array - _, ok = pt.proxies[proxyReferenceKey] - require.False(t, ok) - - // session ended - session1.AssertCalled(t, "Terminated") - session1.AssertCalled(t, "End") -} - -func TestProxyTracker_Watch_ErrorConsumerNotReady(t *testing.T) { - resourceID := resourcetest.Resource(types.ProxyStateTemplateType, "test").ID() - proxyReferenceKey := resource.NewReferenceKey(resourceID) - lim := NewMockSessionLimiter(t) - session1 := newMockSession(t) - session1.On("End").Return() - lim.On("BeginSession").Return(session1, nil) - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - //fill up buffered channel while the consumer is not ready to simulate the error - for i := 0; i < 1000; i++ { - event := controller.Event{Obj: &ProxyConnection{ProxyID: resourcetest.Resource(types.ProxyStateTemplateType, fmt.Sprintf("test%d", i)).ID()}} - pt.newProxyConnectionCh <- event - } - - // Watch() - proxyStateChan, sessionTerminatedCh, cancelFunc, err := pt.Watch(resourceID, "node 1", "token") - require.Nil(t, cancelFunc) - require.Nil(t, proxyStateChan) - require.Nil(t, sessionTerminatedCh) - require.Error(t, err) - require.Equal(t, "failed to notify the controller of the proxy connecting", err.Error()) - - // it is not stored in the proxies array - watchData, ok := pt.proxies[proxyReferenceKey] - require.False(t, ok) - require.Nil(t, watchData) -} - -func TestProxyTracker_Watch_ArgValidationErrors(t *testing.T) { - type testcase struct { - description string - proxyID *pbresource.ID - nodeName string - token string - expectedError error - } - testcases := []*testcase{ - { - description: "Empty proxyID", - proxyID: nil, - nodeName: "something", - token: "something", - expectedError: errors.New("proxyID is required"), - }, - { - description: "Empty nodeName", - proxyID: resourcetest.Resource(types.ProxyStateTemplateType, "test").ID(), - nodeName: "", - token: "something", - expectedError: errors.New("nodeName is required"), - }, - { - description: "resource is not ProxyStateTemplate", - proxyID: resourcetest.Resource(types.ProxyConfigurationType, "test").ID(), - nodeName: "something", - token: "something else", - expectedError: errors.New("proxyID must be a ProxyStateTemplate"), - }, - } - for _, tc := range testcases { - lim := NewMockSessionLimiter(t) - lim.On("BeginSession").Return(nil, nil).Maybe() - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - // Watch() - proxyStateChan, sessionTerminateCh, cancelFunc, err := pt.Watch(tc.proxyID, tc.nodeName, tc.token) - require.Error(t, err) - require.Equal(t, tc.expectedError, err) - require.Nil(t, proxyStateChan) - require.Nil(t, sessionTerminateCh) - require.Nil(t, cancelFunc) - } -} - -func TestProxyTracker_Watch_SessionLimiterError(t *testing.T) { - resourceID := resourcetest.Resource(types.ProxyStateTemplateType, "test").ID() - lim := NewMockSessionLimiter(t) - lim.On("BeginSession").Return(nil, errors.New("kaboom")) - logger := testutil.Logger(t) - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - // Watch() - proxyStateChan, sessionTerminateCh, cancelFunc, err := pt.Watch(resourceID, "node 1", "token") - require.Error(t, err) - require.Equal(t, "kaboom", err.Error()) - require.Nil(t, proxyStateChan) - require.Nil(t, sessionTerminateCh) - require.Nil(t, cancelFunc) -} - -func TestProxyTracker_PushChange(t *testing.T) { - resourceID := resourcetest.Resource(types.ProxyStateTemplateType, "test").ID() - proxyReferenceKey := resource.NewReferenceKey(resourceID) - lim := NewMockSessionLimiter(t) - session1 := newMockSession(t) - session1TermCh := make(limiter.SessionTerminatedChan) - session1.On("Terminated").Return(session1TermCh) - lim.On("BeginSession").Return(session1, nil) - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - // Watch() - proxyStateChan, _, _, err := pt.Watch(resourceID, "node 1", "token") - require.NoError(t, err) - - // PushChange - proxyState := &ProxyState{ProxyState: &pbmesh.ProxyState{ - IntentionDefaultAllow: true, - }} - - // using a goroutine so that the channel and main test thread do not cause - // blocking issues with each other - go func() { - err = pt.PushChange(resourceID, proxyState) - require.NoError(t, err) - }() - - // channel receives a copy - receivedState, channelOpen := <-proxyStateChan - require.True(t, channelOpen) - require.Equal(t, proxyState, receivedState) - - // it is stored in the proxies array - watchData, ok := pt.proxies[proxyReferenceKey] - require.True(t, ok) - require.Equal(t, proxyState, watchData.state) -} - -func TestProxyTracker_PushChanges_ErrorProxyNotConnected(t *testing.T) { - resourceID := resourcetest.Resource(types.ProxyStateTemplateType, "test").ID() - lim := NewMockSessionLimiter(t) - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - // PushChange - proxyState := &ProxyState{ProxyState: &pbmesh.ProxyState{ - IntentionDefaultAllow: true, - }} - - err := pt.PushChange(resourceID, proxyState) - require.Error(t, err) - require.Equal(t, "proxyState change could not be sent because proxy is not connected", err.Error()) -} - -func TestProxyTracker_ProxyConnectedToServer(t *testing.T) { - type testcase struct { - name string - shouldExist bool - preProcessingFunc func(pt *ProxyTracker, resourceID *pbresource.ID, limiter *MockSessionLimiter, session *mockSession, channel limiter.SessionTerminatedChan) - } - testsCases := []*testcase{ - { - name: "Resource that has not been sent through Watch() should return false", - shouldExist: false, - preProcessingFunc: func(pt *ProxyTracker, resourceID *pbresource.ID, limiter *MockSessionLimiter, session *mockSession, channel limiter.SessionTerminatedChan) { - session.On("Terminated").Return(channel).Maybe() - session.On("End").Return().Maybe() - limiter.On("BeginSession").Return(session, nil).Maybe() - }, - }, - { - name: "Resource used that is already passed in through Watch() should return true", - shouldExist: true, - preProcessingFunc: func(pt *ProxyTracker, resourceID *pbresource.ID, limiter *MockSessionLimiter, session *mockSession, channel limiter.SessionTerminatedChan) { - session.On("Terminated").Return(channel).Maybe() - session.On("End").Return().Maybe() - limiter.On("BeginSession").Return(session, nil) - _, _, _, _ = pt.Watch(resourceID, "node 1", "token") - }, - }, - } - - for _, tc := range testsCases { - lim := NewMockSessionLimiter(t) - session1 := newMockSession(t) - session1TermCh := make(limiter.SessionTerminatedChan) - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - resourceID := resourcetest.Resource(types.ProxyStateTemplateType, "test").ID() - tc.preProcessingFunc(pt, resourceID, lim, session1, session1TermCh) - require.Equal(t, tc.shouldExist, pt.ProxyConnectedToServer(resourceID)) - } -} - -func TestProxyTracker_Shutdown(t *testing.T) { - resourceID := resourcetest.Resource(types.ProxyStateTemplateType, "test").ID() - proxyReferenceKey := resource.NewReferenceKey(resourceID) - lim := NewMockSessionLimiter(t) - session1 := newMockSession(t) - session1TermCh := make(limiter.SessionTerminatedChan) - session1.On("Terminated").Return(session1TermCh) - session1.On("End").Return().Maybe() - lim.On("BeginSession").Return(session1, nil) - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - // Watch() - proxyStateChan, _, _, err := pt.Watch(resourceID, "node 1", "token") - require.NoError(t, err) - - pt.Shutdown() - - // proxy channels are all disconnected and proxy is removed from proxies map - receivedState, channelOpen := <-proxyStateChan - require.Nil(t, receivedState) - require.False(t, channelOpen) - _, ok := pt.proxies[proxyReferenceKey] - require.False(t, ok) - - // shutdownCh is closed - select { - case <-pt.ShutdownChannel(): - default: - t.Fatalf("shutdown channel should be closed") - } - // newProxyConnectionCh is closed - select { - case <-pt.EventChannel(): - default: - t.Fatalf("shutdown channel should be closed") - } -} - -type mockSession struct { - mock.Mock -} - -func newMockSession(t *testing.T) *mockSession { - m := &mockSession{} - m.Mock.Test(t) - - t.Cleanup(func() { m.AssertExpectations(t) }) - - return m -} - -func (m *mockSession) End() { m.Called() } - -func (m *mockSession) Terminated() limiter.SessionTerminatedChan { - return m.Called().Get(0).(limiter.SessionTerminatedChan) -} diff --git a/internal/protohcl/any.go b/internal/protohcl/any.go deleted file mode 100644 index 87b4549bfd079..0000000000000 --- a/internal/protohcl/any.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package protohcl - -import ( - "fmt" - "strings" - - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" - "google.golang.org/protobuf/types/known/anypb" -) - -const wellKnownTypeAny = "google.protobuf.Any" - -type AnyTypeProvider interface { - AnyType(*UnmarshalContext, MessageDecoder) (protoreflect.FullName, MessageDecoder, error) -} - -type AnyTypeURLProvider struct { - TypeURLFieldName string -} - -func (p *AnyTypeURLProvider) AnyType(ctx *UnmarshalContext, decoder MessageDecoder) (protoreflect.FullName, MessageDecoder, error) { - typeURLFieldName := "type_url" - if p != nil { - typeURLFieldName = p.TypeURLFieldName - } - - var typeURL *IterField - err := decoder.EachField(FieldIterator{ - Desc: (&anypb.Any{}).ProtoReflect().Descriptor(), - Func: func(field *IterField) error { - if field.Name == typeURLFieldName { - typeURL = field - } - return nil - }, - IgnoreUnknown: true, - }) - if err != nil { - return "", nil, err - } - - if typeURL == nil || typeURL.Val == nil { - return "", nil, fmt.Errorf("%s field is required to decode Any", typeURLFieldName) - } - - url, err := stringFromCty(*typeURL.Val) - if err != nil { - return "", nil, err - } - - slashIdx := strings.LastIndex(url, "/") - typeName := url - // strip all "hostname" parts of the URL path - if slashIdx > 1 && slashIdx+1 < len(url) { - typeName = url[slashIdx+1:] - } - - return protoreflect.FullName(typeName), decoder.SkipFields(typeURLFieldName), nil -} - -func (u UnmarshalOptions) decodeAny(ctx *UnmarshalContext, decoder MessageDecoder, msg protoreflect.Message) error { - var typeProvider AnyTypeProvider = &AnyTypeURLProvider{TypeURLFieldName: "type_url"} - if u.AnyTypeProvider != nil { - typeProvider = u.AnyTypeProvider - } - - var ( - typeName protoreflect.FullName - err error - ) - typeName, decoder, err = typeProvider.AnyType(ctx, decoder) - if err != nil { - return fmt.Errorf("error getting type for Any field: %w", err) - } - - // the type.googleapis.come/ should be optional - mt, err := protoregistry.GlobalTypes.FindMessageByName(typeName) - if err != nil { - return fmt.Errorf("error looking up type information for %s: %w", typeName, err) - } - - newMsg := mt.New() - - err = u.decodeMessage(&UnmarshalContext{ - Parent: ctx.Parent, - Name: ctx.Name, - Message: newMsg, - }, decoder, newMsg) - if err != nil { - return err - } - - enc, err := proto.Marshal(newMsg.Interface()) - if err != nil { - return fmt.Errorf("error marshalling Any data as protobuf value: %w", err) - } - - anyValue := msg.Interface().(*anypb.Any) - - // This will look like . and not quite like a full URL with a path - anyValue.TypeUrl = string(newMsg.Descriptor().FullName()) - anyValue.Value = enc - - return nil -} - -func isAnyField(desc protoreflect.FieldDescriptor) bool { - if desc.Kind() != protoreflect.MessageKind { - return false - } - return desc.Message().FullName() == wellKnownTypeAny -} diff --git a/internal/protohcl/attributes.go b/internal/protohcl/attributes.go deleted file mode 100644 index 90501722b1fe3..0000000000000 --- a/internal/protohcl/attributes.go +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package protohcl - -import ( - "fmt" - - "github.com/pkg/errors" - "github.com/zclconf/go-cty/cty" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" -) - -func (u UnmarshalOptions) decodeAttribute(ctx *UnmarshalContext, newMessage newMessageFn, f protoreflect.FieldDescriptor, val cty.Value, listAllowed bool) (protoreflect.Value, error) { - if f.IsMap() { - return u.decodeAttributeToMap(ctx, newMessage, f, val) - } - - if f.IsList() && listAllowed { - return u.decodeAttributeToList(ctx, newMessage, f, val) - } - - ok, value, err := decodeAttributeToWellKnownType(f, val) - if ok { - return value, errors.Wrapf(err, "%s: Failed to unmarshal argument %s", ctx.ErrorRange(), ctx.Name) - } - - ok, value, err = u.decodeAttributeToMessage(ctx, newMessage, f, val) - if ok { - return value, err - } - - value, err = decodeAttributeToPrimitive(f, val) - if err != nil { - return value, errors.Wrapf(err, "%s: Failed to unmarshal argument %s", ctx.ErrorRange(), ctx.Name) - } - return value, nil -} - -func (u UnmarshalOptions) decodeAttributeToMessage(ctx *UnmarshalContext, newMessage newMessageFn, desc protoreflect.FieldDescriptor, val cty.Value) (bool, protoreflect.Value, error) { - if desc.Kind() != protoreflect.MessageKind { - return false, protoreflect.Value{}, nil - } - - msg := newMessage().Message() - - ctx = &UnmarshalContext{ - Parent: ctx.Parent, - Name: ctx.Name, - Message: msg, - Range: ctx.Range, - } - - // We have limited support for HCL functions, essentially just those that - // return a protobuf message (like the resource `gvk` function) in which - // case, the message will be wrapped in a cty capsule. - if val.Type().IsCapsuleType() { - msg, ok := val.EncapsulatedValue().(proto.Message) - if ok { - return true, protoreflect.ValueOf(msg.ProtoReflect()), nil - } else { - return true, protoreflect.Value{}, fmt.Errorf("expected encapsulated value to be a message, actual type: %T", val.EncapsulatedValue()) - } - } - - if !val.Type().IsObjectType() { - return false, protoreflect.Value{}, nil - } - - decoder := newObjectDecoder(val, u.FieldNamer, ctx.ErrorRange()) - - if err := u.decodeMessage(ctx, decoder, msg); err != nil { - return true, protoreflect.Value{}, err - } - return true, protoreflect.ValueOf(msg), nil -} - -func (u UnmarshalOptions) decodeAttributeToList(ctx *UnmarshalContext, newMessage newMessageFn, desc protoreflect.FieldDescriptor, value cty.Value) (protoreflect.Value, error) { - if value.IsNull() { - return protoreflect.Value{}, nil - } - - valueType := value.Type() - if !valueType.IsListType() && !valueType.IsTupleType() { - return protoreflect.Value{}, fmt.Errorf("expected list/tuple type after HCL decode but the actual type was %s", valueType.FriendlyName()) - } - - if value.LengthInt() < 1 { - return protoreflect.Value{}, nil - } - - protoList := newMessage().List() - - var err error - var idx int - value.ForEachElement(func(_ cty.Value, val cty.Value) bool { - var protoVal protoreflect.Value - protoVal, err = u.decodeAttribute(&UnmarshalContext{ - Parent: ctx, - Name: fmt.Sprintf("%s[%d]", u.FieldNamer.NameField(desc), idx), - }, protoList.NewElement, desc, val, false) - if err != nil { - return true - } - - idx++ - protoList.Append(protoVal) - return false - }) - if err != nil { - return protoreflect.Value{}, err - } - - return protoreflect.ValueOfList(protoList), nil -} - -func (u UnmarshalOptions) decodeAttributeToMap(ctx *UnmarshalContext, newMessage newMessageFn, desc protoreflect.FieldDescriptor, value cty.Value) (protoreflect.Value, error) { - if value.IsNull() { - return protoreflect.Value{}, nil - } - - valueType := value.Type() - if !valueType.IsMapType() && !valueType.IsObjectType() { - return protoreflect.Value{}, fmt.Errorf("expected map/object type after HCL decode but the actual type was %s", valueType.FriendlyName()) - } - - if value.LengthInt() < 1 { - return protoreflect.Value{}, nil - } - - protoMap := newMessage().Map() - protoValueDesc := desc.MapValue() - var err error - - value.ForEachElement(func(key cty.Value, val cty.Value) (stop bool) { - var protoVal protoreflect.Value - protoVal, err = u.decodeAttribute(&UnmarshalContext{ - Parent: ctx, - Name: fmt.Sprintf("%s[%q]", u.FieldNamer.NameField(desc), key.AsString()), - Message: nil, // TODO: what should this really be? - }, protoMap.NewValue, protoValueDesc, val, false) - if err != nil { - return true - } - if protoVal.IsValid() { - // HCL doesn't support non-string keyed maps so we blindly use string keys - protoMap.Set(protoreflect.ValueOfString(key.AsString()).MapKey(), protoVal) - } - return false - }) - if err != nil { - return protoreflect.Value{}, err - } - - return protoreflect.ValueOfMap(protoMap), nil -} diff --git a/internal/protohcl/blocks.go b/internal/protohcl/blocks.go deleted file mode 100644 index cafffa99367da..0000000000000 --- a/internal/protohcl/blocks.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package protohcl - -import ( - "fmt" - - "github.com/hashicorp/hcl/v2" - "google.golang.org/protobuf/reflect/protoreflect" -) - -func (u UnmarshalOptions) decodeBlocks(ctx *UnmarshalContext, blocks hcl.Blocks, msg protoreflect.Message, f protoreflect.FieldDescriptor) (protoreflect.Value, error) { - if f.Kind() != protoreflect.MessageKind { - return protoreflect.Value{}, fmt.Errorf("only protobuf message kinds can use HCL block syntax") - } - - if f.IsMap() { - return u.decodeBlocksToMap(ctx, blocks, msg, f) - } - - if f.IsList() { - return u.decodeBlocksToList(ctx, blocks, msg, f) - } - - return u.decodeBlocksToMessage(ctx, blocks, msg, f) -} - -func (u UnmarshalOptions) decodeBlocksToMap(ctx *UnmarshalContext, blocks hcl.Blocks, msg protoreflect.Message, f protoreflect.FieldDescriptor) (protoreflect.Value, error) { - val := msg.NewField(f) - mapVal := val.Map() - - for _, block := range blocks { - if len(block.Labels) != 1 { - return protoreflect.Value{}, fmt.Errorf("protobuf map fields must have 1 HCL block label") - } - - key := protoreflect.ValueOfString(block.Labels[0]) - value := mapVal.NewValue() - msgVal := value.Message() - - err := u.decodeMessage( - &UnmarshalContext{ - Parent: ctx, - Name: fmt.Sprintf("%s[%q]", u.FieldNamer.NameField(f), block.Labels[0]), - Message: msgVal, - Range: block.DefRange, - }, - u.bodyDecoder(block.Body), - msgVal, - ) - if err != nil { - return protoreflect.Value{}, err - } - - mapVal.Set(key.MapKey(), value) - } - return val, nil -} - -func (u UnmarshalOptions) decodeBlocksToList(ctx *UnmarshalContext, blocks hcl.Blocks, msg protoreflect.Message, f protoreflect.FieldDescriptor) (protoreflect.Value, error) { - val := msg.NewField(f) - listVal := val.List() - - var err error - for idx, block := range blocks { - if len(block.Labels) > 0 { - return protoreflect.Value{}, fmt.Errorf("repeated protobuf fields must not have HCL block labels") - } - elem := listVal.NewElement() - elemMsg := elem.Message() - - err = u.decodeMessage( - &UnmarshalContext{ - Parent: ctx, - Name: fmt.Sprintf("%s[%d]", u.FieldNamer.NameField(f), idx), - Message: elemMsg, - Range: block.DefRange, - }, - u.bodyDecoder(block.Body), - elemMsg, - ) - if err != nil { - return protoreflect.Value{}, err - } - listVal.Append(elem) - } - - return val, nil -} - -func (u UnmarshalOptions) decodeBlocksToMessage(ctx *UnmarshalContext, blocks hcl.Blocks, msg protoreflect.Message, f protoreflect.FieldDescriptor) (protoreflect.Value, error) { - if len(blocks) > 1 { - return protoreflect.Value{}, fmt.Errorf("only one HCL block may be specified for a non-repeated protobuf Message") - } - - val := msg.NewField(f) - valMsg := val.Message() - - err := u.decodeMessage( - &UnmarshalContext{ - Parent: ctx, - Name: blocks[0].Type, - Message: valMsg, - Range: blocks[0].DefRange, - }, - u.bodyDecoder(blocks[0].Body), - valMsg, - ) - if err != nil { - return protoreflect.Value{}, err - } - - return val, nil -} diff --git a/internal/protohcl/cty.go b/internal/protohcl/cty.go deleted file mode 100644 index e7ed37ed16996..0000000000000 --- a/internal/protohcl/cty.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package protohcl - -import ( - "encoding/base64" - "fmt" - - "github.com/zclconf/go-cty/cty" - "github.com/zclconf/go-cty/cty/gocty" -) - -func boolFromCty(val cty.Value) (bool, error) { - if val.Type() != cty.Bool { - return false, fmt.Errorf("expected value of type %s but actual type is %s", cty.Bool.FriendlyName(), val.Type().FriendlyName()) - } - - if val.IsNull() { - return false, nil - } - - return val.True(), nil -} - -func int32FromCty(val cty.Value) (int32, error) { - if val.Type() != cty.Number { - return 0, fmt.Errorf("expected value of type %s but actual type is %s", cty.Number.FriendlyName(), val.Type().FriendlyName()) - } - - if val.IsNull() { - return 0, nil - } - - var goVal int32 - if err := gocty.FromCtyValue(val, &goVal); err != nil { - return 0, fmt.Errorf("error converting cty value of type %s to int32: %w", val.Type().FriendlyName(), err) - } - return goVal, nil -} - -func uint32FromCty(val cty.Value) (uint32, error) { - if val.Type() != cty.Number { - return 0, fmt.Errorf("expected value of type %s but actual type is %s", cty.Number.FriendlyName(), val.Type().FriendlyName()) - } - - if val.IsNull() { - return 0, nil - } - - var goVal uint32 - if err := gocty.FromCtyValue(val, &goVal); err != nil { - return 0, fmt.Errorf("error converting cty value of type %s to uint32: %w", val.Type().FriendlyName(), err) - } - return goVal, nil -} - -func int64FromCty(val cty.Value) (int64, error) { - if val.Type() != cty.Number { - return 0, fmt.Errorf("expected value of type %s but actual type is %s", cty.Number.FriendlyName(), val.Type().FriendlyName()) - } - - if val.IsNull() { - return 0, nil - } - - var goVal int64 - if err := gocty.FromCtyValue(val, &goVal); err != nil { - return 0, fmt.Errorf("error converting cty value of type %s to int64: %w", val.Type().FriendlyName(), err) - } - return goVal, nil -} - -func uint64FromCty(val cty.Value) (uint64, error) { - if val.Type() != cty.Number { - return 0, fmt.Errorf("expected value of type %s but actual type is %s", cty.Number.FriendlyName(), val.Type().FriendlyName()) - } - - if val.IsNull() { - return 0, nil - } - - var goVal uint64 - if err := gocty.FromCtyValue(val, &goVal); err != nil { - return 0, fmt.Errorf("error converting cty value of type %s to uint64: %w", val.Type().FriendlyName(), err) - } - return goVal, nil -} - -func floatFromCty(val cty.Value) (float32, error) { - if val.Type() != cty.Number { - return 0, fmt.Errorf("expected value of type %s but actual type is %s", cty.Number.FriendlyName(), val.Type().FriendlyName()) - } - - if val.IsNull() { - return 0, nil - } - - var goVal float32 - if err := gocty.FromCtyValue(val, &goVal); err != nil { - return 0, fmt.Errorf("error converting cty value of type %s to float32: %w", val.Type().FriendlyName(), err) - } - return goVal, nil -} - -func doubleFromCty(val cty.Value) (float64, error) { - if val.Type() != cty.Number { - return 0, fmt.Errorf("expected value of type %s but actual type is %s", cty.Number.FriendlyName(), val.Type().FriendlyName()) - } - - if val.IsNull() { - return 0, nil - } - - var goVal float64 - if err := gocty.FromCtyValue(val, &goVal); err != nil { - return 0, fmt.Errorf("error converting cty value of type %s to float64: %w", val.Type().FriendlyName(), err) - } - return goVal, nil -} - -func stringFromCty(val cty.Value) (string, error) { - if val.Type() != cty.String { - return "", fmt.Errorf("expected value of type %s but actual type is %s", cty.String.FriendlyName(), val.Type().FriendlyName()) - } - - if val.IsNull() { - return "", nil - } - return val.AsString(), nil -} - -func bytesFromCty(val cty.Value) ([]byte, error) { - if val.Type() != cty.String { - return nil, fmt.Errorf("expected value of type %s but actual type is %s", cty.String.FriendlyName(), val.Type().FriendlyName()) - } - - if val.IsNull() { - return nil, nil - } - - encoded := val.AsString() - decoded, err := base64.StdEncoding.DecodeString(encoded) - if err != nil { - return nil, fmt.Errorf("error base64 decoding byte string: %w", err) - } - - return decoded, nil -} diff --git a/internal/protohcl/decoder.go b/internal/protohcl/decoder.go deleted file mode 100644 index 67ee074ec1c00..0000000000000 --- a/internal/protohcl/decoder.go +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package protohcl - -import ( - "fmt" - "sort" - - "github.com/hashicorp/hcl/v2" - "github.com/zclconf/go-cty/cty" - "github.com/zclconf/go-cty/cty/function" - "google.golang.org/protobuf/reflect/protoreflect" -) - -// MessageDecoder provides an abstract way to decode protobuf messages from HCL -// blocks or objects. -type MessageDecoder interface { - // EachField calls the given iterator for each field provided in the HCL source. - EachField(iter FieldIterator) error - - // SkipFields returns a MessageDecoder that skips over the given fields. It is - // primarily used for doing two-pass decoding of protobuf `Any` fields. - SkipFields(fields ...string) MessageDecoder -} - -// IterField represents a field discovered by the MessageDecoder. -type IterField struct { - // Name is the HCL name of the field. - Name string - - // Desc is the protobuf field descriptor. - Desc protoreflect.FieldDescriptor - - // Val is the field value, only if it was given using HCL attribute syntax. - Val *cty.Value - - // Blocks contains the HCL blocks that were given for this field. - Blocks []*hcl.Block - - // Range determines where in the HCL source the field was given, it is useful - // for error messages. - Range hcl.Range -} - -// FieldIterator is given to MessageDecoder.EachField to iterate over all of the -// fields in a given HCL block or object. -type FieldIterator struct { - // IgnoreUnknown instructs the MessageDecoder to skip over any fields not - // included in Desc. - IgnoreUnknown bool - - // Desc is the protobuf descriptor for the message the caller is decoding into. - // It is used to determine which fields are valid. - Desc protoreflect.MessageDescriptor - - // Func is called for each field in the given HCL block or object. - Func func(field *IterField) error -} - -func newBodyDecoder( - body hcl.Body, - namer FieldNamer, - functions map[string]function.Function, -) MessageDecoder { - return bodyDecoder{ - body: body, - namer: namer, - functions: functions, - skipFields: make(map[string]struct{}), - } -} - -type bodyDecoder struct { - body hcl.Body - namer FieldNamer - functions map[string]function.Function - skipFields map[string]struct{} -} - -func (bd bodyDecoder) EachField(iter FieldIterator) error { - schema, err := bd.schema(iter.Desc) - if err != nil { - return err - } - - var ( - content *hcl.BodyContent - diags hcl.Diagnostics - ) - if iter.IgnoreUnknown { - content, _, diags = bd.body.PartialContent(schema) - } else { - content, diags = bd.body.Content(schema) - } - if diags.HasErrors() { - return diags - } - - fields := make([]*IterField, 0) - - for _, attr := range content.Attributes { - if _, ok := bd.skipFields[attr.Name]; ok { - continue - } - - desc := bd.namer.GetField(iter.Desc.Fields(), attr.Name) - - val, err := attr.Expr.Value(&hcl.EvalContext{Functions: bd.functions}) - if err != nil { - return err - } - - fields = append(fields, &IterField{ - Name: attr.Name, - Desc: desc, - Val: &val, - Range: attr.Expr.Range(), - }) - } - - for blockType, blocks := range content.Blocks.ByType() { - if _, ok := bd.skipFields[blockType]; ok { - continue - } - - desc := bd.namer.GetField(iter.Desc.Fields(), blockType) - - fields = append(fields, &IterField{ - Name: blockType, - Desc: desc, - Blocks: blocks, - }) - } - - // Always handle Any fields last, as decoding them may require type information - // gathered from other fields (e.g. as in the case of Resource GVKs). - sort.Slice(fields, func(a, b int) bool { - if isAnyField(fields[b].Desc) && !isAnyField(fields[a].Desc) { - return true - } - return a < b - }) - - for _, field := range fields { - if err := iter.Func(field); err != nil { - return err - } - } - - return nil -} - -func (bd bodyDecoder) SkipFields(fields ...string) MessageDecoder { - skip := make(map[string]struct{}, len(fields)+len(bd.skipFields)) - for k, v := range bd.skipFields { - skip[k] = v - } - for _, field := range fields { - skip[field] = struct{}{} - } - - // Note: we rely on the fact bd isn't a pointer to copy the struct here. - bd.skipFields = skip - return bd -} - -func (bd bodyDecoder) schema(desc protoreflect.MessageDescriptor) (*hcl.BodySchema, error) { - var schema hcl.BodySchema - - fields := desc.Fields() - for i := 0; i < fields.Len(); i++ { - f := fields.Get(i) - - kind := f.Kind() - // maps are special and whether they use block or attribute syntax depends - // on the value type - if f.IsMap() { - valueDesc := f.MapValue() - valueKind := valueDesc.Kind() - - wktHint := wellKnownTypeSchemaHint(valueDesc) - - // Message types should generally be encoded as blocks unless its a special Well Known Type - // that should use attribute encoding - if valueKind == protoreflect.MessageKind && wktHint != wellKnownAttribute { - schema.Blocks = append(schema.Blocks, hcl.BlockHeaderSchema{ - Type: bd.namer.NameField(f), - LabelNames: []string{"key"}, - }) - continue - } - - // non-message types or Well Known Message types that need attribute encoding - // get decoded as attributes - schema.Attributes = append(schema.Attributes, hcl.AttributeSchema{ - Name: bd.namer.NameField(f), - }) - continue - } - - wktHint := wellKnownTypeSchemaHint(f) - - // message types generally will use block syntax unless its a well known - // message type that requires attribute syntax specifically. - if kind == protoreflect.MessageKind && wktHint != wellKnownAttribute { - schema.Blocks = append(schema.Blocks, hcl.BlockHeaderSchema{ - Type: bd.namer.NameField(f), - }) - } - - // by default use attribute encoding - // - primitives - // - repeated primitives - // - Well Known Types requiring attribute syntax - // - repeated Well Known Types requiring attribute syntax - schema.Attributes = append(schema.Attributes, hcl.AttributeSchema{ - Name: bd.namer.NameField(f), - }) - continue - } - - // Add skipped fields to the schema so HCL doesn't throw an error when it finds them. - for field := range bd.skipFields { - schema.Attributes = append(schema.Attributes, hcl.AttributeSchema{Name: field}) - schema.Blocks = append(schema.Blocks, hcl.BlockHeaderSchema{Type: field}) - } - - return &schema, nil -} - -func newObjectDecoder(object cty.Value, namer FieldNamer, rng hcl.Range) MessageDecoder { - return objectDecoder{ - object: object, - namer: namer, - rng: rng, - skipFields: make(map[string]struct{}), - } -} - -type objectDecoder struct { - object cty.Value - namer FieldNamer - rng hcl.Range - skipFields map[string]struct{} -} - -func (od objectDecoder) EachField(iter FieldIterator) error { - for attr := range od.object.Type().AttributeTypes() { - if _, ok := od.skipFields[attr]; ok { - continue - } - - desc := od.namer.GetField(iter.Desc.Fields(), attr) - if desc == nil { - if iter.IgnoreUnknown { - continue - } else { - return fmt.Errorf("%s: Unsupported argument; An argument named %q is not expected here.", od.rng, attr) - } - } - - val := od.object.GetAttr(attr) - if err := iter.Func(&IterField{ - Name: attr, - Desc: desc, - Val: &val, - }); err != nil { - return err - } - } - return nil -} - -func (od objectDecoder) SkipFields(fields ...string) MessageDecoder { - skip := make(map[string]struct{}, len(fields)+len(od.skipFields)) - for k, v := range od.skipFields { - skip[k] = v - } - for _, field := range fields { - skip[field] = struct{}{} - } - - // Note: we rely on the fact od isn't a pointer to copy the struct here. - od.skipFields = skip - return od -} diff --git a/internal/protohcl/doc.go b/internal/protohcl/doc.go deleted file mode 100644 index e3270f7cdcf19..0000000000000 --- a/internal/protohcl/doc.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// The protohcl package aims to define a canonical way to translate between -// protobuf and HCL encodings of data. -// -// Similar to google.golang.org/protobuf/encoding/protojson it intends to be -// opinionated about what the canonical HCL representation of a protobuf type -// should be. -// -// As HCL is a user centric data format as opposed to JSON/Protobuf which -// are intended to be used more by machines, efficiency is not a primary goal -// of this package as it is expected that users are either doing the encoding to and -// decoding from HCL at the edge (such as within the Consul CLI) or that even -// when done on servers, the rate that servers perform these translations should -// be low enough to have any inefficiency produce a tangible performance impact. -// -// HCL has two different syntaxes that could be used to represent data: attribute and block -// -// This implementation chooses to represent primitive values, enums and the well known wrapper types and -// collections of these values (maps and repeated fields) with attribute syntax. Other messages and collections -// with message value types will be represented with block syntax for example -// -// message Foo { -// map map_of_ints = 1; -// map map_of_messages = 2; -// } -// -// would have HCL like: -// -// map_of_ints = { -// "foo": 1, -// "bar": 2, -// } -// map_of_messages "foo" { -// ...other fields -// } -// map_of_messages "bar" { -// ...other fields -// } -// -// Similar goes for list of primitives vs list of messages (except the block syntax uses no labels). The differences -// between primitive fields outside of a collection and a message field really just amounts to not having to specify -// the "=" between the field name and the "{" character. -// -// Field Mapping -// | proto3 | HCL Type | example | notes | -// |------------------------+---------------+---------+---------------------------------------------------------------------------------+ -// | message | Object | | Represented as a block | -// | enum | String | | | -// | map | Map | | All keys are converted to/from strings. | -// | repeated V | List | | | -// | bool | Bool | | | -// | string | String | | | -// | bytes | base64 String | | | -// | int32, fixed32, uint32 | Number | | | -// | int64, fixed64, uint64 | Number | | | -// | float, double | Number | | | -// -// ----- Well Known Types ----- -// -// | Any | Object | | | -// | Timestamp | String | | RFC 3339 compliant | -// | Duration | String | | String form is what would be accepted by time.ParseDuration | -// | Struct | Map | | | -// | Empty | Object | | An object with no fields | -// | BoolValue | Bool | | Mostly the same as a regular bool except null values in the HCL are preserved | -// | BytesValue | Bytes | | Mostly the same as a regular bytes except null values in the HCL are preserved | -// | StringValue | String | | Mostly the same as a regular string except null values in the HCL are preserved | -// | FloatValue | Number | | Mostly the same as a regular float except null values in the HCL are preserved | -// | DoubleValue | Number | | Mostly the same as a regular double except null values in the HCL are preserved | -// | Int32Value | Number | | Mostly the same as a regular int32 except null values in the HCL are preserved | -// | UInt32Value | Number | | Mostly the same as a regular uint32 except null values in the HCL are preserved | -// | Int64Value | Number | | Mostly the same as a regular int64 except null values in the HCL are preserved | -// | UInt64Value | Number | | Mostly the same as a regular uint64 except null values in the HCL are preserved | -// | FieldMask | String | | Each string of the FieldMask will be joined with a '.' | -// - -package protohcl diff --git a/internal/protohcl/naming.go b/internal/protohcl/naming.go deleted file mode 100644 index d8eef2275fd7d..0000000000000 --- a/internal/protohcl/naming.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package protohcl - -import "google.golang.org/protobuf/reflect/protoreflect" - -type FieldNamer interface { - NameField(protoreflect.FieldDescriptor) string - GetField(protoreflect.FieldDescriptors, string) protoreflect.FieldDescriptor -} - -type textFieldNamer struct{} - -func (textFieldNamer) NameField(fd protoreflect.FieldDescriptor) string { - return fd.TextName() -} - -func (textFieldNamer) GetField(fds protoreflect.FieldDescriptors, name string) protoreflect.FieldDescriptor { - return fds.ByTextName(name) -} diff --git a/internal/protohcl/oneof.go b/internal/protohcl/oneof.go deleted file mode 100644 index 0c95326614bda..0000000000000 --- a/internal/protohcl/oneof.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package protohcl - -import ( - "fmt" - "strings" - - "google.golang.org/protobuf/reflect/protoreflect" -) - -type oneOfTracker struct { - namer FieldNamer - set map[protoreflect.FullName]string -} - -func newOneOfTracker(namer FieldNamer) *oneOfTracker { - return &oneOfTracker{ - namer: namer, - set: make(map[protoreflect.FullName]string), - } -} - -func (o *oneOfTracker) markFieldAsSet(desc protoreflect.FieldDescriptor) error { - oneof := desc.ContainingOneof() - if oneof == nil { - return nil - } - - oneOfName := oneof.FullName() - - if otherFieldName, ok := o.set[oneOfName]; ok { - oneOfFields := oneof.Fields() - var builder strings.Builder - - for i := 0; i < oneOfFields.Len(); i++ { - name := o.namer.NameField(oneOfFields.Get(i)) - - if i == oneOfFields.Len()-1 { - builder.WriteString(fmt.Sprintf("%q", name)) - } else if i == oneOfFields.Len()-2 { - builder.WriteString(fmt.Sprintf("%q and ", name)) - } else { - builder.WriteString(fmt.Sprintf("%q, ", name)) - } - } - - return fmt.Errorf("Cannot set %q because %q was previously set. Only one of %s may be set.", o.namer.NameField(desc), otherFieldName, builder.String()) - } - - o.set[oneOfName] = o.namer.NameField(desc) - return nil -} diff --git a/internal/protohcl/primitives.go b/internal/protohcl/primitives.go deleted file mode 100644 index 4d1f220330269..0000000000000 --- a/internal/protohcl/primitives.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package protohcl - -import ( - "fmt" - - "github.com/zclconf/go-cty/cty" - "google.golang.org/protobuf/reflect/protoreflect" -) - -func decodeAttributeToPrimitive(desc protoreflect.FieldDescriptor, val cty.Value) (protoreflect.Value, error) { - switch kind := desc.Kind(); kind { - case protoreflect.BoolKind: - return protoBoolFromCty(val) - case protoreflect.EnumKind: - return protoEnumFromCty(desc, val) - case protoreflect.Int32Kind: - return protoInt32FromCty(val) - case protoreflect.Sint32Kind: - return protoInt32FromCty(val) - case protoreflect.Uint32Kind: - return protoUint32FromCty(val) - case protoreflect.Int64Kind: - return protoInt64FromCty(val) - case protoreflect.Sint64Kind: - return protoInt64FromCty(val) - case protoreflect.Uint64Kind: - return protoUint64FromCty(val) - case protoreflect.Sfixed32Kind: - return protoInt32FromCty(val) - case protoreflect.Fixed32Kind: - return protoUint32FromCty(val) - case protoreflect.FloatKind: - return protoFloatFromCty(val) - case protoreflect.Sfixed64Kind: - return protoInt64FromCty(val) - case protoreflect.Fixed64Kind: - return protoUint64FromCty(val) - case protoreflect.DoubleKind: - return protoDoubleFromCty(val) - case protoreflect.StringKind: - return protoStringFromCty(val) - case protoreflect.BytesKind: - return protoBytesFromCty(val) - default: - return protoreflect.Value{}, fmt.Errorf("unknown primitive protobuf kind: %q", kind.String()) - } -} - -func protoBoolFromCty(val cty.Value) (protoreflect.Value, error) { - goVal, err := boolFromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoreflect.ValueOfBool(goVal), nil -} - -func protoEnumFromCty(desc protoreflect.FieldDescriptor, val cty.Value) (protoreflect.Value, error) { - if val.Type() != cty.String { - return protoreflect.Value{}, fmt.Errorf("expected value of type %s but actual type is %s", cty.String.FriendlyName(), val.Type().FriendlyName()) - } - - if val.IsNull() { - defaultValDesc := desc.DefaultEnumValue() - return protoreflect.ValueOfEnum(defaultValDesc.Number()), nil - } - - valDesc := desc.Enum().Values().ByName(protoreflect.Name(val.AsString())) - if valDesc == nil { - defaultValDesc := desc.DefaultEnumValue() - return protoreflect.ValueOfEnum(defaultValDesc.Number()), nil - } - - return protoreflect.ValueOfEnum(valDesc.Number()), nil -} - -func protoInt32FromCty(val cty.Value) (protoreflect.Value, error) { - goVal, err := int32FromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoreflect.ValueOfInt32(goVal), nil -} - -func protoUint32FromCty(val cty.Value) (protoreflect.Value, error) { - goVal, err := uint32FromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoreflect.ValueOfUint32(goVal), nil -} - -func protoInt64FromCty(val cty.Value) (protoreflect.Value, error) { - goVal, err := int64FromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoreflect.ValueOfInt64(goVal), nil -} - -func protoUint64FromCty(val cty.Value) (protoreflect.Value, error) { - goVal, err := uint64FromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoreflect.ValueOfUint64(goVal), nil -} - -func protoFloatFromCty(val cty.Value) (protoreflect.Value, error) { - goVal, err := floatFromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoreflect.ValueOfFloat32(goVal), nil -} - -func protoDoubleFromCty(val cty.Value) (protoreflect.Value, error) { - goVal, err := doubleFromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoreflect.ValueOfFloat64(goVal), nil -} - -func protoStringFromCty(val cty.Value) (protoreflect.Value, error) { - goVal, err := stringFromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoreflect.ValueOfString(goVal), nil -} - -func protoBytesFromCty(val cty.Value) (protoreflect.Value, error) { - goVal, err := bytesFromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoreflect.ValueOfBytes(goVal), nil -} diff --git a/internal/protohcl/testproto/buf.gen.yaml b/internal/protohcl/testproto/buf.gen.yaml deleted file mode 100644 index fecee5cf24962..0000000000000 --- a/internal/protohcl/testproto/buf.gen.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - -version: v1 -managed: - enabled: true - go_package_prefix: - default: github.com/hashicorp/consul/internal/protohcl/testproto -plugins: - - name: go - out: . - opt: paths=source_relative diff --git a/internal/protohcl/testproto/example.pb.go b/internal/protohcl/testproto/example.pb.go deleted file mode 100644 index 304eac53d6d90..0000000000000 --- a/internal/protohcl/testproto/example.pb.go +++ /dev/null @@ -1,997 +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: example.proto - -package testproto - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - anypb "google.golang.org/protobuf/types/known/anypb" - durationpb "google.golang.org/protobuf/types/known/durationpb" - emptypb "google.golang.org/protobuf/types/known/emptypb" - structpb "google.golang.org/protobuf/types/known/structpb" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - 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 Protocol int32 - -const ( - Protocol_PROTOCOL_UNSPECIFIED Protocol = 0 - Protocol_PROTOCOL_TCP Protocol = 1 - Protocol_PROTOCOL_UDP Protocol = 2 -) - -// Enum value maps for Protocol. -var ( - Protocol_name = map[int32]string{ - 0: "PROTOCOL_UNSPECIFIED", - 1: "PROTOCOL_TCP", - 2: "PROTOCOL_UDP", - } - Protocol_value = map[string]int32{ - "PROTOCOL_UNSPECIFIED": 0, - "PROTOCOL_TCP": 1, - "PROTOCOL_UDP": 2, - } -) - -func (x Protocol) Enum() *Protocol { - p := new(Protocol) - *p = x - return p -} - -func (x Protocol) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Protocol) Descriptor() protoreflect.EnumDescriptor { - return file_example_proto_enumTypes[0].Descriptor() -} - -func (Protocol) Type() protoreflect.EnumType { - return &file_example_proto_enumTypes[0] -} - -func (x Protocol) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Protocol.Descriptor instead. -func (Protocol) EnumDescriptor() ([]byte, []int) { - return file_example_proto_rawDescGZIP(), []int{0} -} - -type Primitives struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DoubleVal float64 `protobuf:"fixed64,1,opt,name=double_val,json=doubleVal,proto3" json:"double_val,omitempty"` - FloatVal float32 `protobuf:"fixed32,2,opt,name=float_val,json=floatVal,proto3" json:"float_val,omitempty"` - Int32Val int32 `protobuf:"varint,3,opt,name=int32_val,json=int32Val,proto3" json:"int32_val,omitempty"` - Int64Val int64 `protobuf:"varint,4,opt,name=int64_val,json=int64Val,proto3" json:"int64_val,omitempty"` - Uint32Val uint32 `protobuf:"varint,5,opt,name=uint32_val,json=uint32Val,proto3" json:"uint32_val,omitempty"` - Uint64Val uint64 `protobuf:"varint,6,opt,name=uint64_val,json=uint64Val,proto3" json:"uint64_val,omitempty"` - Sint32Val int32 `protobuf:"zigzag32,7,opt,name=sint32_val,json=sint32Val,proto3" json:"sint32_val,omitempty"` - Sint64Val int64 `protobuf:"zigzag64,8,opt,name=sint64_val,json=sint64Val,proto3" json:"sint64_val,omitempty"` - Fixed32Val uint32 `protobuf:"fixed32,9,opt,name=fixed32_val,json=fixed32Val,proto3" json:"fixed32_val,omitempty"` - Fixed64Val uint64 `protobuf:"fixed64,10,opt,name=fixed64_val,json=fixed64Val,proto3" json:"fixed64_val,omitempty"` - Sfixed32Val int32 `protobuf:"fixed32,11,opt,name=sfixed32_val,json=sfixed32Val,proto3" json:"sfixed32_val,omitempty"` - Sfixed64Val int64 `protobuf:"fixed64,12,opt,name=sfixed64_val,json=sfixed64Val,proto3" json:"sfixed64_val,omitempty"` - BoolVal bool `protobuf:"varint,13,opt,name=bool_val,json=boolVal,proto3" json:"bool_val,omitempty"` - StringVal string `protobuf:"bytes,14,opt,name=string_val,json=stringVal,proto3" json:"string_val,omitempty"` - ByteVal []byte `protobuf:"bytes,15,opt,name=byte_val,json=byteVal,proto3" json:"byte_val,omitempty"` -} - -func (x *Primitives) Reset() { - *x = Primitives{} - if protoimpl.UnsafeEnabled { - mi := &file_example_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Primitives) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Primitives) ProtoMessage() {} - -func (x *Primitives) ProtoReflect() protoreflect.Message { - mi := &file_example_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 Primitives.ProtoReflect.Descriptor instead. -func (*Primitives) Descriptor() ([]byte, []int) { - return file_example_proto_rawDescGZIP(), []int{0} -} - -func (x *Primitives) GetDoubleVal() float64 { - if x != nil { - return x.DoubleVal - } - return 0 -} - -func (x *Primitives) GetFloatVal() float32 { - if x != nil { - return x.FloatVal - } - return 0 -} - -func (x *Primitives) GetInt32Val() int32 { - if x != nil { - return x.Int32Val - } - return 0 -} - -func (x *Primitives) GetInt64Val() int64 { - if x != nil { - return x.Int64Val - } - return 0 -} - -func (x *Primitives) GetUint32Val() uint32 { - if x != nil { - return x.Uint32Val - } - return 0 -} - -func (x *Primitives) GetUint64Val() uint64 { - if x != nil { - return x.Uint64Val - } - return 0 -} - -func (x *Primitives) GetSint32Val() int32 { - if x != nil { - return x.Sint32Val - } - return 0 -} - -func (x *Primitives) GetSint64Val() int64 { - if x != nil { - return x.Sint64Val - } - return 0 -} - -func (x *Primitives) GetFixed32Val() uint32 { - if x != nil { - return x.Fixed32Val - } - return 0 -} - -func (x *Primitives) GetFixed64Val() uint64 { - if x != nil { - return x.Fixed64Val - } - return 0 -} - -func (x *Primitives) GetSfixed32Val() int32 { - if x != nil { - return x.Sfixed32Val - } - return 0 -} - -func (x *Primitives) GetSfixed64Val() int64 { - if x != nil { - return x.Sfixed64Val - } - return 0 -} - -func (x *Primitives) GetBoolVal() bool { - if x != nil { - return x.BoolVal - } - return false -} - -func (x *Primitives) GetStringVal() string { - if x != nil { - return x.StringVal - } - return "" -} - -func (x *Primitives) GetByteVal() []byte { - if x != nil { - return x.ByteVal - } - return nil -} - -type NestedAndCollections struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Primitives *Primitives `protobuf:"bytes,1,opt,name=primitives,proto3" json:"primitives,omitempty"` - PrimitivesList []*Primitives `protobuf:"bytes,2,rep,name=primitives_list,json=primitivesList,proto3" json:"primitives_list,omitempty"` - PrimitivesMap map[string]*Primitives `protobuf:"bytes,3,rep,name=primitives_map,json=primitivesMap,proto3" json:"primitives_map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - ProtocolMap map[string]Protocol `protobuf:"bytes,4,rep,name=protocol_map,json=protocolMap,proto3" json:"protocol_map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3,enum=hashicorp.consul.internal.protohcl.testproto.Protocol"` - IntList []int32 `protobuf:"varint,5,rep,packed,name=int_list,json=intList,proto3" json:"int_list,omitempty"` -} - -func (x *NestedAndCollections) Reset() { - *x = NestedAndCollections{} - if protoimpl.UnsafeEnabled { - mi := &file_example_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NestedAndCollections) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NestedAndCollections) ProtoMessage() {} - -func (x *NestedAndCollections) ProtoReflect() protoreflect.Message { - mi := &file_example_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 NestedAndCollections.ProtoReflect.Descriptor instead. -func (*NestedAndCollections) Descriptor() ([]byte, []int) { - return file_example_proto_rawDescGZIP(), []int{1} -} - -func (x *NestedAndCollections) GetPrimitives() *Primitives { - if x != nil { - return x.Primitives - } - return nil -} - -func (x *NestedAndCollections) GetPrimitivesList() []*Primitives { - if x != nil { - return x.PrimitivesList - } - return nil -} - -func (x *NestedAndCollections) GetPrimitivesMap() map[string]*Primitives { - if x != nil { - return x.PrimitivesMap - } - return nil -} - -func (x *NestedAndCollections) GetProtocolMap() map[string]Protocol { - if x != nil { - return x.ProtocolMap - } - return nil -} - -func (x *NestedAndCollections) GetIntList() []int32 { - if x != nil { - return x.IntList - } - return nil -} - -type Wrappers struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DoubleVal *wrapperspb.DoubleValue `protobuf:"bytes,1,opt,name=double_val,json=doubleVal,proto3" json:"double_val,omitempty"` - FloatVal *wrapperspb.FloatValue `protobuf:"bytes,2,opt,name=float_val,json=floatVal,proto3" json:"float_val,omitempty"` - Int32Val *wrapperspb.Int32Value `protobuf:"bytes,3,opt,name=int32_val,json=int32Val,proto3" json:"int32_val,omitempty"` - Int64Val *wrapperspb.Int64Value `protobuf:"bytes,4,opt,name=int64_val,json=int64Val,proto3" json:"int64_val,omitempty"` - Uint32Val *wrapperspb.UInt32Value `protobuf:"bytes,5,opt,name=uint32_val,json=uint32Val,proto3" json:"uint32_val,omitempty"` - Uint64Val *wrapperspb.UInt64Value `protobuf:"bytes,6,opt,name=uint64_val,json=uint64Val,proto3" json:"uint64_val,omitempty"` - BoolVal *wrapperspb.BoolValue `protobuf:"bytes,13,opt,name=bool_val,json=boolVal,proto3" json:"bool_val,omitempty"` - StringVal *wrapperspb.StringValue `protobuf:"bytes,14,opt,name=string_val,json=stringVal,proto3" json:"string_val,omitempty"` - BytesVal *wrapperspb.BytesValue `protobuf:"bytes,15,opt,name=bytes_val,json=bytesVal,proto3" json:"bytes_val,omitempty"` -} - -func (x *Wrappers) Reset() { - *x = Wrappers{} - if protoimpl.UnsafeEnabled { - mi := &file_example_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Wrappers) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Wrappers) ProtoMessage() {} - -func (x *Wrappers) ProtoReflect() protoreflect.Message { - mi := &file_example_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 Wrappers.ProtoReflect.Descriptor instead. -func (*Wrappers) Descriptor() ([]byte, []int) { - return file_example_proto_rawDescGZIP(), []int{2} -} - -func (x *Wrappers) GetDoubleVal() *wrapperspb.DoubleValue { - if x != nil { - return x.DoubleVal - } - return nil -} - -func (x *Wrappers) GetFloatVal() *wrapperspb.FloatValue { - if x != nil { - return x.FloatVal - } - return nil -} - -func (x *Wrappers) GetInt32Val() *wrapperspb.Int32Value { - if x != nil { - return x.Int32Val - } - return nil -} - -func (x *Wrappers) GetInt64Val() *wrapperspb.Int64Value { - if x != nil { - return x.Int64Val - } - return nil -} - -func (x *Wrappers) GetUint32Val() *wrapperspb.UInt32Value { - if x != nil { - return x.Uint32Val - } - return nil -} - -func (x *Wrappers) GetUint64Val() *wrapperspb.UInt64Value { - if x != nil { - return x.Uint64Val - } - return nil -} - -func (x *Wrappers) GetBoolVal() *wrapperspb.BoolValue { - if x != nil { - return x.BoolVal - } - return nil -} - -func (x *Wrappers) GetStringVal() *wrapperspb.StringValue { - if x != nil { - return x.StringVal - } - return nil -} - -func (x *Wrappers) GetBytesVal() *wrapperspb.BytesValue { - if x != nil { - return x.BytesVal - } - return nil -} - -type OneOf struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Data: - // - // *OneOf_Int32Val - // *OneOf_Primitives - Data isOneOf_Data `protobuf_oneof:"data"` -} - -func (x *OneOf) Reset() { - *x = OneOf{} - if protoimpl.UnsafeEnabled { - mi := &file_example_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OneOf) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OneOf) ProtoMessage() {} - -func (x *OneOf) ProtoReflect() protoreflect.Message { - mi := &file_example_proto_msgTypes[3] - 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 OneOf.ProtoReflect.Descriptor instead. -func (*OneOf) Descriptor() ([]byte, []int) { - return file_example_proto_rawDescGZIP(), []int{3} -} - -func (m *OneOf) GetData() isOneOf_Data { - if m != nil { - return m.Data - } - return nil -} - -func (x *OneOf) GetInt32Val() int32 { - if x, ok := x.GetData().(*OneOf_Int32Val); ok { - return x.Int32Val - } - return 0 -} - -func (x *OneOf) GetPrimitives() *Primitives { - if x, ok := x.GetData().(*OneOf_Primitives); ok { - return x.Primitives - } - return nil -} - -type isOneOf_Data interface { - isOneOf_Data() -} - -type OneOf_Int32Val struct { - Int32Val int32 `protobuf:"varint,1,opt,name=int32_val,json=int32Val,proto3,oneof"` -} - -type OneOf_Primitives struct { - Primitives *Primitives `protobuf:"bytes,2,opt,name=primitives,proto3,oneof"` // note repeated fields (including maps) are not allowed in oneofs -} - -func (*OneOf_Int32Val) isOneOf_Data() {} - -func (*OneOf_Primitives) isOneOf_Data() {} - -type NonDynamicWellKnown struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - EmptyVal *emptypb.Empty `protobuf:"bytes,1,opt,name=empty_val,json=emptyVal,proto3" json:"empty_val,omitempty"` - TimestampVal *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=timestamp_val,json=timestampVal,proto3" json:"timestamp_val,omitempty"` - DurationVal *durationpb.Duration `protobuf:"bytes,3,opt,name=duration_val,json=durationVal,proto3" json:"duration_val,omitempty"` -} - -func (x *NonDynamicWellKnown) Reset() { - *x = NonDynamicWellKnown{} - if protoimpl.UnsafeEnabled { - mi := &file_example_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NonDynamicWellKnown) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NonDynamicWellKnown) ProtoMessage() {} - -func (x *NonDynamicWellKnown) ProtoReflect() protoreflect.Message { - mi := &file_example_proto_msgTypes[4] - 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 NonDynamicWellKnown.ProtoReflect.Descriptor instead. -func (*NonDynamicWellKnown) Descriptor() ([]byte, []int) { - return file_example_proto_rawDescGZIP(), []int{4} -} - -func (x *NonDynamicWellKnown) GetEmptyVal() *emptypb.Empty { - if x != nil { - return x.EmptyVal - } - return nil -} - -func (x *NonDynamicWellKnown) GetTimestampVal() *timestamppb.Timestamp { - if x != nil { - return x.TimestampVal - } - return nil -} - -func (x *NonDynamicWellKnown) GetDurationVal() *durationpb.Duration { - if x != nil { - return x.DurationVal - } - return nil -} - -type DynamicWellKnown struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AnyVal *anypb.Any `protobuf:"bytes,1,opt,name=any_val,json=anyVal,proto3" json:"any_val,omitempty"` - StructVal *structpb.Struct `protobuf:"bytes,2,opt,name=struct_val,json=structVal,proto3" json:"struct_val,omitempty"` - AnyList []*anypb.Any `protobuf:"bytes,3,rep,name=any_list,json=anyList,proto3" json:"any_list,omitempty"` -} - -func (x *DynamicWellKnown) Reset() { - *x = DynamicWellKnown{} - if protoimpl.UnsafeEnabled { - mi := &file_example_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DynamicWellKnown) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DynamicWellKnown) ProtoMessage() {} - -func (x *DynamicWellKnown) ProtoReflect() protoreflect.Message { - mi := &file_example_proto_msgTypes[5] - 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 DynamicWellKnown.ProtoReflect.Descriptor instead. -func (*DynamicWellKnown) Descriptor() ([]byte, []int) { - return file_example_proto_rawDescGZIP(), []int{5} -} - -func (x *DynamicWellKnown) GetAnyVal() *anypb.Any { - if x != nil { - return x.AnyVal - } - return nil -} - -func (x *DynamicWellKnown) GetStructVal() *structpb.Struct { - if x != nil { - return x.StructVal - } - return nil -} - -func (x *DynamicWellKnown) GetAnyList() []*anypb.Any { - if x != nil { - return x.AnyList - } - return nil -} - -var File_example_proto protoreflect.FileDescriptor - -var file_example_proto_rawDesc = []byte{ - 0x0a, 0x0d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x2c, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x68, 0x63, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, - 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, - 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdb, 0x03, 0x0a, 0x0a, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, - 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x12, - 0x1b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x08, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, - 0x69, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x69, 0x6e, 0x74, - 0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x75, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x6e, 0x74, 0x33, - 0x32, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x11, 0x52, 0x09, 0x73, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x6e, 0x74, 0x36, 0x34, - 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x12, 0x52, 0x09, 0x73, 0x69, 0x6e, 0x74, - 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, - 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x07, 0x52, 0x0a, 0x66, 0x69, 0x78, 0x65, - 0x64, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, - 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x06, 0x52, 0x0a, 0x66, 0x69, 0x78, - 0x65, 0x64, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x66, 0x69, 0x78, 0x65, - 0x64, 0x33, 0x32, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x0b, 0x73, - 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x66, - 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x10, - 0x52, 0x0b, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x19, 0x0a, - 0x08, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x07, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x79, 0x74, 0x65, 0x5f, - 0x76, 0x61, 0x6c, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x62, 0x79, 0x74, 0x65, 0x56, - 0x61, 0x6c, 0x22, 0xd8, 0x05, 0x0a, 0x14, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x41, 0x6e, 0x64, - 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x0a, 0x70, - 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x68, 0x63, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, - 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x12, 0x61, 0x0a, 0x0f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x68, 0x63, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x52, 0x0e, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x7c, 0x0a, 0x0e, 0x70, 0x72, 0x69, 0x6d, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x55, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x41, 0x6e, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x4d, - 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x12, 0x76, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x53, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63, - 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4e, 0x65, 0x73, 0x74, - 0x65, 0x64, 0x41, 0x6e, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x4d, 0x61, 0x70, 0x12, 0x19, - 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x05, - 0x52, 0x07, 0x69, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x7a, 0x0a, 0x12, 0x50, 0x72, 0x69, - 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x4e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x76, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4c, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x9d, 0x04, - 0x0a, 0x08, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x12, 0x3b, 0x0a, 0x0a, 0x64, 0x6f, - 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x09, 0x64, 0x6f, - 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x12, 0x38, 0x0a, 0x09, 0x66, 0x6c, 0x6f, 0x61, 0x74, - 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x6c, 0x6f, - 0x61, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x56, 0x61, - 0x6c, 0x12, 0x38, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x38, 0x0a, 0x09, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x74, - 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x3b, 0x0a, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, - 0x76, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, - 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x56, - 0x61, 0x6c, 0x12, 0x3b, 0x0a, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, - 0x35, 0x0a, 0x08, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x62, - 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x12, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x09, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x56, 0x61, 0x6c, 0x12, 0x38, 0x0a, 0x09, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x76, 0x61, 0x6c, - 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x08, 0x62, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, 0x22, 0x8a, 0x01, - 0x0a, 0x05, 0x4f, 0x6e, 0x65, 0x4f, 0x66, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x33, 0x32, - 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x5a, 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xc9, 0x01, 0x0a, 0x13, 0x4e, - 0x6f, 0x6e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, - 0x77, 0x6e, 0x12, 0x33, 0x0a, 0x09, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x08, 0x65, - 0x6d, 0x70, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x12, 0x3f, 0x0a, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x56, 0x61, 0x6c, 0x12, 0x3c, 0x0a, 0x0c, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x22, 0xaa, 0x01, 0x0a, 0x10, 0x44, 0x79, 0x6e, 0x61, 0x6d, - 0x69, 0x63, 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x12, 0x2d, 0x0a, 0x07, 0x61, - 0x6e, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, - 0x6e, 0x79, 0x52, 0x06, 0x61, 0x6e, 0x79, 0x56, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x0a, 0x73, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x09, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x56, - 0x61, 0x6c, 0x12, 0x2f, 0x0a, 0x08, 0x61, 0x6e, 0x79, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x61, 0x6e, 0x79, 0x4c, - 0x69, 0x73, 0x74, 0x2a, 0x48, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, - 0x18, 0x0a, 0x14, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x4f, - 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x50, - 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x55, 0x44, 0x50, 0x10, 0x02, 0x42, 0xcf, 0x02, - 0x0a, 0x30, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x42, 0x0c, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x37, 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, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63, - 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xa2, 0x02, 0x05, 0x48, 0x43, - 0x49, 0x50, 0x54, 0xaa, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0xca, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x5c, 0x54, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0xe2, 0x02, 0x38, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x5c, 0x54, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x30, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x68, 0x63, 0x6c, 0x3a, 0x3a, 0x54, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_example_proto_rawDescOnce sync.Once - file_example_proto_rawDescData = file_example_proto_rawDesc -) - -func file_example_proto_rawDescGZIP() []byte { - file_example_proto_rawDescOnce.Do(func() { - file_example_proto_rawDescData = protoimpl.X.CompressGZIP(file_example_proto_rawDescData) - }) - return file_example_proto_rawDescData -} - -var file_example_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_example_proto_msgTypes = make([]protoimpl.MessageInfo, 8) -var file_example_proto_goTypes = []interface{}{ - (Protocol)(0), // 0: hashicorp.consul.internal.protohcl.testproto.Protocol - (*Primitives)(nil), // 1: hashicorp.consul.internal.protohcl.testproto.Primitives - (*NestedAndCollections)(nil), // 2: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections - (*Wrappers)(nil), // 3: hashicorp.consul.internal.protohcl.testproto.Wrappers - (*OneOf)(nil), // 4: hashicorp.consul.internal.protohcl.testproto.OneOf - (*NonDynamicWellKnown)(nil), // 5: hashicorp.consul.internal.protohcl.testproto.NonDynamicWellKnown - (*DynamicWellKnown)(nil), // 6: hashicorp.consul.internal.protohcl.testproto.DynamicWellKnown - nil, // 7: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.PrimitivesMapEntry - nil, // 8: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.ProtocolMapEntry - (*wrapperspb.DoubleValue)(nil), // 9: google.protobuf.DoubleValue - (*wrapperspb.FloatValue)(nil), // 10: google.protobuf.FloatValue - (*wrapperspb.Int32Value)(nil), // 11: google.protobuf.Int32Value - (*wrapperspb.Int64Value)(nil), // 12: google.protobuf.Int64Value - (*wrapperspb.UInt32Value)(nil), // 13: google.protobuf.UInt32Value - (*wrapperspb.UInt64Value)(nil), // 14: google.protobuf.UInt64Value - (*wrapperspb.BoolValue)(nil), // 15: google.protobuf.BoolValue - (*wrapperspb.StringValue)(nil), // 16: google.protobuf.StringValue - (*wrapperspb.BytesValue)(nil), // 17: google.protobuf.BytesValue - (*emptypb.Empty)(nil), // 18: google.protobuf.Empty - (*timestamppb.Timestamp)(nil), // 19: google.protobuf.Timestamp - (*durationpb.Duration)(nil), // 20: google.protobuf.Duration - (*anypb.Any)(nil), // 21: google.protobuf.Any - (*structpb.Struct)(nil), // 22: google.protobuf.Struct -} -var file_example_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.primitives:type_name -> hashicorp.consul.internal.protohcl.testproto.Primitives - 1, // 1: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.primitives_list:type_name -> hashicorp.consul.internal.protohcl.testproto.Primitives - 7, // 2: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.primitives_map:type_name -> hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.PrimitivesMapEntry - 8, // 3: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.protocol_map:type_name -> hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.ProtocolMapEntry - 9, // 4: hashicorp.consul.internal.protohcl.testproto.Wrappers.double_val:type_name -> google.protobuf.DoubleValue - 10, // 5: hashicorp.consul.internal.protohcl.testproto.Wrappers.float_val:type_name -> google.protobuf.FloatValue - 11, // 6: hashicorp.consul.internal.protohcl.testproto.Wrappers.int32_val:type_name -> google.protobuf.Int32Value - 12, // 7: hashicorp.consul.internal.protohcl.testproto.Wrappers.int64_val:type_name -> google.protobuf.Int64Value - 13, // 8: hashicorp.consul.internal.protohcl.testproto.Wrappers.uint32_val:type_name -> google.protobuf.UInt32Value - 14, // 9: hashicorp.consul.internal.protohcl.testproto.Wrappers.uint64_val:type_name -> google.protobuf.UInt64Value - 15, // 10: hashicorp.consul.internal.protohcl.testproto.Wrappers.bool_val:type_name -> google.protobuf.BoolValue - 16, // 11: hashicorp.consul.internal.protohcl.testproto.Wrappers.string_val:type_name -> google.protobuf.StringValue - 17, // 12: hashicorp.consul.internal.protohcl.testproto.Wrappers.bytes_val:type_name -> google.protobuf.BytesValue - 1, // 13: hashicorp.consul.internal.protohcl.testproto.OneOf.primitives:type_name -> hashicorp.consul.internal.protohcl.testproto.Primitives - 18, // 14: hashicorp.consul.internal.protohcl.testproto.NonDynamicWellKnown.empty_val:type_name -> google.protobuf.Empty - 19, // 15: hashicorp.consul.internal.protohcl.testproto.NonDynamicWellKnown.timestamp_val:type_name -> google.protobuf.Timestamp - 20, // 16: hashicorp.consul.internal.protohcl.testproto.NonDynamicWellKnown.duration_val:type_name -> google.protobuf.Duration - 21, // 17: hashicorp.consul.internal.protohcl.testproto.DynamicWellKnown.any_val:type_name -> google.protobuf.Any - 22, // 18: hashicorp.consul.internal.protohcl.testproto.DynamicWellKnown.struct_val:type_name -> google.protobuf.Struct - 21, // 19: hashicorp.consul.internal.protohcl.testproto.DynamicWellKnown.any_list:type_name -> google.protobuf.Any - 1, // 20: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.PrimitivesMapEntry.value:type_name -> hashicorp.consul.internal.protohcl.testproto.Primitives - 0, // 21: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.ProtocolMapEntry.value:type_name -> hashicorp.consul.internal.protohcl.testproto.Protocol - 22, // [22:22] is the sub-list for method output_type - 22, // [22:22] is the sub-list for method input_type - 22, // [22:22] is the sub-list for extension type_name - 22, // [22:22] is the sub-list for extension extendee - 0, // [0:22] is the sub-list for field type_name -} - -func init() { file_example_proto_init() } -func file_example_proto_init() { - if File_example_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_example_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Primitives); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_example_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NestedAndCollections); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_example_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Wrappers); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_example_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OneOf); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_example_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NonDynamicWellKnown); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_example_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DynamicWellKnown); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_example_proto_msgTypes[3].OneofWrappers = []interface{}{ - (*OneOf_Int32Val)(nil), - (*OneOf_Primitives)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_example_proto_rawDesc, - NumEnums: 1, - NumMessages: 8, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_example_proto_goTypes, - DependencyIndexes: file_example_proto_depIdxs, - EnumInfos: file_example_proto_enumTypes, - MessageInfos: file_example_proto_msgTypes, - }.Build() - File_example_proto = out.File - file_example_proto_rawDesc = nil - file_example_proto_goTypes = nil - file_example_proto_depIdxs = nil -} diff --git a/internal/protohcl/testproto/example.proto b/internal/protohcl/testproto/example.proto deleted file mode 100644 index 17bf737fa3aca..0000000000000 --- a/internal/protohcl/testproto/example.proto +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -syntax = "proto3"; - -package hashicorp.consul.internal.protohcl.testproto; - -import "google/protobuf/duration.proto"; -import "google/protobuf/empty.proto"; -import "google/protobuf/timestamp.proto"; -import "google/protobuf/wrappers.proto"; -import "google/protobuf/any.proto"; -import "google/protobuf/struct.proto"; - -message Primitives { - double double_val = 1; - float float_val = 2; - int32 int32_val = 3; - int64 int64_val = 4; - uint32 uint32_val = 5; - uint64 uint64_val = 6; - sint32 sint32_val = 7; - sint64 sint64_val = 8; - fixed32 fixed32_val = 9; - fixed64 fixed64_val = 10; - sfixed32 sfixed32_val = 11; - sfixed64 sfixed64_val = 12; - bool bool_val = 13; - string string_val = 14; - bytes byte_val = 15; -} - -enum Protocol { - PROTOCOL_UNSPECIFIED = 0; - PROTOCOL_TCP = 1; - PROTOCOL_UDP = 2; -} - -message NestedAndCollections { - Primitives primitives = 1; - repeated Primitives primitives_list = 2; - map primitives_map = 3; - map protocol_map = 4; - repeated int32 int_list = 5; -} - -message Wrappers { - google.protobuf.DoubleValue double_val = 1; - google.protobuf.FloatValue float_val = 2; - google.protobuf.Int32Value int32_val = 3; - google.protobuf.Int64Value int64_val = 4; - google.protobuf.UInt32Value uint32_val = 5; - google.protobuf.UInt64Value uint64_val = 6; - google.protobuf.BoolValue bool_val = 13; - google.protobuf.StringValue string_val = 14; - google.protobuf.BytesValue bytes_val = 15; -} - -message OneOf { - oneof data { - int32 int32_val = 1; - Primitives primitives = 2; - // note repeated fields (including maps) are not allowed in oneofs - } -} - -message NonDynamicWellKnown { - google.protobuf.Empty empty_val = 1; - google.protobuf.Timestamp timestamp_val = 2; - google.protobuf.Duration duration_val = 3; -} - -message DynamicWellKnown { - google.protobuf.Any any_val = 1; - google.protobuf.Struct struct_val = 2; - repeated google.protobuf.Any any_list = 3; -} diff --git a/internal/protohcl/unmarshal.go b/internal/protohcl/unmarshal.go deleted file mode 100644 index 0f3c80a4c26e3..0000000000000 --- a/internal/protohcl/unmarshal.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package protohcl - -import ( - "github.com/hashicorp/hcl/v2" - "github.com/hashicorp/hcl/v2/hclparse" - "github.com/zclconf/go-cty/cty/function" - "google.golang.org/protobuf/reflect/protoreflect" -) - -// UnmarshalContext provides information about the context in which we are -// unmarshalling HCL. It is primarily used for decoding Any fields based on -// surrounding information (e.g. the resource Type block). -type UnmarshalContext struct { - // Parent context. - Parent *UnmarshalContext - - // Name of the field that we are unmarshalling. - Name string - - // Message is the protobuf message that we are unmarshalling into (may be nil). - Message protoreflect.Message - - // Range of where this field was in the HCL source. - Range hcl.Range -} - -// ErrorRange returns a range that can be used in error messages. -func (ctx *UnmarshalContext) ErrorRange() hcl.Range { - for { - if !ctx.Range.Empty() || ctx.Parent == nil { - return ctx.Range - } - ctx = ctx.Parent - } -} - -func Unmarshal(src []byte, dest protoreflect.ProtoMessage) error { - return UnmarshalOptions{}.Unmarshal(src, dest) -} - -type UnmarshalOptions struct { - AnyTypeProvider AnyTypeProvider - SourceFileName string - FieldNamer FieldNamer - Functions map[string]function.Function -} - -func (u UnmarshalOptions) Unmarshal(src []byte, dest protoreflect.ProtoMessage) error { - rmsg := dest.ProtoReflect() - - file, diags := hclparse.NewParser().ParseHCL(src, u.SourceFileName) - - // error performing basic HCL parsing - if diags.HasErrors() { - return diags - } - - u.clearAll(rmsg) - - if u.FieldNamer == nil { - u.FieldNamer = textFieldNamer{} - } - - return u.decodeMessage( - &UnmarshalContext{Message: rmsg}, - u.bodyDecoder(file.Body), - rmsg, - ) -} - -func (u UnmarshalOptions) bodyDecoder(body hcl.Body) MessageDecoder { - return newBodyDecoder(body, u.FieldNamer, u.Functions) -} - -func (u UnmarshalOptions) decodeMessage(ctx *UnmarshalContext, decoder MessageDecoder, msg protoreflect.Message) error { - desc := msg.Descriptor() - - if desc.FullName() == wellKnownTypeAny { - return u.decodeAny(ctx, decoder, msg) - } - - tracker := newOneOfTracker(u.FieldNamer) - - return decoder.EachField(FieldIterator{ - Desc: desc, - Func: func(field *IterField) error { - if err := tracker.markFieldAsSet(field.Desc); err != nil { - return err - } - - var ( - protoVal protoreflect.Value - err error - ) - switch { - case field.Val != nil: - protoVal, err = u.decodeAttribute( - &UnmarshalContext{ - Parent: ctx, - Name: field.Name, - Range: field.Range, - }, - func() protoreflect.Value { return msg.NewField(field.Desc) }, - field.Desc, - *field.Val, - true, - ) - case len(field.Blocks) != 0: - protoVal, err = u.decodeBlocks(ctx, field.Blocks, msg, field.Desc) - default: - panic("decoder yielded no blocks or attributes") - } - if err != nil { - return err - } - - if protoVal.IsValid() { - msg.Set(field.Desc, protoVal) - } - - return nil - }, - }) -} - -type newMessageFn func() protoreflect.Value - -func (u UnmarshalOptions) clearAll(msg protoreflect.Message) { - fields := msg.Descriptor().Fields() - - for i := 0; i < fields.Len(); i++ { - msg.Clear(fields.Get(i)) - } -} diff --git a/internal/protohcl/unmarshal_test.go b/internal/protohcl/unmarshal_test.go deleted file mode 100644 index ef00de3ffbb63..0000000000000 --- a/internal/protohcl/unmarshal_test.go +++ /dev/null @@ -1,560 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package protohcl - -import ( - "encoding/json" - "fmt" - "reflect" - "testing" - "time" - - "github.com/stretchr/testify/require" - "github.com/zclconf/go-cty/cty" - "github.com/zclconf/go-cty/cty/function" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/protohcl/testproto" - "github.com/hashicorp/hcl/v2/hclparse" -) - -func TestPrimitives(t *testing.T) { - hcl := ` - double_val = 1.234 - float_val = 2.345 - int32_val = 536870912 - int64_val = 25769803776 - uint32_val = 2148532224 - uint64_val = 9223372041149743104 - sint32_val = 536870912 - sint64_val = 25769803776 - fixed32_val = 2148532224 - fixed64_val = 9223372041149743104 - sfixed32_val = 536870912 - sfixed64_val = 25769803776 - bool_val = true - string_val = "foo" - // This is base64 encoded "bar" - byte_val = "YmFy" - ` - - var out testproto.Primitives - - err := Unmarshal([]byte(hcl), &out) - require.NoError(t, err) - - require.Equal(t, out.DoubleVal, float64(1.234)) - require.Equal(t, out.FloatVal, float32(2.345)) - require.Equal(t, out.Int32Val, int32(536870912)) - require.Equal(t, out.Int64Val, int64(25769803776)) - require.Equal(t, out.Uint32Val, uint32(2148532224)) - require.Equal(t, out.Uint64Val, uint64(9223372041149743104)) - require.Equal(t, out.Sint32Val, int32(536870912)) - require.Equal(t, out.Sint64Val, int64(25769803776)) - require.Equal(t, out.Fixed32Val, uint32(2148532224)) - require.Equal(t, out.Fixed64Val, uint64(9223372041149743104)) - require.Equal(t, out.Sfixed32Val, int32(536870912)) - require.Equal(t, out.Sfixed64Val, int64(25769803776)) - require.Equal(t, out.BoolVal, true) - require.Equal(t, out.StringVal, "foo") - require.Equal(t, out.ByteVal, []byte("bar")) -} - -func TestNestedAndCollections(t *testing.T) { - hcl := ` - primitives { - uint32_val = 42 - } - - primitives_map "foo" { - uint32_val = 42 - } - - protocol_map = { - "foo" = "PROTOCOL_TCP" - } - - primitives_list { - uint32_val = 42 - } - - primitives_list { - uint32_val = 56 - } - - int_list = [ - 1, - 2 - ] - - ` - - var out testproto.NestedAndCollections - - err := Unmarshal([]byte(hcl), &out) - require.NoError(t, err) - - require.NotNil(t, out.Primitives) - require.Equal(t, out.Primitives.Uint32Val, uint32(42)) - require.NotNil(t, out.PrimitivesMap) - require.Equal(t, out.PrimitivesMap["foo"].Uint32Val, uint32(42)) - require.NotNil(t, out.ProtocolMap) - require.Equal(t, out.ProtocolMap["foo"], testproto.Protocol_PROTOCOL_TCP) - require.Len(t, out.PrimitivesList, 2) - require.Equal(t, out.PrimitivesList[0].Uint32Val, uint32(42)) - require.Equal(t, out.PrimitivesList[1].Uint32Val, uint32(56)) - require.Len(t, out.IntList, 2) - require.Equal(t, out.IntList[1], int32(2)) -} - -func TestPrimitiveWrappers(t *testing.T) { - hcl := ` - double_val = 1.234 - float_val = 2.345 - int32_val = 536870912 - int64_val = 25769803776 - uint32_val = 2148532224 - uint64_val = 9223372041149743104 - bool_val = true - string_val = "foo" - // This is base64 encoded "bar" - bytes_val = "YmFy" - ` - var out testproto.Wrappers - - err := Unmarshal([]byte(hcl), &out) - require.NoError(t, err) - require.Equal(t, out.DoubleVal.Value, float64(1.234)) - require.Equal(t, out.FloatVal.Value, float32(2.345)) - require.Equal(t, out.Int32Val.Value, int32(536870912)) - require.Equal(t, out.Int64Val.Value, int64(25769803776)) - require.Equal(t, out.Uint32Val.Value, uint32(2148532224)) - require.Equal(t, out.Uint64Val.Value, uint64(9223372041149743104)) - require.Equal(t, out.BoolVal.Value, true) - require.Equal(t, out.StringVal.Value, "foo") - require.Equal(t, out.BytesVal.Value, []byte("bar")) -} - -func TestNonDynamicWellKnown(t *testing.T) { - hcl := ` - empty_val = {} - timestamp_val = "2023-02-27T12:34:56.789Z" - duration_val = "12s" - ` - var out testproto.NonDynamicWellKnown - - err := Unmarshal([]byte(hcl), &out) - require.NoError(t, err) - require.NotNil(t, out.EmptyVal) - require.NotNil(t, out.TimestampVal) - require.Equal(t, out.TimestampVal.AsTime(), time.Date(2023, 2, 27, 12, 34, 56, 789000000, time.UTC)) - require.NotNil(t, out.DurationVal) - require.Equal(t, out.DurationVal.AsDuration(), time.Second*12) -} - -func TestInvalidTimestamp(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - - cases := map[string]struct { - hcl string - expectXDS bool - }{ - "invalid": { - hcl: ` - timestamp_val = "Sat Jun 12 2023 14:59:57 GMT+0200" - `, - }, - "range error": { - hcl: ` - timestamp_val = "2023-02-27T25:34:56.789Z" - `, - }, - } - - for name, tc := range cases { - tc := tc - var out testproto.NonDynamicWellKnown - t.Run(name, func(t *testing.T) { - - err := Unmarshal([]byte(tc.hcl), &out) - require.Error(t, err) - require.Nil(t, out.TimestampVal) - require.ErrorContains(t, err, "error parsing timestamp") - }) - } -} - -func TestInvalidDuration(t *testing.T) { - hcl := ` - duration_val = "abc" - ` - var out testproto.NonDynamicWellKnown - - err := Unmarshal([]byte(hcl), &out) - require.ErrorContains(t, err, "error parsing string duration:") - require.Nil(t, out.DurationVal) -} - -func TestOneOf(t *testing.T) { - hcl1 := ` - int32_val = 3 - ` - - hcl2 := ` - primitives { - int32_val = 3 - } - ` - - hcl3 := ` - int32_val = 3 - primitives { - int32_val = 4 - } - ` - - var out testproto.OneOf - - err := Unmarshal([]byte(hcl1), &out) - require.NoError(t, err) - require.Equal(t, out.GetInt32Val(), int32(3)) - - err = Unmarshal([]byte(hcl2), &out) - require.NoError(t, err) - primitives := out.GetPrimitives() - require.NotNil(t, primitives) - require.Equal(t, primitives.Int32Val, int32(3)) - - err = Unmarshal([]byte(hcl3), &out) - require.Error(t, err) -} - -func TestAny(t *testing.T) { - hcl := ` - any_val { - type_url = "hashicorp.consul.internal.protohcl.testproto.Primitives" - uint32_val = 42 - } - - any_list = [ - { - type_url = "hashicorp.consul.internal.protohcl.testproto.Primitives" - uint32_val = 123 - }, - { - type_url = "hashicorp.consul.internal.protohcl.testproto.Wrappers" - uint32_val = 321 - } - ] - ` - var out testproto.DynamicWellKnown - - err := Unmarshal([]byte(hcl), &out) - require.NoError(t, err) - require.NotNil(t, out.AnyVal) - require.Equal(t, out.AnyVal.TypeUrl, "hashicorp.consul.internal.protohcl.testproto.Primitives") - - raw, err := anypb.UnmarshalNew(out.AnyVal, proto.UnmarshalOptions{}) - require.NoError(t, err) - require.NotNil(t, raw) - - primitives, ok := raw.(*testproto.Primitives) - require.True(t, ok) - require.Equal(t, primitives.Uint32Val, uint32(42)) -} - -func TestAnyTypeDynamicWellKnown(t *testing.T) { - hcl := ` - any_val { - type_url = "hashicorp.consul.internal.protohcl.testproto.DynamicWellKnown" - any_val { - type_url = "hashicorp.consul.internal.protohcl.testproto.Primitives" - uint32_val = 42 - } - } - ` - var out testproto.DynamicWellKnown - - err := Unmarshal([]byte(hcl), &out) - require.NoError(t, err) - require.NotNil(t, out.AnyVal) - require.Equal(t, out.AnyVal.TypeUrl, "hashicorp.consul.internal.protohcl.testproto.DynamicWellKnown") - - raw, err := anypb.UnmarshalNew(out.AnyVal, proto.UnmarshalOptions{}) - require.NoError(t, err) - require.NotNil(t, raw) - - anyVal, ok := raw.(*testproto.DynamicWellKnown) - require.True(t, ok) - - res, err := anypb.UnmarshalNew(anyVal.AnyVal, proto.UnmarshalOptions{}) - require.NoError(t, err) - require.NotNil(t, res) - - primitives, ok := res.(*testproto.Primitives) - require.True(t, ok) - require.Equal(t, primitives.Uint32Val, uint32(42)) -} - -func TestAnyTypeNestedAndCollections(t *testing.T) { - hcl := ` - any_val { - type_url = "hashicorp.consul.internal.protohcl.testproto.NestedAndCollections" - primitives { - uint32_val = 42 - } - } - ` - var out testproto.DynamicWellKnown - - err := Unmarshal([]byte(hcl), &out) - require.NoError(t, err) - require.NotNil(t, out.AnyVal) - require.Equal(t, out.AnyVal.TypeUrl, "hashicorp.consul.internal.protohcl.testproto.NestedAndCollections") - - raw, err := anypb.UnmarshalNew(out.AnyVal, proto.UnmarshalOptions{}) - require.NoError(t, err) - require.NotNil(t, raw) - - nestedCollections, ok := raw.(*testproto.NestedAndCollections) - require.True(t, ok) - require.NotNil(t, nestedCollections.Primitives) - require.Equal(t, nestedCollections.Primitives.Uint32Val, uint32(42)) -} - -func TestAnyTypeErrors(t *testing.T) { - type testCase struct { - description string - hcl string - error string - } - testCases := []testCase{ - { - description: "type_url is expected", - hcl: ` - any_val { - uint32_val = 42 - } - `, - error: "type_url field is required to decode Any", - }, - { - description: "type_url is unknown", - hcl: ` - any_val { - type_url = "hashicorp.consul.internal.protohcl.testproto.Integer" - uint32_val = 42 - } - `, - error: "error looking up type information for hashicorp.consul.internal.protohcl.testproto.Integer", - }, - { - description: "unknown field", - hcl: ` - any_val { - type_url = "hashicorp.consul.internal.protohcl.testproto.Primitives" - int_val = 42 - } - `, - error: "Unsupported argument; An argument named \"int_val\" is not expected here", - }, - } - - for _, tc := range testCases { - tc := tc - t.Run(tc.description, func(t *testing.T) { - t.Parallel() - var out testproto.DynamicWellKnown - - err := Unmarshal([]byte(tc.hcl), &out) - require.Error(t, err) - require.Contains(t, err.Error(), tc.error) - }) - } -} - -func TestStruct(t *testing.T) { - hcl := ` - struct_val = { - "null"= null - "bool"= true - "foo" = "bar" - "baz" = 1.234 - "nested" = { - "foo" = 12, - "bar" = "something" - } - } - ` - - var out testproto.DynamicWellKnown - - err := Unmarshal([]byte(hcl), &out) - require.NoError(t, err) - require.NotNil(t, out.StructVal) - - valMap := out.StructVal.AsMap() - jsonVal, err := json.Marshal(valMap) - require.NoError(t, err) - - expected := `{ - "null": null, - "bool": true, - "foo": "bar", - "baz": 1.234, - "nested": { - "foo": 12, - "bar": "something" - } - } - ` - require.JSONEq(t, expected, string(jsonVal)) -} - -func TestStructList(t *testing.T) { - hcl := ` - struct_val = { - "list_int" = [ - 1, - 2, - 3, - ] - "list_string": [ - "abc", - "def" - ] - "list_bool": [ - true, - false - ] - "list_maps" = [ - { - "arrr" = "matey" - }, - { - "hoist" = "the colors" - } - ] - "list_list" = [ - [ - "hello", - "world", - null - ] - ] - } - ` - - var out testproto.DynamicWellKnown - - err := Unmarshal([]byte(hcl), &out) - require.NoError(t, err) - require.NotNil(t, out.StructVal) - - valMap := out.StructVal.AsMap() - jsonVal, err := json.Marshal(valMap) - require.NoError(t, err) - - expected := `{ - "list_int": [ - 1, - 2, - 3 - ], - "list_string": [ - "abc", - "def" - ], - "list_bool": [ - true, - false - ], - "list_maps": [ - { - "arrr": "matey" - }, - { - "hoist": "the colors" - } - ], - "list_list": [ - [ - "hello", - "world", - null - ] - ] - } - ` - require.JSONEq(t, expected, string(jsonVal)) -} - -func TestFunctionExecution(t *testing.T) { - hcl := ` - primitives = primitive_defaults() - ` - - var out testproto.NestedAndCollections - - var ( - testType = cty.Capsule("type", reflect.TypeOf(testproto.Primitives{})) - - test = function.New(&function.Spec{ - Params: []function.Parameter{}, - Type: function.StaticReturnType(testType), - Impl: func(args []cty.Value, _ cty.Type) (cty.Value, error) { - t := &testproto.Primitives{ - StringVal: "test", - Int32Val: 10, - BoolVal: false, - } - return cty.CapsuleVal(testType, t), nil - }, - }) - ) - - err := UnmarshalOptions{ - Functions: map[string]function.Function{"primitive_defaults": test}, - }.Unmarshal([]byte(hcl), &out) - - require.NoError(t, err) - - require.NotNil(t, out.Primitives) - require.Equal(t, out.Primitives.StringVal, "test") - require.Equal(t, out.Primitives.Int32Val, int32(10)) - require.Equal(t, out.Primitives.BoolVal, false) -} - -func TestSkipFields(t *testing.T) { - - u := UnmarshalOptions{} - - hcl := ` - any_val { - type_url = "hashicorp.consul.internal.protohcl.testproto.Primitives" - uint32_val = 10 - }` - - file, diags := hclparse.NewParser().ParseHCL([]byte(hcl), "") - - require.False(t, diags.HasErrors()) - - decoder := u.bodyDecoder(file.Body) - - decoder = decoder.SkipFields("type_url") - - decoder = decoder.SkipFields("type_url", "uint32_val") - - expected := map[string]struct{}{ - "type_url": {}, - "uint32_val": {}, - } - - require.Contains(t, fmt.Sprintf("%v", decoder), fmt.Sprintf("%v", expected)) -} diff --git a/internal/protohcl/well_known_types.go b/internal/protohcl/well_known_types.go deleted file mode 100644 index 756f908fc413d..0000000000000 --- a/internal/protohcl/well_known_types.go +++ /dev/null @@ -1,421 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package protohcl - -import ( - "fmt" - "time" - - "github.com/zclconf/go-cty/cty" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/emptypb" - "google.golang.org/protobuf/types/known/structpb" - "google.golang.org/protobuf/types/known/timestamppb" - "google.golang.org/protobuf/types/known/wrapperspb" -) - -const ( - // maximum time in seconds that a time.Time which comes from - // an RFC 3339 timestamp can represent - maxTimestampSeconds = 253402300799 - // minimum time in seconds that a time.Time which comes from - // an RFC 3339 timestamp can represent. This is negative - // because RFC 3339 base time is year 0001 whereas time.Time - // starts in 1970 - minTimestampSeconds = -62135596800 -) - -var ( - // minTime is the earliest time representable as both an - // RFC 3339 timestamp and a time.Time value - minTime = time.Unix(minTimestampSeconds, 0) - // maxTime is the latest time respresentable as both an - // RFC 3339 timestamp and a time.Time value - maxTime = time.Unix(maxTimestampSeconds, 999999999) -) - -type wktSchemaHint int - -const ( - notWellKnownType wktSchemaHint = iota - wellKnownBlock - wellKnownAttribute -) - -// wellKnownTypeSchemaHint returns what sort of syntax should be used to represent -// the well known type field. -// -// NotWellKnownType - use attribute block syntax based on other information -// WellKnownAttribute - use attribute syntax -// WellKnownBlock - use block syntax -func wellKnownTypeSchemaHint(desc protoreflect.FieldDescriptor) wktSchemaHint { - if desc.Kind() != protoreflect.MessageKind { - return notWellKnownType - } - - switch desc.Message().FullName() { - case "google.protobuf.DoubleValue": - return wellKnownAttribute - case "google.protobuf.FloatValue": - return wellKnownAttribute - case "google.protobuf.Int32Value": - return wellKnownAttribute - case "google.protobuf.Int64Value": - return wellKnownAttribute - case "google.protobuf.UInt32Value": - return wellKnownAttribute - case "google.protobuf.UInt64Value": - return wellKnownAttribute - case "google.protobuf.BoolValue": - return wellKnownAttribute - case "google.protobuf.StringValue": - return wellKnownAttribute - case "google.protobuf.BytesValue": - return wellKnownAttribute - case "google.protobuf.Empty": - // block syntax is used for Empty to allow transitioning to using - // a different proto message with fields in the future. - return wellKnownBlock - case "google.protobuf.Timestamp": - return wellKnownAttribute - case "google.protobuf.Duration": - return wellKnownAttribute - case "google.protobuf.Struct": - // as the Struct has completely free form fields that we cannot - // know about in advance we cannot use block syntax - return wellKnownAttribute - case "google.protobuf.Any": - return wellKnownBlock - default: - return notWellKnownType - } -} - -func decodeAttributeToWellKnownType(desc protoreflect.FieldDescriptor, val cty.Value) (bool, protoreflect.Value, error) { - if desc.Kind() != protoreflect.MessageKind { - return false, protoreflect.Value{}, nil - } - - switch desc.Message().FullName() { - case "google.protobuf.DoubleValue": - protoVal, err := protoDoubleWrapperFromCty(val) - return true, protoVal, err - case "google.protobuf.FloatValue": - protoVal, err := protoFloatWrapperFromCty(val) - return true, protoVal, err - case "google.protobuf.Int32Value": - protoVal, err := protoInt32WrapperFromCty(val) - return true, protoVal, err - case "google.protobuf.Int64Value": - protoVal, err := protoInt64WrapperFromCty(val) - return true, protoVal, err - case "google.protobuf.UInt32Value": - protoVal, err := protoUint32WrapperFromCty(val) - return true, protoVal, err - case "google.protobuf.UInt64Value": - protoVal, err := protoUint64WrapperFromCty(val) - return true, protoVal, err - case "google.protobuf.BoolValue": - protoVal, err := protoBoolWrapperFromCty(val) - return true, protoVal, err - case "google.protobuf.StringValue": - protoVal, err := protoStringWrapperFromCty(val) - return true, protoVal, err - case "google.protobuf.BytesValue": - protoVal, err := protoBytesWrapperFromCty(val) - return true, protoVal, err - case "google.protobuf.Empty": - protoVal, err := protoEmptyFromCty(val) - return true, protoVal, err - case "google.protobuf.Timestamp": - protoVal, err := protoTimestampFromCty(val) - return true, protoVal, err - case "google.protobuf.Duration": - protoVal, err := protoDurationFromCty(val) - return true, protoVal, err - case "google.protobuf.Struct": - protoVal, err := protoStructFromCty(val) - return true, protoVal, err - default: - return false, protoreflect.Value{}, nil - } -} - -func protoWrapperFromBool(v bool) protoreflect.Value { - return protoreflect.ValueOfMessage(wrapperspb.Bool(v).ProtoReflect()) -} -func protoWrapperFromInt32(v int32) protoreflect.Value { - return protoreflect.ValueOfMessage(wrapperspb.Int32(v).ProtoReflect()) -} -func protoWrapperFromInt64(v int64) protoreflect.Value { - return protoreflect.ValueOfMessage(wrapperspb.Int64(v).ProtoReflect()) -} -func protoWrapperFromUint32(v uint32) protoreflect.Value { - return protoreflect.ValueOfMessage(wrapperspb.UInt32(v).ProtoReflect()) -} -func protoWrapperFromUint64(v uint64) protoreflect.Value { - return protoreflect.ValueOfMessage(wrapperspb.UInt64(v).ProtoReflect()) -} -func protoWrapperFromFloat(v float32) protoreflect.Value { - return protoreflect.ValueOfMessage(wrapperspb.Float(v).ProtoReflect()) -} -func protoWrapperFromDouble(v float64) protoreflect.Value { - return protoreflect.ValueOfMessage(wrapperspb.Double(v).ProtoReflect()) -} -func protoWrapperFromString(v string) protoreflect.Value { - return protoreflect.ValueOfMessage(wrapperspb.String(v).ProtoReflect()) -} -func protoWrapperFromBytes(v []byte) protoreflect.Value { - return protoreflect.ValueOfMessage(wrapperspb.Bytes(v).ProtoReflect()) -} - -func protoBoolWrapperFromCty(val cty.Value) (protoreflect.Value, error) { - v, err := boolFromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoWrapperFromBool(v), nil -} -func protoInt32WrapperFromCty(val cty.Value) (protoreflect.Value, error) { - v, err := int32FromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoWrapperFromInt32(v), nil -} -func protoInt64WrapperFromCty(val cty.Value) (protoreflect.Value, error) { - v, err := int64FromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoWrapperFromInt64(v), nil -} -func protoUint32WrapperFromCty(val cty.Value) (protoreflect.Value, error) { - v, err := uint32FromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoWrapperFromUint32(v), nil -} -func protoUint64WrapperFromCty(val cty.Value) (protoreflect.Value, error) { - v, err := uint64FromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoWrapperFromUint64(v), nil -} -func protoFloatWrapperFromCty(val cty.Value) (protoreflect.Value, error) { - v, err := floatFromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoWrapperFromFloat(v), nil -} -func protoDoubleWrapperFromCty(val cty.Value) (protoreflect.Value, error) { - v, err := doubleFromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoWrapperFromDouble(v), nil -} -func protoStringWrapperFromCty(val cty.Value) (protoreflect.Value, error) { - v, err := stringFromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoWrapperFromString(v), nil -} -func protoBytesWrapperFromCty(val cty.Value) (protoreflect.Value, error) { - v, err := bytesFromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - return protoWrapperFromBytes(v), nil -} - -func protoEmptyFromCty(val cty.Value) (protoreflect.Value, error) { - var e emptypb.Empty - if val.IsNull() { - return protoreflect.Value{}, nil - } - - valType := val.Type() - if (valType.IsObjectType() || valType.IsMapType()) && val.LengthInt() == 0 { - return protoreflect.ValueOfMessage(e.ProtoReflect()), nil - } - - return protoreflect.Value{}, fmt.Errorf("well known empty type can only be represented as an hcl map/object - actual type %q", valType.FriendlyName()) -} - -func protoTimestampFromCty(val cty.Value) (protoreflect.Value, error) { - v, err := stringFromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - - t, err := time.Parse(time.RFC3339Nano, v) - if err != nil { - return protoreflect.Value{}, fmt.Errorf("error parsing timestamp: %w", err) - } - - if t.Before(minTime) || t.After(maxTime) { - return protoreflect.Value{}, fmt.Errorf("time is out of range %s to %s - %s", minTime.String(), maxTime.String(), v) - } - - return protoreflect.ValueOfMessage(timestamppb.New(t).ProtoReflect()), nil -} - -func protoDurationFromCty(val cty.Value) (protoreflect.Value, error) { - v, err := stringFromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - - d, err := time.ParseDuration(v) - if err != nil { - return protoreflect.Value{}, fmt.Errorf("error parsing string duration: %w", err) - } - - return protoreflect.ValueOfMessage(durationpb.New(d).ProtoReflect()), nil -} - -func protoStructFromCty(val cty.Value) (protoreflect.Value, error) { - s, err := protoStructObjectFromCty(val) - if err != nil { - return protoreflect.Value{}, err - } - - return protoreflect.ValueOfMessage(s.ProtoReflect()), nil -} - -func protoStructObjectFromCty(val cty.Value) (*structpb.Struct, error) { - valType := val.Type() - if !valType.IsObjectType() && !valType.IsMapType() { - return nil, fmt.Errorf("Struct type must be either an object or map type") - } - - structValues := make(map[string]*structpb.Value) - - for k, v := range val.AsValueMap() { - vType := v.Type() - - if v.IsNull() { - structValues[k] = structpb.NewNullValue() - } else if vType.IsListType() || vType.IsSetType() || vType.IsTupleType() { - listVal, err := protoStructListValueFromCty(v) - if err != nil { - return nil, err - } - structValues[k] = structpb.NewListValue(listVal) - } else if vType.IsMapType() || vType.IsObjectType() { - objVal, err := protoStructObjectFromCty(v) - if err != nil { - return nil, err - } - structValues[k] = structpb.NewStructValue(objVal) - } else if vType.IsPrimitiveType() { - switch vType { - case cty.String: - stringVal, err := stringFromCty(v) - if err != nil { - return nil, err - } - - structValues[k] = structpb.NewStringValue(stringVal) - case cty.Bool: - boolVal, err := boolFromCty(v) - if err != nil { - return nil, err - } - - structValues[k] = structpb.NewBoolValue(boolVal) - case cty.Number: - doubleVal, err := doubleFromCty(v) - if err != nil { - return nil, err - } - - structValues[k] = structpb.NewNumberValue(doubleVal) - default: - return nil, fmt.Errorf("unknown cty primitive type: %s", vType.FriendlyName()) - } - } else { - return nil, fmt.Errorf("unsupported cty type: %s", vType.FriendlyName()) - } - } - - return &structpb.Struct{ - Fields: structValues, - }, nil -} - -func protoStructListValueFromCty(val cty.Value) (*structpb.ListValue, error) { - var values []*structpb.Value - - var err error - val.ForEachElement(func(_ cty.Value, value cty.Value) bool { - vType := value.Type() - - if value.IsNull() { - values = append(values, structpb.NewNullValue()) - } else if vType.IsListType() || vType.IsSetType() || vType.IsTupleType() { - var listVal *structpb.ListValue - listVal, err = protoStructListValueFromCty(value) - if err != nil { - return true - } - values = append(values, structpb.NewListValue(listVal)) - } else if vType.IsMapType() || vType.IsObjectType() { - var objVal *structpb.Struct - objVal, err = protoStructObjectFromCty(value) - if err != nil { - return true - } - values = append(values, structpb.NewStructValue(objVal)) - } else if vType.IsPrimitiveType() { - switch vType { - case cty.String: - var stringVal string - stringVal, err = stringFromCty(value) - if err != nil { - return true - } - - values = append(values, structpb.NewStringValue(stringVal)) - case cty.Bool: - var boolVal bool - boolVal, err = boolFromCty(value) - if err != nil { - return true - } - - values = append(values, structpb.NewBoolValue(boolVal)) - case cty.Number: - var doubleVal float64 - doubleVal, err = doubleFromCty(value) - if err != nil { - return true - } - - values = append(values, structpb.NewNumberValue(doubleVal)) - default: - err = fmt.Errorf("unknown cty primitive type: %s", vType.FriendlyName()) - return true - } - } else { - err = fmt.Errorf("unsupported cty type: %s", vType.FriendlyName()) - return true - } - return false - }) - - if err != nil { - return nil, err - } - - return &structpb.ListValue{ - Values: values, - }, nil -} diff --git a/internal/radix/doc.go b/internal/radix/doc.go index f69f68a2d6b07..47e8961d0d0a5 100644 --- a/internal/radix/doc.go +++ b/internal/radix/doc.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - // This packages contents were originally copied from github.com/armon/go-radix. // After the intial copy all the data structures were made to use Go 1.18 generics // instead of relying on the use of interface{} or the any type. diff --git a/internal/radix/radix.go b/internal/radix/radix.go index c2b7ee838935f..0f1d8d772ac7c 100644 --- a/internal/radix/radix.go +++ b/internal/radix/radix.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package radix import ( diff --git a/internal/radix/radix_test.go b/internal/radix/radix_test.go index ea7015dc29c24..9f616b73f438e 100644 --- a/internal/radix/radix_test.go +++ b/internal/radix/radix_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package radix import ( diff --git a/internal/resource/authz_ce.go b/internal/resource/authz_ce.go deleted file mode 100644 index 4d68ccd6b98a0..0000000000000 --- a/internal/resource/authz_ce.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package resource - -import ( - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// AuthorizerContext builds an ACL AuthorizerContext for the given tenancy. -func AuthorizerContext(t *pbresource.Tenancy) *acl.AuthorizerContext { - return &acl.AuthorizerContext{Peer: t.PeerName} -} diff --git a/internal/resource/decode.go b/internal/resource/decode.go deleted file mode 100644 index 35ee0886035b2..0000000000000 --- a/internal/resource/decode.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resource - -import ( - "context" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// DecodedResource is a generic holder to contain an original Resource and its -// decoded contents. -type DecodedResource[T proto.Message] struct { - Resource *pbresource.Resource - Data T -} - -func (d *DecodedResource[T]) GetResource() *pbresource.Resource { - if d == nil { - return nil - } - - return d.Resource -} - -func (d *DecodedResource[T]) GetData() T { - if d == nil { - var zero T - return zero - } - - return d.Data -} - -// Decode will generically decode the provided resource into a 2-field -// structure that holds onto the original Resource and the decoded contents. -// -// Returns an ErrDataParse on unmarshalling errors. -func Decode[T proto.Message](res *pbresource.Resource) (*DecodedResource[T], error) { - var zero T - data := zero.ProtoReflect().New().Interface().(T) - - if err := res.Data.UnmarshalTo(data); err != nil { - return nil, NewErrDataParse(data, err) - } - return &DecodedResource[T]{ - Resource: res, - Data: data, - }, nil -} - -// GetDecodedResource will generically read the requested resource using the -// client and either return nil on a NotFound or decode the response value. -func GetDecodedResource[T proto.Message](ctx context.Context, client pbresource.ResourceServiceClient, id *pbresource.ID) (*DecodedResource[T], error) { - rsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: id}) - switch { - case status.Code(err) == codes.NotFound: - return nil, nil - case err != nil: - return nil, err - } - - return Decode[T](rsp.Resource) -} diff --git a/internal/resource/decode_test.go b/internal/resource/decode_test.go deleted file mode 100644 index a516673e43915..0000000000000 --- a/internal/resource/decode_test.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resource_test - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/anypb" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "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/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestGetDecodedResource(t *testing.T) { - var ( - baseClient = svctest.RunResourceService(t, demo.RegisterTypes) - client = rtest.NewClient(baseClient) - ctx = testutil.TestContext(t) - ) - - babypantsID := &pbresource.ID{ - Type: demo.TypeV2Artist, - Tenancy: resource.DefaultNamespacedTenancy(), - Name: "babypants", - } - - testutil.RunStep(t, "not found", func(t *testing.T) { - got, err := resource.GetDecodedResource[*pbdemo.Artist](ctx, client, babypantsID) - require.NoError(t, err) - require.Nil(t, got) - }) - - testutil.RunStep(t, "found", func(t *testing.T) { - data := &pbdemo.Artist{ - Name: "caspar babypants", - } - res := rtest.Resource(demo.TypeV2Artist, "babypants"). - WithData(t, data). - Write(t, client) - - got, err := resource.GetDecodedResource[*pbdemo.Artist](ctx, client, babypantsID) - require.NoError(t, err) - require.NotNil(t, got) - - // Clone generated fields over. - res.Id.Uid = got.Resource.Id.Uid - res.Version = got.Resource.Version - res.Generation = got.Resource.Generation - - // Clone defaulted fields over - data.Genre = pbdemo.Genre_GENRE_DISCO - - prototest.AssertDeepEqual(t, res, got.Resource) - prototest.AssertDeepEqual(t, data, got.Data) - }) -} - -func TestDecode(t *testing.T) { - t.Run("good", func(t *testing.T) { - fooData := &pbdemo.Artist{ - Name: "caspar babypants", - } - any, err := anypb.New(fooData) - require.NoError(t, err) - - foo := &pbresource.Resource{ - Id: &pbresource.ID{ - Type: demo.TypeV2Artist, - Tenancy: resource.DefaultNamespacedTenancy(), - Name: "babypants", - }, - Data: any, - Metadata: map[string]string{ - "generated_at": time.Now().Format(time.RFC3339), - }, - } - - dec, err := resource.Decode[*pbdemo.Artist](foo) - require.NoError(t, err) - - prototest.AssertDeepEqual(t, foo, dec.Resource) - prototest.AssertDeepEqual(t, fooData, dec.Data) - }) - - t.Run("bad", func(t *testing.T) { - foo := &pbresource.Resource{ - Id: &pbresource.ID{ - Type: demo.TypeV2Artist, - Tenancy: resource.DefaultNamespacedTenancy(), - Name: "babypants", - }, - Data: &anypb.Any{ - TypeUrl: "garbage", - Value: []byte("more garbage"), - }, - Metadata: map[string]string{ - "generated_at": time.Now().Format(time.RFC3339), - }, - } - - _, err := resource.Decode[*pbdemo.Artist](foo) - require.Error(t, err) - }) -} diff --git a/internal/resource/demo/controller.go b/internal/resource/demo/controller.go index 7f1bba902ea51..11afc3bac5e6e 100644 --- a/internal/resource/demo/controller.go +++ b/internal/resource/demo/controller.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package demo diff --git a/internal/resource/demo/controller_test.go b/internal/resource/demo/controller_test.go index a8c2640d615a8..8d4ee79c73e00 100644 --- a/internal/resource/demo/controller_test.go +++ b/internal/resource/demo/controller_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package demo diff --git a/internal/resource/demo/demo.go b/internal/resource/demo/demo.go index 0a8f2e440095b..20ad89c962c42 100644 --- a/internal/resource/demo/demo.go +++ b/internal/resource/demo/demo.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package demo includes fake resource types for working on Consul's generic // state storage without having to refer to specific features. @@ -22,12 +22,11 @@ import ( ) var ( - // TypeV1RecordLabel represents a record label which artists are signed to. - // Used specifically as a resource to test partition only scoped resources. - TypeV1RecordLabel = &pbresource.Type{ - Group: "demo", - GroupVersion: "v1", - Kind: "RecordLabel", + // TenancyDefault contains the default values for all tenancy units. + TenancyDefault = &pbresource.Tenancy{ + Partition: "default", + PeerName: "local", + Namespace: "default", } // TypeV1Artist represents a musician or group of musicians. @@ -73,20 +72,20 @@ const ( // TODO(spatel): We're standing-in key ACLs for demo resources until our ACL // system can be more modularly extended (or support generic resource permissions). func RegisterTypes(r resource.Registry) { - readACL := func(authz acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID) error { + readACL := func(authz acl.Authorizer, id *pbresource.ID) error { key := fmt.Sprintf("resource/%s/%s", resource.ToGVK(id.Type), id.Name) - return authz.ToAllowAuthorizer().KeyReadAllowed(key, authzContext) + return authz.ToAllowAuthorizer().KeyReadAllowed(key, &acl.AuthorizerContext{}) } - writeACL := func(authz acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { - key := fmt.Sprintf("resource/%s/%s", resource.ToGVK(res.Id.Type), res.Id.Name) - return authz.ToAllowAuthorizer().KeyWriteAllowed(key, authzContext) + writeACL := func(authz acl.Authorizer, id *pbresource.ID) error { + key := fmt.Sprintf("resource/%s/%s", resource.ToGVK(id.Type), id.Name) + return authz.ToAllowAuthorizer().KeyWriteAllowed(key, &acl.AuthorizerContext{}) } - makeListACL := func(typ *pbresource.Type) func(acl.Authorizer, *acl.AuthorizerContext) error { - return func(authz acl.Authorizer, authzContext *acl.AuthorizerContext) error { + makeListACL := func(typ *pbresource.Type) func(acl.Authorizer, *pbresource.Tenancy) error { + return func(authz acl.Authorizer, tenancy *pbresource.Tenancy) error { key := fmt.Sprintf("resource/%s", resource.ToGVK(typ)) - return authz.ToAllowAuthorizer().KeyListAllowed(key, authzContext) + return authz.ToAllowAuthorizer().KeyListAllowed(key, &acl.AuthorizerContext{}) } } @@ -125,17 +124,6 @@ func RegisterTypes(r resource.Registry) { return nil } - r.Register(resource.Registration{ - Type: TypeV1RecordLabel, - Proto: &pbdemov1.RecordLabel{}, - ACLs: &resource.ACLHooks{ - Read: readACL, - Write: writeACL, - List: makeListACL(TypeV1RecordLabel), - }, - Scope: resource.ScopePartition, - }) - r.Register(resource.Registration{ Type: TypeV1Artist, Proto: &pbdemov1.Artist{}, @@ -145,7 +133,6 @@ func RegisterTypes(r resource.Registry) { List: makeListACL(TypeV1Artist), }, Validate: validateV1ArtistFn, - Scope: resource.ScopeNamespace, }) r.Register(resource.Registration{ @@ -156,7 +143,6 @@ func RegisterTypes(r resource.Registry) { Write: writeACL, List: makeListACL(TypeV1Album), }, - Scope: resource.ScopeNamespace, }) r.Register(resource.Registration{ @@ -169,7 +155,6 @@ func RegisterTypes(r resource.Registry) { }, Validate: validateV2ArtistFn, Mutate: mutateV2ArtistFn, - Scope: resource.ScopeNamespace, }) r.Register(resource.Registration{ @@ -180,30 +165,9 @@ func RegisterTypes(r resource.Registry) { Write: writeACL, List: makeListACL(TypeV2Album), }, - Scope: resource.ScopeNamespace, }) } -// GenerateV1RecordLabel generates a named RecordLabel resource. -func GenerateV1RecordLabel(name string) (*pbresource.Resource, error) { - data, err := anypb.New(&pbdemov1.RecordLabel{Name: name}) - if err != nil { - return nil, err - } - - return &pbresource.Resource{ - Id: &pbresource.ID{ - Type: TypeV1RecordLabel, - Tenancy: resource.DefaultPartitionedTenancy(), - Name: name, - }, - Data: data, - Metadata: map[string]string{ - "generated_at": time.Now().Format(time.RFC3339), - }, - }, nil -} - // GenerateV2Artist generates a random Artist resource. func GenerateV2Artist() (*pbresource.Resource, error) { adjective := adjectives[rand.Intn(len(adjectives))] @@ -227,7 +191,7 @@ func GenerateV2Artist() (*pbresource.Resource, error) { return &pbresource.Resource{ Id: &pbresource.ID{ Type: TypeV2Artist, - Tenancy: resource.DefaultNamespacedTenancy(), + Tenancy: TenancyDefault, Name: fmt.Sprintf("%s-%s", strings.ToLower(adjective), strings.ToLower(noun)), }, Data: data, @@ -270,7 +234,7 @@ func generateV2Album(artistID *pbresource.ID, rand *rand.Rand) (*pbresource.Reso return &pbresource.Resource{ Id: &pbresource.ID{ Type: TypeV2Album, - Tenancy: clone(artistID.Tenancy), + Tenancy: artistID.Tenancy, Name: fmt.Sprintf("%s/%s-%s", artistID.Name, strings.ToLower(adjective), strings.ToLower(noun)), }, Owner: artistID, diff --git a/internal/resource/equality.go b/internal/resource/equality.go index 25e098b1a3610..c7c880cddc9eb 100644 --- a/internal/resource/equality.go +++ b/internal/resource/equality.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -20,7 +20,7 @@ func EqualType(a, b *pbresource.Type) bool { a.Kind == b.Kind } -// EqualTenancy compares two resource tenancies for equality without reflection. +// EqualType compares two resource tenancies for equality without reflection. func EqualTenancy(a, b *pbresource.Tenancy) bool { if a == b { return true @@ -35,7 +35,7 @@ func EqualTenancy(a, b *pbresource.Tenancy) bool { a.Namespace == b.Namespace } -// EqualID compares two resource IDs for equality without reflection. +// EqualType compares two resource IDs for equality without reflection. func EqualID(a, b *pbresource.ID) bool { if a == b { return true @@ -120,22 +120,6 @@ func EqualReference(a, b *pbresource.Reference) bool { a.Section == b.Section } -// ReferenceOrIDMatch compares two references or IDs to see if they both refer -// to the same thing. -// -// Note that this only compares fields that are common between them as -// represented by the ReferenceOrID interface and notably ignores the section -// field on references and the uid field on ids. -func ReferenceOrIDMatch(ref1, ref2 ReferenceOrID) bool { - if ref1 == nil || ref2 == nil { - return false - } - - return EqualType(ref1.GetType(), ref2.GetType()) && - EqualTenancy(ref1.GetTenancy(), ref2.GetTenancy()) && - ref1.GetName() == ref2.GetName() -} - // EqualStatusMap compares two status maps for equality without reflection. func EqualStatusMap(a, b map[string]*pbresource.Status) bool { if len(a) != len(b) { diff --git a/internal/resource/equality_test.go b/internal/resource/equality_test.go index 8413905606383..4fb7cb666b3aa 100644 --- a/internal/resource/equality_test.go +++ b/internal/resource/equality_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource_test @@ -283,310 +283,6 @@ func TestEqualID(t *testing.T) { }) } -func TestEqualReference(t *testing.T) { - t.Run("same pointer", func(t *testing.T) { - id := &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Section: "blah", - } - require.True(t, resource.EqualReference(id, id)) - }) - - t.Run("equal", func(t *testing.T) { - a := &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Section: "blah", - } - b := clone(a) - require.True(t, resource.EqualReference(a, b)) - }) - - t.Run("nil", func(t *testing.T) { - a := &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Section: "blah", - } - require.False(t, resource.EqualReference(a, nil)) - require.False(t, resource.EqualReference(nil, a)) - }) - - t.Run("different type", func(t *testing.T) { - a := &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Section: "blah", - } - b := clone(a) - b.Type.Kind = "album" - require.False(t, resource.EqualReference(a, b)) - }) - - t.Run("different tenancy", func(t *testing.T) { - a := &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Section: "blah", - } - b := clone(a) - b.Tenancy.Namespace = "qux" - require.False(t, resource.EqualReference(a, b)) - }) - - t.Run("different name", func(t *testing.T) { - a := &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Section: "blah", - } - b := clone(a) - b.Name = "boom" - require.False(t, resource.EqualReference(a, b)) - }) - - t.Run("different section", func(t *testing.T) { - a := &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Section: "blah", - } - b := clone(a) - b.Section = "not-blah" - require.False(t, resource.EqualReference(a, b)) - }) -} - -func TestReferenceOrIDMatch(t *testing.T) { - t.Run("equal", func(t *testing.T) { - a := &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Section: "blah", - } - b := &pbresource.ID{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Uid: ulid.Make().String(), - } - require.True(t, resource.ReferenceOrIDMatch(a, b)) - }) - - t.Run("nil", func(t *testing.T) { - a := &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Section: "blah", - } - b := &pbresource.ID{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Uid: ulid.Make().String(), - } - require.False(t, resource.ReferenceOrIDMatch(a, nil)) - require.False(t, resource.ReferenceOrIDMatch(nil, b)) - }) - - t.Run("different type", func(t *testing.T) { - a := &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Section: "blah", - } - b := &pbresource.ID{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Uid: ulid.Make().String(), - } - b.Type.Kind = "album" - require.False(t, resource.ReferenceOrIDMatch(a, b)) - }) - - t.Run("different tenancy", func(t *testing.T) { - a := &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Section: "blah", - } - b := &pbresource.ID{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Uid: ulid.Make().String(), - } - b.Tenancy.Namespace = "qux" - require.False(t, resource.ReferenceOrIDMatch(a, b)) - }) - - t.Run("different name", func(t *testing.T) { - a := &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Section: "blah", - } - b := &pbresource.ID{ - Type: &pbresource.Type{ - Group: "demo", - GroupVersion: "v2", - Kind: "artist", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - }, - Name: "qux", - Uid: ulid.Make().String(), - } - b.Name = "boom" - require.False(t, resource.ReferenceOrIDMatch(a, b)) - }) -} - func TestEqualStatus(t *testing.T) { orig := &pbresource.Status{ ObservedGeneration: ulid.Make().String(), diff --git a/internal/resource/errors.go b/internal/resource/errors.go index dbb624c8d0045..c258f9ad35b13 100644 --- a/internal/resource/errors.go +++ b/internal/resource/errors.go @@ -1,9 +1,10 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource import ( + "errors" "fmt" "github.com/hashicorp/consul/proto-public/pbresource" @@ -11,33 +12,11 @@ import ( ) var ( - ErrMissing = NewConstError("missing required field") - ErrEmpty = NewConstError("cannot be empty") - ErrReferenceTenancyNotEqual = NewConstError("resource tenancy and reference tenancy differ") + ErrMissing = errors.New("missing required field") + ErrEmpty = errors.New("cannot be empty") + ErrReferenceTenancyNotEqual = errors.New("resource tenancy and reference tenancy differ") ) -// ConstError is more or less equivalent to the stdlib errors.errorstring. However, having -// our own exported type allows us to more accurately compare error values in tests. -// -// - go-cmp will not compared unexported fields by default. -// - cmp.AllowUnexported() requires a concrete struct type and due to the stdlib not -// exporting the errorstring type there doesn't seem to be a way to get at the type. -// - cmpopts.EquateErrors has issues with protobuf types within other error structs. -// -// Due to these factors the easiest thing to do is to create a custom comparer for -// the ConstError type and use it where necessary. -type ConstError struct { - message string -} - -func NewConstError(msg string) ConstError { - return ConstError{message: msg} -} - -func (e ConstError) Error() string { - return e.message -} - type ErrDataParse struct { TypeName string Wrapped error diff --git a/internal/resource/errors_test.go b/internal/resource/errors_test.go index e6739bd7fd807..990a91607723b 100644 --- a/internal/resource/errors_test.go +++ b/internal/resource/errors_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource diff --git a/internal/resource/http/http.go b/internal/resource/http/http.go deleted file mode 100644 index 2a5cfce1fb2be..0000000000000 --- a/internal/resource/http/http.go +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package http - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "path" - "strings" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/go-hclog" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - HeaderConsulToken = "x-consul-token" - HeaderConsistencyMode = "x-consul-consistency-mode" -) - -func NewHandler( - client pbresource.ResourceServiceClient, - registry resource.Registry, - parseToken func(req *http.Request, token *string), - logger hclog.Logger) http.Handler { - mux := http.NewServeMux() - for _, t := range registry.Types() { - // List Endpoint - base := strings.ToLower(fmt.Sprintf("/%s/%s/%s", t.Type.Group, t.Type.GroupVersion, t.Type.Kind)) - mux.Handle(base, http.StripPrefix(base, &listHandler{t, client, parseToken, logger})) - - // Individual Resource Endpoints - prefix := strings.ToLower(fmt.Sprintf("%s/", base)) - logger.Info("Registered resource endpoint", "endpoint", prefix) - mux.Handle(prefix, http.StripPrefix(prefix, &resourceHandler{t, client, parseToken, logger})) - } - - return mux -} - -type writeRequest struct { - Metadata map[string]string `json:"metadata"` - Data json.RawMessage `json:"data"` - Owner *pbresource.ID `json:"owner"` -} - -type resourceHandler struct { - reg resource.Registration - client pbresource.ResourceServiceClient - parseToken func(req *http.Request, token *string) - logger hclog.Logger -} - -func (h *resourceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - var token string - h.parseToken(r, &token) - ctx := metadata.AppendToOutgoingContext(r.Context(), HeaderConsulToken, token) - switch r.Method { - case http.MethodPut: - h.handleWrite(w, r, ctx) - case http.MethodGet: - h.handleRead(w, r, ctx) - case http.MethodDelete: - h.handleDelete(w, r, ctx) - default: - w.WriteHeader(http.StatusMethodNotAllowed) - return - } -} - -func (h *resourceHandler) handleWrite(w http.ResponseWriter, r *http.Request, ctx context.Context) { - var req writeRequest - // convert req body to writeRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("Request body didn't follow schema.")) - } - // convert data struct to proto message - data := h.reg.Proto.ProtoReflect().New().Interface() - if err := protojson.Unmarshal(req.Data, data); err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("Request body didn't follow schema.")) - } - // proto message to any - anyProtoMsg, err := anypb.New(data) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - h.logger.Error("Failed to convert proto message to any type", "error", err) - return - } - - tenancyInfo, params := parseParams(r) - - rsp, err := h.client.Write(ctx, &pbresource.WriteRequest{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: h.reg.Type, - Tenancy: tenancyInfo, - Name: params["resourceName"], - }, - Owner: req.Owner, - Version: params["version"], - Metadata: req.Metadata, - Data: anyProtoMsg, - }, - }) - if err != nil { - handleResponseError(err, w, h.logger) - return - } - - output, err := jsonMarshal(rsp.Resource) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - h.logger.Error("Failed to unmarshal GRPC resource response", "error", err) - return - } - w.Write(output) -} - -func (h *resourceHandler) handleRead(w http.ResponseWriter, r *http.Request, ctx context.Context) { - tenancyInfo, params := parseParams(r) - if params["consistent"] != "" { - ctx = metadata.AppendToOutgoingContext(ctx, "x-consul-consistency-mode", "consistent") - } - - rsp, err := h.client.Read(ctx, &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Type: h.reg.Type, - Tenancy: tenancyInfo, - Name: params["resourceName"], - }, - }) - if err != nil { - handleResponseError(err, w, h.logger) - return - } - - output, err := jsonMarshal(rsp.Resource) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - h.logger.Error("Failed to unmarshal GRPC resource response", "error", err) - return - } - w.Write(output) -} - -// Note: The HTTP endpoints do not accept UID since it is quite unlikely that the user will have access to it -func (h *resourceHandler) handleDelete(w http.ResponseWriter, r *http.Request, ctx context.Context) { - tenancyInfo, params := parseParams(r) - _, err := h.client.Delete(ctx, &pbresource.DeleteRequest{ - Id: &pbresource.ID{ - Type: h.reg.Type, - Tenancy: tenancyInfo, - Name: params["resourceName"], - }, - Version: params["version"], - }) - if err != nil { - handleResponseError(err, w, h.logger) - return - } - w.WriteHeader(http.StatusNoContent) - w.Write([]byte("{}")) -} - -func parseParams(r *http.Request) (tenancy *pbresource.Tenancy, params map[string]string) { - query := r.URL.Query() - tenancy = &pbresource.Tenancy{ - Partition: query.Get("partition"), - PeerName: query.Get("peer_name"), - Namespace: query.Get("namespace"), - } - - resourceName := path.Base(r.URL.Path) - if resourceName == "." || resourceName == "/" { - resourceName = "" - } - - params = make(map[string]string) - params["resourceName"] = resourceName - params["version"] = query.Get("version") - params["namePrefix"] = query.Get("name_prefix") - if _, ok := query["consistent"]; ok { - params["consistent"] = "true" - } - - return tenancy, params -} - -func jsonMarshal(res *pbresource.Resource) ([]byte, error) { - output, err := protojson.Marshal(res) - if err != nil { - return nil, err - } - - var stuff map[string]any - if err := json.Unmarshal(output, &stuff); err != nil { - return nil, err - } - - delete(stuff["data"].(map[string]any), "@type") - return json.MarshalIndent(stuff, "", " ") -} - -func handleResponseError(err error, w http.ResponseWriter, logger hclog.Logger) { - if e, ok := status.FromError(err); ok { - switch e.Code() { - case codes.InvalidArgument: - w.WriteHeader(http.StatusBadRequest) - logger.Info("User has mal-formed request", "error", err) - case codes.NotFound: - w.WriteHeader(http.StatusNotFound) - logger.Info("Received error from resource service: Not found", "error", err) - case codes.PermissionDenied: - w.WriteHeader(http.StatusForbidden) - logger.Info("Received error from resource service: User not authenticated", "error", err) - case codes.Aborted: - w.WriteHeader(http.StatusConflict) - logger.Info("Received error from resource service: the request conflict with the current state of the target resource", "error", err) - default: - w.WriteHeader(http.StatusInternalServerError) - logger.Error("Received error from resource service", "error", err) - } - } else { - w.WriteHeader(http.StatusInternalServerError) - logger.Error("Received error from resource service: not able to parse error returned", "error", err) - } - w.Write([]byte(err.Error())) -} - -type listHandler struct { - reg resource.Registration - client pbresource.ResourceServiceClient - parseToken func(req *http.Request, token *string) - logger hclog.Logger -} - -func (h *listHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodGet { - w.WriteHeader(http.StatusMethodNotAllowed) - return - } - - var token string - h.parseToken(r, &token) - ctx := metadata.AppendToOutgoingContext(r.Context(), HeaderConsulToken, token) - - tenancyInfo, params := parseParams(r) - if params["consistent"] == "true" { - ctx = metadata.AppendToOutgoingContext(ctx, HeaderConsistencyMode, "consistent") - } - - rsp, err := h.client.List(ctx, &pbresource.ListRequest{ - Type: h.reg.Type, - Tenancy: tenancyInfo, - NamePrefix: params["namePrefix"], - }) - if err != nil { - handleResponseError(err, w, h.logger) - return - } - - output := make([]json.RawMessage, len(rsp.Resources)) - for idx, res := range rsp.Resources { - b, err := jsonMarshal(res) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - h.logger.Error("Failed to unmarshal GRPC resource response", "error", err) - return - } - output[idx] = b - } - - b, err := json.MarshalIndent(struct { - Resources []json.RawMessage `json:"resources"` - }{output}, "", " ") - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - h.logger.Error("Failed to correctly format the list response", "error", err) - return - } - w.Write(b) -} diff --git a/internal/resource/http/http_test.go b/internal/resource/http/http_test.go deleted file mode 100644 index 93c458ecbf4a8..0000000000000 --- a/internal/resource/http/http_test.go +++ /dev/null @@ -1,596 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package http - -import ( - "encoding/json" - "fmt" - "net/http" - "net/http/httptest" - "strings" - "testing" - - "github.com/hashicorp/go-hclog" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - resourceSvc "github.com/hashicorp/consul/agent/grpc-external/services/resource" - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - pbdemov1 "github.com/hashicorp/consul/proto/private/pbdemo/v1" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/demo" - "github.com/hashicorp/consul/proto-public/pbresource" - pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2" - "github.com/hashicorp/consul/sdk/testutil" -) - -const testACLTokenArtistReadPolicy = "00000000-0000-0000-0000-000000000001" -const testACLTokenArtistWritePolicy = "00000000-0000-0000-0000-000000000002" -const testACLTokenArtistListPolicy = "00000000-0000-0000-0000-000000000003" -const fakeToken = "fake-token" - -func parseToken(req *http.Request, token *string) { - *token = req.Header.Get("x-consul-token") -} - -func TestResourceHandler_InputValidation(t *testing.T) { - type testCase struct { - description string - request *http.Request - response *httptest.ResponseRecorder - expectedResponseCode int - } - client := svctest.RunResourceService(t, demo.RegisterTypes) - resourceHandler := resourceHandler{ - resource.Registration{ - Type: demo.TypeV2Artist, - Proto: &pbdemov2.Artist{}, - }, - client, - func(req *http.Request, token *string) { return }, - hclog.NewNullLogger(), - } - - testCases := []testCase{ - { - description: "missing resource name", - request: httptest.NewRequest("PUT", "/?partition=default&peer_name=local&namespace=default", strings.NewReader(` - { - "metadata": { - "foo": "bar" - }, - "data": { - "name": "Keith Urban", - "genre": "GENRE_COUNTRY" - } - } - `)), - response: httptest.NewRecorder(), - expectedResponseCode: http.StatusBadRequest, - }, - { - description: "wrong schema", - request: httptest.NewRequest("PUT", "/keith-urban?partition=default&peer_name=local&namespace=default", strings.NewReader(` - { - "metadata": { - "foo": "bar" - }, - "dada": { - "name": "Keith Urban", - "genre": "GENRE_COUNTRY" - } - } - `)), - response: httptest.NewRecorder(), - expectedResponseCode: http.StatusBadRequest, - }, - { - description: "no id", - request: httptest.NewRequest("DELETE", "/?partition=default&peer_name=local&namespace=default", strings.NewReader("")), - response: httptest.NewRecorder(), - expectedResponseCode: http.StatusBadRequest, - }, - } - - for _, tc := range testCases { - t.Run(tc.description, func(t *testing.T) { - resourceHandler.ServeHTTP(tc.response, tc.request) - - require.Equal(t, tc.expectedResponseCode, tc.response.Result().StatusCode) - }) - } -} - -func TestResourceWriteHandler(t *testing.T) { - aclResolver := &resourceSvc.MockACLResolver{} - aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistReadPolicy, mock.Anything, mock.Anything). - Return(svctest.AuthorizerFrom(t, demo.ArtistV1ReadPolicy, demo.ArtistV2ReadPolicy), nil) - aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistWritePolicy, mock.Anything, mock.Anything). - Return(svctest.AuthorizerFrom(t, demo.ArtistV1WritePolicy, demo.ArtistV2WritePolicy), nil) - - client := svctest.RunResourceServiceWithACL(t, aclResolver, demo.RegisterTypes) - - r := resource.NewRegistry() - demo.RegisterTypes(r) - handler := NewHandler(client, r, parseToken, hclog.NewNullLogger()) - - t.Run("should be blocked if the token is not authorized", 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(` - { - "metadata": { - "foo": "bar" - }, - "data": { - "name": "Keith Urban", - "genre": "GENRE_COUNTRY" - } - } - `)) - - req.Header.Add("x-consul-token", testACLTokenArtistReadPolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusForbidden, rsp.Result().StatusCode) - }) - - 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(` - { - "metadata": { - "foo": "bar" - }, - "data": { - "name": "Keith Urban", - "genre": "GENRE_COUNTRY" - } - } - `)) - - req.Header.Add("x-consul-token", testACLTokenArtistWritePolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusOK, rsp.Result().StatusCode) - - var result map[string]any - require.NoError(t, json.NewDecoder(rsp.Body).Decode(&result)) - require.Equal(t, "Keith Urban", result["data"].(map[string]any)["name"]) - require.Equal(t, "keith-urban", result["id"].(map[string]any)["name"]) - - readRsp, err := client.Read(testutil.TestContext(t), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Type: demo.TypeV2Artist, - Tenancy: resource.DefaultNamespacedTenancy(), - Name: "keith-urban", - }, - }) - require.NoError(t, err) - require.NotNil(t, readRsp.Resource) - - var artist pbdemov2.Artist - require.NoError(t, readRsp.Resource.Data.UnmarshalTo(&artist)) - require.Equal(t, "Keith Urban", artist.Name) - }) - - t.Run("should update the record with version parameter", func(t *testing.T) { - rsp := httptest.NewRecorder() - req := httptest.NewRequest("PUT", "/demo/v2/artist/keith-urban?partition=default&peer_name=local&namespace=default&version=1", strings.NewReader(` - { - "metadata": { - "foo": "bar" - }, - "data": { - "name": "Keith Urban Two", - "genre": "GENRE_COUNTRY" - } - } - `)) - - req.Header.Add("x-consul-token", testACLTokenArtistWritePolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusOK, rsp.Result().StatusCode) - var result map[string]any - require.NoError(t, json.NewDecoder(rsp.Body).Decode(&result)) - require.Equal(t, "Keith Urban Two", result["data"].(map[string]any)["name"]) - require.Equal(t, "keith-urban", result["id"].(map[string]any)["name"]) - }) - - t.Run("should fail the update if the resource's version doesn't match the version of the existing resource", func(t *testing.T) { - rsp := httptest.NewRecorder() - req := httptest.NewRequest("PUT", "/demo/v2/artist/keith-urban?partition=default&peer_name=local&namespace=default&version=1", strings.NewReader(` - { - "metadata": { - "foo": "bar" - }, - "data": { - "name": "Keith Urban", - "genre": "GENRE_COUNTRY" - } - } - `)) - - req.Header.Add("x-consul-token", testACLTokenArtistWritePolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusConflict, rsp.Result().StatusCode) - }) - - t.Run("should write to the resource backend with owner", func(t *testing.T) { - rsp := httptest.NewRecorder() - req := httptest.NewRequest("PUT", "/demo/v1/artist/keith-urban-v1?partition=default&peer_name=local&namespace=default", strings.NewReader(` - { - "metadata": { - "foo": "bar" - }, - "data": { - "name": "Keith Urban V1", - "genre": "GENRE_COUNTRY" - }, - "owner": { - "name": "keith-urban", - "type": { - "group": "demo", - "group_version": "v2", - "kind": "Artist" - }, - "tenancy": { - "partition": "default", - "peer_name": "local", - "namespace": "default" - } - } - } - `)) - - req.Header.Add("x-consul-token", testACLTokenArtistWritePolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusOK, rsp.Result().StatusCode) - - var result map[string]any - require.NoError(t, json.NewDecoder(rsp.Body).Decode(&result)) - require.Equal(t, "Keith Urban V1", result["data"].(map[string]any)["name"]) - require.Equal(t, "keith-urban-v1", result["id"].(map[string]any)["name"]) - - readRsp, err := client.Read(testutil.TestContext(t), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Type: demo.TypeV1Artist, - Tenancy: resource.DefaultNamespacedTenancy(), - Name: "keith-urban-v1", - }, - }) - require.NoError(t, err) - require.NotNil(t, readRsp.Resource) - require.Equal(t, "keith-urban", readRsp.Resource.Owner.Name) - - var artist pbdemov1.Artist - require.NoError(t, readRsp.Resource.Data.UnmarshalTo(&artist)) - require.Equal(t, "Keith Urban V1", artist.Name) - }) -} - -type ResourceUri struct { - group string - version string - kind string - resourceName string -} - -func createResource(t *testing.T, artistHandler http.Handler, resourceUri *ResourceUri) map[string]any { - rsp := httptest.NewRecorder() - - if resourceUri == nil { - resourceUri = &ResourceUri{group: "demo", version: "v2", kind: "artist", resourceName: "keith-urban"} - } - - req := httptest.NewRequest("PUT", fmt.Sprintf("/%s/%s/%s/%s?partition=default&peer_name=local&namespace=default", resourceUri.group, resourceUri.version, resourceUri.kind, resourceUri.resourceName), strings.NewReader(` - { - "metadata": { - "foo": "bar" - }, - "data": { - "name": "test", - "genre": "GENRE_COUNTRY" - } - } - `)) - - req.Header.Add("x-consul-token", testACLTokenArtistWritePolicy) - - artistHandler.ServeHTTP(rsp, req) - require.Equal(t, http.StatusOK, rsp.Result().StatusCode) - - var result map[string]any - require.NoError(t, json.NewDecoder(rsp.Body).Decode(&result)) - return result -} - -func deleteResource(t *testing.T, artistHandler http.Handler, resourceUri *ResourceUri) { - rsp := httptest.NewRecorder() - - if resourceUri == nil { - resourceUri = &ResourceUri{group: "demo", version: "v2", kind: "artist", resourceName: "keith-urban"} - } - - req := httptest.NewRequest("DELETE", fmt.Sprintf("/%s/%s/%s/%s?partition=default&peer_name=local&namespace=default", resourceUri.group, resourceUri.version, resourceUri.kind, resourceUri.resourceName), strings.NewReader("")) - - req.Header.Add("x-consul-token", testACLTokenArtistWritePolicy) - - artistHandler.ServeHTTP(rsp, req) - require.Equal(t, http.StatusNoContent, rsp.Result().StatusCode) -} - -func TestResourceReadHandler(t *testing.T) { - aclResolver := &resourceSvc.MockACLResolver{} - aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistReadPolicy, mock.Anything, mock.Anything). - Return(svctest.AuthorizerFrom(t, demo.ArtistV1ReadPolicy, demo.ArtistV2ReadPolicy), nil) - aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistWritePolicy, mock.Anything, mock.Anything). - Return(svctest.AuthorizerFrom(t, demo.ArtistV1WritePolicy, demo.ArtistV2WritePolicy), nil) - aclResolver.On("ResolveTokenAndDefaultMeta", fakeToken, mock.Anything, mock.Anything). - Return(svctest.AuthorizerFrom(t, ""), nil) - - client := svctest.RunResourceServiceWithACL(t, aclResolver, demo.RegisterTypes) - - r := resource.NewRegistry() - demo.RegisterTypes(r) - handler := NewHandler(client, r, parseToken, hclog.NewNullLogger()) - - createdResource := createResource(t, handler, nil) - - t.Run("Read resource", func(t *testing.T) { - rsp := httptest.NewRecorder() - req := httptest.NewRequest("GET", "/demo/v2/artist/keith-urban?partition=default&peer_name=local&namespace=default&consistent", nil) - - req.Header.Add("x-consul-token", testACLTokenArtistReadPolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusOK, rsp.Result().StatusCode) - - var result map[string]any - require.NoError(t, json.NewDecoder(rsp.Body).Decode(&result)) - require.Equal(t, result, createdResource) - }) - - t.Run("should not be found if resource not exist", func(t *testing.T) { - rsp := httptest.NewRecorder() - req := httptest.NewRequest("GET", "/demo/v2/artist/keith-not-exist?partition=default&peer_name=local&namespace=default&consistent", nil) - - req.Header.Add("x-consul-token", testACLTokenArtistReadPolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusNotFound, rsp.Result().StatusCode) - }) - - t.Run("should be blocked if the token is not authorized", func(t *testing.T) { - rsp := httptest.NewRecorder() - req := httptest.NewRequest("GET", "/demo/v2/artist/keith-urban?partition=default&peer_name=local&namespace=default&consistent", nil) - - req.Header.Add("x-consul-token", fakeToken) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusForbidden, rsp.Result().StatusCode) - }) -} - -func TestResourceDeleteHandler(t *testing.T) { - aclResolver := &resourceSvc.MockACLResolver{} - aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistReadPolicy, mock.Anything, mock.Anything). - Return(svctest.AuthorizerFrom(t, demo.ArtistV2ReadPolicy), nil) - aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistWritePolicy, mock.Anything, mock.Anything). - Return(svctest.AuthorizerFrom(t, demo.ArtistV2WritePolicy), nil) - - client := svctest.RunResourceServiceWithACL(t, aclResolver, demo.RegisterTypes) - - r := resource.NewRegistry() - demo.RegisterTypes(r) - - handler := NewHandler(client, r, parseToken, hclog.NewNullLogger()) - - t.Run("should surface PermissionDenied error from resource service", func(t *testing.T) { - createResource(t, handler, nil) - - deleteRsp := httptest.NewRecorder() - deletReq := httptest.NewRequest("DELETE", "/demo/v2/artist/keith-urban?partition=default&peer_name=local&namespace=default", strings.NewReader("")) - - deletReq.Header.Add("x-consul-token", testACLTokenArtistReadPolicy) - - handler.ServeHTTP(deleteRsp, deletReq) - - require.Equal(t, http.StatusForbidden, deleteRsp.Result().StatusCode) - }) - - t.Run("should delete a resource without version", func(t *testing.T) { - createResource(t, handler, nil) - - deleteRsp := httptest.NewRecorder() - deletReq := httptest.NewRequest("DELETE", "/demo/v2/artist/keith-urban?partition=default&peer_name=local&namespace=default", strings.NewReader("")) - - deletReq.Header.Add("x-consul-token", testACLTokenArtistWritePolicy) - - handler.ServeHTTP(deleteRsp, deletReq) - - require.Equal(t, http.StatusNoContent, deleteRsp.Result().StatusCode) - - var result map[string]any - require.NoError(t, json.NewDecoder(deleteRsp.Body).Decode(&result)) - require.Empty(t, result) - - _, err := client.Read(testutil.TestContext(t), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Type: demo.TypeV2Artist, - Tenancy: resource.DefaultNamespacedTenancy(), - Name: "keith-urban", - }, - }) - require.ErrorContains(t, err, "resource not found") - }) - - t.Run("should delete a resource with version", func(t *testing.T) { - createResource(t, handler, nil) - - rsp := httptest.NewRecorder() - req := httptest.NewRequest("DELETE", "/demo/v2/artist/keith-urban?partition=default&peer_name=local&namespace=default&version=1", strings.NewReader("")) - - req.Header.Add("x-consul-token", testACLTokenArtistWritePolicy) - req.Header.Add("x-consul-token", testACLTokenArtistListPolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusNoContent, rsp.Result().StatusCode) - - _, err := client.Read(testutil.TestContext(t), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Type: demo.TypeV2Artist, - Tenancy: resource.DefaultNamespacedTenancy(), - Name: "keith-urban", - }, - }) - require.ErrorContains(t, err, "resource not found") - }) -} - -func TestResourceListHandler(t *testing.T) { - aclResolver := &resourceSvc.MockACLResolver{} - aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistListPolicy, mock.Anything, mock.Anything). - Return(svctest.AuthorizerFrom(t, demo.ArtistV2ListPolicy), nil) - aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistWritePolicy, mock.Anything, mock.Anything). - Return(svctest.AuthorizerFrom(t, demo.ArtistV2WritePolicy), nil) - - client := svctest.RunResourceServiceWithACL(t, aclResolver, demo.RegisterTypes) - - r := resource.NewRegistry() - demo.RegisterTypes(r) - - handler := NewHandler(client, r, parseToken, hclog.NewNullLogger()) - - t.Run("should return MethodNotAllowed", func(t *testing.T) { - rsp := httptest.NewRecorder() - req := httptest.NewRequest("PUT", "/demo/v2/artist?partition=default&peer_name=local&namespace=default", strings.NewReader("")) - - req.Header.Add("x-consul-token", testACLTokenArtistListPolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusMethodNotAllowed, rsp.Result().StatusCode) - }) - - t.Run("should be blocked if the token is not authorized", func(t *testing.T) { - rsp := httptest.NewRecorder() - req := httptest.NewRequest("GET", "/demo/v2/artist?partition=default&peer_name=local&namespace=default", strings.NewReader("")) - - req.Header.Add("x-consul-token", testACLTokenArtistWritePolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusForbidden, rsp.Result().StatusCode) - }) - - t.Run("should return list of resources", func(t *testing.T) { - resourceUri1 := &ResourceUri{group: "demo", version: "v2", kind: "artist", resourceName: "steve"} - resource1 := createResource(t, handler, resourceUri1) - resourceUri2 := &ResourceUri{group: "demo", version: "v2", kind: "artist", resourceName: "elvis"} - resource2 := createResource(t, handler, resourceUri2) - - rsp := httptest.NewRecorder() - req := httptest.NewRequest("GET", "/demo/v2/artist?partition=default&peer_name=local&namespace=default", strings.NewReader("")) - - req.Header.Add("x-consul-token", testACLTokenArtistListPolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusOK, rsp.Result().StatusCode) - - var result map[string]any - require.NoError(t, json.NewDecoder(rsp.Body).Decode(&result)) - - resources, _ := result["resources"].([]any) - require.Len(t, resources, 2) - - expected := []map[string]any{resource1, resource2} - require.Contains(t, expected, resources[0]) - require.Contains(t, expected, resources[1]) - - // clean up - deleteResource(t, handler, resourceUri1) - deleteResource(t, handler, resourceUri2) - }) - - t.Run("should return empty list when no resources are found", func(t *testing.T) { - rsp := httptest.NewRecorder() - req := httptest.NewRequest("GET", "/demo/v2/artist?partition=default&peer_name=local&namespace=default", strings.NewReader("")) - - req.Header.Add("x-consul-token", testACLTokenArtistListPolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusOK, rsp.Result().StatusCode) - - var result map[string]any - require.NoError(t, json.NewDecoder(rsp.Body).Decode(&result)) - - resources, _ := result["resources"].([]any) - require.Len(t, resources, 0) - }) - - t.Run("should return empty list when name prefix matches don't match", func(t *testing.T) { - createResource(t, handler, nil) - - rsp := httptest.NewRecorder() - req := httptest.NewRequest("GET", "/demo/v2/artist?partition=default&peer_name=local&namespace=default&name_prefix=noname", strings.NewReader("")) - - req.Header.Add("x-consul-token", testACLTokenArtistListPolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusOK, rsp.Result().StatusCode) - - var result map[string]any - require.NoError(t, json.NewDecoder(rsp.Body).Decode(&result)) - - resources, _ := result["resources"].([]any) - require.Len(t, resources, 0) - - // clean up - deleteResource(t, handler, nil) - }) - - t.Run("should return list of resources matching name prefix", func(t *testing.T) { - resourceUri1 := &ResourceUri{group: "demo", version: "v2", kind: "artist", resourceName: "steve"} - resource1 := createResource(t, handler, resourceUri1) - resourceUri2 := &ResourceUri{group: "demo", version: "v2", kind: "artist", resourceName: "elvis"} - createResource(t, handler, resourceUri2) - - rsp := httptest.NewRecorder() - req := httptest.NewRequest("GET", "/demo/v2/artist?partition=default&peer_name=local&namespace=default&name_prefix=steve", strings.NewReader("")) - - req.Header.Add("x-consul-token", testACLTokenArtistListPolicy) - - handler.ServeHTTP(rsp, req) - - require.Equal(t, http.StatusOK, rsp.Result().StatusCode) - - var result map[string]any - require.NoError(t, json.NewDecoder(rsp.Body).Decode(&result)) - - resources, _ := result["resources"].([]any) - require.Len(t, resources, 1) - - require.Equal(t, resource1, resources[0]) - - // clean up - deleteResource(t, handler, resourceUri1) - deleteResource(t, handler, resourceUri2) - }) -} diff --git a/internal/resource/mappers/bimapper/bimapper.go b/internal/resource/mappers/bimapper/bimapper.go deleted file mode 100644 index b173813067372..0000000000000 --- a/internal/resource/mappers/bimapper/bimapper.go +++ /dev/null @@ -1,304 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package bimapper - -import ( - "context" - "fmt" - "sync" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// Mapper tracks bidirectional lookup for an item that contains references to -// other items. For example: an HTTPRoute has many references to Services. -// -// The primary object is called the "item" and an item has many "links". -// Tracking is done on items. -type Mapper struct { - itemType, linkType *pbresource.Type - - lock sync.Mutex - itemToLink map[resource.ReferenceKey]map[resource.ReferenceKey]struct{} - linkToItem map[resource.ReferenceKey]map[resource.ReferenceKey]struct{} -} - -// New creates a bimapper between the two required provided types. -func New(itemType, linkType *pbresource.Type) *Mapper { - if itemType == nil { - panic("itemType is required") - } - if linkType == nil { - panic("linkType is required") - } - return &Mapper{ - itemType: itemType, - linkType: linkType, - itemToLink: make(map[resource.ReferenceKey]map[resource.ReferenceKey]struct{}), - linkToItem: make(map[resource.ReferenceKey]map[resource.ReferenceKey]struct{}), - } -} - -// Reset clears the internal mappings. -func (m *Mapper) Reset() { - m.lock.Lock() - defer m.lock.Unlock() - m.itemToLink = make(map[resource.ReferenceKey]map[resource.ReferenceKey]struct{}) - m.linkToItem = make(map[resource.ReferenceKey]map[resource.ReferenceKey]struct{}) -} - -// IsEmpty returns true if the internal structures are empty. -func (m *Mapper) IsEmpty() bool { - m.lock.Lock() - defer m.lock.Unlock() - return len(m.itemToLink) == 0 && len(m.linkToItem) == 0 -} - -// UntrackItem removes tracking for the provided item. The item type MUST match -// the type configured for the item. -func (m *Mapper) UntrackItem(item resource.ReferenceOrID) { - if !resource.EqualType(item.GetType(), m.itemType) { - panic(fmt.Sprintf("expected item type %q got %q", - resource.TypeToString(m.itemType), - resource.TypeToString(item.GetType()), - )) - } - m.untrackItem(resource.NewReferenceKey(item)) -} - -// UntrackLink removes tracking for the provided link. The link type MUST match -// the type configured for the link. -func (m *Mapper) UntrackLink(link resource.ReferenceOrID) { - if !resource.EqualType(link.GetType(), m.linkType) { - panic(fmt.Sprintf("expected link type %q got %q", - resource.TypeToString(m.linkType), - resource.TypeToString(link.GetType()), - )) - } - m.untrackLink(resource.NewReferenceKey(link)) -} - -func (m *Mapper) untrackLink(link resource.ReferenceKey) { - m.lock.Lock() - defer m.lock.Unlock() - m.removeLinkLocked(link) -} - -func (m *Mapper) untrackItem(item resource.ReferenceKey) { - m.lock.Lock() - defer m.lock.Unlock() - m.removeItemLocked(item) -} - -// TrackItem adds tracking for the provided item. The item and link types MUST -// match the types configured for the items and links. -func (m *Mapper) TrackItem(item resource.ReferenceOrID, links []resource.ReferenceOrID) { - if !resource.EqualType(item.GetType(), m.itemType) { - panic(fmt.Sprintf("expected item type %q got %q", - resource.TypeToString(m.itemType), - resource.TypeToString(item.GetType()), - )) - } - - linksAsKeys := make([]resource.ReferenceKey, 0, len(links)) - for _, link := range links { - if !resource.EqualType(link.GetType(), m.linkType) { - panic(fmt.Sprintf("expected link type %q got %q", - resource.TypeToString(m.linkType), - resource.TypeToString(link.GetType()), - )) - } - linksAsKeys = append(linksAsKeys, resource.NewReferenceKey(link)) - } - - m.trackItem(resource.NewReferenceKey(item), linksAsKeys) -} - -func (m *Mapper) trackItem(item resource.ReferenceKey, links []resource.ReferenceKey) { - m.lock.Lock() - defer m.lock.Unlock() - - m.removeItemLocked(item) - m.addItemLocked(item, links) -} - -// you must hold the lock before calling this function -func (m *Mapper) removeItemLocked(item resource.ReferenceKey) { - for link := range m.itemToLink[item] { - delete(m.linkToItem[link], item) - if len(m.linkToItem[link]) == 0 { - delete(m.linkToItem, link) - } - } - delete(m.itemToLink, item) -} - -func (m *Mapper) removeLinkLocked(link resource.ReferenceKey) { - for item := range m.linkToItem[link] { - delete(m.itemToLink[item], link) - if len(m.itemToLink[item]) == 0 { - delete(m.itemToLink, item) - } - } - delete(m.linkToItem, link) -} - -// you must hold the lock before calling this function -func (m *Mapper) addItemLocked(item resource.ReferenceKey, links []resource.ReferenceKey) { - if m.itemToLink[item] == nil { - m.itemToLink[item] = make(map[resource.ReferenceKey]struct{}) - } - for _, link := range links { - m.itemToLink[item][link] = struct{}{} - - if m.linkToItem[link] == nil { - m.linkToItem[link] = make(map[resource.ReferenceKey]struct{}) - } - m.linkToItem[link][item] = struct{}{} - } -} - -// LinksForItem returns references to links related to the requested item. -// Deprecated: use LinksRefs -func (m *Mapper) LinksForItem(item *pbresource.ID) []*pbresource.Reference { - return m.LinkRefsForItem(item) -} - -// LinkRefsForItem returns references to links related to the requested item. -func (m *Mapper) LinkRefsForItem(item *pbresource.ID) []*pbresource.Reference { - if !resource.EqualType(item.Type, m.itemType) { - panic(fmt.Sprintf("expected item type %q got %q", - resource.TypeToString(m.itemType), - resource.TypeToString(item.Type), - )) - } - - m.lock.Lock() - defer m.lock.Unlock() - - links, ok := m.itemToLink[resource.NewReferenceKey(item)] - if !ok { - return nil - } - - out := make([]*pbresource.Reference, 0, len(links)) - for link := range links { - out = append(out, link.ToReference()) - } - return out -} - -// LinkIDsForItem returns IDs to links related to the requested item. -func (m *Mapper) LinkIDsForItem(item *pbresource.ID) []*pbresource.ID { - if !resource.EqualType(item.Type, m.itemType) { - panic(fmt.Sprintf("expected item type %q got %q", - resource.TypeToString(m.itemType), - resource.TypeToString(item.Type), - )) - } - - m.lock.Lock() - defer m.lock.Unlock() - - links, ok := m.itemToLink[resource.NewReferenceKey(item)] - if !ok { - return nil - } - - out := make([]*pbresource.ID, 0, len(links)) - for l := range links { - out = append(out, l.ToID()) - } - return out -} - -// ItemsForLink returns item ids for items related to the provided link. -// Deprecated: use ItemIDsForLink -func (m *Mapper) ItemsForLink(link *pbresource.ID) []*pbresource.ID { - return m.ItemIDsForLink(link) -} - -// ItemIDsForLink returns item ids for items related to the provided link. -func (m *Mapper) ItemIDsForLink(link *pbresource.ID) []*pbresource.ID { - if !resource.EqualType(link.Type, m.linkType) { - panic(fmt.Sprintf("expected link type %q got %q", - resource.TypeToString(m.linkType), - resource.TypeToString(link.Type), - )) - } - - return m.itemIDsByLink(resource.NewReferenceKey(link)) -} - -// ItemRefsForLink returns item references for items related to the provided link. -func (m *Mapper) ItemRefsForLink(link *pbresource.ID) []*pbresource.Reference { - if !resource.EqualType(link.Type, m.linkType) { - panic(fmt.Sprintf("expected link type %q got %q", - resource.TypeToString(m.linkType), - resource.TypeToString(link.Type), - )) - } - - return m.itemRefsByLink(resource.NewReferenceKey(link)) -} - -// MapLink is suitable as a DependencyMapper to map the provided link event to its item. -func (m *Mapper) MapLink(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - link := res.Id - - if !resource.EqualType(link.Type, m.linkType) { - return nil, fmt.Errorf("expected type %q got %q", - resource.TypeToString(m.linkType), - resource.TypeToString(link.Type), - ) - } - - itemIDs := m.itemIDsByLink(resource.NewReferenceKey(link)) - - out := make([]controller.Request, 0, len(itemIDs)) - for _, item := range itemIDs { - if !resource.EqualType(item.Type, m.itemType) { - return nil, fmt.Errorf("expected type %q got %q", - resource.TypeToString(m.itemType), - resource.TypeToString(item.Type), - ) - } - out = append(out, controller.Request{ID: item}) - } - return out, nil -} - -func (m *Mapper) itemIDsByLink(link resource.ReferenceKey) []*pbresource.ID { - m.lock.Lock() - defer m.lock.Unlock() - - items, ok := m.linkToItem[link] - if !ok { - return nil - } - - out := make([]*pbresource.ID, 0, len(items)) - for item := range items { - out = append(out, item.ToID()) - } - return out -} - -func (m *Mapper) itemRefsByLink(link resource.ReferenceKey) []*pbresource.Reference { - m.lock.Lock() - defer m.lock.Unlock() - - items, ok := m.linkToItem[link] - if !ok { - return nil - } - - out := make([]*pbresource.Reference, 0, len(items)) - for item := range items { - out = append(out, item.ToReference()) - } - return out -} diff --git a/internal/resource/mappers/bimapper/bimapper_test.go b/internal/resource/mappers/bimapper/bimapper_test.go deleted file mode 100644 index ce355bfc416da..0000000000000 --- a/internal/resource/mappers/bimapper/bimapper_test.go +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package bimapper - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" -) - -const ( - fakeGroupName = "catalog" - fakeVersion = "v1" -) - -var ( - fakeFooType = &pbresource.Type{ - Group: fakeGroupName, - GroupVersion: fakeVersion, - Kind: "Foo", - } - fakeBarType = &pbresource.Type{ - Group: fakeGroupName, - GroupVersion: fakeVersion, - Kind: "Bar", - } -) - -func TestMapper(t *testing.T) { - // Create an advance pointer to some services. - - randoSvc := rtest.Resource(fakeBarType, "rando").Build() - apiSvc := rtest.Resource(fakeBarType, "api").Build() - fooSvc := rtest.Resource(fakeBarType, "foo").Build() - barSvc := rtest.Resource(fakeBarType, "bar").Build() - wwwSvc := rtest.Resource(fakeBarType, "www").Build() - - apiRef := newRef(fakeBarType, "api") - fooRef := newRef(fakeBarType, "foo") - barRef := newRef(fakeBarType, "bar") - wwwRef := newRef(fakeBarType, "www") - - fail1 := rtest.Resource(fakeFooType, "api").Build() - fail1Refs := []resource.ReferenceOrID{ - apiRef, - fooRef, - barRef, - } - - fail2 := rtest.Resource(fakeFooType, "www").Build() - fail2Refs := []resource.ReferenceOrID{ - wwwRef, - fooRef, - } - - fail1UpdatedRefs := []resource.ReferenceOrID{ - apiRef, - barRef, - } - - m := New(fakeFooType, fakeBarType) - - // Nothing tracked yet so we assume nothing. - requireLinksForItem(t, m, fail1.Id) - requireLinksForItem(t, m, fail2.Id) - requireItemsForLink(t, m, apiRef) - requireItemsForLink(t, m, fooRef) - requireItemsForLink(t, m, barRef) - requireItemsForLink(t, m, wwwRef) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc) - requireServicesTracked(t, m, fooSvc) - requireServicesTracked(t, m, barSvc) - requireServicesTracked(t, m, wwwSvc) - - // no-ops - m.UntrackItem(fail1.Id) - - // still nothing - requireLinksForItem(t, m, fail1.Id) - requireLinksForItem(t, m, fail2.Id) - requireItemsForLink(t, m, apiRef) - requireItemsForLink(t, m, fooRef) - requireItemsForLink(t, m, barRef) - requireItemsForLink(t, m, wwwRef) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc) - requireServicesTracked(t, m, fooSvc) - requireServicesTracked(t, m, barSvc) - requireServicesTracked(t, m, wwwSvc) - - // Actually insert some data. - m.TrackItem(fail1.Id, fail1Refs) - - // Check links mapping - requireLinksForItem(t, m, fail1.Id, fail1Refs...) - - requireLinksForItem(t, m, fail1.Id, fail1Refs...) - requireItemsForLink(t, m, apiRef, fail1.Id) - requireItemsForLink(t, m, fooRef, fail1.Id) - requireItemsForLink(t, m, barRef, fail1.Id) - requireItemsForLink(t, m, wwwRef) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc, fail1.Id) - requireServicesTracked(t, m, fooSvc, fail1.Id) - requireServicesTracked(t, m, barSvc, fail1.Id) - requireServicesTracked(t, m, wwwSvc) - - // track it again, no change - m.TrackItem(fail1.Id, fail1Refs) - - requireLinksForItem(t, m, fail1.Id, fail1Refs...) - requireItemsForLink(t, m, apiRef, fail1.Id) - requireItemsForLink(t, m, fooRef, fail1.Id) - requireItemsForLink(t, m, barRef, fail1.Id) - requireItemsForLink(t, m, wwwRef) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc, fail1.Id) - requireServicesTracked(t, m, fooSvc, fail1.Id) - requireServicesTracked(t, m, barSvc, fail1.Id) - requireServicesTracked(t, m, wwwSvc) - - // track new one that overlaps slightly - m.TrackItem(fail2.Id, fail2Refs) - - // Check links mapping for the new one - requireLinksForItem(t, m, fail1.Id, fail1Refs...) - requireLinksForItem(t, m, fail2.Id, fail2Refs...) - requireItemsForLink(t, m, apiRef, fail1.Id) - requireItemsForLink(t, m, fooRef, fail1.Id, fail2.Id) - requireItemsForLink(t, m, barRef, fail1.Id) - requireItemsForLink(t, m, wwwRef, fail2.Id) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc, fail1.Id) - requireServicesTracked(t, m, fooSvc, fail1.Id, fail2.Id) - requireServicesTracked(t, m, barSvc, fail1.Id) - requireServicesTracked(t, m, wwwSvc, fail2.Id) - - // update the original to change it - m.TrackItem(fail1.Id, fail1UpdatedRefs) - - requireLinksForItem(t, m, fail1.Id, fail1UpdatedRefs...) - requireLinksForItem(t, m, fail2.Id, fail2Refs...) - requireItemsForLink(t, m, apiRef, fail1.Id) - requireItemsForLink(t, m, fooRef, fail2.Id) - requireItemsForLink(t, m, barRef, fail1.Id) - requireItemsForLink(t, m, wwwRef, fail2.Id) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc, fail1.Id) - requireServicesTracked(t, m, fooSvc, fail2.Id) - requireServicesTracked(t, m, barSvc, fail1.Id) - requireServicesTracked(t, m, wwwSvc, fail2.Id) - - // delete the original - m.UntrackItem(fail1.Id) - - requireLinksForItem(t, m, fail1.Id) - requireLinksForItem(t, m, fail2.Id, fail2Refs...) - requireItemsForLink(t, m, apiRef) - requireItemsForLink(t, m, fooRef, fail2.Id) - requireItemsForLink(t, m, barRef) - requireItemsForLink(t, m, wwwRef, fail2.Id) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc) - requireServicesTracked(t, m, fooSvc, fail2.Id) - requireServicesTracked(t, m, barSvc) - requireServicesTracked(t, m, wwwSvc, fail2.Id) - - // delete the link - m.UntrackLink(newRef(fakeBarType, "www")) - - requireLinksForItem(t, m, fail2.Id, newRef(fakeBarType, "foo")) - - m.UntrackLink(newRef(fakeBarType, "foo")) - - requireLinksForItem(t, m, fail2.Id) - - // delete another item - m.UntrackItem(fail2.Id) - - requireLinksForItem(t, m, fail1.Id) - requireLinksForItem(t, m, fail2.Id) - requireItemsForLink(t, m, apiRef) - requireItemsForLink(t, m, fooRef) - requireItemsForLink(t, m, barRef) - requireItemsForLink(t, m, wwwRef) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc) - requireServicesTracked(t, m, fooSvc) - requireServicesTracked(t, m, barSvc) - requireServicesTracked(t, m, wwwSvc) - - // Reset the mapper and check that its internal maps are empty. - m.Reset() - require.True(t, m.IsEmpty()) -} - -func TestPanics(t *testing.T) { - t.Run("new mapper without types", func(t *testing.T) { - require.PanicsWithValue(t, "itemType is required", func() { - New(nil, nil) - }) - - require.PanicsWithValue(t, "itemType is required", func() { - New(nil, fakeBarType) - }) - - require.PanicsWithValue(t, "linkType is required", func() { - New(fakeFooType, nil) - }) - }) - - t.Run("UntrackItem: mismatched type", func(t *testing.T) { - m := New(fakeFooType, fakeBarType) - require.PanicsWithValue(t, "expected item type \"catalog.v1.Foo\" got \"catalog.v1.Bar\"", func() { - // Calling UntrackItem with link type instead of item type - m.UntrackItem(rtest.Resource(fakeBarType, "test").ID()) - }) - }) - - t.Run("TrackItem: mismatched item type", func(t *testing.T) { - m := New(fakeFooType, fakeBarType) - require.PanicsWithValue(t, "expected item type \"catalog.v1.Foo\" got \"catalog.v1.Bar\"", func() { - // Calling UntrackItem with link type instead of item type - m.TrackItem(rtest.Resource(fakeBarType, "test").ID(), nil) - }) - }) - - t.Run("TrackItem: mismatched link type", func(t *testing.T) { - m := New(fakeFooType, fakeBarType) - require.PanicsWithValue(t, "expected link type \"catalog.v1.Bar\" got \"catalog.v1.Foo\"", func() { - // Calling UntrackItem with link type instead of item type - links := []resource.ReferenceOrID{ - rtest.Resource(fakeFooType, "link").ID(), - } - m.TrackItem(rtest.Resource(fakeFooType, "test").ID(), links) - }) - }) - - t.Run("UntrackLink: mismatched type", func(t *testing.T) { - m := New(fakeFooType, fakeBarType) - require.PanicsWithValue(t, "expected link type \"catalog.v1.Bar\" got \"catalog.v1.Foo\"", func() { - m.UntrackLink(rtest.Resource(fakeFooType, "test").ID()) - }) - }) - - t.Run("LinkRefsForItem: mismatched type", func(t *testing.T) { - m := New(fakeFooType, fakeBarType) - require.PanicsWithValue(t, "expected item type \"catalog.v1.Foo\" got \"catalog.v1.Bar\"", func() { - m.LinkRefsForItem(rtest.Resource(fakeBarType, "test").ID()) - }) - }) - - t.Run("LinkRefsForItem: mismatched type", func(t *testing.T) { - m := New(fakeFooType, fakeBarType) - require.PanicsWithValue(t, "expected item type \"catalog.v1.Foo\" got \"catalog.v1.Bar\"", func() { - m.LinkIDsForItem(rtest.Resource(fakeBarType, "test").ID()) - }) - }) - - t.Run("ItemRefsForLink: mismatched type", func(t *testing.T) { - m := New(fakeFooType, fakeBarType) - require.PanicsWithValue(t, "expected link type \"catalog.v1.Bar\" got \"catalog.v1.Foo\"", func() { - m.ItemRefsForLink(rtest.Resource(fakeFooType, "test").ID()) - }) - }) - - t.Run("ItemIDsForLink: mismatched type", func(t *testing.T) { - m := New(fakeFooType, fakeBarType) - require.PanicsWithValue(t, "expected link type \"catalog.v1.Bar\" got \"catalog.v1.Foo\"", func() { - m.ItemIDsForLink(rtest.Resource(fakeFooType, "test").ID()) - }) - }) -} - -func requireServicesTracked(t *testing.T, mapper *Mapper, link *pbresource.Resource, items ...*pbresource.ID) { - t.Helper() - - reqs, err := mapper.MapLink( - context.Background(), - controller.Runtime{}, - link, - ) - require.NoError(t, err) - - require.Len(t, reqs, len(items)) - - // Also check items IDs and Refs for link. - ids := mapper.ItemIDsForLink(link.Id) - require.Len(t, ids, len(items)) - - refs := mapper.ItemRefsForLink(link.Id) - require.Len(t, refs, len(items)) - - for _, item := range items { - prototest.AssertContainsElement(t, reqs, controller.Request{ID: item}) - prototest.AssertContainsElement(t, ids, item) - prototest.AssertContainsElement(t, refs, resource.Reference(item, "")) - } -} - -func requireItemsForLink(t *testing.T, mapper *Mapper, link *pbresource.Reference, items ...*pbresource.ID) { - t.Helper() - - got := mapper.ItemIDsForLink(resource.IDFromReference(link)) - - prototest.AssertElementsMatch(t, items, got) -} - -func requireLinksForItem(t *testing.T, mapper *Mapper, item *pbresource.ID, links ...resource.ReferenceOrID) { - t.Helper() - - var expLinkRefs []*pbresource.Reference - var expLinkIDs []*pbresource.ID - - for _, l := range links { - expLinkRefs = append(expLinkRefs, &pbresource.Reference{ - Name: l.GetName(), - Tenancy: l.GetTenancy(), - Type: l.GetType(), - }) - expLinkIDs = append(expLinkIDs, &pbresource.ID{ - Name: l.GetName(), - Tenancy: l.GetTenancy(), - Type: l.GetType(), - }) - } - - refs := mapper.LinkRefsForItem(item) - require.Len(t, refs, len(links)) - prototest.AssertElementsMatch(t, expLinkRefs, refs) - - ids := mapper.LinkIDsForItem(item) - require.Len(t, refs, len(links)) - prototest.AssertElementsMatch(t, expLinkIDs, ids) -} - -func newRef(typ *pbresource.Type, name string) *pbresource.Reference { - return rtest.Resource(typ, name).Reference("") -} diff --git a/internal/resource/reaper/controller.go b/internal/resource/reaper/controller.go index f8de86f92196e..7a7789f986a0d 100644 --- a/internal/resource/reaper/controller.go +++ b/internal/resource/reaper/controller.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package reaper diff --git a/internal/resource/reaper/controller_test.go b/internal/resource/reaper/controller_test.go index c06ccedab582d..9e6f0f3d5a07f 100644 --- a/internal/resource/reaper/controller_test.go +++ b/internal/resource/reaper/controller_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package reaper diff --git a/internal/resource/reference.go b/internal/resource/reference.go index 47c2a0da2dedf..80492c98787a2 100644 --- a/internal/resource/reference.go +++ b/internal/resource/reference.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource @@ -14,26 +14,3 @@ func Reference(id *pbresource.ID, section string) *pbresource.Reference { Section: section, } } - -// IDFromReference returns a Reference converted into an ID. NOTE: the UID -// field is not populated, and the Section field of a reference is dropped. -func IDFromReference(ref *pbresource.Reference) *pbresource.ID { - return &pbresource.ID{ - Type: ref.Type, - Tenancy: ref.Tenancy, - Name: ref.Name, - } -} - -// ReferenceOrID is the common accessors shared by pbresource.Reference and -// pbresource.ID. -type ReferenceOrID interface { - GetType() *pbresource.Type - GetTenancy() *pbresource.Tenancy - GetName() string -} - -var ( - _ ReferenceOrID = (*pbresource.ID)(nil) - _ ReferenceOrID = (*pbresource.Reference)(nil) -) diff --git a/internal/resource/refkey.go b/internal/resource/refkey.go deleted file mode 100644 index 44f0765c206c0..0000000000000 --- a/internal/resource/refkey.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resource - -import ( - "fmt" - "strings" - - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// ReferenceKey is the pointer-free representation of a ReferenceOrID -// suitable for a go map key. -type ReferenceKey struct { - GVK string - Partition string // Tenancy.* - Namespace string // Tenancy.* - PeerName string // Tenancy.* - Name string -} - -// String returns a string representation of the ReferenceKey. This should not -// be relied upon nor parsed and is provided just for debugging and logging -// reasons. -// -// This format should be aligned with IDToString and ReferenceToString. -func (r ReferenceKey) String() string { - return fmt.Sprintf("%s/%s.%s.%s/%s", - r.GVK, - orDefault(r.Partition, "default"), - orDefault(r.PeerName, "local"), - orDefault(r.Namespace, "default"), - r.Name, - ) -} - -func (r ReferenceKey) GetTenancy() *pbresource.Tenancy { - return &pbresource.Tenancy{ - Partition: r.Partition, - PeerName: r.PeerName, - Namespace: r.Namespace, - } -} - -// ToReference converts this back into a pbresource.ID. -func (r ReferenceKey) ToID() *pbresource.ID { - return &pbresource.ID{ - Type: GVKToType(r.GVK), - Tenancy: r.GetTenancy(), - Name: r.Name, - } -} - -// ToReference converts this back into a pbresource.Reference. -func (r ReferenceKey) ToReference() *pbresource.Reference { - return &pbresource.Reference{ - Type: GVKToType(r.GVK), - Tenancy: r.GetTenancy(), - Name: r.Name, - } -} - -func (r ReferenceKey) GoString() string { return r.String() } - -func NewReferenceKey(refOrID ReferenceOrID) ReferenceKey { - return ReferenceKey{ - GVK: ToGVK(refOrID.GetType()), - Partition: orDefault(refOrID.GetTenancy().GetPartition(), "default"), - Namespace: orDefault(refOrID.GetTenancy().GetNamespace(), "default"), - PeerName: orDefault(refOrID.GetTenancy().GetPeerName(), "local"), - Name: refOrID.GetName(), - } -} - -func orDefault(v, def string) string { - if v == "" { - return def - } - return v -} - -func GVKToType(gvk string) *pbresource.Type { - parts := strings.Split(gvk, ".") - if len(parts) != 3 { - panic("bad gvk") - } - return &pbresource.Type{ - Group: parts[0], - GroupVersion: parts[1], - Kind: parts[2], - } -} diff --git a/internal/resource/refkey_test.go b/internal/resource/refkey_test.go deleted file mode 100644 index 8c4b5eaf92b2f..0000000000000 --- a/internal/resource/refkey_test.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resource_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/demo" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestReferenceKey(t *testing.T) { - tenancy1 := &pbresource.Tenancy{} - tenancy1_actual := defaultTenancy() - tenancy2 := &pbresource.Tenancy{ - Partition: "ap1", - Namespace: "ns-billing", - PeerName: "peer-dc4", - } - tenancy3 := &pbresource.Tenancy{ - Partition: "ap2", - Namespace: "ns-intern", - PeerName: "peer-sea", - } - - res1, err := demo.GenerateV2Artist() - require.NoError(t, err) - res1.Id.Tenancy = tenancy1 - - res2, err := demo.GenerateV2Artist() - require.NoError(t, err) - res2.Id.Tenancy = tenancy2 - - res3, err := demo.GenerateV2Artist() - require.NoError(t, err) - res3.Id.Tenancy = tenancy3 - - id1 := res1.Id - id2 := res2.Id - id3 := res3.Id - - ref1 := resource.Reference(id1, "") - ref2 := resource.Reference(id2, "") - ref3 := resource.Reference(id3, "") - - idRK1 := resource.NewReferenceKey(id1) - idRK2 := resource.NewReferenceKey(id2) - idRK3 := resource.NewReferenceKey(id3) - - refRK1 := resource.NewReferenceKey(ref1) - refRK2 := resource.NewReferenceKey(ref2) - refRK3 := resource.NewReferenceKey(ref3) - - require.Equal(t, idRK1, refRK1) - require.Equal(t, idRK2, refRK2) - require.Equal(t, idRK3, refRK3) - - prototest.AssertDeepEqual(t, tenancy1_actual, idRK1.GetTenancy()) - prototest.AssertDeepEqual(t, tenancy2, idRK2.GetTenancy()) - prototest.AssertDeepEqual(t, tenancy3, idRK3.GetTenancy()) - - // Now that we tested the defaulting, swap out the tenancy in the id so - // that the comparisons work. - id1.Tenancy = tenancy1_actual - ref1.Tenancy = tenancy1_actual - - prototest.AssertDeepEqual(t, id1, idRK1.ToID()) - prototest.AssertDeepEqual(t, id2, idRK2.ToID()) - prototest.AssertDeepEqual(t, id3, idRK3.ToID()) - - prototest.AssertDeepEqual(t, ref1, refRK1.ToReference()) - prototest.AssertDeepEqual(t, ref2, refRK2.ToReference()) - prototest.AssertDeepEqual(t, ref3, refRK3.ToReference()) -} - -func defaultTenancy() *pbresource.Tenancy { - return &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - } -} diff --git a/internal/resource/registry.go b/internal/resource/registry.go index 575bf6feafdc6..0004acfff4c6a 100644 --- a/internal/resource/registry.go +++ b/internal/resource/registry.go @@ -1,12 +1,11 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource import ( "fmt" "regexp" - "strings" "sync" "google.golang.org/protobuf/proto" @@ -27,8 +26,6 @@ type Registry interface { // Resolve the given resource type and its hooks. Resolve(typ *pbresource.Type) (reg Registration, ok bool) - - Types() []Registration } type Registration struct { @@ -45,12 +42,11 @@ type Registration struct { // check for required fields). Validate func(*pbresource.Resource) error - // Mutate is called to fill out any autogenerated fields (e.g. UUIDs) or - // apply defaults before validation. + // Mutate is called to fill out any autogenerated fields (e.g. UUIDs). Mutate func(*pbresource.Resource) error - // Scope describes the tenancy scope of a resource. - Scope Scope + // In the future, we'll add hooks, the controller etc. here. + // TODO: https://github.com/hashicorp/consul/pull/16622#discussion_r1134515909 } type ACLHooks struct { @@ -58,17 +54,17 @@ type ACLHooks struct { // RPCs. // // If it is omitted, `operator:read` permission is assumed. - Read func(acl.Authorizer, *acl.AuthorizerContext, *pbresource.ID) error + Read func(acl.Authorizer, *pbresource.ID) error // Write is used to authorize Write and Delete RPCs. // // If it is omitted, `operator:write` permission is assumed. - Write func(acl.Authorizer, *acl.AuthorizerContext, *pbresource.Resource) error + Write func(acl.Authorizer, *pbresource.ID) error // List is used to authorize List RPCs. // // If it is omitted, we only filter the results using Read. - List func(acl.Authorizer, *acl.AuthorizerContext) error + List func(acl.Authorizer, *pbresource.Tenancy) error } // Resource type registry @@ -120,17 +116,17 @@ func (r *TypeRegistry) Register(registration Registration) { registration.ACLs = &ACLHooks{} } if registration.ACLs.Read == nil { - registration.ACLs.Read = func(authz acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID) error { - return authz.ToAllowAuthorizer().OperatorReadAllowed(authzContext) + registration.ACLs.Read = func(authz acl.Authorizer, id *pbresource.ID) error { + return authz.ToAllowAuthorizer().OperatorReadAllowed(&acl.AuthorizerContext{}) } } if registration.ACLs.Write == nil { - registration.ACLs.Write = func(authz acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.Resource) error { - return authz.ToAllowAuthorizer().OperatorWriteAllowed(authzContext) + registration.ACLs.Write = func(authz acl.Authorizer, id *pbresource.ID) error { + return authz.ToAllowAuthorizer().OperatorWriteAllowed(&acl.AuthorizerContext{}) } } if registration.ACLs.List == nil { - registration.ACLs.List = func(authz acl.Authorizer, authzContext *acl.AuthorizerContext) error { + registration.ACLs.List = func(authz acl.Authorizer, tenancy *pbresource.Tenancy) error { return authz.ToAllowAuthorizer().OperatorReadAllowed(&acl.AuthorizerContext{}) } } @@ -158,29 +154,6 @@ func (r *TypeRegistry) Resolve(typ *pbresource.Type) (reg Registration, ok bool) return Registration{}, false } -func (r *TypeRegistry) Types() []Registration { - r.lock.RLock() - defer r.lock.RUnlock() - - types := make([]Registration, 0, len(r.registrations)) - for _, v := range r.registrations { - types = append(types, v) - } - return types -} - func ToGVK(resourceType *pbresource.Type) string { return fmt.Sprintf("%s.%s.%s", resourceType.Group, resourceType.GroupVersion, resourceType.Kind) } - -func ParseGVK(gvk string) (*pbresource.Type, error) { - parts := strings.Split(gvk, ".") - if len(parts) != 3 { - return nil, fmt.Errorf("GVK string must be in the form .., got: %s", gvk) - } - return &pbresource.Type{ - Group: parts[0], - GroupVersion: parts[1], - Kind: parts[2], - }, nil -} diff --git a/internal/resource/registry_test.go b/internal/resource/registry_test.go index a7d3ec6a11879..c9d1777159f8c 100644 --- a/internal/resource/registry_test.go +++ b/internal/resource/registry_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package resource_test @@ -43,16 +43,16 @@ func TestRegister_Defaults(t *testing.T) { require.True(t, ok) // verify default read hook requires operator:read - require.NoError(t, reg.ACLs.Read(testutils.ACLOperatorRead(t), nil, artist.Id)) - require.True(t, acl.IsErrPermissionDenied(reg.ACLs.Read(testutils.ACLNoPermissions(t), nil, artist.Id))) + require.NoError(t, reg.ACLs.Read(testutils.ACLOperatorRead(t), artist.Id)) + require.True(t, acl.IsErrPermissionDenied(reg.ACLs.Read(testutils.ACLNoPermissions(t), artist.Id))) // verify default write hook requires operator:write - require.NoError(t, reg.ACLs.Write(testutils.ACLOperatorWrite(t), nil, artist)) - require.True(t, acl.IsErrPermissionDenied(reg.ACLs.Write(testutils.ACLNoPermissions(t), nil, artist))) + require.NoError(t, reg.ACLs.Write(testutils.ACLOperatorWrite(t), artist.Id)) + require.True(t, acl.IsErrPermissionDenied(reg.ACLs.Write(testutils.ACLNoPermissions(t), artist.Id))) // verify default list hook requires operator:read - require.NoError(t, reg.ACLs.List(testutils.ACLOperatorRead(t), nil)) - require.True(t, acl.IsErrPermissionDenied(reg.ACLs.List(testutils.ACLNoPermissions(t), nil))) + require.NoError(t, reg.ACLs.List(testutils.ACLOperatorRead(t), artist.Id.Tenancy)) + require.True(t, acl.IsErrPermissionDenied(reg.ACLs.List(testutils.ACLNoPermissions(t), artist.Id.Tenancy))) // verify default validate is a no-op require.NoError(t, reg.Validate(nil)) diff --git a/internal/resource/resourcetest/builder.go b/internal/resource/resourcetest/builder.go index 86294ce571056..7355f38824ec1 100644 --- a/internal/resource/resourcetest/builder.go +++ b/internal/resource/resourcetest/builder.go @@ -1,24 +1,14 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package resourcetest import ( - "strings" + "context" + "github.com/hashicorp/consul/proto-public/pbresource" "github.com/oklog/ulid/v2" "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/storage" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" ) type resourceBuilder struct { @@ -37,8 +27,8 @@ func Resource(rtype *pbresource.Type, name string) *resourceBuilder { Kind: rtype.Kind, }, Tenancy: &pbresource.Tenancy{ - Partition: resource.DefaultPartitionName, - Namespace: resource.DefaultNamespaceName, + Partition: "default", + Namespace: "default", PeerName: "local", }, Name: name, @@ -47,19 +37,6 @@ func Resource(rtype *pbresource.Type, name string) *resourceBuilder { } } -func ResourceID(id *pbresource.ID) *resourceBuilder { - return &resourceBuilder{ - resource: &pbresource.Resource{ - Id: id, - }, - } -} - -func (b *resourceBuilder) WithTenancy(tenant *pbresource.Tenancy) *resourceBuilder { - b.resource.Id.Tenancy = tenant - return b -} - func (b *resourceBuilder) WithData(t T, data protoreflect.ProtoMessage) *resourceBuilder { t.Helper() @@ -128,47 +105,25 @@ func (b *resourceBuilder) ID() *pbresource.ID { return b.resource.Id } -func (b *resourceBuilder) Reference(section string) *pbresource.Reference { - return resource.Reference(b.ID(), section) -} - func (b *resourceBuilder) Write(t T, client pbresource.ResourceServiceClient) *pbresource.Resource { t.Helper() - ctx := testutil.TestContext(t) - res := b.resource - var rsp *pbresource.WriteResponse - var err error - - // Retry any writes where the error is a UID mismatch and the UID was not specified. This is indicative - // of using a follower to rewrite an object who is not perfectly in-sync with the leader. - retry.Run(t, func(r *retry.R) { - rsp, err = client.Write(ctx, &pbresource.WriteRequest{ - Resource: res, - }) - - if err == nil || res.Id.Uid != "" || status.Code(err) != codes.FailedPrecondition { - if err != nil { - t.Logf("write saw error: %v", err) - } - return - } - - if strings.Contains(err.Error(), storage.ErrWrongUid.Error()) { - r.Fatalf("resource write failed due to uid mismatch - most likely a transient issue when talking to a non-leader") - } else { - // other errors are unexpected and should cause an immediate failure - r.Stop(err) - } + rsp, err := client.Write(context.Background(), &pbresource.WriteRequest{ + Resource: res, }) + require.NoError(t, err) + if !b.dontCleanup { - id := proto.Clone(rsp.Resource.Id).(*pbresource.ID) - id.Uid = "" - t.Cleanup(func() { - NewClient(client).MustDelete(t, id) + cleaner, ok := t.(CleanupT) + require.True(t, ok, "T does not implement a Cleanup method and cannot be used with automatic resource cleanup") + cleaner.Cleanup(func() { + _, err := client.Delete(context.Background(), &pbresource.DeleteRequest{ + Id: rsp.Resource.Id, + }) + require.NoError(t, err) }) } @@ -181,7 +136,7 @@ func (b *resourceBuilder) Write(t T, client pbresource.ResourceServiceClient) *p ObservedGeneration: rsp.Resource.Generation, Conditions: original.Conditions, } - _, err := client.WriteStatus(ctx, &pbresource.WriteStatusRequest{ + _, err := client.WriteStatus(context.Background(), &pbresource.WriteStatusRequest{ Id: rsp.Resource.Id, Key: key, Status: status, @@ -189,7 +144,7 @@ func (b *resourceBuilder) Write(t T, client pbresource.ResourceServiceClient) *p require.NoError(t, err) } - readResp, err := client.Read(ctx, &pbresource.ReadRequest{ + readResp, err := client.Read(context.Background(), &pbresource.ReadRequest{ Id: rsp.Resource.Id, }) diff --git a/internal/resource/resourcetest/client.go b/internal/resource/resourcetest/client.go index f3b3bd799fe2b..dab5b03c3adbe 100644 --- a/internal/resource/resourcetest/client.go +++ b/internal/resource/resourcetest/client.go @@ -1,22 +1,17 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package resourcetest import ( - "fmt" + "context" "math/rand" "time" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/stretchr/testify/require" "golang.org/x/exp/slices" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" ) type Client struct { @@ -40,14 +35,11 @@ func (client *Client) SetRetryerConfig(timeout time.Duration, wait time.Duration } func (client *Client) retry(t T, fn func(r *retry.R)) { - t.Helper() retryer := &retry.Timer{Timeout: client.timeout, Wait: client.wait} retry.RunWith(retryer, t, fn) } func (client *Client) PublishResources(t T, resources []*pbresource.Resource) { - ctx := testutil.TestContext(t) - // Randomize the order of insertion. Generally insertion order shouldn't matter as the // controllers should eventually converge on the desired state. The exception to this // is that you cannot insert resources with owner refs before the resource they are @@ -82,17 +74,12 @@ func (client *Client) PublishResources(t T, resources []*pbresource.Resource) { } t.Logf("Writing resource %s with type %s", res.Id.Name, resource.ToGVK(res.Id.Type)) - rsp, err := client.Write(ctx, &pbresource.WriteRequest{ + _, err := client.Write(context.Background(), &pbresource.WriteRequest{ Resource: res, }) require.NoError(t, err) - id := rsp.Resource.Id - t.Cleanup(func() { - client.MustDelete(t, id) - }) - - // track the number of resources published + // track the number o published += 1 written = append(written, res.Id) } @@ -114,7 +101,7 @@ func (client *Client) PublishResources(t T, resources []*pbresource.Resource) { func (client *Client) RequireResourceNotFound(t T, id *pbresource.ID) { t.Helper() - rsp, err := client.Read(testutil.TestContext(t), &pbresource.ReadRequest{Id: id}) + rsp, err := client.Read(context.Background(), &pbresource.ReadRequest{Id: id}) require.Error(t, err) require.Equal(t, codes.NotFound, status.Code(err)) require.Nil(t, rsp) @@ -123,7 +110,7 @@ func (client *Client) RequireResourceNotFound(t T, id *pbresource.ID) { func (client *Client) RequireResourceExists(t T, id *pbresource.ID) *pbresource.Resource { t.Helper() - rsp, err := client.Read(testutil.TestContext(t), &pbresource.ReadRequest{Id: id}) + rsp, err := client.Read(context.Background(), &pbresource.ReadRequest{Id: id}) require.NoError(t, err, "error reading %s with type %s", id.Name, resource.ToGVK(id.Type)) require.NotNil(t, rsp) return rsp.Resource @@ -161,16 +148,6 @@ func (client *Client) RequireStatusConditionForCurrentGen(t T, id *pbresource.ID return res } -func (client *Client) RequireStatusConditionsForCurrentGen(t T, id *pbresource.ID, statusKey string, conditions []*pbresource.Condition) *pbresource.Resource { - t.Helper() - - res := client.RequireResourceExists(t, id) - for _, condition := range conditions { - RequireStatusConditionForCurrentGen(t, res, statusKey, condition) - } - return res -} - func (client *Client) RequireResourceMeta(t T, id *pbresource.ID, key string, value string) *pbresource.Resource { t.Helper() @@ -204,18 +181,7 @@ func (client *Client) WaitForStatusCondition(t T, id *pbresource.ID, statusKey s var res *pbresource.Resource client.retry(t, func(r *retry.R) { - res = client.RequireStatusConditionForCurrentGen(r, id, statusKey, condition) - }) - - return res -} - -func (client *Client) WaitForStatusConditions(t T, id *pbresource.ID, statusKey string, conditions ...*pbresource.Condition) *pbresource.Resource { - t.Helper() - - var res *pbresource.Resource - client.retry(t, func(r *retry.R) { - res = client.RequireStatusConditionsForCurrentGen(r, id, statusKey, conditions) + res = client.RequireStatusConditionForCurrentGen(t, id, statusKey, condition) }) return res @@ -243,14 +209,6 @@ func (client *Client) WaitForResourceState(t T, id *pbresource.ID, verify func(T return res } -func (client *Client) WaitForDeletion(t T, id *pbresource.ID) { - t.Helper() - - client.retry(t, func(r *retry.R) { - client.RequireResourceNotFound(r, id) - }) -} - // ResolveResourceID will read the specified resource and returns its full ID. // This is mainly useful to get the ID with the Uid filled out. func (client *Client) ResolveResourceID(t T, id *pbresource.ID) *pbresource.ID { @@ -258,24 +216,3 @@ func (client *Client) ResolveResourceID(t T, id *pbresource.ID) *pbresource.ID { return client.RequireResourceExists(t, id).Id } - -func (client *Client) MustDelete(t T, id *pbresource.ID) { - t.Helper() - ctx := testutil.TestContext(t) - - client.retry(t, func(r *retry.R) { - _, err := client.Delete(ctx, &pbresource.DeleteRequest{Id: id}) - if status.Code(err) == codes.NotFound { - return - } - - // codes.Aborted indicates a CAS failure and that the delete request should - // be retried. Anything else should be considered an unrecoverable error. - if err != nil && status.Code(err) != codes.Aborted { - r.Stop(fmt.Errorf("failed to delete the resource: %w", err)) - return - } - - require.NoError(r, err) - }) -} diff --git a/internal/resource/resourcetest/decode.go b/internal/resource/resourcetest/decode.go deleted file mode 100644 index d68fff8655172..0000000000000 --- a/internal/resource/resourcetest/decode.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resourcetest - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func MustDecode[T proto.Message](t *testing.T, res *pbresource.Resource) *resource.DecodedResource[T] { - dec, err := resource.Decode[T](res) - require.NoError(t, err) - return dec -} diff --git a/internal/resource/resourcetest/fs.go b/internal/resource/resourcetest/fs.go index a31ac0f10c4b7..e7a1417a59083 100644 --- a/internal/resource/resourcetest/fs.go +++ b/internal/resource/resourcetest/fs.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package resourcetest import ( diff --git a/internal/resource/resourcetest/require.go b/internal/resource/resourcetest/require.go index b57bab8b2e3a2..fff8cb2aebf2c 100644 --- a/internal/resource/resourcetest/require.go +++ b/internal/resource/resourcetest/require.go @@ -1,42 +1,13 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package resourcetest import ( "github.com/google/go-cmp/cmp" - "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/proto/private/prototest" "github.com/stretchr/testify/require" "google.golang.org/protobuf/testing/protocmp" ) -// CompareErrorString is a helper to generate a custom go-cmp comparer method -// that will perform an equality check on the error message. This is mainly -// useful to get around not being able to see unexported data within errors. -func CompareErrorString[T error]() cmp.Option { - return cmp.Comparer(func(e1, e2 T) bool { - return e1.Error() == e2.Error() - }) -} - -// default comparers for known types that don't play well with go-cmp -var comparers = []cmp.Option{ - CompareErrorString[resource.ConstError](), -} - -// RequireError is useful for asserting that some chained multierror contains a specific error. -func RequireError[E error](t T, err error, expected E, opts ...cmp.Option) { - t.Helper() - - var actual E - require.ErrorAs(t, err, &actual) - - opts = append(opts, comparers...) - prototest.AssertDeepEqual(t, expected, actual, opts...) -} - func RequireVersionUnchanged(t T, res *pbresource.Resource, version string) { t.Helper() require.Equal(t, version, res.Version) diff --git a/internal/resource/resourcetest/testing.go b/internal/resource/resourcetest/testing.go index 1be9947226bd2..d02b70da9d039 100644 --- a/internal/resource/resourcetest/testing.go +++ b/internal/resource/resourcetest/testing.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package resourcetest // T represents the subset of testing.T methods that will be used @@ -12,5 +9,9 @@ type T interface { Errorf(format string, args ...interface{}) Fatalf(format string, args ...interface{}) FailNow() +} + +type CleanupT interface { + T Cleanup(func()) } diff --git a/internal/resource/resourcetest/validation.go b/internal/resource/resourcetest/validation.go deleted file mode 100644 index d7588221186f1..0000000000000 --- a/internal/resource/resourcetest/validation.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resourcetest - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func ValidateAndNormalize(t *testing.T, registry resource.Registry, res *pbresource.Resource) { - typ := res.Id.Type - - typeInfo, ok := registry.Resolve(typ) - if !ok { - t.Fatalf("unhandled resource type: %q", resource.ToGVK(typ)) - } - - if typeInfo.Mutate != nil { - require.NoError(t, typeInfo.Mutate(res), "failed to apply type mutation to resource") - } - - if typeInfo.Validate != nil { - require.NoError(t, typeInfo.Validate(res), "failed to validate resource") - } -} diff --git a/internal/resource/stringer.go b/internal/resource/stringer.go deleted file mode 100644 index 075c08ac0d9c4..0000000000000 --- a/internal/resource/stringer.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resource - -import ( - "fmt" - - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// IDToString returns a string representation of pbresource.ID. This should not -// be relied upon nor parsed and is provided just for debugging and logging -// reasons. -// -// This format should be aligned with ReferenceToString and -// (ReferenceKey).String. -func IDToString(id *pbresource.ID) string { - s := fmt.Sprintf("%s/%s/%s", - TypeToString(id.Type), - TenancyToString(id.Tenancy), - id.Name, - ) - if id.Uid != "" { - return s + "?uid=" + id.Uid - } - return s -} - -// ReferenceToString returns a string representation of pbresource.Reference. -// This should not be relied upon nor parsed and is provided just for debugging -// and logging reasons. -// -// This format should be aligned with IDToString and (ReferenceKey).String. -func ReferenceToString(ref *pbresource.Reference) string { - s := fmt.Sprintf("%s/%s/%s", - TypeToString(ref.Type), - TenancyToString(ref.Tenancy), - ref.Name, - ) - - if ref.Section != "" { - return s + "?section=" + ref.Section - } - return s -} - -// TenancyToString returns a string representation of pbresource.Tenancy. This -// should not be relied upon nor parsed and is provided just for debugging and -// logging reasons. -func TenancyToString(tenancy *pbresource.Tenancy) string { - return fmt.Sprintf("%s.%s.%s", tenancy.Partition, tenancy.PeerName, tenancy.Namespace) -} - -// TypeToString returns a string representation of pbresource.Type. This should -// not be relied upon nor parsed and is provided just for debugging and logging -// reasons. -func TypeToString(typ *pbresource.Type) string { - return ToGVK(typ) -} diff --git a/internal/resource/tenancy.go b/internal/resource/tenancy.go deleted file mode 100644 index 16032205badda..0000000000000 --- a/internal/resource/tenancy.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resource - -import ( - "fmt" - "strings" - - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - DefaultPartitionName = "default" - DefaultNamespaceName = "default" -) - -// Scope describes the tenancy scope of a resource. -type Scope int - -const ( - // There is no default scope, it must be set explicitly. - ScopeUndefined Scope = iota - // ScopeCluster describes a resource that is scoped to a cluster. - ScopeCluster - // ScopePartition describes a resource that is scoped to a partition. - ScopePartition - // ScopeNamespace applies to a resource that is scoped to a partition and namespace. - ScopeNamespace -) - -func (s Scope) String() string { - switch s { - case ScopeUndefined: - return "undefined" - case ScopeCluster: - return "cluster" - case ScopePartition: - return "partition" - case ScopeNamespace: - return "namespace" - } - 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) -} - -// DefaultClusteredTenancy returns the default tenancy for a cluster scoped resource. -func DefaultClusteredTenancy() *pbresource.Tenancy { - return &pbresource.Tenancy{ - // TODO(spatel): Remove as part of "peer is not part of tenancy" ADR - PeerName: "local", - } -} - -// DefaultPartitionedTenancy returns the default tenancy for a partition scoped resource. -func DefaultPartitionedTenancy() *pbresource.Tenancy { - return &pbresource.Tenancy{ - Partition: DefaultPartitionName, - // TODO(spatel): Remove as part of "peer is not part of tenancy" ADR - PeerName: "local", - } -} - -// DefaultNamespedTenancy returns the default tenancy for a namespace scoped resource. -func DefaultNamespacedTenancy() *pbresource.Tenancy { - return &pbresource.Tenancy{ - Partition: DefaultPartitionName, - Namespace: DefaultNamespaceName, - // TODO(spatel): Remove as part of "peer is not part of tenancy" ADR - PeerName: "local", - } -} diff --git a/internal/resource/tombstone.go b/internal/resource/tombstone.go index d86ae96ec4d50..6d0285c602de9 100644 --- a/internal/resource/tombstone.go +++ b/internal/resource/tombstone.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package resource import "github.com/hashicorp/consul/proto-public/pbresource" diff --git a/internal/resourcehcl/any.go b/internal/resourcehcl/any.go deleted file mode 100644 index 3d797c48e5b88..0000000000000 --- a/internal/resourcehcl/any.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resourcehcl - -import ( - "errors" - "fmt" - - "google.golang.org/protobuf/reflect/protoreflect" - - "github.com/hashicorp/consul/internal/protohcl" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// anyProvider implements protohcl.AnyTypeProvider to infer the `Data` block -// type from `ID.Type`. -type anyProvider struct { - base protohcl.AnyTypeProvider - reg resource.Registry -} - -func (p anyProvider) AnyType(ctx *protohcl.UnmarshalContext, decoder protohcl.MessageDecoder) (protoreflect.FullName, protohcl.MessageDecoder, error) { - if ctx.Name != "Data" { - return p.base.AnyType(ctx, decoder) - } - - if ctx.Parent == nil || ctx.Parent.Message == nil { - return p.base.AnyType(ctx, decoder) - } - - res, isResource := ctx.Parent.Message.Interface().(*pbresource.Resource) - if !isResource { - return p.base.AnyType(ctx, decoder) - } - - resourceType := res.GetId().GetType() - if res == nil { - return "", nil, errors.New("ID.Type not found") - } - - reg, ok := p.reg.Resolve(resourceType) - if !ok { - return "", nil, fmt.Errorf("unknown resource type: %s", resource.ToGVK(resourceType)) - } - - return reg.Proto.ProtoReflect().Descriptor().FullName(), decoder, nil -} diff --git a/internal/resourcehcl/naming.go b/internal/resourcehcl/naming.go deleted file mode 100644 index a1160cc323639..0000000000000 --- a/internal/resourcehcl/naming.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resourcehcl - -import ( - "strings" - - "google.golang.org/protobuf/reflect/protoreflect" -) - -// fieldNamer implements protohcl.FieldNamer to name fields using PascalCase -// with support for acroynms (e.g. ID, TCP). -type fieldNamer struct{ acroynms []string } - -func (n fieldNamer) NameField(fd protoreflect.FieldDescriptor) string { - camel := fd.JSONName() - upper := strings.ToUpper(camel) - - for _, a := range n.acroynms { - if upper == a { - return a - } - } - - return strings.ToUpper(camel[:1]) + camel[1:] -} - -func (n fieldNamer) GetField(fds protoreflect.FieldDescriptors, name string) protoreflect.FieldDescriptor { - for _, a := range n.acroynms { - if name == a { - return fds.ByJSONName(strings.ToLower(a)) - } - } - - camel := strings.ToLower(name[:1]) + name[1:] - return fds.ByJSONName(camel) -} diff --git a/internal/resourcehcl/testdata/gvk-no-arguments.error b/internal/resourcehcl/testdata/gvk-no-arguments.error deleted file mode 100644 index 1c290dd3d6135..0000000000000 --- a/internal/resourcehcl/testdata/gvk-no-arguments.error +++ /dev/null @@ -1 +0,0 @@ -gvk-no-arguments.hcl:2,14-15: Not enough function arguments; Function "gvk" expects 1 argument(s). Missing value for "GVK String". \ No newline at end of file diff --git a/internal/resourcehcl/testdata/gvk-no-arguments.hcl b/internal/resourcehcl/testdata/gvk-no-arguments.hcl deleted file mode 100644 index 69aee02b2cfa8..0000000000000 --- a/internal/resourcehcl/testdata/gvk-no-arguments.hcl +++ /dev/null @@ -1,4 +0,0 @@ -ID { - Type = gvk() - Name = "foo" -} diff --git a/internal/resourcehcl/testdata/invalid-group.error b/internal/resourcehcl/testdata/invalid-group.error deleted file mode 100644 index 6db3a339c2a18..0000000000000 --- a/internal/resourcehcl/testdata/invalid-group.error +++ /dev/null @@ -1 +0,0 @@ -invalid-group.hcl:3,13-17: Failed to unmarshal argument Group: expected value of type string but actual type is number \ No newline at end of file diff --git a/internal/resourcehcl/testdata/invalid-group.hcl b/internal/resourcehcl/testdata/invalid-group.hcl deleted file mode 100644 index ca6920163ecce..0000000000000 --- a/internal/resourcehcl/testdata/invalid-group.hcl +++ /dev/null @@ -1,8 +0,0 @@ -ID { - Type { - Group = 1234 - GroupVersion = "v1" - Kind = "Artist" - } - Name = "foo" -} diff --git a/internal/resourcehcl/testdata/invalid-gvk.error b/internal/resourcehcl/testdata/invalid-gvk.error deleted file mode 100644 index 92ebca5eb0c12..0000000000000 --- a/internal/resourcehcl/testdata/invalid-gvk.error +++ /dev/null @@ -1 +0,0 @@ -invalid-gvk.hcl:2,10-14: Error in function call; Call to function "gvk" failed: GVK string must be in the form .., got: nope. \ No newline at end of file diff --git a/internal/resourcehcl/testdata/invalid-gvk.hcl b/internal/resourcehcl/testdata/invalid-gvk.hcl deleted file mode 100644 index 565a4cc3f9c84..0000000000000 --- a/internal/resourcehcl/testdata/invalid-gvk.hcl +++ /dev/null @@ -1,4 +0,0 @@ -ID { - Type = gvk("nope") - Name = "foo" -} diff --git a/internal/resourcehcl/testdata/invalid-metadata.error b/internal/resourcehcl/testdata/invalid-metadata.error deleted file mode 100644 index 352f2ffa056c6..0000000000000 --- a/internal/resourcehcl/testdata/invalid-metadata.error +++ /dev/null @@ -1 +0,0 @@ -invalid-metadata.hcl:6,12-8,2: Failed to unmarshal argument Metadata["foo"]: expected value of type string but actual type is tuple \ No newline at end of file diff --git a/internal/resourcehcl/testdata/invalid-metadata.hcl b/internal/resourcehcl/testdata/invalid-metadata.hcl deleted file mode 100644 index aa10b5686e7f1..0000000000000 --- a/internal/resourcehcl/testdata/invalid-metadata.hcl +++ /dev/null @@ -1,8 +0,0 @@ -ID { - Type = gvk("demo.v1.Artist") - Name = "korn" -} - -Metadata = { - "foo" = ["bar"] -} diff --git a/internal/resourcehcl/testdata/invalid-name.error b/internal/resourcehcl/testdata/invalid-name.error deleted file mode 100644 index ba977a2e279c7..0000000000000 --- a/internal/resourcehcl/testdata/invalid-name.error +++ /dev/null @@ -1 +0,0 @@ -invalid-name.hcl:3,10-14: Failed to unmarshal argument Name: expected value of type string but actual type is number \ No newline at end of file diff --git a/internal/resourcehcl/testdata/invalid-name.hcl b/internal/resourcehcl/testdata/invalid-name.hcl deleted file mode 100644 index 54ca6b186bbcf..0000000000000 --- a/internal/resourcehcl/testdata/invalid-name.hcl +++ /dev/null @@ -1,4 +0,0 @@ -ID { - Type = gvk("demo.v1.Artist") - Name = 1234 -} diff --git a/internal/resourcehcl/testdata/no-blocks-any-first.golden b/internal/resourcehcl/testdata/no-blocks-any-first.golden deleted file mode 100644 index 18a7cfd9aeecb..0000000000000 --- a/internal/resourcehcl/testdata/no-blocks-any-first.golden +++ /dev/null @@ -1 +0,0 @@ -{"id":{"name":"korn","type":{"group":"demo","groupVersion":"v1","kind":"Artist"}},"data":{"@type":"hashicorp.consul.internal.demo.v1.Artist","name":"Korn"}} \ No newline at end of file diff --git a/internal/resourcehcl/testdata/no-blocks-any-first.hcl b/internal/resourcehcl/testdata/no-blocks-any-first.hcl deleted file mode 100644 index 8eb8d75f43170..0000000000000 --- a/internal/resourcehcl/testdata/no-blocks-any-first.hcl +++ /dev/null @@ -1,8 +0,0 @@ -Data = { - Name = "Korn" -} - -ID = { - Type = gvk("demo.v1.Artist") - Name = "korn" -} diff --git a/internal/resourcehcl/testdata/no-blocks.golden b/internal/resourcehcl/testdata/no-blocks.golden deleted file mode 100644 index c7243ad16163b..0000000000000 --- a/internal/resourcehcl/testdata/no-blocks.golden +++ /dev/null @@ -1 +0,0 @@ -{"id":{"type":{"group":"mesh","groupVersion":"v1alpha1","kind":"Upstreams"}},"data":{"@type":"hashicorp.consul.mesh.v1alpha1.Upstreams","workloads":{"prefixes":["api"]},"upstreams":[{"destinationRef":{"name":"db","type":{"group":"catalog","groupVersion":"v1alpha1","kind":"Service"}},"destinationPort":"tcp","ipPort":{"port":1234}}]}} diff --git a/internal/resourcehcl/testdata/no-blocks.hcl b/internal/resourcehcl/testdata/no-blocks.hcl deleted file mode 100644 index b134e81246213..0000000000000 --- a/internal/resourcehcl/testdata/no-blocks.hcl +++ /dev/null @@ -1,33 +0,0 @@ -ID = { - Type = { - Group = "mesh" - GroupVersion = "v1alpha1" - Kind = "Upstreams" - } -} - -Data = { - Workloads = { - Prefixes = ["api"] - } - - Upstreams = [ - { - DestinationRef = { - Type = { - Group = "catalog" - GroupVersion = "v1alpha1" - Kind = "Service" - } - - Name = "db" - } - - DestinationPort = "tcp" - - IpPort = { - Port = 1234 - } - } - ] -} diff --git a/internal/resourcehcl/testdata/owner.golden b/internal/resourcehcl/testdata/owner.golden deleted file mode 100644 index 9054db09bfd35..0000000000000 --- a/internal/resourcehcl/testdata/owner.golden +++ /dev/null @@ -1 +0,0 @@ -{"id":{"name":"twisted-transistor","type":{"group":"demo","groupVersion":"v1","kind":"Album"}},"owner":{"name":"korn","type":{"group":"demo","groupVersion":"v1","kind":"Artist"}}} \ No newline at end of file diff --git a/internal/resourcehcl/testdata/owner.hcl b/internal/resourcehcl/testdata/owner.hcl deleted file mode 100644 index 2cc65e4c66582..0000000000000 --- a/internal/resourcehcl/testdata/owner.hcl +++ /dev/null @@ -1,9 +0,0 @@ -ID { - Type = gvk("demo.v1.Album") - Name = "twisted-transistor" -} - -Owner { - Type = gvk("demo.v1.Artist") - Name = "korn" -} diff --git a/internal/resourcehcl/testdata/simple-gvk.golden b/internal/resourcehcl/testdata/simple-gvk.golden deleted file mode 100644 index ba3fddcd6d176..0000000000000 --- a/internal/resourcehcl/testdata/simple-gvk.golden +++ /dev/null @@ -1 +0,0 @@ -{"id":{"name":"korn","type":{"group":"demo","groupVersion":"v1","kind":"Artist"}},"metadata":{"foo":"bar"},"data":{"@type":"hashicorp.consul.internal.demo.v1.Artist","name":"Korn","genre":"GENRE_METAL"}} \ No newline at end of file diff --git a/internal/resourcehcl/testdata/simple-gvk.hcl b/internal/resourcehcl/testdata/simple-gvk.hcl deleted file mode 100644 index adddcd42c8c1c..0000000000000 --- a/internal/resourcehcl/testdata/simple-gvk.hcl +++ /dev/null @@ -1,13 +0,0 @@ -ID { - Type = gvk("demo.v1.Artist") - Name = "korn" -} - -Data { - Name = "Korn" - Genre = "GENRE_METAL" -} - -Metadata = { - "foo" = "bar" -} diff --git a/internal/resourcehcl/testdata/type-block.golden b/internal/resourcehcl/testdata/type-block.golden deleted file mode 100644 index 963695616bee8..0000000000000 --- a/internal/resourcehcl/testdata/type-block.golden +++ /dev/null @@ -1 +0,0 @@ -{"id":{"name":"korn","type":{"group":"demo","groupVersion":"v1","kind":"Artist"}}} \ No newline at end of file diff --git a/internal/resourcehcl/testdata/type-block.hcl b/internal/resourcehcl/testdata/type-block.hcl deleted file mode 100644 index f927fbe2fe613..0000000000000 --- a/internal/resourcehcl/testdata/type-block.hcl +++ /dev/null @@ -1,8 +0,0 @@ -ID { - Type { - Group = "demo" - GroupVersion = "v1" - Kind = "Artist" - } - Name = "korn" -} diff --git a/internal/resourcehcl/testdata/unknown-field-block.error b/internal/resourcehcl/testdata/unknown-field-block.error deleted file mode 100644 index 602212543d66a..0000000000000 --- a/internal/resourcehcl/testdata/unknown-field-block.error +++ /dev/null @@ -1 +0,0 @@ -unknown-field-block.hcl:2,3-6: Unsupported argument; An argument named "Foo" is not expected here. \ No newline at end of file diff --git a/internal/resourcehcl/testdata/unknown-field-block.hcl b/internal/resourcehcl/testdata/unknown-field-block.hcl deleted file mode 100644 index 534fdb11b8d25..0000000000000 --- a/internal/resourcehcl/testdata/unknown-field-block.hcl +++ /dev/null @@ -1,3 +0,0 @@ -ID { - Foo = "bar" -} diff --git a/internal/resourcehcl/testdata/unknown-field-object.error b/internal/resourcehcl/testdata/unknown-field-object.error deleted file mode 100644 index b7651d5eb0d59..0000000000000 --- a/internal/resourcehcl/testdata/unknown-field-object.error +++ /dev/null @@ -1 +0,0 @@ -unknown-field-object.hcl:1,6-3,2: Unsupported argument; An argument named "Foo" is not expected here. \ No newline at end of file diff --git a/internal/resourcehcl/testdata/unknown-field-object.hcl b/internal/resourcehcl/testdata/unknown-field-object.hcl deleted file mode 100644 index 43220099bb0a3..0000000000000 --- a/internal/resourcehcl/testdata/unknown-field-object.hcl +++ /dev/null @@ -1,3 +0,0 @@ -ID = { - Foo = "bar" -} diff --git a/internal/resourcehcl/testdata/unknown-type.error b/internal/resourcehcl/testdata/unknown-type.error deleted file mode 100644 index 81e0ea1c81597..0000000000000 --- a/internal/resourcehcl/testdata/unknown-type.error +++ /dev/null @@ -1 +0,0 @@ -error getting type for Any field: unknown resource type: foo.bar.Baz \ No newline at end of file diff --git a/internal/resourcehcl/testdata/unknown-type.hcl b/internal/resourcehcl/testdata/unknown-type.hcl deleted file mode 100644 index f1669b8ba882b..0000000000000 --- a/internal/resourcehcl/testdata/unknown-type.hcl +++ /dev/null @@ -1,8 +0,0 @@ -ID { - Type = gvk("foo.bar.Baz") - Name = "qux" -} - -Data { - Foo = "bar" -} diff --git a/internal/resourcehcl/testdata/upstreams.golden b/internal/resourcehcl/testdata/upstreams.golden deleted file mode 100644 index 26608ae3d5d7c..0000000000000 --- a/internal/resourcehcl/testdata/upstreams.golden +++ /dev/null @@ -1 +0,0 @@ -{"id":{"name":"api","type":{"group":"mesh","groupVersion":"v1alpha1","kind":"Upstreams"}},"data":{"@type":"hashicorp.consul.mesh.v1alpha1.Upstreams","workloads":{"prefixes":["api"]},"upstreams":[{"destinationRef":{"name":"db","type":{"group":"catalog","groupVersion":"v1alpha1","kind":"Service"}},"destinationPort":"tcp","ipPort":{"port":1234}}]}} diff --git a/internal/resourcehcl/testdata/upstreams.hcl b/internal/resourcehcl/testdata/upstreams.hcl deleted file mode 100644 index c0993e4d5bac1..0000000000000 --- a/internal/resourcehcl/testdata/upstreams.hcl +++ /dev/null @@ -1,25 +0,0 @@ -ID { - Type = gvk("mesh.v1alpha1.Upstreams") - Name = "api" -} - -Data { - Workloads { - Prefixes = ["api"] - } - - Upstreams = [ - { - DestinationRef = { - Type = gvk("catalog.v1alpha1.Service") - Name = "db" - } - - DestinationPort = "tcp" - - IpPort = { - Port = 1234 - } - } - ] -} diff --git a/internal/resourcehcl/unmarshal.go b/internal/resourcehcl/unmarshal.go deleted file mode 100644 index 610ebc641b825..0000000000000 --- a/internal/resourcehcl/unmarshal.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resourcehcl - -import ( - "reflect" - - "github.com/zclconf/go-cty/cty" - "github.com/zclconf/go-cty/cty/function" - - "github.com/hashicorp/consul/internal/protohcl" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// Unmarshal the given HCL source into a resource. -func Unmarshal(src []byte, reg resource.Registry) (*pbresource.Resource, error) { - return UnmarshalOptions{}.Unmarshal(src, reg) -} - -type UnmarshalOptions struct{ SourceFileName string } - -// Unmarshal the given HCL source into a resource. -func (u UnmarshalOptions) Unmarshal(src []byte, reg resource.Registry) (*pbresource.Resource, error) { - var out pbresource.Resource - err := (protohcl.UnmarshalOptions{ - SourceFileName: u.SourceFileName, - AnyTypeProvider: anyProvider{ - base: &protohcl.AnyTypeURLProvider{TypeURLFieldName: "Type"}, - reg: reg, - }, - FieldNamer: fieldNamer{acroynms: []string{"ID", "TCP", "UDP", "HTTP"}}, - Functions: map[string]function.Function{"gvk": gvk}, - }).Unmarshal(src, &out) - return &out, err -} - -var ( - typeType = cty.Capsule("type", reflect.TypeOf(pbresource.Type{})) - - gvk = function.New(&function.Spec{ - Params: []function.Parameter{ - {Name: "GVK String", Type: cty.String}, - }, - Type: function.StaticReturnType(typeType), - Impl: func(args []cty.Value, _ cty.Type) (cty.Value, error) { - t, err := resource.ParseGVK(args[0].AsString()) - if err != nil { - return cty.NilVal, err - } - return cty.CapsuleVal(typeType, t), nil - }, - }) -) diff --git a/internal/resourcehcl/unmarshal_test.go b/internal/resourcehcl/unmarshal_test.go deleted file mode 100644 index 5e35f7df66b13..0000000000000 --- a/internal/resourcehcl/unmarshal_test.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package resourcehcl_test - -import ( - "flag" - "fmt" - "os" - "path" - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/encoding/protojson" - - "github.com/hashicorp/consul/internal/mesh" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/demo" - "github.com/hashicorp/consul/internal/resourcehcl" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" -) - -var update = flag.Bool("update", false, "update golden files") - -func TestUnmarshal(t *testing.T) { - entries, err := os.ReadDir("./testdata") - require.NoError(t, err) - - read := func(t *testing.T, path string) ([]byte, bool) { - t.Helper() - - bytes, err := os.ReadFile(fmt.Sprintf("./testdata/%s", path)) - switch { - case err == nil: - return bytes, true - case os.IsNotExist(err): - return nil, false - } - - t.Fatalf("failed to read file %s %v", path, err) - return nil, false - } - - write := func(t *testing.T, path string, src []byte) { - t.Helper() - - require.NoError(t, os.WriteFile(fmt.Sprintf("./testdata/%s", path), src, 0o600)) - } - - for _, entry := range entries { - name := entry.Name() - ext := path.Ext(name) - - if ext != ".hcl" { - continue - } - - base := name[0 : len(name)-len(ext)] - - t.Run(base, func(t *testing.T) { - input, _ := read(t, name) - - registry := resource.NewRegistry() - demo.RegisterTypes(registry) - mesh.RegisterTypes(registry) - - output, err := resourcehcl.UnmarshalOptions{SourceFileName: name}. - Unmarshal(input, registry) - - if *update { - if err == nil { - json, err := protojson.Marshal(output) - require.NoError(t, err) - write(t, base+".golden", json) - } else { - write(t, base+".error", []byte(err.Error())) - } - } - - goldenJSON, haveGoldenJSON := read(t, base+".golden") - goldenError, haveGoldenError := read(t, base+".error") - - if haveGoldenError && haveGoldenJSON { - t.Fatalf("both %s.golden and %s.error exist, delete one", base, base) - } - - if !haveGoldenError && !haveGoldenJSON && !*update { - t.Fatalf("neither %s.golden or %s.error exist, run the tests again with the -update flag to create one", base, base) - } - - if haveGoldenError { - require.Error(t, err) - require.Equal(t, string(goldenError), err.Error()) - } - - if haveGoldenJSON { - require.NoError(t, err) - - var exp pbresource.Resource - require.NoError(t, protojson.Unmarshal(goldenJSON, &exp)) - prototest.AssertDeepEqual(t, &exp, output) - } - }) - } -} diff --git a/internal/storage/conformance/conformance.go b/internal/storage/conformance/conformance.go index 543a574fb5a60..22356a88a9c15 100644 --- a/internal/storage/conformance/conformance.go +++ b/internal/storage/conformance/conformance.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package conformance diff --git a/internal/storage/inmem/backend.go b/internal/storage/inmem/backend.go index bf256e508f4d6..fc22aa5ace81b 100644 --- a/internal/storage/inmem/backend.go +++ b/internal/storage/inmem/backend.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package inmem diff --git a/internal/storage/inmem/backend_test.go b/internal/storage/inmem/backend_test.go index 7978dcdf29935..e37de15afab44 100644 --- a/internal/storage/inmem/backend_test.go +++ b/internal/storage/inmem/backend_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package inmem_test diff --git a/internal/storage/inmem/event_index.go b/internal/storage/inmem/event_index.go index f71e809289aca..68d9ec13b142a 100644 --- a/internal/storage/inmem/event_index.go +++ b/internal/storage/inmem/event_index.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package inmem diff --git a/internal/storage/inmem/schema.go b/internal/storage/inmem/schema.go index 37e39dbc57076..6a58eacd586b1 100644 --- a/internal/storage/inmem/schema.go +++ b/internal/storage/inmem/schema.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package inmem diff --git a/internal/storage/inmem/snapshot.go b/internal/storage/inmem/snapshot.go index 36739ac65b20e..6233f4d30bfe4 100644 --- a/internal/storage/inmem/snapshot.go +++ b/internal/storage/inmem/snapshot.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package inmem diff --git a/internal/storage/inmem/snapshot_test.go b/internal/storage/inmem/snapshot_test.go index f3e1bdbaa79e5..b703495d2c7fa 100644 --- a/internal/storage/inmem/snapshot_test.go +++ b/internal/storage/inmem/snapshot_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package inmem_test diff --git a/internal/storage/inmem/store.go b/internal/storage/inmem/store.go index d9c27d339fa3d..5c50b1c138a3f 100644 --- a/internal/storage/inmem/store.go +++ b/internal/storage/inmem/store.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package inmem diff --git a/internal/storage/inmem/watch.go b/internal/storage/inmem/watch.go index bdab0fc5ee864..85c657e3a3c6c 100644 --- a/internal/storage/inmem/watch.go +++ b/internal/storage/inmem/watch.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package inmem diff --git a/internal/storage/raft/backend.go b/internal/storage/raft/backend.go index 8a7a973c3e7cf..4e1cd05bbb18a 100644 --- a/internal/storage/raft/backend.go +++ b/internal/storage/raft/backend.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package raft diff --git a/internal/storage/raft/conformance_test.go b/internal/storage/raft/conformance_test.go index 6c75e462d21c3..ef79087e171d2 100644 --- a/internal/storage/raft/conformance_test.go +++ b/internal/storage/raft/conformance_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package raft_test diff --git a/internal/storage/raft/forwarding.go b/internal/storage/raft/forwarding.go index 2700339afbe58..798ca58465d5e 100644 --- a/internal/storage/raft/forwarding.go +++ b/internal/storage/raft/forwarding.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package raft diff --git a/internal/storage/storage.go b/internal/storage/storage.go index 2a86a769fee94..24a763e395473 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package storage diff --git a/internal/testing/golden/golden.go b/internal/testing/golden/golden.go index 4466ad4cbcff8..079f69f02aa5a 100644 --- a/internal/testing/golden/golden.go +++ b/internal/testing/golden/golden.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package golden diff --git a/internal/tools/proto-gen-rpc-glue/e2e/consul/agent/structs/structs.go b/internal/tools/proto-gen-rpc-glue/e2e/consul/agent/structs/structs.go index 6e76027299ded..59d2a19b8c9bb 100644 --- a/internal/tools/proto-gen-rpc-glue/e2e/consul/agent/structs/structs.go +++ b/internal/tools/proto-gen-rpc-glue/e2e/consul/agent/structs/structs.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package structs diff --git a/internal/tools/proto-gen-rpc-glue/e2e/consul/proto/pbcommon/common.go b/internal/tools/proto-gen-rpc-glue/e2e/consul/proto/pbcommon/common.go index 1395e682edd3c..5c1b497e55185 100644 --- a/internal/tools/proto-gen-rpc-glue/e2e/consul/proto/pbcommon/common.go +++ b/internal/tools/proto-gen-rpc-glue/e2e/consul/proto/pbcommon/common.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbcommon diff --git a/internal/tools/proto-gen-rpc-glue/e2e/source.pb.go b/internal/tools/proto-gen-rpc-glue/e2e/source.pb.go index c69dac63b5c08..3a83b84317526 100644 --- a/internal/tools/proto-gen-rpc-glue/e2e/source.pb.go +++ b/internal/tools/proto-gen-rpc-glue/e2e/source.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build example // +build example diff --git a/internal/tools/proto-gen-rpc-glue/main.go b/internal/tools/proto-gen-rpc-glue/main.go index 2412c3386208d..65a25122bc708 100644 --- a/internal/tools/proto-gen-rpc-glue/main.go +++ b/internal/tools/proto-gen-rpc-glue/main.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package main diff --git a/internal/tools/proto-gen-rpc-glue/main_test.go b/internal/tools/proto-gen-rpc-glue/main_test.go index 01eb28e92a31d..87ed4e3917ede 100644 --- a/internal/tools/proto-gen-rpc-glue/main_test.go +++ b/internal/tools/proto-gen-rpc-glue/main_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package main diff --git a/internal/tools/protoc-gen-consul-rate-limit/main.go b/internal/tools/protoc-gen-consul-rate-limit/main.go index 349c371c28e9c..b4bf5711584a6 100644 --- a/internal/tools/protoc-gen-consul-rate-limit/main.go +++ b/internal/tools/protoc-gen-consul-rate-limit/main.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // protoc-gen-consul-rate-limit // This protoc plugin maintains the mapping of gRPC method names to diff --git a/internal/tools/protoc-gen-consul-rate-limit/postprocess/main.go b/internal/tools/protoc-gen-consul-rate-limit/postprocess/main.go index b1f00a2dcdd7c..bd9ea5779ce14 100644 --- a/internal/tools/protoc-gen-consul-rate-limit/postprocess/main.go +++ b/internal/tools/protoc-gen-consul-rate-limit/postprocess/main.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package main diff --git a/ipaddr/detect.go b/ipaddr/detect.go index bc2bf56c350cb..e208b13ed5be5 100644 --- a/ipaddr/detect.go +++ b/ipaddr/detect.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ipaddr diff --git a/ipaddr/detect_test.go b/ipaddr/detect_test.go index c199492c174f9..865421e10cf00 100644 --- a/ipaddr/detect_test.go +++ b/ipaddr/detect_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ipaddr diff --git a/ipaddr/ipaddr.go b/ipaddr/ipaddr.go index 89f8c70a4ceba..92a04e80181d2 100644 --- a/ipaddr/ipaddr.go +++ b/ipaddr/ipaddr.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ipaddr diff --git a/ipaddr/ipaddr_test.go b/ipaddr/ipaddr_test.go index 009144c2de25d..a8aae7f32dde1 100644 --- a/ipaddr/ipaddr_test.go +++ b/ipaddr/ipaddr_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ipaddr diff --git a/lib/cluster.go b/lib/cluster.go index a97ceea722e97..3b121da59835c 100644 --- a/lib/cluster.go +++ b/lib/cluster.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/cluster_test.go b/lib/cluster_test.go index 3493a6fb39f12..44b77332dfec1 100644 --- a/lib/cluster_test.go +++ b/lib/cluster_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/decode/decode.go b/lib/decode/decode.go index 645916d2d6654..fc1558a9f7890 100644 --- a/lib/decode/decode.go +++ b/lib/decode/decode.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 /* Package decode provides tools for customizing the decoding of configuration, diff --git a/lib/decode/decode_test.go b/lib/decode/decode_test.go index 3219e96b4bf9a..b1250ebcc81aa 100644 --- a/lib/decode/decode_test.go +++ b/lib/decode/decode_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package decode diff --git a/lib/eof.go b/lib/eof.go index e208ca73d7535..b8f6ac0e240ec 100644 --- a/lib/eof.go +++ b/lib/eof.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/eof_test.go b/lib/eof_test.go index 330a1152a8eb7..373846a72c942 100644 --- a/lib/eof_test.go +++ b/lib/eof_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/file/atomic.go b/lib/file/atomic.go index 4053f443d8b36..3fa5890052c8d 100644 --- a/lib/file/atomic.go +++ b/lib/file/atomic.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package file diff --git a/lib/file/atomic_test.go b/lib/file/atomic_test.go index baf4bc1771f8e..a74b2d2ecd497 100644 --- a/lib/file/atomic_test.go +++ b/lib/file/atomic_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package file diff --git a/lib/hoststats/collector.go b/lib/hoststats/collector.go index fb316e0dce38f..c4c57b35c5c25 100644 --- a/lib/hoststats/collector.go +++ b/lib/hoststats/collector.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package hoststats import ( diff --git a/lib/hoststats/cpu.go b/lib/hoststats/cpu.go index 420a80ef94240..45633b40df064 100644 --- a/lib/hoststats/cpu.go +++ b/lib/hoststats/cpu.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package hoststats import ( diff --git a/lib/hoststats/cpu_test.go b/lib/hoststats/cpu_test.go index dcc1df9aab50e..5d5efbe9769a1 100644 --- a/lib/hoststats/cpu_test.go +++ b/lib/hoststats/cpu_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package hoststats import ( diff --git a/lib/hoststats/host.go b/lib/hoststats/host.go index 3a44618d20f16..426cf43ea21e5 100644 --- a/lib/hoststats/host.go +++ b/lib/hoststats/host.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package hoststats import ( diff --git a/lib/hoststats/metrics.go b/lib/hoststats/metrics.go index 95055cea43fb3..c89d40b813ff1 100644 --- a/lib/hoststats/metrics.go +++ b/lib/hoststats/metrics.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package hoststats import ( diff --git a/lib/json.go b/lib/json.go index 7e58942a823de..c5ae22b2f90c7 100644 --- a/lib/json.go +++ b/lib/json.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/map_walker.go b/lib/map_walker.go index 1be33b61f15fd..3e8cec77ca643 100644 --- a/lib/map_walker.go +++ b/lib/map_walker.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/map_walker_test.go b/lib/map_walker_test.go index 6156abe4624f8..2a3b4c189d9ec 100644 --- a/lib/map_walker_test.go +++ b/lib/map_walker_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/maps/maps.go b/lib/maps/maps.go index ae19d030a2c01..1996d5f4cd9a9 100644 --- a/lib/maps/maps.go +++ b/lib/maps/maps.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package maps diff --git a/lib/maps/maps_test.go b/lib/maps/maps_test.go index 5d0f4edbc44ef..bebb9afb5f155 100644 --- a/lib/maps/maps_test.go +++ b/lib/maps/maps_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package maps diff --git a/lib/math.go b/lib/math.go index 673dfb84e99cf..75859a2a65801 100644 --- a/lib/math.go +++ b/lib/math.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/math_test.go b/lib/math_test.go index 2ce631fe75dce..7ac4141a268c8 100644 --- a/lib/math_test.go +++ b/lib/math_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib_test diff --git a/lib/mutex/mutex.go b/lib/mutex/mutex.go index 8101204c2e006..a28290c0b3b44 100644 --- a/lib/mutex/mutex.go +++ b/lib/mutex/mutex.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 /* Package mutex implements the sync.Locker interface using x/sync/semaphore. It diff --git a/lib/mutex/mutex_test.go b/lib/mutex/mutex_test.go index 2d51706e4e855..000681d03e86f 100644 --- a/lib/mutex/mutex_test.go +++ b/lib/mutex/mutex_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package mutex diff --git a/lib/path.go b/lib/path.go index fd45378ec1804..347de0cbde09b 100644 --- a/lib/path.go +++ b/lib/path.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/retry/retry.go b/lib/retry/retry.go index e0605f89c4a89..ee9a8b2354e63 100644 --- a/lib/retry/retry.go +++ b/lib/retry/retry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package retry diff --git a/lib/retry/retry_test.go b/lib/retry/retry_test.go index d8a822f6b606a..74bb982b91edc 100644 --- a/lib/retry/retry_test.go +++ b/lib/retry/retry_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package retry diff --git a/lib/routine/routine.go b/lib/routine/routine.go index b5ebe85e22f14..3bcbd1fbee452 100644 --- a/lib/routine/routine.go +++ b/lib/routine/routine.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package routine diff --git a/lib/routine/routine_test.go b/lib/routine/routine_test.go index c04311ac59f49..cfb98d98c3c84 100644 --- a/lib/routine/routine_test.go +++ b/lib/routine/routine_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package routine diff --git a/lib/rtt.go b/lib/rtt.go index d716e6fcbe1c5..5d90431f5d65a 100644 --- a/lib/rtt.go +++ b/lib/rtt.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/rtt_test.go b/lib/rtt_test.go index 1e7779b9addeb..a8a6786ecf622 100644 --- a/lib/rtt_test.go +++ b/lib/rtt_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/semaphore/semaphore.go b/lib/semaphore/semaphore.go index fdfbbb34db021..662d21152868a 100644 --- a/lib/semaphore/semaphore.go +++ b/lib/semaphore/semaphore.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Package semaphore implements a simple semaphore that is based on // golang.org/x/sync/semaphore but doesn't support weights. It's advantage over diff --git a/lib/semaphore/semaphore_test.go b/lib/semaphore/semaphore_test.go index b3182e1107af7..d7da1979b00f4 100644 --- a/lib/semaphore/semaphore_test.go +++ b/lib/semaphore/semaphore_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package semaphore diff --git a/lib/serf/serf.go b/lib/serf/serf.go index 932fed427ba94..ad5297e58b616 100644 --- a/lib/serf/serf.go +++ b/lib/serf/serf.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package serf diff --git a/lib/stop_context.go b/lib/stop_context.go index 98bde25e452b5..ea560e0929e96 100644 --- a/lib/stop_context.go +++ b/lib/stop_context.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/stop_context_test.go b/lib/stop_context_test.go index b62749513f2f7..6da3a6fc61aea 100644 --- a/lib/stop_context_test.go +++ b/lib/stop_context_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/strings.go b/lib/strings.go index 7213a93259141..d268845acc9c4 100644 --- a/lib/strings.go +++ b/lib/strings.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/stringslice/stringslice.go b/lib/stringslice/stringslice.go index 7c32864b9458c..325f603d778dc 100644 --- a/lib/stringslice/stringslice.go +++ b/lib/stringslice/stringslice.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package stringslice diff --git a/lib/stringslice/stringslice_test.go b/lib/stringslice/stringslice_test.go index dd25071757442..975fe34976ec2 100644 --- a/lib/stringslice/stringslice_test.go +++ b/lib/stringslice/stringslice_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package stringslice diff --git a/lib/telemetry.go b/lib/telemetry.go index e06341eefb05b..b66ec721b1dc0 100644 --- a/lib/telemetry.go +++ b/lib/telemetry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/telemetry_test.go b/lib/telemetry_test.go index ab0f7e5b91411..a2c0075598ecc 100644 --- a/lib/telemetry_test.go +++ b/lib/telemetry_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/template/hil.go b/lib/template/hil.go index 502f10d258b20..5b9cc0e2cf148 100644 --- a/lib/template/hil.go +++ b/lib/template/hil.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package template diff --git a/lib/template/hil_test.go b/lib/template/hil_test.go index 4f582f61d1685..84f3558a4a6a4 100644 --- a/lib/template/hil_test.go +++ b/lib/template/hil_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package template diff --git a/lib/translate.go b/lib/translate.go index 6fd49010fc81e..adb58539c0fd9 100644 --- a/lib/translate.go +++ b/lib/translate.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/translate_test.go b/lib/translate_test.go index f36588b7404b1..36d113004a749 100644 --- a/lib/translate_test.go +++ b/lib/translate_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/ttlcache/eviction.go b/lib/ttlcache/eviction.go index 5d5012e7dbacb..3e20bb09b6276 100644 --- a/lib/ttlcache/eviction.go +++ b/lib/ttlcache/eviction.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 /* Package ttlcache provides an ExpiryHeap that can be used by a cache to track the diff --git a/lib/ttlcache/eviction_test.go b/lib/ttlcache/eviction_test.go index 18bf2fbbc78bf..fe55b68cf1760 100644 --- a/lib/ttlcache/eviction_test.go +++ b/lib/ttlcache/eviction_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package ttlcache diff --git a/lib/useragent.go b/lib/useragent.go index 89c73dec55297..e967ed11ffc74 100644 --- a/lib/useragent.go +++ b/lib/useragent.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/useragent_test.go b/lib/useragent_test.go index 23df537c9d4ac..4890e454a598b 100644 --- a/lib/useragent_test.go +++ b/lib/useragent_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/lib/uuid.go b/lib/uuid.go index 2c0d657f5b062..8db9517d70228 100644 --- a/lib/uuid.go +++ b/lib/uuid.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package lib diff --git a/logging/gated_writer.go b/logging/gated_writer.go index 5a28c8cf52339..2e0023369a770 100644 --- a/logging/gated_writer.go +++ b/logging/gated_writer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logging diff --git a/logging/gated_writer_test.go b/logging/gated_writer_test.go index cc44ad04b2b94..f0adc8de85a18 100644 --- a/logging/gated_writer_test.go +++ b/logging/gated_writer_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logging diff --git a/logging/grpc.go b/logging/grpc.go index ebe2207e454b8..f565b865fbd93 100644 --- a/logging/grpc.go +++ b/logging/grpc.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logging diff --git a/logging/grpc_test.go b/logging/grpc_test.go index 0a90f11066093..29f1c976e555d 100644 --- a/logging/grpc_test.go +++ b/logging/grpc_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logging diff --git a/logging/log_levels.go b/logging/log_levels.go index 5ed830ee30503..dc3bb8b530b8f 100644 --- a/logging/log_levels.go +++ b/logging/log_levels.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logging diff --git a/logging/logfile.go b/logging/logfile.go index bc7b38d91c263..f84d12de4b199 100644 --- a/logging/logfile.go +++ b/logging/logfile.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logging @@ -60,31 +60,50 @@ func (l *LogFile) fileNamePattern() string { } func (l *LogFile) openNew() error { - fileNamePattern := l.fileNamePattern() - - createTime := now() - newfileName := fmt.Sprintf(fileNamePattern, strconv.FormatInt(createTime.UnixNano(), 10)) + newfileName := l.fileName newfilePath := filepath.Join(l.logPath, newfileName) - // Try creating a file. We truncate the file because we are the only authority to write the logs - filePointer, err := os.OpenFile(newfilePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0640) + // Try creating or opening the active log file. Since the active log file + // always has the same name, append log entries to prevent overwriting + // previous log data. + filePointer, err := os.OpenFile(newfilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0640) if err != nil { return err } l.FileInfo = filePointer + stat, err := filePointer.Stat() + if err != nil { + return err + } // New file, new bytes tracker, new creation time :) - l.LastCreated = createTime + l.LastCreated = l.createTime(stat) l.BytesWritten = 0 return nil } +func (l *LogFile) renameCurrentFile() error { + fileNamePattern := l.fileNamePattern() + + createTime := now() + // Current file is consul.log always + currentFilePath := filepath.Join(l.logPath, l.fileName) + + oldFileName := fmt.Sprintf(fileNamePattern, strconv.FormatInt(createTime.UnixNano(), 10)) + oldFilePath := filepath.Join(l.logPath, oldFileName) + + return os.Rename(currentFilePath, oldFilePath) +} + func (l *LogFile) rotate() error { // Get the time from the last point of contact timeElapsed := time.Since(l.LastCreated) // Rotate if we hit the byte file limit or the time limit if (l.BytesWritten >= int64(l.MaxBytes) && (l.MaxBytes > 0)) || timeElapsed >= l.duration { l.FileInfo.Close() + if err := l.renameCurrentFile(); err != nil { + return err + } if err := l.pruneFiles(); err != nil { return err } diff --git a/logging/logfile_bsd.go b/logging/logfile_bsd.go new file mode 100644 index 0000000000000..d81d065be1ce5 --- /dev/null +++ b/logging/logfile_bsd.go @@ -0,0 +1,16 @@ +//go:build darwin || freebsd || netbsd || openbsd +// +build darwin freebsd netbsd openbsd + +package logging + +import ( + "os" + "syscall" + "time" +) + +func (l *LogFile) createTime(stat os.FileInfo) time.Time { + stat_t := stat.Sys().(*syscall.Stat_t) + createTime := stat_t.Ctimespec + return time.Unix(int64(createTime.Sec), int64(createTime.Nsec)) +} diff --git a/logging/logfile_linux.go b/logging/logfile_linux.go new file mode 100644 index 0000000000000..6cdacfe80e227 --- /dev/null +++ b/logging/logfile_linux.go @@ -0,0 +1,17 @@ +//go:build dragonfly || linux +// +build dragonfly linux + +package logging + +import ( + "os" + "syscall" + "time" +) + +func (l *LogFile) createTime(stat os.FileInfo) time.Time { + stat_t := stat.Sys().(*syscall.Stat_t) + createTime := stat_t.Ctim + // Sec and Nsec are int32 in 32-bit architectures. + return time.Unix(int64(createTime.Sec), int64(createTime.Nsec)) //nolint:unconvert +} diff --git a/logging/logfile_solaris.go b/logging/logfile_solaris.go new file mode 100644 index 0000000000000..b64610cc38fc6 --- /dev/null +++ b/logging/logfile_solaris.go @@ -0,0 +1,17 @@ +//go:build solaris +// +build solaris + +package logging + +import ( + "os" + "syscall" + "time" +) + +func (l *LogFile) createTime(stat os.FileInfo) time.Time { + stat_t := stat.Sys().(*syscall.Stat_t) + createTime := stat_t.Ctim + // Sec and Nsec are int32 in 32-bit architectures. + return time.Unix(int64(createTime.Sec), int64(createTime.Nsec)) //nolint:unconvert +} diff --git a/logging/logfile_test.go b/logging/logfile_test.go index ae9d8fb1b0cd3..6f97305662974 100644 --- a/logging/logfile_test.go +++ b/logging/logfile_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logging @@ -51,6 +51,22 @@ func TestLogFile_openNew(t *testing.T) { require.Contains(t, string(content), msg) } +func TestLogFile_renameCurrentFile(t *testing.T) { + logFile := LogFile{ + fileName: "consul.log", + logPath: testutil.TempDir(t, ""), + duration: defaultRotateDuration, + } + err := logFile.openNew() + require.NoError(t, err) + + err = logFile.renameCurrentFile() + require.NoError(t, err) + + _, err = os.ReadFile(logFile.FileInfo.Name()) + require.Contains(t, err.Error(), "no such file or directory") +} + func TestLogFile_Rotation_MaxBytes(t *testing.T) { tempDir := testutil.TempDir(t, "LogWriterBytes") logFile := LogFile{ diff --git a/logging/logfile_windows.go b/logging/logfile_windows.go new file mode 100644 index 0000000000000..688a8351cdbea --- /dev/null +++ b/logging/logfile_windows.go @@ -0,0 +1,14 @@ +package logging + +import ( + "os" + "time" +) + +func (l *LogFile) createTime(stat os.FileInfo) time.Time { + // Use `ModTime` as an approximation if the exact create time is not + // available. + // On Windows, the file create time is not updated after the active log + // rotates, so use `ModTime` as an approximation as well. + return stat.ModTime() +} diff --git a/logging/logger.go b/logging/logger.go index 8d63ed7e15eb3..fb5128790fd0a 100644 --- a/logging/logger.go +++ b/logging/logger.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logging diff --git a/logging/logger_test.go b/logging/logger_test.go index 5cb0c1e44189a..ca5f1eecd2481 100644 --- a/logging/logger_test.go +++ b/logging/logger_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logging diff --git a/logging/monitor/monitor.go b/logging/monitor/monitor.go index 6a812a879f642..7440a6586f632 100644 --- a/logging/monitor/monitor.go +++ b/logging/monitor/monitor.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package monitor diff --git a/logging/monitor/monitor_test.go b/logging/monitor/monitor_test.go index 5f834f4f2322e..ba77eab36fdd7 100644 --- a/logging/monitor/monitor_test.go +++ b/logging/monitor/monitor_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package monitor diff --git a/logging/names.go b/logging/names.go index 69a859443cfb9..1c7ecc4487872 100644 --- a/logging/names.go +++ b/logging/names.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logging diff --git a/logging/syslog.go b/logging/syslog.go index ceb0ae0ac2f2d..8eb1391fcb3b3 100644 --- a/logging/syslog.go +++ b/logging/syslog.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package logging diff --git a/logging/syslog_test.go b/logging/syslog_test.go index 1b3d66feba0c6..fdef92b5284b4 100644 --- a/logging/syslog_test.go +++ b/logging/syslog_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build linux || darwin || dragonfly || freebsd || netbsd || openbsd || solaris // +build linux darwin dragonfly freebsd netbsd openbsd solaris diff --git a/logging/syslog_unsupported_test.go b/logging/syslog_unsupported_test.go index dab3d47d72fc2..d616580d2f220 100644 --- a/logging/syslog_unsupported_test.go +++ b/logging/syslog_unsupported_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build windows || plan9 || nacl // +build windows plan9 nacl diff --git a/main.go b/main.go index d29454035b12f..63f5a4f26dd84 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package main diff --git a/proto-public/LICENSE b/proto-public/LICENSE deleted file mode 100644 index 7c5baa45e1c29..0000000000000 --- a/proto-public/LICENSE +++ /dev/null @@ -1,365 +0,0 @@ -Copyright (c) 2020 HashiCorp, Inc. - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - diff --git a/proto-public/pbcatalog/v1alpha1/failover_policy.pb.binary.go b/proto-public/pbcatalog/v1alpha1/failover_policy.pb.binary.go deleted file mode 100644 index 85aa74cd41db5..0000000000000 --- a/proto-public/pbcatalog/v1alpha1/failover_policy.pb.binary.go +++ /dev/null @@ -1,38 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbcatalog/v1alpha1/failover_policy.proto - -package catalogv1alpha1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *FailoverPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *FailoverPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *FailoverConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *FailoverConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *FailoverDestination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *FailoverDestination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbcatalog/v1alpha1/failover_policy.pb.go b/proto-public/pbcatalog/v1alpha1/failover_policy.pb.go deleted file mode 100644 index 568405a1cd535..0000000000000 --- a/proto-public/pbcatalog/v1alpha1/failover_policy.pb.go +++ /dev/null @@ -1,457 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbcatalog/v1alpha1/failover_policy.proto - -package catalogv1alpha1 - -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 FailoverMode int32 - -const ( - FailoverMode_FAILOVER_MODE_UNSPECIFIED FailoverMode = 0 - FailoverMode_FAILOVER_MODE_SEQUENTIAL FailoverMode = 1 - FailoverMode_FAILOVER_MODE_ORDER_BY_LOCALITY FailoverMode = 2 -) - -// Enum value maps for FailoverMode. -var ( - FailoverMode_name = map[int32]string{ - 0: "FAILOVER_MODE_UNSPECIFIED", - 1: "FAILOVER_MODE_SEQUENTIAL", - 2: "FAILOVER_MODE_ORDER_BY_LOCALITY", - } - FailoverMode_value = map[string]int32{ - "FAILOVER_MODE_UNSPECIFIED": 0, - "FAILOVER_MODE_SEQUENTIAL": 1, - "FAILOVER_MODE_ORDER_BY_LOCALITY": 2, - } -) - -func (x FailoverMode) Enum() *FailoverMode { - p := new(FailoverMode) - *p = x - return p -} - -func (x FailoverMode) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (FailoverMode) Descriptor() protoreflect.EnumDescriptor { - return file_pbcatalog_v1alpha1_failover_policy_proto_enumTypes[0].Descriptor() -} - -func (FailoverMode) Type() protoreflect.EnumType { - return &file_pbcatalog_v1alpha1_failover_policy_proto_enumTypes[0] -} - -func (x FailoverMode) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use FailoverMode.Descriptor instead. -func (FailoverMode) EnumDescriptor() ([]byte, []int) { - return file_pbcatalog_v1alpha1_failover_policy_proto_rawDescGZIP(), []int{0} -} - -// This is a Resource type. -type FailoverPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Config defines failover for any named port not present in PortConfigs. - Config *FailoverConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - // PortConfigs defines failover for a specific port on this service and takes - // precedence over Config. - PortConfigs map[string]*FailoverConfig `protobuf:"bytes,2,rep,name=port_configs,json=portConfigs,proto3" json:"port_configs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *FailoverPolicy) Reset() { - *x = FailoverPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v1alpha1_failover_policy_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FailoverPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FailoverPolicy) ProtoMessage() {} - -func (x *FailoverPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v1alpha1_failover_policy_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 FailoverPolicy.ProtoReflect.Descriptor instead. -func (*FailoverPolicy) Descriptor() ([]byte, []int) { - return file_pbcatalog_v1alpha1_failover_policy_proto_rawDescGZIP(), []int{0} -} - -func (x *FailoverPolicy) GetConfig() *FailoverConfig { - if x != nil { - return x.Config - } - return nil -} - -func (x *FailoverPolicy) GetPortConfigs() map[string]*FailoverConfig { - if x != nil { - return x.PortConfigs - } - return nil -} - -type FailoverConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Destinations specifies a fixed list of failover destinations to try. We - // never try a destination multiple times, so those are subtracted from this - // list before proceeding. - Destinations []*FailoverDestination `protobuf:"bytes,1,rep,name=destinations,proto3" json:"destinations,omitempty"` - // Mode specifies the type of failover that will be performed. Valid values are - // "sequential", "" (equivalent to "sequential") and "order-by-locality". - Mode FailoverMode `protobuf:"varint,2,opt,name=mode,proto3,enum=hashicorp.consul.catalog.v1alpha1.FailoverMode" json:"mode,omitempty"` - Regions []string `protobuf:"bytes,3,rep,name=regions,proto3" json:"regions,omitempty"` - // SamenessGroup specifies the sameness group to failover to. - SamenessGroup string `protobuf:"bytes,4,opt,name=sameness_group,json=samenessGroup,proto3" json:"sameness_group,omitempty"` -} - -func (x *FailoverConfig) Reset() { - *x = FailoverConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v1alpha1_failover_policy_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FailoverConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FailoverConfig) ProtoMessage() {} - -func (x *FailoverConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v1alpha1_failover_policy_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 FailoverConfig.ProtoReflect.Descriptor instead. -func (*FailoverConfig) Descriptor() ([]byte, []int) { - return file_pbcatalog_v1alpha1_failover_policy_proto_rawDescGZIP(), []int{1} -} - -func (x *FailoverConfig) GetDestinations() []*FailoverDestination { - if x != nil { - return x.Destinations - } - return nil -} - -func (x *FailoverConfig) GetMode() FailoverMode { - if x != nil { - return x.Mode - } - return FailoverMode_FAILOVER_MODE_UNSPECIFIED -} - -func (x *FailoverConfig) GetRegions() []string { - if x != nil { - return x.Regions - } - return nil -} - -func (x *FailoverConfig) GetSamenessGroup() string { - if x != nil { - return x.SamenessGroup - } - return "" -} - -type FailoverDestination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // This must be a Service. - Ref *pbresource.Reference `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` - // TODO: what should an empty port mean? - Port string `protobuf:"bytes,2,opt,name=port,proto3" json:"port,omitempty"` - Datacenter string `protobuf:"bytes,3,opt,name=datacenter,proto3" json:"datacenter,omitempty"` -} - -func (x *FailoverDestination) Reset() { - *x = FailoverDestination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v1alpha1_failover_policy_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FailoverDestination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FailoverDestination) ProtoMessage() {} - -func (x *FailoverDestination) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v1alpha1_failover_policy_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 FailoverDestination.ProtoReflect.Descriptor instead. -func (*FailoverDestination) Descriptor() ([]byte, []int) { - return file_pbcatalog_v1alpha1_failover_policy_proto_rawDescGZIP(), []int{2} -} - -func (x *FailoverDestination) GetRef() *pbresource.Reference { - if x != nil { - return x.Ref - } - return nil -} - -func (x *FailoverDestination) GetPort() string { - if x != nil { - return x.Port - } - return "" -} - -func (x *FailoverDestination) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - -var File_pbcatalog_v1alpha1_failover_policy_proto protoreflect.FileDescriptor - -var file_pbcatalog_v1alpha1_failover_policy_proto_rawDesc = []byte{ - 0x0a, 0x28, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 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, 0x63, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 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, 0xb5, 0x02, 0x0a, 0x0e, 0x46, 0x61, 0x69, - 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x49, 0x0a, 0x06, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, - 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x65, 0x0a, 0x0c, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x50, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x0b, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x1a, 0x71, 0x0a, - 0x10, 0x50, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x47, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0xf2, 0x01, 0x0a, 0x0e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x5a, 0x0a, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x61, - 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x43, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, - 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, - 0x0a, 0x0e, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x81, 0x01, 0x0a, 0x13, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, - 0x65, 0x72, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, - 0x03, 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, 0x03, 0x72, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, - 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, - 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x2a, 0x70, 0x0a, 0x0c, 0x46, 0x61, 0x69, - 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x41, 0x49, - 0x4c, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x46, 0x41, 0x49, 0x4c, - 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x45, 0x51, 0x55, 0x45, 0x4e, - 0x54, 0x49, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x46, 0x41, 0x49, 0x4c, 0x4f, 0x56, - 0x45, 0x52, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x42, 0x59, - 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x49, 0x54, 0x59, 0x10, 0x02, 0x42, 0xb0, 0x02, 0x0a, 0x25, - 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x13, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 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, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, - 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, - 0x67, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x43, 0xaa, - 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 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, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 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, 0x43, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 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, 0x43, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbcatalog_v1alpha1_failover_policy_proto_rawDescOnce sync.Once - file_pbcatalog_v1alpha1_failover_policy_proto_rawDescData = file_pbcatalog_v1alpha1_failover_policy_proto_rawDesc -) - -func file_pbcatalog_v1alpha1_failover_policy_proto_rawDescGZIP() []byte { - file_pbcatalog_v1alpha1_failover_policy_proto_rawDescOnce.Do(func() { - file_pbcatalog_v1alpha1_failover_policy_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbcatalog_v1alpha1_failover_policy_proto_rawDescData) - }) - return file_pbcatalog_v1alpha1_failover_policy_proto_rawDescData -} - -var file_pbcatalog_v1alpha1_failover_policy_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbcatalog_v1alpha1_failover_policy_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_pbcatalog_v1alpha1_failover_policy_proto_goTypes = []interface{}{ - (FailoverMode)(0), // 0: hashicorp.consul.catalog.v1alpha1.FailoverMode - (*FailoverPolicy)(nil), // 1: hashicorp.consul.catalog.v1alpha1.FailoverPolicy - (*FailoverConfig)(nil), // 2: hashicorp.consul.catalog.v1alpha1.FailoverConfig - (*FailoverDestination)(nil), // 3: hashicorp.consul.catalog.v1alpha1.FailoverDestination - nil, // 4: hashicorp.consul.catalog.v1alpha1.FailoverPolicy.PortConfigsEntry - (*pbresource.Reference)(nil), // 5: hashicorp.consul.resource.Reference -} -var file_pbcatalog_v1alpha1_failover_policy_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.catalog.v1alpha1.FailoverPolicy.config:type_name -> hashicorp.consul.catalog.v1alpha1.FailoverConfig - 4, // 1: hashicorp.consul.catalog.v1alpha1.FailoverPolicy.port_configs:type_name -> hashicorp.consul.catalog.v1alpha1.FailoverPolicy.PortConfigsEntry - 3, // 2: hashicorp.consul.catalog.v1alpha1.FailoverConfig.destinations:type_name -> hashicorp.consul.catalog.v1alpha1.FailoverDestination - 0, // 3: hashicorp.consul.catalog.v1alpha1.FailoverConfig.mode:type_name -> hashicorp.consul.catalog.v1alpha1.FailoverMode - 5, // 4: hashicorp.consul.catalog.v1alpha1.FailoverDestination.ref:type_name -> hashicorp.consul.resource.Reference - 2, // 5: hashicorp.consul.catalog.v1alpha1.FailoverPolicy.PortConfigsEntry.value:type_name -> hashicorp.consul.catalog.v1alpha1.FailoverConfig - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name -} - -func init() { file_pbcatalog_v1alpha1_failover_policy_proto_init() } -func file_pbcatalog_v1alpha1_failover_policy_proto_init() { - if File_pbcatalog_v1alpha1_failover_policy_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbcatalog_v1alpha1_failover_policy_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FailoverPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v1alpha1_failover_policy_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FailoverConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v1alpha1_failover_policy_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FailoverDestination); 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_pbcatalog_v1alpha1_failover_policy_proto_rawDesc, - NumEnums: 1, - NumMessages: 4, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbcatalog_v1alpha1_failover_policy_proto_goTypes, - DependencyIndexes: file_pbcatalog_v1alpha1_failover_policy_proto_depIdxs, - EnumInfos: file_pbcatalog_v1alpha1_failover_policy_proto_enumTypes, - MessageInfos: file_pbcatalog_v1alpha1_failover_policy_proto_msgTypes, - }.Build() - File_pbcatalog_v1alpha1_failover_policy_proto = out.File - file_pbcatalog_v1alpha1_failover_policy_proto_rawDesc = nil - file_pbcatalog_v1alpha1_failover_policy_proto_goTypes = nil - file_pbcatalog_v1alpha1_failover_policy_proto_depIdxs = nil -} diff --git a/proto-public/pbcatalog/v1alpha1/failover_policy.proto b/proto-public/pbcatalog/v1alpha1/failover_policy.proto deleted file mode 100644 index 69dcec0d973de..0000000000000 --- a/proto-public/pbcatalog/v1alpha1/failover_policy.proto +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.catalog.v1alpha1; - -import "pbresource/resource.proto"; - -// This is a Resource type. -message FailoverPolicy { - // Config defines failover for any named port not present in PortConfigs. - FailoverConfig config = 1; - - // PortConfigs defines failover for a specific port on this service and takes - // precedence over Config. - map port_configs = 2; -} - -message FailoverConfig { - // Destinations specifies a fixed list of failover destinations to try. We - // never try a destination multiple times, so those are subtracted from this - // list before proceeding. - repeated FailoverDestination destinations = 1; - - // Mode specifies the type of failover that will be performed. Valid values are - // "sequential", "" (equivalent to "sequential") and "order-by-locality". - FailoverMode mode = 2; - repeated string regions = 3; - - // SamenessGroup specifies the sameness group to failover to. - string sameness_group = 4; -} - -message FailoverDestination { - // This must be a Service. - hashicorp.consul.resource.Reference ref = 1; - // TODO: what should an empty port mean? - string port = 2; - string datacenter = 3; -} - -enum FailoverMode { - FAILOVER_MODE_UNSPECIFIED = 0; - FAILOVER_MODE_SEQUENTIAL = 1; - FAILOVER_MODE_ORDER_BY_LOCALITY = 2; -} diff --git a/proto-public/pbcatalog/v1alpha1/failover_policy_extras.go b/proto-public/pbcatalog/v1alpha1/failover_policy_extras.go deleted file mode 100644 index 8c1f2d104caed..0000000000000 --- a/proto-public/pbcatalog/v1alpha1/failover_policy_extras.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package catalogv1alpha1 - -import pbresource "github.com/hashicorp/consul/proto-public/pbresource" - -// GetUnderlyingDestinations will collect FailoverDestinations from all -// internal fields and bundle them up in one slice. -// -// NOTE: no deduplication occurs. -func (x *FailoverPolicy) GetUnderlyingDestinations() []*FailoverDestination { - if x == nil { - return nil - } - - estimate := 0 - if x.Config != nil { - estimate += len(x.Config.Destinations) - } - for _, pc := range x.PortConfigs { - estimate += len(pc.Destinations) - } - - out := make([]*FailoverDestination, 0, estimate) - if x.Config != nil { - out = append(out, x.Config.Destinations...) - } - for _, pc := range x.PortConfigs { - out = append(out, pc.Destinations...) - } - return out -} - -// GetUnderlyingDestinationRefs is like GetUnderlyingDestinations except it -// returns a slice of References. -// -// NOTE: no deduplication occurs. -func (x *FailoverPolicy) GetUnderlyingDestinationRefs() []*pbresource.Reference { - if x == nil { - return nil - } - - dests := x.GetUnderlyingDestinations() - - out := make([]*pbresource.Reference, 0, len(dests)) - for _, dest := range dests { - if dest.Ref != nil { - out = append(out, dest.Ref) - } - } - - return out -} - -// IsEmpty returns true if a config has no definition. -func (x *FailoverConfig) IsEmpty() bool { - if x == nil { - return true - } - return len(x.Destinations) == 0 && - x.Mode == 0 && - len(x.Regions) == 0 && - x.SamenessGroup == "" -} diff --git a/proto-public/pbcatalog/v1alpha1/failover_policy_extras_test.go b/proto-public/pbcatalog/v1alpha1/failover_policy_extras_test.go deleted file mode 100644 index f9fe3e879dcaf..0000000000000 --- a/proto-public/pbcatalog/v1alpha1/failover_policy_extras_test.go +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package catalogv1alpha1 - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/proto" - - pbresource "github.com/hashicorp/consul/proto-public/pbresource" -) - -func TestFailoverPolicy_IsEmpty(t *testing.T) { - t.Run("nil", func(t *testing.T) { - var fc *FailoverConfig - require.True(t, fc.IsEmpty()) - }) - t.Run("empty", func(t *testing.T) { - fc := &FailoverConfig{} - require.True(t, fc.IsEmpty()) - }) - t.Run("dest", func(t *testing.T) { - fc := &FailoverConfig{ - Destinations: []*FailoverDestination{ - newFailoverDestination("foo"), - }, - } - require.False(t, fc.IsEmpty()) - }) - t.Run("regions", func(t *testing.T) { - fc := &FailoverConfig{ - Regions: []string{"us-east"}, - } - require.False(t, fc.IsEmpty()) - }) - t.Run("regions", func(t *testing.T) { - fc := &FailoverConfig{ - SamenessGroup: "blah", - } - require.False(t, fc.IsEmpty()) - }) -} - -func TestFailoverPolicy_GetUnderlyingDestinations_AndRefs(t *testing.T) { - type testcase struct { - failover *FailoverPolicy - expectDests []*FailoverDestination - expectRefs []*pbresource.Reference - } - - run := func(t *testing.T, tc testcase) { - assertSliceEquals(t, tc.expectDests, tc.failover.GetUnderlyingDestinations()) - assertSliceEquals(t, tc.expectRefs, tc.failover.GetUnderlyingDestinationRefs()) - } - - cases := map[string]testcase{ - "nil": {}, - "kitchen sink dests": { - failover: &FailoverPolicy{ - Config: &FailoverConfig{ - Destinations: []*FailoverDestination{ - newFailoverDestination("foo"), - newFailoverDestination("bar"), - }, - }, - PortConfigs: map[string]*FailoverConfig{ - "admin": { - Destinations: []*FailoverDestination{ - newFailoverDestination("admin"), - }, - }, - "web": { - Destinations: []*FailoverDestination{ - newFailoverDestination("foo"), // duplicated - newFailoverDestination("www"), - }, - }, - }, - }, - expectDests: []*FailoverDestination{ - newFailoverDestination("foo"), - newFailoverDestination("bar"), - newFailoverDestination("admin"), - newFailoverDestination("foo"), // duplicated - newFailoverDestination("www"), - }, - expectRefs: []*pbresource.Reference{ - newFailoverRef("foo"), - newFailoverRef("bar"), - newFailoverRef("admin"), - newFailoverRef("foo"), // duplicated - newFailoverRef("www"), - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func assertSliceEquals[V proto.Message](t *testing.T, expect, got []V) { - t.Helper() - - require.Len(t, got, len(expect)) - - // O(N*M) scan - var expectedMissing []string - for _, expectVal := range expect { - found := false - for j, gotVal := range got { - if proto.Equal(expectVal, gotVal) { - found = true - got = append(got[:j], got[j+1:]...) // remove found item - break - } - } - - if !found { - expectedMissing = append(expectedMissing, protoToString(t, expectVal)) - } - } - - if len(expectedMissing) > 0 || len(got) > 0 { - var gotMissing []string - for _, gotVal := range got { - gotMissing = append(gotMissing, protoToString(t, gotVal)) - } - - t.Fatalf("assertion failed: unmatched values\n\texpected: %s\n\tactual: %s", - expectedMissing, - gotMissing, - ) - } -} - -func protoToString[V proto.Message](t *testing.T, pb V) string { - m := protojson.MarshalOptions{ - Indent: " ", - } - gotJSON, err := m.Marshal(pb) - require.NoError(t, err) - return string(gotJSON) -} - -func newFailoverRef(name string) *pbresource.Reference { - return &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "fake", - GroupVersion: "v1alpha1", - Kind: "fake", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: name, - } -} - -func newFailoverDestination(name string) *FailoverDestination { - return &FailoverDestination{ - Ref: newFailoverRef(name), - } -} diff --git a/proto-public/pbcatalog/v1alpha1/protocol.pb.go b/proto-public/pbcatalog/v1alpha1/protocol.pb.go index 6e2ba0efb0002..71e89aab4aa5a 100644 --- a/proto-public/pbcatalog/v1alpha1/protocol.pb.go +++ b/proto-public/pbcatalog/v1alpha1/protocol.pb.go @@ -26,32 +26,30 @@ const ( type Protocol int32 const ( - Protocol_PROTOCOL_UNSPECIFIED Protocol = 0 - Protocol_PROTOCOL_TCP Protocol = 1 - Protocol_PROTOCOL_HTTP Protocol = 2 - Protocol_PROTOCOL_HTTP2 Protocol = 3 - Protocol_PROTOCOL_GRPC Protocol = 4 + // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX + Protocol_PROTOCOL_TCP Protocol = 0 + Protocol_PROTOCOL_HTTP Protocol = 1 + Protocol_PROTOCOL_HTTP2 Protocol = 2 + Protocol_PROTOCOL_GRPC Protocol = 3 // Protocol Mesh indicates that this port can speak Consul's mTLS based mesh protocol. - Protocol_PROTOCOL_MESH Protocol = 5 + Protocol_PROTOCOL_MESH Protocol = 4 ) // Enum value maps for Protocol. var ( Protocol_name = map[int32]string{ - 0: "PROTOCOL_UNSPECIFIED", - 1: "PROTOCOL_TCP", - 2: "PROTOCOL_HTTP", - 3: "PROTOCOL_HTTP2", - 4: "PROTOCOL_GRPC", - 5: "PROTOCOL_MESH", + 0: "PROTOCOL_TCP", + 1: "PROTOCOL_HTTP", + 2: "PROTOCOL_HTTP2", + 3: "PROTOCOL_GRPC", + 4: "PROTOCOL_MESH", } Protocol_value = map[string]int32{ - "PROTOCOL_UNSPECIFIED": 0, - "PROTOCOL_TCP": 1, - "PROTOCOL_HTTP": 2, - "PROTOCOL_HTTP2": 3, - "PROTOCOL_GRPC": 4, - "PROTOCOL_MESH": 5, + "PROTOCOL_TCP": 0, + "PROTOCOL_HTTP": 1, + "PROTOCOL_HTTP2": 2, + "PROTOCOL_GRPC": 3, + "PROTOCOL_MESH": 4, } ) @@ -89,35 +87,33 @@ var file_pbcatalog_v1alpha1_protocol_proto_rawDesc = []byte{ 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 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, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2a, 0x83, 0x01, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, - 0x0c, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x01, 0x12, - 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, 0x50, - 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, - 0x54, 0x54, 0x50, 0x32, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, - 0x4f, 0x4c, 0x5f, 0x47, 0x52, 0x50, 0x43, 0x10, 0x04, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, - 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x4d, 0x45, 0x53, 0x48, 0x10, 0x05, 0x42, 0xaa, 0x02, 0x0a, - 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 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, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x43, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x43, 0x61, - 0x74, 0x61, 0x6c, 0x6f, 0x67, 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, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 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, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 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, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x3a, - 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2a, 0x69, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x54, + 0x43, 0x50, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, + 0x5f, 0x48, 0x54, 0x54, 0x50, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x54, 0x4f, + 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x32, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x50, + 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x47, 0x52, 0x50, 0x43, 0x10, 0x03, 0x12, 0x11, + 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x4d, 0x45, 0x53, 0x48, 0x10, + 0x04, 0x42, 0xaa, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0d, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 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, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, + 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, + 0x67, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x43, 0xaa, + 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 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, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 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, 0x43, 0x61, 0x74, 0x61, 0x6c, + 0x6f, 0x67, 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, 0x43, 0x61, 0x74, + 0x61, 0x6c, 0x6f, 0x67, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto-public/pbcatalog/v1alpha1/protocol.proto b/proto-public/pbcatalog/v1alpha1/protocol.proto index 909271b9a6cc2..a18351c5d6d8f 100644 --- a/proto-public/pbcatalog/v1alpha1/protocol.proto +++ b/proto-public/pbcatalog/v1alpha1/protocol.proto @@ -6,12 +6,12 @@ syntax = "proto3"; package hashicorp.consul.catalog.v1alpha1; enum Protocol { - PROTOCOL_UNSPECIFIED = 0; - PROTOCOL_TCP = 1; - PROTOCOL_HTTP = 2; - PROTOCOL_HTTP2 = 3; - PROTOCOL_GRPC = 4; + // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX + PROTOCOL_TCP = 0; + PROTOCOL_HTTP = 1; + PROTOCOL_HTTP2 = 2; + PROTOCOL_GRPC = 3; // Protocol Mesh indicates that this port can speak Consul's mTLS based mesh protocol. - PROTOCOL_MESH = 5; + PROTOCOL_MESH = 4; } diff --git a/proto-public/pbcatalog/v1alpha1/selector.pb.go b/proto-public/pbcatalog/v1alpha1/selector.pb.go index 8caf0f51d6c89..a6f5a3ef880d3 100644 --- a/proto-public/pbcatalog/v1alpha1/selector.pb.go +++ b/proto-public/pbcatalog/v1alpha1/selector.pb.go @@ -31,7 +31,6 @@ type WorkloadSelector struct { Prefixes []string `protobuf:"bytes,1,rep,name=prefixes,proto3" json:"prefixes,omitempty"` Names []string `protobuf:"bytes,2,rep,name=names,proto3" json:"names,omitempty"` - Filter string `protobuf:"bytes,3,opt,name=filter,proto3" json:"filter,omitempty"` } func (x *WorkloadSelector) Reset() { @@ -80,13 +79,6 @@ func (x *WorkloadSelector) GetNames() []string { return nil } -func (x *WorkloadSelector) GetFilter() string { - if x != nil { - return x.Filter - } - return "" -} - var File_pbcatalog_v1alpha1_selector_proto protoreflect.FileDescriptor var file_pbcatalog_v1alpha1_selector_proto_rawDesc = []byte{ @@ -94,32 +86,31 @@ var file_pbcatalog_v1alpha1_selector_proto_rawDesc = []byte{ 0x70, 0x68, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 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, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x22, 0x5c, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x22, 0x44, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, - 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x42, 0xaa, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, - 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0d, - 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 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, 0x63, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, - 0x43, 0x43, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 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, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, - 0x67, 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, 0x43, 0x61, - 0x74, 0x61, 0x6c, 0x6f, 0x67, 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, - 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x42, 0xaa, 0x02, 0x0a, + 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0d, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, + 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, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x43, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x43, 0x61, + 0x74, 0x61, 0x6c, 0x6f, 0x67, 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, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 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, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 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, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x3a, + 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( diff --git a/proto-public/pbcatalog/v1alpha1/selector.proto b/proto-public/pbcatalog/v1alpha1/selector.proto index 1b5aa366e07fc..b1b39409ba3a6 100644 --- a/proto-public/pbcatalog/v1alpha1/selector.proto +++ b/proto-public/pbcatalog/v1alpha1/selector.proto @@ -9,5 +9,4 @@ package hashicorp.consul.catalog.v1alpha1; message WorkloadSelector { repeated string prefixes = 1; repeated string names = 2; - string filter = 3; } diff --git a/proto-public/pbcatalog/v1alpha1/service.pb.go b/proto-public/pbcatalog/v1alpha1/service.pb.go index ac4afa2c9efa9..cd72ccf268ff8 100644 --- a/proto-public/pbcatalog/v1alpha1/service.pb.go +++ b/proto-public/pbcatalog/v1alpha1/service.pb.go @@ -158,7 +158,7 @@ func (x *ServicePort) GetProtocol() Protocol { if x != nil { return x.Protocol } - return Protocol_PROTOCOL_UNSPECIFIED + return Protocol_PROTOCOL_TCP } var File_pbcatalog_v1alpha1_service_proto protoreflect.FileDescriptor diff --git a/proto-public/pbcatalog/v1alpha1/workload.pb.go b/proto-public/pbcatalog/v1alpha1/workload.pb.go index e6fa7936d0b3d..e1f75d810cb81 100644 --- a/proto-public/pbcatalog/v1alpha1/workload.pb.go +++ b/proto-public/pbcatalog/v1alpha1/workload.pb.go @@ -269,7 +269,7 @@ func (x *WorkloadPort) GetProtocol() Protocol { if x != nil { return x.Protocol } - return Protocol_PROTOCOL_UNSPECIFIED + return Protocol_PROTOCOL_TCP } type Locality struct { diff --git a/proto-public/pbmesh/v1alpha1/common.pb.binary.go b/proto-public/pbmesh/v1alpha1/common.pb.binary.go deleted file mode 100644 index a02a97e494a17..0000000000000 --- a/proto-public/pbmesh/v1alpha1/common.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/common.proto - -package meshv1alpha1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ParentReference) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ParentReference) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *BackendReference) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *BackendReference) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/common.pb.go b/proto-public/pbmesh/v1alpha1/common.pb.go deleted file mode 100644 index 4262d3872c3db..0000000000000 --- a/proto-public/pbmesh/v1alpha1/common.pb.go +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/common.proto - -package meshv1alpha1 - -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) -) - -// NOTE: roughly equivalent to structs.ResourceReference -type ParentReference struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // For east/west configuration, this should point to a pbcatalog.Service. - // For north/south it should point to a gateway (TBD) - Ref *pbresource.Reference `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` - // Port is the network port this Route targets. It can be interpreted - // differently based on the type of parent resource. - // - // When the parent resource is a Gateway, this targets all listeners - // listening on the specified port that also support this kind of Route(and - // select this Route). It’s not recommended to set Port unless the networking - // behaviors specified in a Route must apply to a specific port as opposed to - // a listener(s) whose port(s) may be changed. When both Port and SectionName - // are specified, the name and port of the selected listener must match both - // specified values. - // - // Implementations MAY choose to support other parent resources. - // Implementations supporting other types of parent resources MUST clearly - // document how/if Port is interpreted. - // - // For the purpose of status, an attachment is considered successful as long - // as the parent resource accepts it partially. For example, Gateway - // listeners can restrict which Routes can attach to them by Route kind, - // namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from - // the referencing Route, the Route MUST be considered successfully attached. - // If no Gateway listeners accept attachment from this Route, the Route MUST - // be considered detached from the Gateway. - // - // For east/west this is the name of the consul port. - // For north/south this is the stringified integer port expected by GAMMA. - // - // https://gateway-api.sigs.k8s.io/geps/gep-957/ - Port string `protobuf:"bytes,2,opt,name=port,proto3" json:"port,omitempty"` -} - -func (x *ParentReference) Reset() { - *x = ParentReference{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_common_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ParentReference) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ParentReference) ProtoMessage() {} - -func (x *ParentReference) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_common_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 ParentReference.ProtoReflect.Descriptor instead. -func (*ParentReference) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_common_proto_rawDescGZIP(), []int{0} -} - -func (x *ParentReference) GetRef() *pbresource.Reference { - if x != nil { - return x.Ref - } - return nil -} - -func (x *ParentReference) GetPort() string { - if x != nil { - return x.Port - } - return "" -} - -type BackendReference struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // For east/west configuration, this should point to either a - // pbcatalog.Service or ServiceSubset. - // - // For Partition/PeerName fields likely we could map them to ServiceImports - // (MCS+GAMMA) when translating - Ref *pbresource.Reference `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` - // For east/west this is the name of the consul port. - Port string `protobuf:"bytes,2,opt,name=port,proto3" json:"port,omitempty"` - // NOT IN GAMMA; multi-cluster + GWapi is still unknown - // - // Likely we could map this to ServiceImports (MCS+GAMMA) when translating - // to/from k8s. - // - // https://gateway-api.sigs.k8s.io/geps/gep-1748/ - Datacenter string `protobuf:"bytes,3,opt,name=datacenter,proto3" json:"datacenter,omitempty"` -} - -func (x *BackendReference) Reset() { - *x = BackendReference{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_common_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BackendReference) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BackendReference) ProtoMessage() {} - -func (x *BackendReference) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_common_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 BackendReference.ProtoReflect.Descriptor instead. -func (*BackendReference) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_common_proto_rawDescGZIP(), []int{1} -} - -func (x *BackendReference) GetRef() *pbresource.Reference { - if x != nil { - return x.Ref - } - return nil -} - -func (x *BackendReference) GetPort() string { - if x != nil { - return x.Port - } - return "" -} - -func (x *BackendReference) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - -var File_pbmesh_v1alpha1_common_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_common_proto_rawDesc = []byte{ - 0x0a, 0x1c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 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, 0x5d, 0x0a, 0x0f, 0x50, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x03, - 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, - 0x03, 0x72, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x7e, 0x0a, 0x10, 0x42, 0x61, 0x63, 0x6b, - 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x03, - 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, - 0x03, 0x72, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, - 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, - 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x42, 0x93, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, - 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, - 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, 0x65, 0x73, 0x68, 0x2f, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1e, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, - 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, - 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_common_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_common_proto_rawDescData = file_pbmesh_v1alpha1_common_proto_rawDesc -) - -func file_pbmesh_v1alpha1_common_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_common_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_common_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_common_proto_rawDescData -} - -var file_pbmesh_v1alpha1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbmesh_v1alpha1_common_proto_goTypes = []interface{}{ - (*ParentReference)(nil), // 0: hashicorp.consul.mesh.v1alpha1.ParentReference - (*BackendReference)(nil), // 1: hashicorp.consul.mesh.v1alpha1.BackendReference - (*pbresource.Reference)(nil), // 2: hashicorp.consul.resource.Reference -} -var file_pbmesh_v1alpha1_common_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.mesh.v1alpha1.ParentReference.ref:type_name -> hashicorp.consul.resource.Reference - 2, // 1: hashicorp.consul.mesh.v1alpha1.BackendReference.ref:type_name -> hashicorp.consul.resource.Reference - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_common_proto_init() } -func file_pbmesh_v1alpha1_common_proto_init() { - if File_pbmesh_v1alpha1_common_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_common_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ParentReference); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_common_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BackendReference); 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_pbmesh_v1alpha1_common_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_common_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_common_proto_depIdxs, - MessageInfos: file_pbmesh_v1alpha1_common_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_common_proto = out.File - file_pbmesh_v1alpha1_common_proto_rawDesc = nil - file_pbmesh_v1alpha1_common_proto_goTypes = nil - file_pbmesh_v1alpha1_common_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/common.proto b/proto-public/pbmesh/v1alpha1/common.proto deleted file mode 100644 index 48668e59dd5a7..0000000000000 --- a/proto-public/pbmesh/v1alpha1/common.proto +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1; - -import "pbresource/resource.proto"; - -// NOTE: roughly equivalent to structs.ResourceReference -message ParentReference { - // For east/west configuration, this should point to a pbcatalog.Service. - // For north/south it should point to a gateway (TBD) - hashicorp.consul.resource.Reference ref = 1; - - // Port is the network port this Route targets. It can be interpreted - // differently based on the type of parent resource. - // - // When the parent resource is a Gateway, this targets all listeners - // listening on the specified port that also support this kind of Route(and - // select this Route). It’s not recommended to set Port unless the networking - // behaviors specified in a Route must apply to a specific port as opposed to - // a listener(s) whose port(s) may be changed. When both Port and SectionName - // are specified, the name and port of the selected listener must match both - // specified values. - // - // Implementations MAY choose to support other parent resources. - // Implementations supporting other types of parent resources MUST clearly - // document how/if Port is interpreted. - // - // For the purpose of status, an attachment is considered successful as long - // as the parent resource accepts it partially. For example, Gateway - // listeners can restrict which Routes can attach to them by Route kind, - // namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from - // the referencing Route, the Route MUST be considered successfully attached. - // If no Gateway listeners accept attachment from this Route, the Route MUST - // be considered detached from the Gateway. - // - // For east/west this is the name of the consul port. - // For north/south this is the stringified integer port expected by GAMMA. - // - // https://gateway-api.sigs.k8s.io/geps/gep-957/ - string port = 2; -} - -message BackendReference { - // For east/west configuration, this should point to either a - // pbcatalog.Service or ServiceSubset. - // - // For Partition/PeerName fields likely we could map them to ServiceImports - // (MCS+GAMMA) when translating - hashicorp.consul.resource.Reference ref = 1; - - // For east/west this is the name of the consul port. - string port = 2; - - // NOT IN GAMMA; multi-cluster + GWapi is still unknown - // - // Likely we could map this to ServiceImports (MCS+GAMMA) when translating - // to/from k8s. - // - // https://gateway-api.sigs.k8s.io/geps/gep-1748/ - string datacenter = 3; -} diff --git a/proto-public/pbmesh/v1alpha1/computed_routes.pb.binary.go b/proto-public/pbmesh/v1alpha1/computed_routes.pb.binary.go deleted file mode 100644 index cd30ceac27071..0000000000000 --- a/proto-public/pbmesh/v1alpha1/computed_routes.pb.binary.go +++ /dev/null @@ -1,128 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/computed_routes.proto - -package meshv1alpha1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedRoutes) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedRoutes) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedPortRoutes) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedPortRoutes) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InterpretedHTTPRoute) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InterpretedHTTPRoute) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InterpretedHTTPRouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InterpretedHTTPRouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InterpretedHTTPBackendRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InterpretedHTTPBackendRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InterpretedGRPCRoute) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InterpretedGRPCRoute) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InterpretedGRPCRouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InterpretedGRPCRouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InterpretedGRPCBackendRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InterpretedGRPCBackendRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InterpretedTCPRoute) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InterpretedTCPRoute) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InterpretedTCPRouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InterpretedTCPRouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InterpretedTCPBackendRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InterpretedTCPBackendRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *BackendTargetDetails) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *BackendTargetDetails) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/computed_routes.pb.go b/proto-public/pbmesh/v1alpha1/computed_routes.pb.go deleted file mode 100644 index 605e4fbd679e1..0000000000000 --- a/proto-public/pbmesh/v1alpha1/computed_routes.pb.go +++ /dev/null @@ -1,1321 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/computed_routes.proto - -package meshv1alpha1 - -import ( - v1alpha1 "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - 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) -) - -// This is a Resource type. -type ComputedRoutes struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PortedConfigs map[string]*ComputedPortRoutes `protobuf:"bytes,1,rep,name=ported_configs,json=portedConfigs,proto3" json:"ported_configs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *ComputedRoutes) Reset() { - *x = ComputedRoutes{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedRoutes) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedRoutes) ProtoMessage() {} - -func (x *ComputedRoutes) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_computed_routes_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 ComputedRoutes.ProtoReflect.Descriptor instead. -func (*ComputedRoutes) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{0} -} - -func (x *ComputedRoutes) GetPortedConfigs() map[string]*ComputedPortRoutes { - if x != nil { - return x.PortedConfigs - } - return nil -} - -type ComputedPortRoutes struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Config: - // - // *ComputedPortRoutes_Http - // *ComputedPortRoutes_Grpc - // *ComputedPortRoutes_Tcp - Config isComputedPortRoutes_Config `protobuf_oneof:"config"` - UsingDefaultConfig bool `protobuf:"varint,4,opt,name=using_default_config,json=usingDefaultConfig,proto3" json:"using_default_config,omitempty"` // TODO - // map key is an opaque string; like disco chain target name - Targets map[string]*BackendTargetDetails `protobuf:"bytes,5,rep,name=targets,proto3" json:"targets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *ComputedPortRoutes) Reset() { - *x = ComputedPortRoutes{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedPortRoutes) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedPortRoutes) ProtoMessage() {} - -func (x *ComputedPortRoutes) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_computed_routes_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 ComputedPortRoutes.ProtoReflect.Descriptor instead. -func (*ComputedPortRoutes) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{1} -} - -func (m *ComputedPortRoutes) GetConfig() isComputedPortRoutes_Config { - if m != nil { - return m.Config - } - return nil -} - -func (x *ComputedPortRoutes) GetHttp() *InterpretedHTTPRoute { - if x, ok := x.GetConfig().(*ComputedPortRoutes_Http); ok { - return x.Http - } - return nil -} - -func (x *ComputedPortRoutes) GetGrpc() *InterpretedGRPCRoute { - if x, ok := x.GetConfig().(*ComputedPortRoutes_Grpc); ok { - return x.Grpc - } - return nil -} - -func (x *ComputedPortRoutes) GetTcp() *InterpretedTCPRoute { - if x, ok := x.GetConfig().(*ComputedPortRoutes_Tcp); ok { - return x.Tcp - } - return nil -} - -func (x *ComputedPortRoutes) GetUsingDefaultConfig() bool { - if x != nil { - return x.UsingDefaultConfig - } - return false -} - -func (x *ComputedPortRoutes) GetTargets() map[string]*BackendTargetDetails { - if x != nil { - return x.Targets - } - return nil -} - -type isComputedPortRoutes_Config interface { - isComputedPortRoutes_Config() -} - -type ComputedPortRoutes_Http struct { - Http *InterpretedHTTPRoute `protobuf:"bytes,1,opt,name=http,proto3,oneof"` -} - -type ComputedPortRoutes_Grpc struct { - Grpc *InterpretedGRPCRoute `protobuf:"bytes,2,opt,name=grpc,proto3,oneof"` -} - -type ComputedPortRoutes_Tcp struct { - Tcp *InterpretedTCPRoute `protobuf:"bytes,3,opt,name=tcp,proto3,oneof"` -} - -func (*ComputedPortRoutes_Http) isComputedPortRoutes_Config() {} - -func (*ComputedPortRoutes_Grpc) isComputedPortRoutes_Config() {} - -func (*ComputedPortRoutes_Tcp) isComputedPortRoutes_Config() {} - -type InterpretedHTTPRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ParentRef *ParentReference `protobuf:"bytes,1,opt,name=parent_ref,json=parentRef,proto3" json:"parent_ref,omitempty"` - Rules []*InterpretedHTTPRouteRule `protobuf:"bytes,3,rep,name=rules,proto3" json:"rules,omitempty"` -} - -func (x *InterpretedHTTPRoute) Reset() { - *x = InterpretedHTTPRoute{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InterpretedHTTPRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InterpretedHTTPRoute) ProtoMessage() {} - -func (x *InterpretedHTTPRoute) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_computed_routes_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 InterpretedHTTPRoute.ProtoReflect.Descriptor instead. -func (*InterpretedHTTPRoute) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{2} -} - -func (x *InterpretedHTTPRoute) GetParentRef() *ParentReference { - if x != nil { - return x.ParentRef - } - return nil -} - -func (x *InterpretedHTTPRoute) GetRules() []*InterpretedHTTPRouteRule { - if x != nil { - return x.Rules - } - return nil -} - -type InterpretedHTTPRouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Matches []*HTTPRouteMatch `protobuf:"bytes,1,rep,name=matches,proto3" json:"matches,omitempty"` - Filters []*HTTPRouteFilter `protobuf:"bytes,2,rep,name=filters,proto3" json:"filters,omitempty"` - BackendRefs []*InterpretedHTTPBackendRef `protobuf:"bytes,3,rep,name=backend_refs,json=backendRefs,proto3" json:"backend_refs,omitempty"` - Timeouts *HTTPRouteTimeouts `protobuf:"bytes,4,opt,name=timeouts,proto3" json:"timeouts,omitempty"` - Retries *HTTPRouteRetries `protobuf:"bytes,5,opt,name=retries,proto3" json:"retries,omitempty"` -} - -func (x *InterpretedHTTPRouteRule) Reset() { - *x = InterpretedHTTPRouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InterpretedHTTPRouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InterpretedHTTPRouteRule) ProtoMessage() {} - -func (x *InterpretedHTTPRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[3] - 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 InterpretedHTTPRouteRule.ProtoReflect.Descriptor instead. -func (*InterpretedHTTPRouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{3} -} - -func (x *InterpretedHTTPRouteRule) GetMatches() []*HTTPRouteMatch { - if x != nil { - return x.Matches - } - return nil -} - -func (x *InterpretedHTTPRouteRule) GetFilters() []*HTTPRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -func (x *InterpretedHTTPRouteRule) GetBackendRefs() []*InterpretedHTTPBackendRef { - if x != nil { - return x.BackendRefs - } - return nil -} - -func (x *InterpretedHTTPRouteRule) GetTimeouts() *HTTPRouteTimeouts { - if x != nil { - return x.Timeouts - } - return nil -} - -func (x *InterpretedHTTPRouteRule) GetRetries() *HTTPRouteRetries { - if x != nil { - return x.Retries - } - return nil -} - -type InterpretedHTTPBackendRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BackendTarget string `protobuf:"bytes,1,opt,name=backend_target,json=backendTarget,proto3" json:"backend_target,omitempty"` - Weight uint32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` - Filters []*HTTPRouteFilter `protobuf:"bytes,3,rep,name=filters,proto3" json:"filters,omitempty"` -} - -func (x *InterpretedHTTPBackendRef) Reset() { - *x = InterpretedHTTPBackendRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InterpretedHTTPBackendRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InterpretedHTTPBackendRef) ProtoMessage() {} - -func (x *InterpretedHTTPBackendRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[4] - 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 InterpretedHTTPBackendRef.ProtoReflect.Descriptor instead. -func (*InterpretedHTTPBackendRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{4} -} - -func (x *InterpretedHTTPBackendRef) GetBackendTarget() string { - if x != nil { - return x.BackendTarget - } - return "" -} - -func (x *InterpretedHTTPBackendRef) GetWeight() uint32 { - if x != nil { - return x.Weight - } - return 0 -} - -func (x *InterpretedHTTPBackendRef) GetFilters() []*HTTPRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -type InterpretedGRPCRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ParentRef *ParentReference `protobuf:"bytes,1,opt,name=parent_ref,json=parentRef,proto3" json:"parent_ref,omitempty"` - Rules []*InterpretedGRPCRouteRule `protobuf:"bytes,3,rep,name=rules,proto3" json:"rules,omitempty"` -} - -func (x *InterpretedGRPCRoute) Reset() { - *x = InterpretedGRPCRoute{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InterpretedGRPCRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InterpretedGRPCRoute) ProtoMessage() {} - -func (x *InterpretedGRPCRoute) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[5] - 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 InterpretedGRPCRoute.ProtoReflect.Descriptor instead. -func (*InterpretedGRPCRoute) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{5} -} - -func (x *InterpretedGRPCRoute) GetParentRef() *ParentReference { - if x != nil { - return x.ParentRef - } - return nil -} - -func (x *InterpretedGRPCRoute) GetRules() []*InterpretedGRPCRouteRule { - if x != nil { - return x.Rules - } - return nil -} - -type InterpretedGRPCRouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Matches []*GRPCRouteMatch `protobuf:"bytes,1,rep,name=matches,proto3" json:"matches,omitempty"` - Filters []*GRPCRouteFilter `protobuf:"bytes,2,rep,name=filters,proto3" json:"filters,omitempty"` - BackendRefs []*InterpretedGRPCBackendRef `protobuf:"bytes,3,rep,name=backend_refs,json=backendRefs,proto3" json:"backend_refs,omitempty"` - Timeouts *HTTPRouteTimeouts `protobuf:"bytes,4,opt,name=timeouts,proto3" json:"timeouts,omitempty"` - Retries *HTTPRouteRetries `protobuf:"bytes,5,opt,name=retries,proto3" json:"retries,omitempty"` -} - -func (x *InterpretedGRPCRouteRule) Reset() { - *x = InterpretedGRPCRouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InterpretedGRPCRouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InterpretedGRPCRouteRule) ProtoMessage() {} - -func (x *InterpretedGRPCRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[6] - 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 InterpretedGRPCRouteRule.ProtoReflect.Descriptor instead. -func (*InterpretedGRPCRouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{6} -} - -func (x *InterpretedGRPCRouteRule) GetMatches() []*GRPCRouteMatch { - if x != nil { - return x.Matches - } - return nil -} - -func (x *InterpretedGRPCRouteRule) GetFilters() []*GRPCRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -func (x *InterpretedGRPCRouteRule) GetBackendRefs() []*InterpretedGRPCBackendRef { - if x != nil { - return x.BackendRefs - } - return nil -} - -func (x *InterpretedGRPCRouteRule) GetTimeouts() *HTTPRouteTimeouts { - if x != nil { - return x.Timeouts - } - return nil -} - -func (x *InterpretedGRPCRouteRule) GetRetries() *HTTPRouteRetries { - if x != nil { - return x.Retries - } - return nil -} - -type InterpretedGRPCBackendRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BackendTarget string `protobuf:"bytes,1,opt,name=backend_target,json=backendTarget,proto3" json:"backend_target,omitempty"` - Weight uint32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` - Filters []*GRPCRouteFilter `protobuf:"bytes,3,rep,name=filters,proto3" json:"filters,omitempty"` -} - -func (x *InterpretedGRPCBackendRef) Reset() { - *x = InterpretedGRPCBackendRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InterpretedGRPCBackendRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InterpretedGRPCBackendRef) ProtoMessage() {} - -func (x *InterpretedGRPCBackendRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[7] - 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 InterpretedGRPCBackendRef.ProtoReflect.Descriptor instead. -func (*InterpretedGRPCBackendRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{7} -} - -func (x *InterpretedGRPCBackendRef) GetBackendTarget() string { - if x != nil { - return x.BackendTarget - } - return "" -} - -func (x *InterpretedGRPCBackendRef) GetWeight() uint32 { - if x != nil { - return x.Weight - } - return 0 -} - -func (x *InterpretedGRPCBackendRef) GetFilters() []*GRPCRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -type InterpretedTCPRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ParentRef *ParentReference `protobuf:"bytes,1,opt,name=parent_ref,json=parentRef,proto3" json:"parent_ref,omitempty"` - Rules []*InterpretedTCPRouteRule `protobuf:"bytes,2,rep,name=rules,proto3" json:"rules,omitempty"` -} - -func (x *InterpretedTCPRoute) Reset() { - *x = InterpretedTCPRoute{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InterpretedTCPRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InterpretedTCPRoute) ProtoMessage() {} - -func (x *InterpretedTCPRoute) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[8] - 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 InterpretedTCPRoute.ProtoReflect.Descriptor instead. -func (*InterpretedTCPRoute) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{8} -} - -func (x *InterpretedTCPRoute) GetParentRef() *ParentReference { - if x != nil { - return x.ParentRef - } - return nil -} - -func (x *InterpretedTCPRoute) GetRules() []*InterpretedTCPRouteRule { - if x != nil { - return x.Rules - } - return nil -} - -type InterpretedTCPRouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BackendRefs []*InterpretedTCPBackendRef `protobuf:"bytes,1,rep,name=backend_refs,json=backendRefs,proto3" json:"backend_refs,omitempty"` -} - -func (x *InterpretedTCPRouteRule) Reset() { - *x = InterpretedTCPRouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InterpretedTCPRouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InterpretedTCPRouteRule) ProtoMessage() {} - -func (x *InterpretedTCPRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[9] - 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 InterpretedTCPRouteRule.ProtoReflect.Descriptor instead. -func (*InterpretedTCPRouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{9} -} - -func (x *InterpretedTCPRouteRule) GetBackendRefs() []*InterpretedTCPBackendRef { - if x != nil { - return x.BackendRefs - } - return nil -} - -// TODO: look into smuggling the target through a different typeURL, or just -// skip in favor of letting the caller do their own lookups? -type InterpretedTCPBackendRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BackendTarget string `protobuf:"bytes,1,opt,name=backend_target,json=backendTarget,proto3" json:"backend_target,omitempty"` - Weight uint32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` -} - -func (x *InterpretedTCPBackendRef) Reset() { - *x = InterpretedTCPBackendRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InterpretedTCPBackendRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InterpretedTCPBackendRef) ProtoMessage() {} - -func (x *InterpretedTCPBackendRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[10] - 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 InterpretedTCPBackendRef.ProtoReflect.Descriptor instead. -func (*InterpretedTCPBackendRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{10} -} - -func (x *InterpretedTCPBackendRef) GetBackendTarget() string { - if x != nil { - return x.BackendTarget - } - return "" -} - -func (x *InterpretedTCPBackendRef) GetWeight() uint32 { - if x != nil { - return x.Weight - } - return 0 -} - -type BackendTargetDetails struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // identity info - BackendRef *BackendReference `protobuf:"bytes,1,opt,name=backend_ref,json=backendRef,proto3" json:"backend_ref,omitempty"` - NullRouteTraffic bool `protobuf:"varint,2,opt,name=null_route_traffic,json=nullRouteTraffic,proto3" json:"null_route_traffic,omitempty"` - Service *v1alpha1.Service `protobuf:"bytes,3,opt,name=service,proto3" json:"service,omitempty"` - FailoverPolicy *v1alpha1.FailoverPolicy `protobuf:"bytes,4,opt,name=failover_policy,json=failoverPolicy,proto3" json:"failover_policy,omitempty"` - DestinationPolicy *DestinationPolicy `protobuf:"bytes,5,opt,name=destination_policy,json=destinationPolicy,proto3" json:"destination_policy,omitempty"` -} - -func (x *BackendTargetDetails) Reset() { - *x = BackendTargetDetails{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BackendTargetDetails) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BackendTargetDetails) ProtoMessage() {} - -func (x *BackendTargetDetails) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[11] - 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 BackendTargetDetails.ProtoReflect.Descriptor instead. -func (*BackendTargetDetails) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP(), []int{11} -} - -func (x *BackendTargetDetails) GetBackendRef() *BackendReference { - if x != nil { - return x.BackendRef - } - return nil -} - -func (x *BackendTargetDetails) GetNullRouteTraffic() bool { - if x != nil { - return x.NullRouteTraffic - } - return false -} - -func (x *BackendTargetDetails) GetService() *v1alpha1.Service { - if x != nil { - return x.Service - } - return nil -} - -func (x *BackendTargetDetails) GetFailoverPolicy() *v1alpha1.FailoverPolicy { - if x != nil { - return x.FailoverPolicy - } - return nil -} - -func (x *BackendTargetDetails) GetDestinationPolicy() *DestinationPolicy { - if x != nil { - return x.DestinationPolicy - } - return nil -} - -var File_pbmesh_v1alpha1_computed_routes_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_computed_routes_proto_rawDesc = []byte{ - 0x0a, 0x25, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x28, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x66, 0x61, 0x69, 0x6c, - 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x70, 0x62, 0x6d, - 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x67, 0x72, 0x70, - 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x70, - 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x68, - 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x70, 0x62, 0x6d, 0x65, 0x73, - 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, - 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf0, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, - 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x68, 0x0a, 0x0e, 0x70, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2e, - 0x50, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x0d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x73, 0x1a, 0x74, 0x0a, 0x12, 0x50, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x48, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, - 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xfe, 0x03, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x70, - 0x75, 0x74, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x4a, - 0x0a, 0x04, 0x68, 0x74, 0x74, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x48, 0x00, 0x52, 0x04, 0x68, 0x74, 0x74, 0x70, 0x12, 0x4a, 0x0a, 0x04, 0x67, 0x72, - 0x70, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x65, 0x74, 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x48, 0x00, - 0x52, 0x04, 0x67, 0x72, 0x70, 0x63, 0x12, 0x47, 0x0a, 0x03, 0x74, 0x63, 0x70, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, - 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x48, 0x00, 0x52, 0x03, 0x74, 0x63, 0x70, 0x12, - 0x30, 0x0a, 0x14, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x75, - 0x73, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x59, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x05, 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, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x1a, 0x70, 0x0a, 0x0c, - 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4a, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, - 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x08, - 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xbc, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x12, 0x4e, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, - 0x66, 0x12, 0x4e, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, - 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, - 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xa8, 0x03, 0x0a, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x52, 0x75, 0x6c, 0x65, 0x12, 0x48, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x49, - 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x5c, 0x0a, 0x0c, 0x62, 0x61, 0x63, - 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, - 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x52, 0x0b, 0x62, 0x61, 0x63, 0x6b, - 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x73, 0x12, 0x4d, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x52, 0x08, 0x74, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, - 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x22, 0xa5, 0x01, 0x0a, 0x19, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, - 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, - 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, - 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, - 0x49, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0xbc, 0x01, 0x0a, 0x14, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x12, 0x4e, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, - 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x52, 0x65, 0x66, 0x12, 0x4e, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x47, - 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, - 0x6c, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xa8, 0x03, 0x0a, 0x18, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x48, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, - 0x12, 0x49, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x5c, 0x0a, 0x0c, 0x62, - 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x47, 0x52, - 0x50, 0x43, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x52, 0x0b, 0x62, 0x61, - 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x73, 0x12, 0x4d, 0x0a, 0x08, 0x74, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, - 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x52, 0x08, - 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x07, 0x72, 0x65, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x07, 0x72, 0x65, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x22, 0xa5, 0x01, 0x0a, 0x19, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x65, 0x74, 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, - 0x65, 0x66, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x61, 0x63, 0x6b, - 0x65, 0x6e, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x12, 0x49, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0xb4, 0x01, 0x0a, - 0x13, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x54, 0x43, 0x50, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4e, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, - 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x66, 0x12, 0x4d, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, - 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, - 0x6c, 0x65, 0x73, 0x22, 0x76, 0x0a, 0x17, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, - 0x65, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x5b, - 0x0a, 0x0c, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, - 0x64, 0x54, 0x43, 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x52, 0x0b, - 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x73, 0x22, 0x59, 0x0a, 0x18, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x54, 0x43, 0x50, 0x42, 0x61, 0x63, - 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x63, 0x6b, 0x65, - 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, - 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x9b, 0x03, 0x0a, 0x14, 0x42, 0x61, 0x63, 0x6b, 0x65, - 0x6e, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, - 0x51, 0x0a, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, - 0x65, 0x66, 0x12, 0x2c, 0x0a, 0x12, 0x6e, 0x75, 0x6c, 0x6c, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, - 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, - 0x6e, 0x75, 0x6c, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, - 0x12, 0x44, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5a, 0x0a, 0x0f, 0x66, 0x61, 0x69, 0x6c, 0x6f, 0x76, - 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x52, 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x12, 0x60, 0x0a, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x52, 0x11, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x42, 0x9b, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x13, 0x43, 0x6f, 0x6d, - 0x70, 0x75, 0x74, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x45, 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, - 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, - 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, - 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_computed_routes_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_computed_routes_proto_rawDescData = file_pbmesh_v1alpha1_computed_routes_proto_rawDesc -) - -func file_pbmesh_v1alpha1_computed_routes_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_computed_routes_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_computed_routes_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_computed_routes_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_computed_routes_proto_rawDescData -} - -var file_pbmesh_v1alpha1_computed_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 14) -var file_pbmesh_v1alpha1_computed_routes_proto_goTypes = []interface{}{ - (*ComputedRoutes)(nil), // 0: hashicorp.consul.mesh.v1alpha1.ComputedRoutes - (*ComputedPortRoutes)(nil), // 1: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes - (*InterpretedHTTPRoute)(nil), // 2: hashicorp.consul.mesh.v1alpha1.InterpretedHTTPRoute - (*InterpretedHTTPRouteRule)(nil), // 3: hashicorp.consul.mesh.v1alpha1.InterpretedHTTPRouteRule - (*InterpretedHTTPBackendRef)(nil), // 4: hashicorp.consul.mesh.v1alpha1.InterpretedHTTPBackendRef - (*InterpretedGRPCRoute)(nil), // 5: hashicorp.consul.mesh.v1alpha1.InterpretedGRPCRoute - (*InterpretedGRPCRouteRule)(nil), // 6: hashicorp.consul.mesh.v1alpha1.InterpretedGRPCRouteRule - (*InterpretedGRPCBackendRef)(nil), // 7: hashicorp.consul.mesh.v1alpha1.InterpretedGRPCBackendRef - (*InterpretedTCPRoute)(nil), // 8: hashicorp.consul.mesh.v1alpha1.InterpretedTCPRoute - (*InterpretedTCPRouteRule)(nil), // 9: hashicorp.consul.mesh.v1alpha1.InterpretedTCPRouteRule - (*InterpretedTCPBackendRef)(nil), // 10: hashicorp.consul.mesh.v1alpha1.InterpretedTCPBackendRef - (*BackendTargetDetails)(nil), // 11: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails - nil, // 12: hashicorp.consul.mesh.v1alpha1.ComputedRoutes.PortedConfigsEntry - nil, // 13: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.TargetsEntry - (*ParentReference)(nil), // 14: hashicorp.consul.mesh.v1alpha1.ParentReference - (*HTTPRouteMatch)(nil), // 15: hashicorp.consul.mesh.v1alpha1.HTTPRouteMatch - (*HTTPRouteFilter)(nil), // 16: hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter - (*HTTPRouteTimeouts)(nil), // 17: hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts - (*HTTPRouteRetries)(nil), // 18: hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries - (*GRPCRouteMatch)(nil), // 19: hashicorp.consul.mesh.v1alpha1.GRPCRouteMatch - (*GRPCRouteFilter)(nil), // 20: hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter - (*BackendReference)(nil), // 21: hashicorp.consul.mesh.v1alpha1.BackendReference - (*v1alpha1.Service)(nil), // 22: hashicorp.consul.catalog.v1alpha1.Service - (*v1alpha1.FailoverPolicy)(nil), // 23: hashicorp.consul.catalog.v1alpha1.FailoverPolicy - (*DestinationPolicy)(nil), // 24: hashicorp.consul.mesh.v1alpha1.DestinationPolicy -} -var file_pbmesh_v1alpha1_computed_routes_proto_depIdxs = []int32{ - 12, // 0: hashicorp.consul.mesh.v1alpha1.ComputedRoutes.ported_configs:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedRoutes.PortedConfigsEntry - 2, // 1: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.http:type_name -> hashicorp.consul.mesh.v1alpha1.InterpretedHTTPRoute - 5, // 2: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.grpc:type_name -> hashicorp.consul.mesh.v1alpha1.InterpretedGRPCRoute - 8, // 3: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.tcp:type_name -> hashicorp.consul.mesh.v1alpha1.InterpretedTCPRoute - 13, // 4: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.targets:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.TargetsEntry - 14, // 5: hashicorp.consul.mesh.v1alpha1.InterpretedHTTPRoute.parent_ref:type_name -> hashicorp.consul.mesh.v1alpha1.ParentReference - 3, // 6: hashicorp.consul.mesh.v1alpha1.InterpretedHTTPRoute.rules:type_name -> hashicorp.consul.mesh.v1alpha1.InterpretedHTTPRouteRule - 15, // 7: hashicorp.consul.mesh.v1alpha1.InterpretedHTTPRouteRule.matches:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteMatch - 16, // 8: hashicorp.consul.mesh.v1alpha1.InterpretedHTTPRouteRule.filters:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter - 4, // 9: hashicorp.consul.mesh.v1alpha1.InterpretedHTTPRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v1alpha1.InterpretedHTTPBackendRef - 17, // 10: hashicorp.consul.mesh.v1alpha1.InterpretedHTTPRouteRule.timeouts:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts - 18, // 11: hashicorp.consul.mesh.v1alpha1.InterpretedHTTPRouteRule.retries:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries - 16, // 12: hashicorp.consul.mesh.v1alpha1.InterpretedHTTPBackendRef.filters:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter - 14, // 13: hashicorp.consul.mesh.v1alpha1.InterpretedGRPCRoute.parent_ref:type_name -> hashicorp.consul.mesh.v1alpha1.ParentReference - 6, // 14: hashicorp.consul.mesh.v1alpha1.InterpretedGRPCRoute.rules:type_name -> hashicorp.consul.mesh.v1alpha1.InterpretedGRPCRouteRule - 19, // 15: hashicorp.consul.mesh.v1alpha1.InterpretedGRPCRouteRule.matches:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCRouteMatch - 20, // 16: hashicorp.consul.mesh.v1alpha1.InterpretedGRPCRouteRule.filters:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter - 7, // 17: hashicorp.consul.mesh.v1alpha1.InterpretedGRPCRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v1alpha1.InterpretedGRPCBackendRef - 17, // 18: hashicorp.consul.mesh.v1alpha1.InterpretedGRPCRouteRule.timeouts:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts - 18, // 19: hashicorp.consul.mesh.v1alpha1.InterpretedGRPCRouteRule.retries:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries - 20, // 20: hashicorp.consul.mesh.v1alpha1.InterpretedGRPCBackendRef.filters:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter - 14, // 21: hashicorp.consul.mesh.v1alpha1.InterpretedTCPRoute.parent_ref:type_name -> hashicorp.consul.mesh.v1alpha1.ParentReference - 9, // 22: hashicorp.consul.mesh.v1alpha1.InterpretedTCPRoute.rules:type_name -> hashicorp.consul.mesh.v1alpha1.InterpretedTCPRouteRule - 10, // 23: hashicorp.consul.mesh.v1alpha1.InterpretedTCPRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v1alpha1.InterpretedTCPBackendRef - 21, // 24: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.backend_ref:type_name -> hashicorp.consul.mesh.v1alpha1.BackendReference - 22, // 25: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.service:type_name -> hashicorp.consul.catalog.v1alpha1.Service - 23, // 26: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.failover_policy:type_name -> hashicorp.consul.catalog.v1alpha1.FailoverPolicy - 24, // 27: hashicorp.consul.mesh.v1alpha1.BackendTargetDetails.destination_policy:type_name -> hashicorp.consul.mesh.v1alpha1.DestinationPolicy - 1, // 28: hashicorp.consul.mesh.v1alpha1.ComputedRoutes.PortedConfigsEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes - 11, // 29: hashicorp.consul.mesh.v1alpha1.ComputedPortRoutes.TargetsEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.BackendTargetDetails - 30, // [30:30] is the sub-list for method output_type - 30, // [30:30] is the sub-list for method input_type - 30, // [30:30] is the sub-list for extension type_name - 30, // [30:30] is the sub-list for extension extendee - 0, // [0:30] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_computed_routes_proto_init() } -func file_pbmesh_v1alpha1_computed_routes_proto_init() { - if File_pbmesh_v1alpha1_computed_routes_proto != nil { - return - } - file_pbmesh_v1alpha1_common_proto_init() - file_pbmesh_v1alpha1_destination_policy_proto_init() - file_pbmesh_v1alpha1_grpc_route_proto_init() - file_pbmesh_v1alpha1_http_route_proto_init() - file_pbmesh_v1alpha1_http_route_retries_proto_init() - file_pbmesh_v1alpha1_http_route_timeouts_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedRoutes); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedPortRoutes); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterpretedHTTPRoute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterpretedHTTPRouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterpretedHTTPBackendRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterpretedGRPCRoute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterpretedGRPCRouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterpretedGRPCBackendRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterpretedTCPRoute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterpretedTCPRouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterpretedTCPBackendRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BackendTargetDetails); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v1alpha1_computed_routes_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*ComputedPortRoutes_Http)(nil), - (*ComputedPortRoutes_Grpc)(nil), - (*ComputedPortRoutes_Tcp)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v1alpha1_computed_routes_proto_rawDesc, - NumEnums: 0, - NumMessages: 14, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_computed_routes_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_computed_routes_proto_depIdxs, - MessageInfos: file_pbmesh_v1alpha1_computed_routes_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_computed_routes_proto = out.File - file_pbmesh_v1alpha1_computed_routes_proto_rawDesc = nil - file_pbmesh_v1alpha1_computed_routes_proto_goTypes = nil - file_pbmesh_v1alpha1_computed_routes_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/computed_routes.proto b/proto-public/pbmesh/v1alpha1/computed_routes.proto deleted file mode 100644 index d48d417d68233..0000000000000 --- a/proto-public/pbmesh/v1alpha1/computed_routes.proto +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1; - -import "pbcatalog/v1alpha1/failover_policy.proto"; -import "pbcatalog/v1alpha1/service.proto"; -import "pbmesh/v1alpha1/common.proto"; -import "pbmesh/v1alpha1/destination_policy.proto"; -import "pbmesh/v1alpha1/grpc_route.proto"; -import "pbmesh/v1alpha1/http_route.proto"; -import "pbmesh/v1alpha1/http_route_retries.proto"; -import "pbmesh/v1alpha1/http_route_timeouts.proto"; - -// This is a Resource type. -message ComputedRoutes { - map ported_configs = 1; -} - -message ComputedPortRoutes { - oneof config { - InterpretedHTTPRoute http = 1; - InterpretedGRPCRoute grpc = 2; - InterpretedTCPRoute tcp = 3; - } - bool using_default_config = 4; // TODO - - // map key is an opaque string; like disco chain target name - map targets = 5; -} - -message InterpretedHTTPRoute { - ParentReference parent_ref = 1; - reserved 2; // hostnames - repeated InterpretedHTTPRouteRule rules = 3; -} - -message InterpretedHTTPRouteRule { - repeated HTTPRouteMatch matches = 1; - repeated HTTPRouteFilter filters = 2; - repeated InterpretedHTTPBackendRef backend_refs = 3; - HTTPRouteTimeouts timeouts = 4; - HTTPRouteRetries retries = 5; -} - -message InterpretedHTTPBackendRef { - string backend_target = 1; - uint32 weight = 2; - repeated HTTPRouteFilter filters = 3; -} - -message InterpretedGRPCRoute { - ParentReference parent_ref = 1; - reserved 2; // hostnames - repeated InterpretedGRPCRouteRule rules = 3; -} - -message InterpretedGRPCRouteRule { - repeated GRPCRouteMatch matches = 1; - repeated GRPCRouteFilter filters = 2; - repeated InterpretedGRPCBackendRef backend_refs = 3; - HTTPRouteTimeouts timeouts = 4; - HTTPRouteRetries retries = 5; -} - -message InterpretedGRPCBackendRef { - string backend_target = 1; - uint32 weight = 2; - repeated GRPCRouteFilter filters = 3; -} - -message InterpretedTCPRoute { - ParentReference parent_ref = 1; - repeated InterpretedTCPRouteRule rules = 2; -} - -message InterpretedTCPRouteRule { - repeated InterpretedTCPBackendRef backend_refs = 1; -} - -// TODO: look into smuggling the target through a different typeURL, or just -// skip in favor of letting the caller do their own lookups? -message InterpretedTCPBackendRef { - string backend_target = 1; - uint32 weight = 2; -} - -message BackendTargetDetails { - // identity info - BackendReference backend_ref = 1; - - bool null_route_traffic = 2; - - hashicorp.consul.catalog.v1alpha1.Service service = 3; - hashicorp.consul.catalog.v1alpha1.FailoverPolicy failover_policy = 4; - DestinationPolicy destination_policy = 5; -} diff --git a/proto-public/pbmesh/v1alpha1/connection.pb.go b/proto-public/pbmesh/v1alpha1/connection.pb.go index 221845b26dbb8..5edc0ee76d1d7 100644 --- a/proto-public/pbmesh/v1alpha1/connection.pb.go +++ b/proto-public/pbmesh/v1alpha1/connection.pb.go @@ -12,7 +12,6 @@ package meshv1alpha1 import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" reflect "reflect" sync "sync" ) @@ -24,61 +23,60 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -type BalanceConnections int32 +type BalanceInboundConnections int32 const ( // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - BalanceConnections_BALANCE_CONNECTIONS_DEFAULT BalanceConnections = 0 - BalanceConnections_BALANCE_CONNECTIONS_EXACT BalanceConnections = 1 + BalanceInboundConnections_BALANCE_INBOUND_CONNECTIONS_DEFAULT BalanceInboundConnections = 0 + BalanceInboundConnections_BALANCE_INBOUND_CONNECTIONS_EXACT BalanceInboundConnections = 1 ) -// Enum value maps for BalanceConnections. +// Enum value maps for BalanceInboundConnections. var ( - BalanceConnections_name = map[int32]string{ - 0: "BALANCE_CONNECTIONS_DEFAULT", - 1: "BALANCE_CONNECTIONS_EXACT", + BalanceInboundConnections_name = map[int32]string{ + 0: "BALANCE_INBOUND_CONNECTIONS_DEFAULT", + 1: "BALANCE_INBOUND_CONNECTIONS_EXACT", } - BalanceConnections_value = map[string]int32{ - "BALANCE_CONNECTIONS_DEFAULT": 0, - "BALANCE_CONNECTIONS_EXACT": 1, + BalanceInboundConnections_value = map[string]int32{ + "BALANCE_INBOUND_CONNECTIONS_DEFAULT": 0, + "BALANCE_INBOUND_CONNECTIONS_EXACT": 1, } ) -func (x BalanceConnections) Enum() *BalanceConnections { - p := new(BalanceConnections) +func (x BalanceInboundConnections) Enum() *BalanceInboundConnections { + p := new(BalanceInboundConnections) *p = x return p } -func (x BalanceConnections) String() string { +func (x BalanceInboundConnections) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } -func (BalanceConnections) Descriptor() protoreflect.EnumDescriptor { +func (BalanceInboundConnections) Descriptor() protoreflect.EnumDescriptor { return file_pbmesh_v1alpha1_connection_proto_enumTypes[0].Descriptor() } -func (BalanceConnections) Type() protoreflect.EnumType { +func (BalanceInboundConnections) Type() protoreflect.EnumType { return &file_pbmesh_v1alpha1_connection_proto_enumTypes[0] } -func (x BalanceConnections) Number() protoreflect.EnumNumber { +func (x BalanceInboundConnections) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } -// Deprecated: Use BalanceConnections.Descriptor instead. -func (BalanceConnections) EnumDescriptor() ([]byte, []int) { +// Deprecated: Use BalanceInboundConnections.Descriptor instead. +func (BalanceInboundConnections) EnumDescriptor() ([]byte, []int) { return file_pbmesh_v1alpha1_connection_proto_rawDescGZIP(), []int{0} } -// Referenced by ProxyConfiguration type ConnectionConfig struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ConnectTimeout *durationpb.Duration `protobuf:"bytes,1,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` - RequestTimeout *durationpb.Duration `protobuf:"bytes,2,opt,name=request_timeout,json=requestTimeout,proto3" json:"request_timeout,omitempty"` + ConnectTimeoutMs uint64 `protobuf:"varint,2,opt,name=connect_timeout_ms,json=connectTimeoutMs,proto3" json:"connect_timeout_ms,omitempty"` + RequestTimeoutMs uint64 `protobuf:"varint,3,opt,name=request_timeout_ms,json=requestTimeoutMs,proto3" json:"request_timeout_ms,omitempty"` } func (x *ConnectionConfig) Reset() { @@ -113,28 +111,27 @@ func (*ConnectionConfig) Descriptor() ([]byte, []int) { return file_pbmesh_v1alpha1_connection_proto_rawDescGZIP(), []int{0} } -func (x *ConnectionConfig) GetConnectTimeout() *durationpb.Duration { +func (x *ConnectionConfig) GetConnectTimeoutMs() uint64 { if x != nil { - return x.ConnectTimeout + return x.ConnectTimeoutMs } - return nil + return 0 } -func (x *ConnectionConfig) GetRequestTimeout() *durationpb.Duration { +func (x *ConnectionConfig) GetRequestTimeoutMs() uint64 { if x != nil { - return x.RequestTimeout + return x.RequestTimeoutMs } - return nil + return 0 } -// Referenced by ProxyConfiguration type InboundConnectionsConfig struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - MaxInboundConnections uint64 `protobuf:"varint,12,opt,name=max_inbound_connections,json=maxInboundConnections,proto3" json:"max_inbound_connections,omitempty"` - BalanceInboundConnections BalanceConnections `protobuf:"varint,13,opt,name=balance_inbound_connections,json=balanceInboundConnections,proto3,enum=hashicorp.consul.mesh.v1alpha1.BalanceConnections" json:"balance_inbound_connections,omitempty"` + MaxInboundConnections uint64 `protobuf:"varint,12,opt,name=max_inbound_connections,json=maxInboundConnections,proto3" json:"max_inbound_connections,omitempty"` + BalanceInboundConnections BalanceInboundConnections `protobuf:"varint,13,opt,name=balance_inbound_connections,json=balanceInboundConnections,proto3,enum=hashicorp.consul.mesh.v1alpha1.BalanceInboundConnections" json:"balance_inbound_connections,omitempty"` } func (x *InboundConnectionsConfig) Reset() { @@ -176,11 +173,11 @@ func (x *InboundConnectionsConfig) GetMaxInboundConnections() uint64 { return 0 } -func (x *InboundConnectionsConfig) GetBalanceInboundConnections() BalanceConnections { +func (x *InboundConnectionsConfig) GetBalanceInboundConnections() BalanceInboundConnections { if x != nil { return x.BalanceInboundConnections } - return BalanceConnections_BALANCE_CONNECTIONS_DEFAULT + return BalanceInboundConnections_BALANCE_INBOUND_CONNECTIONS_DEFAULT } var File_pbmesh_v1alpha1_connection_proto protoreflect.FileDescriptor @@ -190,54 +187,52 @@ var file_pbmesh_v1alpha1_connection_proto_rawDesc = []byte{ 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0x9a, 0x01, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x42, 0x0a, 0x0f, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, - 0xc6, 0x01, 0x0a, 0x18, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x17, - 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x6d, - 0x61, 0x78, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x72, 0x0a, 0x1b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, - 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x19, 0x62, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2a, 0x54, 0x0a, 0x12, 0x42, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, - 0x0a, 0x1b, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, - 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, - 0x1d, 0x0a, 0x19, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, - 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x45, 0x58, 0x41, 0x43, 0x54, 0x10, 0x01, 0x42, 0x97, - 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0f, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, - 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x61, 0x31, 0x22, 0x6e, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, + 0x75, 0x74, 0x4d, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x10, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0x4d, 0x73, 0x22, 0xcd, 0x01, 0x0a, 0x18, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x36, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x15, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x79, 0x0a, 0x1b, 0x62, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x19, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2a, 0x6b, 0x0a, 0x19, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x27, 0x0a, 0x23, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x49, 0x4e, 0x42, 0x4f, 0x55, + 0x4e, 0x44, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x44, + 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x25, 0x0a, 0x21, 0x42, 0x41, 0x4c, 0x41, + 0x4e, 0x43, 0x45, 0x5f, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, + 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x45, 0x58, 0x41, 0x43, 0x54, 0x10, 0x01, 0x42, + 0x97, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0f, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, - 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, - 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, + 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, + 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -255,20 +250,17 @@ func file_pbmesh_v1alpha1_connection_proto_rawDescGZIP() []byte { var file_pbmesh_v1alpha1_connection_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_pbmesh_v1alpha1_connection_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_pbmesh_v1alpha1_connection_proto_goTypes = []interface{}{ - (BalanceConnections)(0), // 0: hashicorp.consul.mesh.v1alpha1.BalanceConnections + (BalanceInboundConnections)(0), // 0: hashicorp.consul.mesh.v1alpha1.BalanceInboundConnections (*ConnectionConfig)(nil), // 1: hashicorp.consul.mesh.v1alpha1.ConnectionConfig (*InboundConnectionsConfig)(nil), // 2: hashicorp.consul.mesh.v1alpha1.InboundConnectionsConfig - (*durationpb.Duration)(nil), // 3: google.protobuf.Duration } var file_pbmesh_v1alpha1_connection_proto_depIdxs = []int32{ - 3, // 0: hashicorp.consul.mesh.v1alpha1.ConnectionConfig.connect_timeout:type_name -> google.protobuf.Duration - 3, // 1: hashicorp.consul.mesh.v1alpha1.ConnectionConfig.request_timeout:type_name -> google.protobuf.Duration - 0, // 2: hashicorp.consul.mesh.v1alpha1.InboundConnectionsConfig.balance_inbound_connections:type_name -> hashicorp.consul.mesh.v1alpha1.BalanceConnections - 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 + 0, // 0: hashicorp.consul.mesh.v1alpha1.InboundConnectionsConfig.balance_inbound_connections:type_name -> hashicorp.consul.mesh.v1alpha1.BalanceInboundConnections + 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_pbmesh_v1alpha1_connection_proto_init() } diff --git a/proto-public/pbmesh/v1alpha1/connection.proto b/proto-public/pbmesh/v1alpha1/connection.proto index 8cae7c1c10995..8a1f4f0e7c575 100644 --- a/proto-public/pbmesh/v1alpha1/connection.proto +++ b/proto-public/pbmesh/v1alpha1/connection.proto @@ -5,22 +5,18 @@ syntax = "proto3"; package hashicorp.consul.mesh.v1alpha1; -import "google/protobuf/duration.proto"; - -// Referenced by ProxyConfiguration message ConnectionConfig { - google.protobuf.Duration connect_timeout = 1; - google.protobuf.Duration request_timeout = 2; + uint64 connect_timeout_ms = 2; + uint64 request_timeout_ms = 3; } -// Referenced by ProxyConfiguration message InboundConnectionsConfig { uint64 max_inbound_connections = 12; - BalanceConnections balance_inbound_connections = 13; + BalanceInboundConnections balance_inbound_connections = 13; } -enum BalanceConnections { +enum BalanceInboundConnections { // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - BALANCE_CONNECTIONS_DEFAULT = 0; - BALANCE_CONNECTIONS_EXACT = 1; + BALANCE_INBOUND_CONNECTIONS_DEFAULT = 0; + BALANCE_INBOUND_CONNECTIONS_EXACT = 1; } diff --git a/proto-public/pbmesh/v1alpha1/destination_policy.pb.binary.go b/proto-public/pbmesh/v1alpha1/destination_policy.pb.binary.go deleted file mode 100644 index e77b667108700..0000000000000 --- a/proto-public/pbmesh/v1alpha1/destination_policy.pb.binary.go +++ /dev/null @@ -1,88 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/destination_policy.proto - -package meshv1alpha1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LocalityPrioritization) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LocalityPrioritization) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LoadBalancer) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LoadBalancer) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RingHashConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RingHashConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LeastRequestConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LeastRequestConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HashPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HashPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *CookieConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *CookieConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/destination_policy.pb.go b/proto-public/pbmesh/v1alpha1/destination_policy.pb.go deleted file mode 100644 index 44a3049d5eb2f..0000000000000 --- a/proto-public/pbmesh/v1alpha1/destination_policy.pb.go +++ /dev/null @@ -1,1091 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/destination_policy.proto - -package meshv1alpha1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - 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 LocalityPrioritizationMode int32 - -const ( - LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED LocalityPrioritizationMode = 0 - LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_NONE LocalityPrioritizationMode = 1 - LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_FAILOVER LocalityPrioritizationMode = 2 -) - -// Enum value maps for LocalityPrioritizationMode. -var ( - LocalityPrioritizationMode_name = map[int32]string{ - 0: "LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED", - 1: "LOCALITY_PRIORITIZATION_MODE_NONE", - 2: "LOCALITY_PRIORITIZATION_MODE_FAILOVER", - } - LocalityPrioritizationMode_value = map[string]int32{ - "LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED": 0, - "LOCALITY_PRIORITIZATION_MODE_NONE": 1, - "LOCALITY_PRIORITIZATION_MODE_FAILOVER": 2, - } -) - -func (x LocalityPrioritizationMode) Enum() *LocalityPrioritizationMode { - p := new(LocalityPrioritizationMode) - *p = x - return p -} - -func (x LocalityPrioritizationMode) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (LocalityPrioritizationMode) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_destination_policy_proto_enumTypes[0].Descriptor() -} - -func (LocalityPrioritizationMode) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_destination_policy_proto_enumTypes[0] -} - -func (x LocalityPrioritizationMode) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use LocalityPrioritizationMode.Descriptor instead. -func (LocalityPrioritizationMode) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_destination_policy_proto_rawDescGZIP(), []int{0} -} - -type LoadBalancerPolicy int32 - -const ( - LoadBalancerPolicy_LOAD_BALANCER_POLICY_UNSPECIFIED LoadBalancerPolicy = 0 - LoadBalancerPolicy_LOAD_BALANCER_POLICY_RANDOM LoadBalancerPolicy = 1 - LoadBalancerPolicy_LOAD_BALANCER_POLICY_ROUND_ROBIN LoadBalancerPolicy = 2 - LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST LoadBalancerPolicy = 3 - LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV LoadBalancerPolicy = 4 - LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH LoadBalancerPolicy = 5 -) - -// Enum value maps for LoadBalancerPolicy. -var ( - LoadBalancerPolicy_name = map[int32]string{ - 0: "LOAD_BALANCER_POLICY_UNSPECIFIED", - 1: "LOAD_BALANCER_POLICY_RANDOM", - 2: "LOAD_BALANCER_POLICY_ROUND_ROBIN", - 3: "LOAD_BALANCER_POLICY_LEAST_REQUEST", - 4: "LOAD_BALANCER_POLICY_MAGLEV", - 5: "LOAD_BALANCER_POLICY_RING_HASH", - } - LoadBalancerPolicy_value = map[string]int32{ - "LOAD_BALANCER_POLICY_UNSPECIFIED": 0, - "LOAD_BALANCER_POLICY_RANDOM": 1, - "LOAD_BALANCER_POLICY_ROUND_ROBIN": 2, - "LOAD_BALANCER_POLICY_LEAST_REQUEST": 3, - "LOAD_BALANCER_POLICY_MAGLEV": 4, - "LOAD_BALANCER_POLICY_RING_HASH": 5, - } -) - -func (x LoadBalancerPolicy) Enum() *LoadBalancerPolicy { - p := new(LoadBalancerPolicy) - *p = x - return p -} - -func (x LoadBalancerPolicy) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (LoadBalancerPolicy) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_destination_policy_proto_enumTypes[1].Descriptor() -} - -func (LoadBalancerPolicy) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_destination_policy_proto_enumTypes[1] -} - -func (x LoadBalancerPolicy) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use LoadBalancerPolicy.Descriptor instead. -func (LoadBalancerPolicy) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_destination_policy_proto_rawDescGZIP(), []int{1} -} - -type HashPolicyField int32 - -const ( - HashPolicyField_HASH_POLICY_FIELD_UNSPECIFIED HashPolicyField = 0 - HashPolicyField_HASH_POLICY_FIELD_HEADER HashPolicyField = 1 - HashPolicyField_HASH_POLICY_FIELD_COOKIE HashPolicyField = 2 - HashPolicyField_HASH_POLICY_FIELD_QUERY_PARAMETER HashPolicyField = 3 -) - -// Enum value maps for HashPolicyField. -var ( - HashPolicyField_name = map[int32]string{ - 0: "HASH_POLICY_FIELD_UNSPECIFIED", - 1: "HASH_POLICY_FIELD_HEADER", - 2: "HASH_POLICY_FIELD_COOKIE", - 3: "HASH_POLICY_FIELD_QUERY_PARAMETER", - } - HashPolicyField_value = map[string]int32{ - "HASH_POLICY_FIELD_UNSPECIFIED": 0, - "HASH_POLICY_FIELD_HEADER": 1, - "HASH_POLICY_FIELD_COOKIE": 2, - "HASH_POLICY_FIELD_QUERY_PARAMETER": 3, - } -) - -func (x HashPolicyField) Enum() *HashPolicyField { - p := new(HashPolicyField) - *p = x - return p -} - -func (x HashPolicyField) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (HashPolicyField) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_destination_policy_proto_enumTypes[2].Descriptor() -} - -func (HashPolicyField) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_destination_policy_proto_enumTypes[2] -} - -func (x HashPolicyField) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use HashPolicyField.Descriptor instead. -func (HashPolicyField) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_destination_policy_proto_rawDescGZIP(), []int{2} -} - -// DestinationPolicy is the destination-controlled set of defaults that -// are used when similar controls defined in an UpstreamConfig are left -// unspecified. -// -// Users may wish to share commonly configured settings for communicating with -// a service in one place, but yet retain the ability to tweak those on a -// client-by-client basis, which is why there are separate resources to control -// the definition of these values from either end of the connection. -// -// This is a Resource type. -type DestinationPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PortConfigs map[string]*DestinationConfig `protobuf:"bytes,1,rep,name=port_configs,json=portConfigs,proto3" json:"port_configs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *DestinationPolicy) Reset() { - *x = DestinationPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationPolicy) ProtoMessage() {} - -func (x *DestinationPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_destination_policy_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 DestinationPolicy.ProtoReflect.Descriptor instead. -func (*DestinationPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_destination_policy_proto_rawDescGZIP(), []int{0} -} - -func (x *DestinationPolicy) GetPortConfigs() map[string]*DestinationConfig { - if x != nil { - return x.PortConfigs - } - return nil -} - -type DestinationConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ConnectTimeout is the timeout for establishing new network connections - // to this service. - ConnectTimeout *durationpb.Duration `protobuf:"bytes,1,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` - // RequestTimeout is the timeout for an HTTP request to complete before the - // connection is automatically terminated. If unspecified, defaults to 15 - // seconds. - RequestTimeout *durationpb.Duration `protobuf:"bytes,2,opt,name=request_timeout,json=requestTimeout,proto3" json:"request_timeout,omitempty"` - // LoadBalancer determines the load balancing policy and configuration for - // services issuing requests to this upstream service. - LoadBalancer *LoadBalancer `protobuf:"bytes,3,opt,name=load_balancer,json=loadBalancer,proto3" json:"load_balancer,omitempty"` - // LocalityPrioritization controls whether the locality of services within the - // local partition will be used to prioritize connectivity. - LocalityPrioritization *LocalityPrioritization `protobuf:"bytes,4,opt,name=locality_prioritization,json=localityPrioritization,proto3" json:"locality_prioritization,omitempty"` -} - -func (x *DestinationConfig) Reset() { - *x = DestinationConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationConfig) ProtoMessage() {} - -func (x *DestinationConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_destination_policy_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 DestinationConfig.ProtoReflect.Descriptor instead. -func (*DestinationConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_destination_policy_proto_rawDescGZIP(), []int{1} -} - -func (x *DestinationConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -func (x *DestinationConfig) GetRequestTimeout() *durationpb.Duration { - if x != nil { - return x.RequestTimeout - } - return nil -} - -func (x *DestinationConfig) GetLoadBalancer() *LoadBalancer { - if x != nil { - return x.LoadBalancer - } - return nil -} - -func (x *DestinationConfig) GetLocalityPrioritization() *LocalityPrioritization { - if x != nil { - return x.LocalityPrioritization - } - return nil -} - -type LocalityPrioritization struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Mode specifies the type of prioritization that will be performed - // when selecting nodes in the local partition. - // Valid values are: "" (default "none"), "none", and "failover". - Mode LocalityPrioritizationMode `protobuf:"varint,1,opt,name=mode,proto3,enum=hashicorp.consul.mesh.v1alpha1.LocalityPrioritizationMode" json:"mode,omitempty"` -} - -func (x *LocalityPrioritization) Reset() { - *x = LocalityPrioritization{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LocalityPrioritization) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LocalityPrioritization) ProtoMessage() {} - -func (x *LocalityPrioritization) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_destination_policy_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 LocalityPrioritization.ProtoReflect.Descriptor instead. -func (*LocalityPrioritization) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_destination_policy_proto_rawDescGZIP(), []int{2} -} - -func (x *LocalityPrioritization) GetMode() LocalityPrioritizationMode { - if x != nil { - return x.Mode - } - return LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED -} - -// LoadBalancer determines the load balancing policy and configuration -// for services issuing requests to this upstream service. -type LoadBalancer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Policy is the load balancing policy used to select a host - Policy LoadBalancerPolicy `protobuf:"varint,1,opt,name=policy,proto3,enum=hashicorp.consul.mesh.v1alpha1.LoadBalancerPolicy" json:"policy,omitempty"` - // HashPolicies is a list of hash policies to use for hashing load balancing - // algorithms. Hash policies are evaluated individually and combined such - // that identical lists result in the same hash. - // - // If no hash policies are present, or none are successfully evaluated, - // then a random backend host will be selected. - HashPolicies []*HashPolicy `protobuf:"bytes,2,rep,name=hash_policies,json=hashPolicies,proto3" json:"hash_policies,omitempty"` - // Types that are assignable to Config: - // - // *LoadBalancer_RingHashConfig - // *LoadBalancer_LeastRequestConfig - Config isLoadBalancer_Config `protobuf_oneof:"config"` -} - -func (x *LoadBalancer) Reset() { - *x = LoadBalancer{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LoadBalancer) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LoadBalancer) ProtoMessage() {} - -func (x *LoadBalancer) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[3] - 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 LoadBalancer.ProtoReflect.Descriptor instead. -func (*LoadBalancer) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_destination_policy_proto_rawDescGZIP(), []int{3} -} - -func (x *LoadBalancer) GetPolicy() LoadBalancerPolicy { - if x != nil { - return x.Policy - } - return LoadBalancerPolicy_LOAD_BALANCER_POLICY_UNSPECIFIED -} - -func (x *LoadBalancer) GetHashPolicies() []*HashPolicy { - if x != nil { - return x.HashPolicies - } - return nil -} - -func (m *LoadBalancer) GetConfig() isLoadBalancer_Config { - if m != nil { - return m.Config - } - return nil -} - -func (x *LoadBalancer) GetRingHashConfig() *RingHashConfig { - if x, ok := x.GetConfig().(*LoadBalancer_RingHashConfig); ok { - return x.RingHashConfig - } - return nil -} - -func (x *LoadBalancer) GetLeastRequestConfig() *LeastRequestConfig { - if x, ok := x.GetConfig().(*LoadBalancer_LeastRequestConfig); ok { - return x.LeastRequestConfig - } - return nil -} - -type isLoadBalancer_Config interface { - isLoadBalancer_Config() -} - -type LoadBalancer_RingHashConfig struct { - // RingHashConfig contains configuration for the "ring_hash" policy type - RingHashConfig *RingHashConfig `protobuf:"bytes,3,opt,name=ring_hash_config,json=ringHashConfig,proto3,oneof"` -} - -type LoadBalancer_LeastRequestConfig struct { - // LeastRequestConfig contains configuration for the "least_request" policy type - LeastRequestConfig *LeastRequestConfig `protobuf:"bytes,4,opt,name=least_request_config,json=leastRequestConfig,proto3,oneof"` -} - -func (*LoadBalancer_RingHashConfig) isLoadBalancer_Config() {} - -func (*LoadBalancer_LeastRequestConfig) isLoadBalancer_Config() {} - -// RingHashConfig contains configuration for the "ring_hash" policy type -type RingHashConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // MinimumRingSize determines the minimum number of entries in the hash ring - MinimumRingSize uint64 `protobuf:"varint,1,opt,name=minimum_ring_size,json=minimumRingSize,proto3" json:"minimum_ring_size,omitempty"` - // MaximumRingSize determines the maximum number of entries in the hash ring - MaximumRingSize uint64 `protobuf:"varint,2,opt,name=maximum_ring_size,json=maximumRingSize,proto3" json:"maximum_ring_size,omitempty"` -} - -func (x *RingHashConfig) Reset() { - *x = RingHashConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RingHashConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RingHashConfig) ProtoMessage() {} - -func (x *RingHashConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[4] - 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 RingHashConfig.ProtoReflect.Descriptor instead. -func (*RingHashConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_destination_policy_proto_rawDescGZIP(), []int{4} -} - -func (x *RingHashConfig) GetMinimumRingSize() uint64 { - if x != nil { - return x.MinimumRingSize - } - return 0 -} - -func (x *RingHashConfig) GetMaximumRingSize() uint64 { - if x != nil { - return x.MaximumRingSize - } - return 0 -} - -// LeastRequestConfig contains configuration for the "least_request" policy type -type LeastRequestConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ChoiceCount determines the number of random healthy hosts from which to select the one with the least requests. - ChoiceCount uint32 `protobuf:"varint,1,opt,name=choice_count,json=choiceCount,proto3" json:"choice_count,omitempty"` -} - -func (x *LeastRequestConfig) Reset() { - *x = LeastRequestConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LeastRequestConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LeastRequestConfig) ProtoMessage() {} - -func (x *LeastRequestConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[5] - 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 LeastRequestConfig.ProtoReflect.Descriptor instead. -func (*LeastRequestConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_destination_policy_proto_rawDescGZIP(), []int{5} -} - -func (x *LeastRequestConfig) GetChoiceCount() uint32 { - if x != nil { - return x.ChoiceCount - } - return 0 -} - -// HashPolicy defines which attributes will be hashed by hash-based LB algorithms -type HashPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Field is the attribute type to hash on. - // Must be one of "header","cookie", or "query_parameter". - // Cannot be specified along with SourceIP. - Field HashPolicyField `protobuf:"varint,1,opt,name=field,proto3,enum=hashicorp.consul.mesh.v1alpha1.HashPolicyField" json:"field,omitempty"` - // FieldValue is the value to hash. - // ie. header name, cookie name, URL query parameter name - // Cannot be specified along with SourceIP. - FieldValue string `protobuf:"bytes,2,opt,name=field_value,json=fieldValue,proto3" json:"field_value,omitempty"` - // CookieConfig contains configuration for the "cookie" hash policy type. - CookieConfig *CookieConfig `protobuf:"bytes,3,opt,name=cookie_config,json=cookieConfig,proto3" json:"cookie_config,omitempty"` - // SourceIP determines whether the hash should be of the source IP rather than of a field and field value. - // Cannot be specified along with Field or FieldValue. - SourceIp bool `protobuf:"varint,4,opt,name=source_ip,json=sourceIp,proto3" json:"source_ip,omitempty"` - // Terminal will short circuit the computation of the hash when multiple hash policies are present. - // If a hash is computed when a Terminal policy is evaluated, - // then that hash will be used and subsequent hash policies will be ignored. - Terminal bool `protobuf:"varint,5,opt,name=terminal,proto3" json:"terminal,omitempty"` -} - -func (x *HashPolicy) Reset() { - *x = HashPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HashPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HashPolicy) ProtoMessage() {} - -func (x *HashPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[6] - 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 HashPolicy.ProtoReflect.Descriptor instead. -func (*HashPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_destination_policy_proto_rawDescGZIP(), []int{6} -} - -func (x *HashPolicy) GetField() HashPolicyField { - if x != nil { - return x.Field - } - return HashPolicyField_HASH_POLICY_FIELD_UNSPECIFIED -} - -func (x *HashPolicy) GetFieldValue() string { - if x != nil { - return x.FieldValue - } - return "" -} - -func (x *HashPolicy) GetCookieConfig() *CookieConfig { - if x != nil { - return x.CookieConfig - } - return nil -} - -func (x *HashPolicy) GetSourceIp() bool { - if x != nil { - return x.SourceIp - } - return false -} - -func (x *HashPolicy) GetTerminal() bool { - if x != nil { - return x.Terminal - } - return false -} - -// CookieConfig contains configuration for the "cookie" hash policy type. -// This is specified to have Envoy generate a cookie for a client on its first request. -type CookieConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Generates a session cookie with no expiration. - Session bool `protobuf:"varint,1,opt,name=session,proto3" json:"session,omitempty"` - // TTL for generated cookies. Cannot be specified for session cookies. - Ttl *durationpb.Duration `protobuf:"bytes,2,opt,name=ttl,proto3" json:"ttl,omitempty"` - // The path to set for the cookie - Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"` -} - -func (x *CookieConfig) Reset() { - *x = CookieConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CookieConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CookieConfig) ProtoMessage() {} - -func (x *CookieConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[7] - 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 CookieConfig.ProtoReflect.Descriptor instead. -func (*CookieConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_destination_policy_proto_rawDescGZIP(), []int{7} -} - -func (x *CookieConfig) GetSession() bool { - if x != nil { - return x.Session - } - return false -} - -func (x *CookieConfig) GetTtl() *durationpb.Duration { - if x != nil { - return x.Ttl - } - return nil -} - -func (x *CookieConfig) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -var File_pbmesh_v1alpha1_destination_policy_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_destination_policy_proto_rawDesc = []byte{ - 0x0a, 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xed, 0x01, 0x0a, 0x11, 0x44, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x12, 0x65, 0x0a, 0x0c, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x70, 0x6f, 0x72, 0x74, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x1a, 0x71, 0x0a, 0x10, 0x50, 0x6f, 0x72, 0x74, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x47, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, - 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdf, 0x02, 0x0a, 0x11, 0x44, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x12, 0x42, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x51, 0x0a, 0x0d, 0x6c, 0x6f, 0x61, 0x64, - 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x52, 0x0c, 0x6c, - 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x6f, 0x0a, 0x17, 0x6c, - 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x16, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, - 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x68, 0x0a, 0x16, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, - 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, - 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0xf9, 0x02, 0x0a, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x12, 0x4f, 0x0a, 0x0d, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x61, 0x73, 0x68, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0c, 0x68, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x69, 0x65, 0x73, 0x12, 0x5a, 0x0a, 0x10, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x73, - 0x68, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, - 0x52, 0x0e, 0x72, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x66, 0x0a, 0x14, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x48, 0x00, 0x52, 0x12, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x08, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x22, 0x68, 0x0a, 0x0e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, - 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x0f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, - 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x72, 0x69, 0x6e, 0x67, - 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x78, - 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x37, 0x0a, 0x12, - 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x80, 0x02, 0x0a, 0x0a, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x12, 0x45, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x51, 0x0a, 0x0d, - 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x0c, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x70, 0x12, 0x1a, 0x0a, 0x08, - 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, - 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x69, 0x0a, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, - 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x12, - 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x2a, 0x9c, 0x01, 0x0a, 0x1a, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, - 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, - 0x64, 0x65, 0x12, 0x2c, 0x0a, 0x28, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, - 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, - 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, - 0x12, 0x25, 0x0a, 0x21, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x52, 0x49, - 0x4f, 0x52, 0x49, 0x54, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, - 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x29, 0x0a, 0x25, 0x4c, 0x4f, 0x43, 0x41, 0x4c, - 0x49, 0x54, 0x59, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x49, 0x5a, 0x41, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x4f, 0x56, 0x45, 0x52, - 0x10, 0x02, 0x2a, 0xee, 0x01, 0x0a, 0x12, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x24, 0x0a, 0x20, 0x4c, 0x4f, 0x41, - 0x44, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x52, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, - 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x1f, 0x0a, 0x1b, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x52, - 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x52, 0x41, 0x4e, 0x44, 0x4f, 0x4d, 0x10, 0x01, - 0x12, 0x24, 0x0a, 0x20, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, - 0x52, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x52, - 0x4f, 0x42, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x26, 0x0a, 0x22, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x42, - 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x52, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x4c, - 0x45, 0x41, 0x53, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x03, 0x12, 0x1f, - 0x0a, 0x1b, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x52, 0x5f, - 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x4d, 0x41, 0x47, 0x4c, 0x45, 0x56, 0x10, 0x04, 0x12, - 0x22, 0x0a, 0x1e, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x52, - 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x48, 0x41, 0x53, - 0x48, 0x10, 0x05, 0x2a, 0x97, 0x01, 0x0a, 0x0f, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x21, 0x0a, 0x1d, 0x48, 0x41, 0x53, 0x48, 0x5f, - 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x48, 0x41, - 0x53, 0x48, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, - 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x48, 0x41, 0x53, 0x48, - 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x43, 0x4f, - 0x4f, 0x4b, 0x49, 0x45, 0x10, 0x02, 0x12, 0x25, 0x0a, 0x21, 0x48, 0x41, 0x53, 0x48, 0x5f, 0x50, - 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x51, 0x55, 0x45, 0x52, - 0x59, 0x5f, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, 0x45, 0x52, 0x10, 0x03, 0x42, 0x9e, 0x02, - 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x42, 0x16, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, - 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, 0x65, 0x73, 0x68, 0x2f, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1e, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, - 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, - 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_destination_policy_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_destination_policy_proto_rawDescData = file_pbmesh_v1alpha1_destination_policy_proto_rawDesc -) - -func file_pbmesh_v1alpha1_destination_policy_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_destination_policy_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_destination_policy_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_destination_policy_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_destination_policy_proto_rawDescData -} - -var file_pbmesh_v1alpha1_destination_policy_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_pbmesh_v1alpha1_destination_policy_proto_msgTypes = make([]protoimpl.MessageInfo, 9) -var file_pbmesh_v1alpha1_destination_policy_proto_goTypes = []interface{}{ - (LocalityPrioritizationMode)(0), // 0: hashicorp.consul.mesh.v1alpha1.LocalityPrioritizationMode - (LoadBalancerPolicy)(0), // 1: hashicorp.consul.mesh.v1alpha1.LoadBalancerPolicy - (HashPolicyField)(0), // 2: hashicorp.consul.mesh.v1alpha1.HashPolicyField - (*DestinationPolicy)(nil), // 3: hashicorp.consul.mesh.v1alpha1.DestinationPolicy - (*DestinationConfig)(nil), // 4: hashicorp.consul.mesh.v1alpha1.DestinationConfig - (*LocalityPrioritization)(nil), // 5: hashicorp.consul.mesh.v1alpha1.LocalityPrioritization - (*LoadBalancer)(nil), // 6: hashicorp.consul.mesh.v1alpha1.LoadBalancer - (*RingHashConfig)(nil), // 7: hashicorp.consul.mesh.v1alpha1.RingHashConfig - (*LeastRequestConfig)(nil), // 8: hashicorp.consul.mesh.v1alpha1.LeastRequestConfig - (*HashPolicy)(nil), // 9: hashicorp.consul.mesh.v1alpha1.HashPolicy - (*CookieConfig)(nil), // 10: hashicorp.consul.mesh.v1alpha1.CookieConfig - nil, // 11: hashicorp.consul.mesh.v1alpha1.DestinationPolicy.PortConfigsEntry - (*durationpb.Duration)(nil), // 12: google.protobuf.Duration -} -var file_pbmesh_v1alpha1_destination_policy_proto_depIdxs = []int32{ - 11, // 0: hashicorp.consul.mesh.v1alpha1.DestinationPolicy.port_configs:type_name -> hashicorp.consul.mesh.v1alpha1.DestinationPolicy.PortConfigsEntry - 12, // 1: hashicorp.consul.mesh.v1alpha1.DestinationConfig.connect_timeout:type_name -> google.protobuf.Duration - 12, // 2: hashicorp.consul.mesh.v1alpha1.DestinationConfig.request_timeout:type_name -> google.protobuf.Duration - 6, // 3: hashicorp.consul.mesh.v1alpha1.DestinationConfig.load_balancer:type_name -> hashicorp.consul.mesh.v1alpha1.LoadBalancer - 5, // 4: hashicorp.consul.mesh.v1alpha1.DestinationConfig.locality_prioritization:type_name -> hashicorp.consul.mesh.v1alpha1.LocalityPrioritization - 0, // 5: hashicorp.consul.mesh.v1alpha1.LocalityPrioritization.mode:type_name -> hashicorp.consul.mesh.v1alpha1.LocalityPrioritizationMode - 1, // 6: hashicorp.consul.mesh.v1alpha1.LoadBalancer.policy:type_name -> hashicorp.consul.mesh.v1alpha1.LoadBalancerPolicy - 9, // 7: hashicorp.consul.mesh.v1alpha1.LoadBalancer.hash_policies:type_name -> hashicorp.consul.mesh.v1alpha1.HashPolicy - 7, // 8: hashicorp.consul.mesh.v1alpha1.LoadBalancer.ring_hash_config:type_name -> hashicorp.consul.mesh.v1alpha1.RingHashConfig - 8, // 9: hashicorp.consul.mesh.v1alpha1.LoadBalancer.least_request_config:type_name -> hashicorp.consul.mesh.v1alpha1.LeastRequestConfig - 2, // 10: hashicorp.consul.mesh.v1alpha1.HashPolicy.field:type_name -> hashicorp.consul.mesh.v1alpha1.HashPolicyField - 10, // 11: hashicorp.consul.mesh.v1alpha1.HashPolicy.cookie_config:type_name -> hashicorp.consul.mesh.v1alpha1.CookieConfig - 12, // 12: hashicorp.consul.mesh.v1alpha1.CookieConfig.ttl:type_name -> google.protobuf.Duration - 4, // 13: hashicorp.consul.mesh.v1alpha1.DestinationPolicy.PortConfigsEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.DestinationConfig - 14, // [14:14] is the sub-list for method output_type - 14, // [14:14] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_destination_policy_proto_init() } -func file_pbmesh_v1alpha1_destination_policy_proto_init() { - if File_pbmesh_v1alpha1_destination_policy_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LocalityPrioritization); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LoadBalancer); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RingHashConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LeastRequestConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HashPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CookieConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v1alpha1_destination_policy_proto_msgTypes[3].OneofWrappers = []interface{}{ - (*LoadBalancer_RingHashConfig)(nil), - (*LoadBalancer_LeastRequestConfig)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v1alpha1_destination_policy_proto_rawDesc, - NumEnums: 3, - NumMessages: 9, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_destination_policy_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_destination_policy_proto_depIdxs, - EnumInfos: file_pbmesh_v1alpha1_destination_policy_proto_enumTypes, - MessageInfos: file_pbmesh_v1alpha1_destination_policy_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_destination_policy_proto = out.File - file_pbmesh_v1alpha1_destination_policy_proto_rawDesc = nil - file_pbmesh_v1alpha1_destination_policy_proto_goTypes = nil - file_pbmesh_v1alpha1_destination_policy_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/destination_policy.proto b/proto-public/pbmesh/v1alpha1/destination_policy.proto deleted file mode 100644 index cc03f38d8c05f..0000000000000 --- a/proto-public/pbmesh/v1alpha1/destination_policy.proto +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1; - -import "google/protobuf/duration.proto"; - -// DestinationPolicy is the destination-controlled set of defaults that -// are used when similar controls defined in an UpstreamConfig are left -// unspecified. -// -// Users may wish to share commonly configured settings for communicating with -// a service in one place, but yet retain the ability to tweak those on a -// client-by-client basis, which is why there are separate resources to control -// the definition of these values from either end of the connection. -// -// This is a Resource type. -message DestinationPolicy { - map port_configs = 1; -} - -message DestinationConfig { - // ConnectTimeout is the timeout for establishing new network connections - // to this service. - google.protobuf.Duration connect_timeout = 1; - - // RequestTimeout is the timeout for an HTTP request to complete before the - // connection is automatically terminated. If unspecified, defaults to 15 - // seconds. - google.protobuf.Duration request_timeout = 2; - - // LoadBalancer determines the load balancing policy and configuration for - // services issuing requests to this upstream service. - LoadBalancer load_balancer = 3; - - // LocalityPrioritization controls whether the locality of services within the - // local partition will be used to prioritize connectivity. - LocalityPrioritization locality_prioritization = 4; -} - -message LocalityPrioritization { - // Mode specifies the type of prioritization that will be performed - // when selecting nodes in the local partition. - // Valid values are: "" (default "none"), "none", and "failover". - LocalityPrioritizationMode mode = 1; -} - -enum LocalityPrioritizationMode { - LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED = 0; - LOCALITY_PRIORITIZATION_MODE_NONE = 1; - LOCALITY_PRIORITIZATION_MODE_FAILOVER = 2; -} - -// LoadBalancer determines the load balancing policy and configuration -// for services issuing requests to this upstream service. -// -message LoadBalancer { - // Policy is the load balancing policy used to select a host - LoadBalancerPolicy policy = 1; - - // HashPolicies is a list of hash policies to use for hashing load balancing - // algorithms. Hash policies are evaluated individually and combined such - // that identical lists result in the same hash. - // - // If no hash policies are present, or none are successfully evaluated, - // then a random backend host will be selected. - repeated HashPolicy hash_policies = 2; - - oneof config { - // RingHashConfig contains configuration for the "ring_hash" policy type - RingHashConfig ring_hash_config = 3; - - // LeastRequestConfig contains configuration for the "least_request" policy type - LeastRequestConfig least_request_config = 4; - } -} - -enum LoadBalancerPolicy { - LOAD_BALANCER_POLICY_UNSPECIFIED = 0; - LOAD_BALANCER_POLICY_RANDOM = 1; - LOAD_BALANCER_POLICY_ROUND_ROBIN = 2; - LOAD_BALANCER_POLICY_LEAST_REQUEST = 3; - LOAD_BALANCER_POLICY_MAGLEV = 4; - LOAD_BALANCER_POLICY_RING_HASH = 5; -} - -// RingHashConfig contains configuration for the "ring_hash" policy type -message RingHashConfig { - // MinimumRingSize determines the minimum number of entries in the hash ring - uint64 minimum_ring_size = 1; - - // MaximumRingSize determines the maximum number of entries in the hash ring - uint64 maximum_ring_size = 2; -} - -// LeastRequestConfig contains configuration for the "least_request" policy type -message LeastRequestConfig { - // ChoiceCount determines the number of random healthy hosts from which to select the one with the least requests. - uint32 choice_count = 1; -} - -// HashPolicy defines which attributes will be hashed by hash-based LB algorithms -message HashPolicy { - // Field is the attribute type to hash on. - // Must be one of "header","cookie", or "query_parameter". - // Cannot be specified along with SourceIP. - HashPolicyField field = 1; - - // FieldValue is the value to hash. - // ie. header name, cookie name, URL query parameter name - // Cannot be specified along with SourceIP. - string field_value = 2; - - // CookieConfig contains configuration for the "cookie" hash policy type. - CookieConfig cookie_config = 3; - - // SourceIP determines whether the hash should be of the source IP rather than of a field and field value. - // Cannot be specified along with Field or FieldValue. - bool source_ip = 4; - - // Terminal will short circuit the computation of the hash when multiple hash policies are present. - // If a hash is computed when a Terminal policy is evaluated, - // then that hash will be used and subsequent hash policies will be ignored. - bool terminal = 5; -} - -enum HashPolicyField { - HASH_POLICY_FIELD_UNSPECIFIED = 0; - HASH_POLICY_FIELD_HEADER = 1; - HASH_POLICY_FIELD_COOKIE = 2; - HASH_POLICY_FIELD_QUERY_PARAMETER = 3; -} - -// CookieConfig contains configuration for the "cookie" hash policy type. -// This is specified to have Envoy generate a cookie for a client on its first request. -message CookieConfig { - // Generates a session cookie with no expiration. - bool session = 1; - - // TTL for generated cookies. Cannot be specified for session cookies. - google.protobuf.Duration ttl = 2; - - // The path to set for the cookie - string path = 3; -} diff --git a/proto-public/pbmesh/v1alpha1/grpc_route.pb.binary.go b/proto-public/pbmesh/v1alpha1/grpc_route.pb.binary.go deleted file mode 100644 index 40efa6110d0b7..0000000000000 --- a/proto-public/pbmesh/v1alpha1/grpc_route.pb.binary.go +++ /dev/null @@ -1,78 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/grpc_route.proto - -package meshv1alpha1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCRoute) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCRoute) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCRouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCRouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCRouteMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCRouteMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCMethodMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCMethodMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCHeaderMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCHeaderMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCRouteFilter) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCRouteFilter) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCBackendRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCBackendRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/grpc_route.pb.go b/proto-public/pbmesh/v1alpha1/grpc_route.pb.go deleted file mode 100644 index 2f25aae654e70..0000000000000 --- a/proto-public/pbmesh/v1alpha1/grpc_route.pb.go +++ /dev/null @@ -1,887 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/grpc_route.proto - -package meshv1alpha1 - -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 GRPCMethodMatchType int32 - -const ( - GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_UNSPECIFIED GRPCMethodMatchType = 0 - GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT GRPCMethodMatchType = 1 - GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_REGEX GRPCMethodMatchType = 2 -) - -// Enum value maps for GRPCMethodMatchType. -var ( - GRPCMethodMatchType_name = map[int32]string{ - 0: "GRPC_METHOD_MATCH_TYPE_UNSPECIFIED", - 1: "GRPC_METHOD_MATCH_TYPE_EXACT", - 2: "GRPC_METHOD_MATCH_TYPE_REGEX", - } - GRPCMethodMatchType_value = map[string]int32{ - "GRPC_METHOD_MATCH_TYPE_UNSPECIFIED": 0, - "GRPC_METHOD_MATCH_TYPE_EXACT": 1, - "GRPC_METHOD_MATCH_TYPE_REGEX": 2, - } -) - -func (x GRPCMethodMatchType) Enum() *GRPCMethodMatchType { - p := new(GRPCMethodMatchType) - *p = x - return p -} - -func (x GRPCMethodMatchType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (GRPCMethodMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_grpc_route_proto_enumTypes[0].Descriptor() -} - -func (GRPCMethodMatchType) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_grpc_route_proto_enumTypes[0] -} - -func (x GRPCMethodMatchType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use GRPCMethodMatchType.Descriptor instead. -func (GRPCMethodMatchType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_grpc_route_proto_rawDescGZIP(), []int{0} -} - -// NOTE: this should align to the GAMMA/gateway-api version, or at least be -// easily translatable. -// -// https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRoute -// -// This is a Resource type. -type GRPCRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ParentRefs references the resources (usually Gateways) that a Route wants - // to be attached to. Note that the referenced parent resource needs to allow - // this for the attachment to be complete. For Gateways, that means the - // Gateway needs to allow attachment from Routes of this kind and namespace. - // - // It is invalid to reference an identical parent more than once. It is valid - // to reference multiple distinct sections within the same parent resource, - // such as 2 Listeners within a Gateway. - ParentRefs []*ParentReference `protobuf:"bytes,1,rep,name=parent_refs,json=parentRefs,proto3" json:"parent_refs,omitempty"` - Hostnames []string `protobuf:"bytes,2,rep,name=hostnames,proto3" json:"hostnames,omitempty"` - // Rules are a list of GRPC matchers, filters and actions. - Rules []*GRPCRouteRule `protobuf:"bytes,3,rep,name=rules,proto3" json:"rules,omitempty"` -} - -func (x *GRPCRoute) Reset() { - *x = GRPCRoute{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCRoute) ProtoMessage() {} - -func (x *GRPCRoute) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_grpc_route_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 GRPCRoute.ProtoReflect.Descriptor instead. -func (*GRPCRoute) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_grpc_route_proto_rawDescGZIP(), []int{0} -} - -func (x *GRPCRoute) GetParentRefs() []*ParentReference { - if x != nil { - return x.ParentRefs - } - return nil -} - -func (x *GRPCRoute) GetHostnames() []string { - if x != nil { - return x.Hostnames - } - return nil -} - -func (x *GRPCRoute) GetRules() []*GRPCRouteRule { - if x != nil { - return x.Rules - } - return nil -} - -type GRPCRouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Matches []*GRPCRouteMatch `protobuf:"bytes,1,rep,name=matches,proto3" json:"matches,omitempty"` - Filters []*GRPCRouteFilter `protobuf:"bytes,2,rep,name=filters,proto3" json:"filters,omitempty"` - BackendRefs []*GRPCBackendRef `protobuf:"bytes,3,rep,name=backend_refs,json=backendRefs,proto3" json:"backend_refs,omitempty"` - // ALTERNATIVE: Timeouts defines the timeouts that can be configured for an HTTP request. - Timeouts *HTTPRouteTimeouts `protobuf:"bytes,4,opt,name=timeouts,proto3" json:"timeouts,omitempty"` - // ALTERNATIVE: - Retries *HTTPRouteRetries `protobuf:"bytes,5,opt,name=retries,proto3" json:"retries,omitempty"` -} - -func (x *GRPCRouteRule) Reset() { - *x = GRPCRouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCRouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCRouteRule) ProtoMessage() {} - -func (x *GRPCRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_grpc_route_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 GRPCRouteRule.ProtoReflect.Descriptor instead. -func (*GRPCRouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_grpc_route_proto_rawDescGZIP(), []int{1} -} - -func (x *GRPCRouteRule) GetMatches() []*GRPCRouteMatch { - if x != nil { - return x.Matches - } - return nil -} - -func (x *GRPCRouteRule) GetFilters() []*GRPCRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -func (x *GRPCRouteRule) GetBackendRefs() []*GRPCBackendRef { - if x != nil { - return x.BackendRefs - } - return nil -} - -func (x *GRPCRouteRule) GetTimeouts() *HTTPRouteTimeouts { - if x != nil { - return x.Timeouts - } - return nil -} - -func (x *GRPCRouteRule) GetRetries() *HTTPRouteRetries { - if x != nil { - return x.Retries - } - return nil -} - -type GRPCRouteMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Method specifies a gRPC request service/method matcher. If this field is - // not specified, all services and methods will match. - Method *GRPCMethodMatch `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"` - // Headers specifies gRPC request header matchers. Multiple match values are - // ANDed together, meaning, a request MUST match all the specified headers to - // select the route. - Headers []*GRPCHeaderMatch `protobuf:"bytes,2,rep,name=headers,proto3" json:"headers,omitempty"` -} - -func (x *GRPCRouteMatch) Reset() { - *x = GRPCRouteMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCRouteMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCRouteMatch) ProtoMessage() {} - -func (x *GRPCRouteMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_grpc_route_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 GRPCRouteMatch.ProtoReflect.Descriptor instead. -func (*GRPCRouteMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_grpc_route_proto_rawDescGZIP(), []int{2} -} - -func (x *GRPCRouteMatch) GetMethod() *GRPCMethodMatch { - if x != nil { - return x.Method - } - return nil -} - -func (x *GRPCRouteMatch) GetHeaders() []*GRPCHeaderMatch { - if x != nil { - return x.Headers - } - return nil -} - -type GRPCMethodMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Type specifies how to match against the service and/or method. Support: - // Core (Exact with service and method specified) - Type GRPCMethodMatchType `protobuf:"varint,1,opt,name=type,proto3,enum=hashicorp.consul.mesh.v1alpha1.GRPCMethodMatchType" json:"type,omitempty"` - // Value of the service to match against. If left empty or omitted, will - // match any service. - // - // At least one of Service and Method MUST be a non-empty string. - Service string `protobuf:"bytes,2,opt,name=service,proto3" json:"service,omitempty"` - // Value of the method to match against. If left empty or omitted, will match - // all services. - // - // At least one of Service and Method MUST be a non-empty string.} - Method string `protobuf:"bytes,3,opt,name=method,proto3" json:"method,omitempty"` -} - -func (x *GRPCMethodMatch) Reset() { - *x = GRPCMethodMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCMethodMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCMethodMatch) ProtoMessage() {} - -func (x *GRPCMethodMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[3] - 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 GRPCMethodMatch.ProtoReflect.Descriptor instead. -func (*GRPCMethodMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_grpc_route_proto_rawDescGZIP(), []int{3} -} - -func (x *GRPCMethodMatch) GetType() GRPCMethodMatchType { - if x != nil { - return x.Type - } - return GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_UNSPECIFIED -} - -func (x *GRPCMethodMatch) GetService() string { - if x != nil { - return x.Service - } - return "" -} - -func (x *GRPCMethodMatch) GetMethod() string { - if x != nil { - return x.Method - } - return "" -} - -type GRPCHeaderMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Type HeaderMatchType `protobuf:"varint,1,opt,name=type,proto3,enum=hashicorp.consul.mesh.v1alpha1.HeaderMatchType" json:"type,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *GRPCHeaderMatch) Reset() { - *x = GRPCHeaderMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCHeaderMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCHeaderMatch) ProtoMessage() {} - -func (x *GRPCHeaderMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[4] - 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 GRPCHeaderMatch.ProtoReflect.Descriptor instead. -func (*GRPCHeaderMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_grpc_route_proto_rawDescGZIP(), []int{4} -} - -func (x *GRPCHeaderMatch) GetType() HeaderMatchType { - if x != nil { - return x.Type - } - return HeaderMatchType_HEADER_MATCH_TYPE_UNSPECIFIED -} - -func (x *GRPCHeaderMatch) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *GRPCHeaderMatch) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -type GRPCRouteFilter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // RequestHeaderModifier defines a schema for a filter that modifies request - // headers. - RequestHeaderModifier *HTTPHeaderFilter `protobuf:"bytes,1,opt,name=request_header_modifier,json=requestHeaderModifier,proto3" json:"request_header_modifier,omitempty"` - // ResponseHeaderModifier defines a schema for a filter that modifies - // response headers. - ResponseHeaderModifier *HTTPHeaderFilter `protobuf:"bytes,2,opt,name=response_header_modifier,json=responseHeaderModifier,proto3" json:"response_header_modifier,omitempty"` - // URLRewrite defines a schema for a filter that modifies a request during - // forwarding. - UrlRewrite *HTTPURLRewriteFilter `protobuf:"bytes,5,opt,name=url_rewrite,json=urlRewrite,proto3" json:"url_rewrite,omitempty"` -} - -func (x *GRPCRouteFilter) Reset() { - *x = GRPCRouteFilter{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCRouteFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCRouteFilter) ProtoMessage() {} - -func (x *GRPCRouteFilter) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[5] - 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 GRPCRouteFilter.ProtoReflect.Descriptor instead. -func (*GRPCRouteFilter) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_grpc_route_proto_rawDescGZIP(), []int{5} -} - -func (x *GRPCRouteFilter) GetRequestHeaderModifier() *HTTPHeaderFilter { - if x != nil { - return x.RequestHeaderModifier - } - return nil -} - -func (x *GRPCRouteFilter) GetResponseHeaderModifier() *HTTPHeaderFilter { - if x != nil { - return x.ResponseHeaderModifier - } - return nil -} - -func (x *GRPCRouteFilter) GetUrlRewrite() *HTTPURLRewriteFilter { - if x != nil { - return x.UrlRewrite - } - return nil -} - -type GRPCBackendRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BackendRef *BackendReference `protobuf:"bytes,1,opt,name=backend_ref,json=backendRef,proto3" json:"backend_ref,omitempty"` - // Weight specifies the proportion of requests forwarded to the referenced - // backend. This is computed as weight/(sum of all weights in this - // BackendRefs list). For non-zero values, there may be some epsilon from the - // exact proportion defined here depending on the precision an implementation - // supports. Weight is not a percentage and the sum of weights does not need - // to equal 100. - // - // If only one backend is specified and it has a weight greater than 0, 100% - // of the traffic is forwarded to that backend. If weight is set to 0, no - // traffic should be forwarded for this entry. If unspecified, weight defaults - // to 1. - Weight uint32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` - // Filters defined at this level should be executed if and only if the - // request is being forwarded to the backend defined here. - Filters []*GRPCRouteFilter `protobuf:"bytes,3,rep,name=filters,proto3" json:"filters,omitempty"` -} - -func (x *GRPCBackendRef) Reset() { - *x = GRPCBackendRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCBackendRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCBackendRef) ProtoMessage() {} - -func (x *GRPCBackendRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[6] - 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 GRPCBackendRef.ProtoReflect.Descriptor instead. -func (*GRPCBackendRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_grpc_route_proto_rawDescGZIP(), []int{6} -} - -func (x *GRPCBackendRef) GetBackendRef() *BackendReference { - if x != nil { - return x.BackendRef - } - return nil -} - -func (x *GRPCBackendRef) GetWeight() uint32 { - if x != nil { - return x.Weight - } - return 0 -} - -func (x *GRPCBackendRef) GetFilters() []*GRPCRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -var File_pbmesh_v1alpha1_grpc_route_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_grpc_route_proto_rawDesc = []byte{ - 0x0a, 0x20, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x1a, 0x1c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x20, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, - 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x70, 0x62, - 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x68, 0x74, - 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc0, 0x01, 0x0a, 0x09, 0x47, 0x52, 0x50, 0x43, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x50, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, - 0x72, 0x65, 0x66, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x68, 0x6f, 0x73, 0x74, - 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, - 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x92, 0x03, 0x0a, 0x0d, 0x47, - 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x48, 0x0a, 0x07, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, - 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x6d, - 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x49, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x73, 0x12, 0x51, 0x0a, 0x0c, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x42, 0x61, 0x63, - 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x52, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, - 0x52, 0x65, 0x66, 0x73, 0x12, 0x4d, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, - 0xa4, 0x01, 0x0a, 0x0e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, - 0x63, 0x68, 0x12, 0x47, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4d, 0x61, - 0x74, 0x63, 0x68, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x49, 0x0a, 0x07, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x52, - 0x50, 0x43, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0x8c, 0x01, 0x0a, 0x0f, 0x47, 0x52, 0x50, 0x43, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x47, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x16, 0x0a, - 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0x80, 0x01, 0x0a, 0x0f, 0x47, 0x52, 0x50, 0x43, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x43, 0x0a, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xbe, 0x02, 0x0a, 0x0f, 0x47, 0x52, 0x50, - 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x68, 0x0a, 0x17, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, - 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, - 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, - 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x6a, 0x0a, 0x18, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, - 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x16, 0x72, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, - 0x65, 0x72, 0x12, 0x55, 0x0a, 0x0b, 0x75, 0x72, 0x6c, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x55, 0x52, 0x4c, - 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x75, - 0x72, 0x6c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22, 0xc6, 0x01, 0x0a, 0x0e, 0x47, 0x52, - 0x50, 0x43, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x51, 0x0a, 0x0b, - 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, - 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x49, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x73, 0x2a, 0x81, 0x01, 0x0a, 0x13, 0x47, 0x52, 0x50, 0x43, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x22, 0x47, 0x52, - 0x50, 0x43, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x47, 0x52, 0x50, 0x43, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, - 0x44, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x41, - 0x43, 0x54, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x47, 0x52, 0x50, 0x43, 0x5f, 0x4d, 0x45, 0x54, - 0x48, 0x4f, 0x44, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, - 0x45, 0x47, 0x45, 0x58, 0x10, 0x02, 0x42, 0x96, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0e, 0x47, - 0x72, 0x70, 0x63, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x45, 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, 0x65, 0x73, 0x68, - 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1e, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, - 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, - 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_grpc_route_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_grpc_route_proto_rawDescData = file_pbmesh_v1alpha1_grpc_route_proto_rawDesc -) - -func file_pbmesh_v1alpha1_grpc_route_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_grpc_route_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_grpc_route_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_grpc_route_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_grpc_route_proto_rawDescData -} - -var file_pbmesh_v1alpha1_grpc_route_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v1alpha1_grpc_route_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_pbmesh_v1alpha1_grpc_route_proto_goTypes = []interface{}{ - (GRPCMethodMatchType)(0), // 0: hashicorp.consul.mesh.v1alpha1.GRPCMethodMatchType - (*GRPCRoute)(nil), // 1: hashicorp.consul.mesh.v1alpha1.GRPCRoute - (*GRPCRouteRule)(nil), // 2: hashicorp.consul.mesh.v1alpha1.GRPCRouteRule - (*GRPCRouteMatch)(nil), // 3: hashicorp.consul.mesh.v1alpha1.GRPCRouteMatch - (*GRPCMethodMatch)(nil), // 4: hashicorp.consul.mesh.v1alpha1.GRPCMethodMatch - (*GRPCHeaderMatch)(nil), // 5: hashicorp.consul.mesh.v1alpha1.GRPCHeaderMatch - (*GRPCRouteFilter)(nil), // 6: hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter - (*GRPCBackendRef)(nil), // 7: hashicorp.consul.mesh.v1alpha1.GRPCBackendRef - (*ParentReference)(nil), // 8: hashicorp.consul.mesh.v1alpha1.ParentReference - (*HTTPRouteTimeouts)(nil), // 9: hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts - (*HTTPRouteRetries)(nil), // 10: hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries - (HeaderMatchType)(0), // 11: hashicorp.consul.mesh.v1alpha1.HeaderMatchType - (*HTTPHeaderFilter)(nil), // 12: hashicorp.consul.mesh.v1alpha1.HTTPHeaderFilter - (*HTTPURLRewriteFilter)(nil), // 13: hashicorp.consul.mesh.v1alpha1.HTTPURLRewriteFilter - (*BackendReference)(nil), // 14: hashicorp.consul.mesh.v1alpha1.BackendReference -} -var file_pbmesh_v1alpha1_grpc_route_proto_depIdxs = []int32{ - 8, // 0: hashicorp.consul.mesh.v1alpha1.GRPCRoute.parent_refs:type_name -> hashicorp.consul.mesh.v1alpha1.ParentReference - 2, // 1: hashicorp.consul.mesh.v1alpha1.GRPCRoute.rules:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCRouteRule - 3, // 2: hashicorp.consul.mesh.v1alpha1.GRPCRouteRule.matches:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCRouteMatch - 6, // 3: hashicorp.consul.mesh.v1alpha1.GRPCRouteRule.filters:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter - 7, // 4: hashicorp.consul.mesh.v1alpha1.GRPCRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCBackendRef - 9, // 5: hashicorp.consul.mesh.v1alpha1.GRPCRouteRule.timeouts:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts - 10, // 6: hashicorp.consul.mesh.v1alpha1.GRPCRouteRule.retries:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries - 4, // 7: hashicorp.consul.mesh.v1alpha1.GRPCRouteMatch.method:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCMethodMatch - 5, // 8: hashicorp.consul.mesh.v1alpha1.GRPCRouteMatch.headers:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCHeaderMatch - 0, // 9: hashicorp.consul.mesh.v1alpha1.GRPCMethodMatch.type:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCMethodMatchType - 11, // 10: hashicorp.consul.mesh.v1alpha1.GRPCHeaderMatch.type:type_name -> hashicorp.consul.mesh.v1alpha1.HeaderMatchType - 12, // 11: hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter.request_header_modifier:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPHeaderFilter - 12, // 12: hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter.response_header_modifier:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPHeaderFilter - 13, // 13: hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter.url_rewrite:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPURLRewriteFilter - 14, // 14: hashicorp.consul.mesh.v1alpha1.GRPCBackendRef.backend_ref:type_name -> hashicorp.consul.mesh.v1alpha1.BackendReference - 6, // 15: hashicorp.consul.mesh.v1alpha1.GRPCBackendRef.filters:type_name -> hashicorp.consul.mesh.v1alpha1.GRPCRouteFilter - 16, // [16:16] is the sub-list for method output_type - 16, // [16:16] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_grpc_route_proto_init() } -func file_pbmesh_v1alpha1_grpc_route_proto_init() { - if File_pbmesh_v1alpha1_grpc_route_proto != nil { - return - } - file_pbmesh_v1alpha1_common_proto_init() - file_pbmesh_v1alpha1_http_route_proto_init() - file_pbmesh_v1alpha1_http_route_retries_proto_init() - file_pbmesh_v1alpha1_http_route_timeouts_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCRoute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCRouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCRouteMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCMethodMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCHeaderMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCRouteFilter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_grpc_route_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCBackendRef); 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_pbmesh_v1alpha1_grpc_route_proto_rawDesc, - NumEnums: 1, - NumMessages: 7, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_grpc_route_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_grpc_route_proto_depIdxs, - EnumInfos: file_pbmesh_v1alpha1_grpc_route_proto_enumTypes, - MessageInfos: file_pbmesh_v1alpha1_grpc_route_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_grpc_route_proto = out.File - file_pbmesh_v1alpha1_grpc_route_proto_rawDesc = nil - file_pbmesh_v1alpha1_grpc_route_proto_goTypes = nil - file_pbmesh_v1alpha1_grpc_route_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/grpc_route.proto b/proto-public/pbmesh/v1alpha1/grpc_route.proto deleted file mode 100644 index ce4ca4d917ca8..0000000000000 --- a/proto-public/pbmesh/v1alpha1/grpc_route.proto +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1; - -import "pbmesh/v1alpha1/common.proto"; -import "pbmesh/v1alpha1/http_route.proto"; -import "pbmesh/v1alpha1/http_route_retries.proto"; -import "pbmesh/v1alpha1/http_route_timeouts.proto"; - -// NOTE: this should align to the GAMMA/gateway-api version, or at least be -// easily translatable. -// -// https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRoute -// -// This is a Resource type. -message GRPCRoute { - // ParentRefs references the resources (usually Gateways) that a Route wants - // to be attached to. Note that the referenced parent resource needs to allow - // this for the attachment to be complete. For Gateways, that means the - // Gateway needs to allow attachment from Routes of this kind and namespace. - // - // It is invalid to reference an identical parent more than once. It is valid - // to reference multiple distinct sections within the same parent resource, - // such as 2 Listeners within a Gateway. - repeated ParentReference parent_refs = 1; - - repeated string hostnames = 2; - - // Rules are a list of GRPC matchers, filters and actions. - repeated GRPCRouteRule rules = 3; -} - -message GRPCRouteRule { - repeated GRPCRouteMatch matches = 1; - repeated GRPCRouteFilter filters = 2; - repeated GRPCBackendRef backend_refs = 3; - - // ALTERNATIVE: Timeouts defines the timeouts that can be configured for an HTTP request. - HTTPRouteTimeouts timeouts = 4; - // ALTERNATIVE: - HTTPRouteRetries retries = 5; -} - -message GRPCRouteMatch { - // Method specifies a gRPC request service/method matcher. If this field is - // not specified, all services and methods will match. - GRPCMethodMatch method = 1; - - // Headers specifies gRPC request header matchers. Multiple match values are - // ANDed together, meaning, a request MUST match all the specified headers to - // select the route. - repeated GRPCHeaderMatch headers = 2; -} - -message GRPCMethodMatch { - // Type specifies how to match against the service and/or method. Support: - // Core (Exact with service and method specified) - GRPCMethodMatchType type = 1; - - // Value of the service to match against. If left empty or omitted, will - // match any service. - // - // At least one of Service and Method MUST be a non-empty string. - string service = 2; - - // Value of the method to match against. If left empty or omitted, will match - // all services. - // - // At least one of Service and Method MUST be a non-empty string.} - string method = 3; -} - -enum GRPCMethodMatchType { - GRPC_METHOD_MATCH_TYPE_UNSPECIFIED = 0; - GRPC_METHOD_MATCH_TYPE_EXACT = 1; - GRPC_METHOD_MATCH_TYPE_REGEX = 2; -} - -message GRPCHeaderMatch { - HeaderMatchType type = 1; - string name = 2; - string value = 3; -} - -message GRPCRouteFilter { - // RequestHeaderModifier defines a schema for a filter that modifies request - // headers. - HTTPHeaderFilter request_header_modifier = 1; - - // ResponseHeaderModifier defines a schema for a filter that modifies - // response headers. - HTTPHeaderFilter response_header_modifier = 2; - - // URLRewrite defines a schema for a filter that modifies a request during - // forwarding. - HTTPURLRewriteFilter url_rewrite = 5; -} - -message GRPCBackendRef { - BackendReference backend_ref = 1; - - // Weight specifies the proportion of requests forwarded to the referenced - // backend. This is computed as weight/(sum of all weights in this - // BackendRefs list). For non-zero values, there may be some epsilon from the - // exact proportion defined here depending on the precision an implementation - // supports. Weight is not a percentage and the sum of weights does not need - // to equal 100. - // - //If only one backend is specified and it has a weight greater than 0, 100% - //of the traffic is forwarded to that backend. If weight is set to 0, no - //traffic should be forwarded for this entry. If unspecified, weight defaults - //to 1. - uint32 weight = 2; - - // Filters defined at this level should be executed if and only if the - // request is being forwarded to the backend defined here. - repeated GRPCRouteFilter filters = 3; -} diff --git a/proto-public/pbmesh/v1alpha1/http_route.pb.binary.go b/proto-public/pbmesh/v1alpha1/http_route.pb.binary.go deleted file mode 100644 index 81b3901a5bd98..0000000000000 --- a/proto-public/pbmesh/v1alpha1/http_route.pb.binary.go +++ /dev/null @@ -1,118 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/http_route.proto - -package meshv1alpha1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPRoute) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPRoute) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPRouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPRouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPRouteMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPRouteMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPPathMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPPathMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPHeaderMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPHeaderMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPQueryParamMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPQueryParamMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPRouteFilter) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPRouteFilter) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPHeaderFilter) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPHeaderFilter) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPHeader) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPHeader) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPURLRewriteFilter) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPURLRewriteFilter) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPBackendRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPBackendRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/http_route.pb.go b/proto-public/pbmesh/v1alpha1/http_route.pb.go deleted file mode 100644 index f69b84f226568..0000000000000 --- a/proto-public/pbmesh/v1alpha1/http_route.pb.go +++ /dev/null @@ -1,1441 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/http_route.proto - -package meshv1alpha1 - -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) -) - -// PathMatchType specifies the semantics of how HTTP paths should be compared. -// Valid PathMatchType values, along with their support levels, are: -// -// PathPrefix and Exact paths must be syntactically valid: -// -// - Must begin with the / character -// - Must not contain consecutive / characters (e.g. /foo///, //). -// - Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the Accepted -// Condition for the Route to status: False, with a Reason of UnsupportedValue. -type PathMatchType int32 - -const ( - PathMatchType_PATH_MATCH_TYPE_UNSPECIFIED PathMatchType = 0 - PathMatchType_PATH_MATCH_TYPE_EXACT PathMatchType = 1 - PathMatchType_PATH_MATCH_TYPE_PREFIX PathMatchType = 2 - PathMatchType_PATH_MATCH_TYPE_REGEX PathMatchType = 3 -) - -// Enum value maps for PathMatchType. -var ( - PathMatchType_name = map[int32]string{ - 0: "PATH_MATCH_TYPE_UNSPECIFIED", - 1: "PATH_MATCH_TYPE_EXACT", - 2: "PATH_MATCH_TYPE_PREFIX", - 3: "PATH_MATCH_TYPE_REGEX", - } - PathMatchType_value = map[string]int32{ - "PATH_MATCH_TYPE_UNSPECIFIED": 0, - "PATH_MATCH_TYPE_EXACT": 1, - "PATH_MATCH_TYPE_PREFIX": 2, - "PATH_MATCH_TYPE_REGEX": 3, - } -) - -func (x PathMatchType) Enum() *PathMatchType { - p := new(PathMatchType) - *p = x - return p -} - -func (x PathMatchType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (PathMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_http_route_proto_enumTypes[0].Descriptor() -} - -func (PathMatchType) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_http_route_proto_enumTypes[0] -} - -func (x PathMatchType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use PathMatchType.Descriptor instead. -func (PathMatchType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{0} -} - -// HeaderMatchType specifies the semantics of how HTTP header values should be -// compared. Valid HeaderMatchType values, along with their conformance levels, -// are: -// -// Note that values may be added to this enum, implementations must ensure that -// unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the Accepted -// Condition for the Route to status: False, with a Reason of UnsupportedValue. -type HeaderMatchType int32 - -const ( - HeaderMatchType_HEADER_MATCH_TYPE_UNSPECIFIED HeaderMatchType = 0 - HeaderMatchType_HEADER_MATCH_TYPE_EXACT HeaderMatchType = 1 - HeaderMatchType_HEADER_MATCH_TYPE_REGEX HeaderMatchType = 2 - // consul only after this point (service-router compat) - HeaderMatchType_HEADER_MATCH_TYPE_PRESENT HeaderMatchType = 3 - HeaderMatchType_HEADER_MATCH_TYPE_PREFIX HeaderMatchType = 4 - HeaderMatchType_HEADER_MATCH_TYPE_SUFFIX HeaderMatchType = 5 -) - -// Enum value maps for HeaderMatchType. -var ( - HeaderMatchType_name = map[int32]string{ - 0: "HEADER_MATCH_TYPE_UNSPECIFIED", - 1: "HEADER_MATCH_TYPE_EXACT", - 2: "HEADER_MATCH_TYPE_REGEX", - 3: "HEADER_MATCH_TYPE_PRESENT", - 4: "HEADER_MATCH_TYPE_PREFIX", - 5: "HEADER_MATCH_TYPE_SUFFIX", - } - HeaderMatchType_value = map[string]int32{ - "HEADER_MATCH_TYPE_UNSPECIFIED": 0, - "HEADER_MATCH_TYPE_EXACT": 1, - "HEADER_MATCH_TYPE_REGEX": 2, - "HEADER_MATCH_TYPE_PRESENT": 3, - "HEADER_MATCH_TYPE_PREFIX": 4, - "HEADER_MATCH_TYPE_SUFFIX": 5, - } -) - -func (x HeaderMatchType) Enum() *HeaderMatchType { - p := new(HeaderMatchType) - *p = x - return p -} - -func (x HeaderMatchType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (HeaderMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_http_route_proto_enumTypes[1].Descriptor() -} - -func (HeaderMatchType) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_http_route_proto_enumTypes[1] -} - -func (x HeaderMatchType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use HeaderMatchType.Descriptor instead. -func (HeaderMatchType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{1} -} - -type QueryParamMatchType int32 - -const ( - QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_UNSPECIFIED QueryParamMatchType = 0 - QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT QueryParamMatchType = 1 - QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_REGEX QueryParamMatchType = 2 - // consul only after this point (service-router compat) - QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_PRESENT QueryParamMatchType = 3 -) - -// Enum value maps for QueryParamMatchType. -var ( - QueryParamMatchType_name = map[int32]string{ - 0: "QUERY_PARAM_MATCH_TYPE_UNSPECIFIED", - 1: "QUERY_PARAM_MATCH_TYPE_EXACT", - 2: "QUERY_PARAM_MATCH_TYPE_REGEX", - 3: "QUERY_PARAM_MATCH_TYPE_PRESENT", - } - QueryParamMatchType_value = map[string]int32{ - "QUERY_PARAM_MATCH_TYPE_UNSPECIFIED": 0, - "QUERY_PARAM_MATCH_TYPE_EXACT": 1, - "QUERY_PARAM_MATCH_TYPE_REGEX": 2, - "QUERY_PARAM_MATCH_TYPE_PRESENT": 3, - } -) - -func (x QueryParamMatchType) Enum() *QueryParamMatchType { - p := new(QueryParamMatchType) - *p = x - return p -} - -func (x QueryParamMatchType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (QueryParamMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_http_route_proto_enumTypes[2].Descriptor() -} - -func (QueryParamMatchType) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_http_route_proto_enumTypes[2] -} - -func (x QueryParamMatchType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use QueryParamMatchType.Descriptor instead. -func (QueryParamMatchType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{2} -} - -// NOTE: this should align to the GAMMA/gateway-api version, or at least be -// easily translatable. -// -// https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.HTTPRoute -// -// This is a Resource type. -type HTTPRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ParentRefs references the resources (usually Gateways) that a Route wants - // to be attached to. Note that the referenced parent resource needs to allow - // this for the attachment to be complete. For Gateways, that means the - // Gateway needs to allow attachment from Routes of this kind and namespace. - // - // It is invalid to reference an identical parent more than once. It is valid - // to reference multiple distinct sections within the same parent resource, - // such as 2 Listeners within a Gateway. - ParentRefs []*ParentReference `protobuf:"bytes,1,rep,name=parent_refs,json=parentRefs,proto3" json:"parent_refs,omitempty"` - // Hostnames are the hostnames for which this HTTPRoute should respond to requests. - Hostnames []string `protobuf:"bytes,2,rep,name=hostnames,proto3" json:"hostnames,omitempty"` - // Rules are a list of HTTP-based routing rules that this route should - // use for constructing a routing table. - Rules []*HTTPRouteRule `protobuf:"bytes,3,rep,name=rules,proto3" json:"rules,omitempty"` -} - -func (x *HTTPRoute) Reset() { - *x = HTTPRoute{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPRoute) ProtoMessage() {} - -func (x *HTTPRoute) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_http_route_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 HTTPRoute.ProtoReflect.Descriptor instead. -func (*HTTPRoute) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{0} -} - -func (x *HTTPRoute) GetParentRefs() []*ParentReference { - if x != nil { - return x.ParentRefs - } - return nil -} - -func (x *HTTPRoute) GetHostnames() []string { - if x != nil { - return x.Hostnames - } - return nil -} - -func (x *HTTPRoute) GetRules() []*HTTPRouteRule { - if x != nil { - return x.Rules - } - return nil -} - -// HTTPRouteRule specifies the routing rules used to determine what upstream -// service an HTTP request is routed to. -type HTTPRouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Matches specified the matching criteria used in the routing table. If a - // request matches the given HTTPMatch configuration, then traffic is routed - // to services specified in the Services field. - Matches []*HTTPRouteMatch `protobuf:"bytes,1,rep,name=matches,proto3" json:"matches,omitempty"` - Filters []*HTTPRouteFilter `protobuf:"bytes,2,rep,name=filters,proto3" json:"filters,omitempty"` - // BackendRefs defines the backend(s) where matching requests should be sent. - // - // Failure behavior here depends on how many BackendRefs are specified and - // how many are invalid. - // - // If all entries in BackendRefs are invalid, and there are also no filters - // specified in this route rule, all traffic which matches this rule MUST - // receive a 500 status code. - // - // See the HTTPBackendRef definition for the rules about what makes a single - // HTTPBackendRef invalid. - // - // When a HTTPBackendRef is invalid, 500 status codes MUST be returned for - // requests that would have otherwise been routed to an invalid backend. If - // multiple backends are specified, and some are invalid, the proportion of - // requests that would otherwise have been routed to an invalid backend MUST - // receive a 500 status code. - // - // For example, if two backends are specified with equal weights, and one is - // invalid, 50 percent of traffic must receive a 500. Implementations may - // choose how that 50 percent is determined. - BackendRefs []*HTTPBackendRef `protobuf:"bytes,3,rep,name=backend_refs,json=backendRefs,proto3" json:"backend_refs,omitempty"` - // ALTERNATIVE: Timeouts defines the timeouts that can be configured for an HTTP request. - Timeouts *HTTPRouteTimeouts `protobuf:"bytes,4,opt,name=timeouts,proto3" json:"timeouts,omitempty"` - // ALTERNATIVE: - Retries *HTTPRouteRetries `protobuf:"bytes,5,opt,name=retries,proto3" json:"retries,omitempty"` -} - -func (x *HTTPRouteRule) Reset() { - *x = HTTPRouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPRouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPRouteRule) ProtoMessage() {} - -func (x *HTTPRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_http_route_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 HTTPRouteRule.ProtoReflect.Descriptor instead. -func (*HTTPRouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{1} -} - -func (x *HTTPRouteRule) GetMatches() []*HTTPRouteMatch { - if x != nil { - return x.Matches - } - return nil -} - -func (x *HTTPRouteRule) GetFilters() []*HTTPRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -func (x *HTTPRouteRule) GetBackendRefs() []*HTTPBackendRef { - if x != nil { - return x.BackendRefs - } - return nil -} - -func (x *HTTPRouteRule) GetTimeouts() *HTTPRouteTimeouts { - if x != nil { - return x.Timeouts - } - return nil -} - -func (x *HTTPRouteRule) GetRetries() *HTTPRouteRetries { - if x != nil { - return x.Retries - } - return nil -} - -type HTTPRouteMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Path specifies a HTTP request path matcher. If this field is not - // specified, a default prefix match on the “/” path is provided. - Path *HTTPPathMatch `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - // Headers specifies HTTP request header matchers. Multiple match values are - // ANDed together, meaning, a request must match all the specified headers to - // select the route. - Headers []*HTTPHeaderMatch `protobuf:"bytes,2,rep,name=headers,proto3" json:"headers,omitempty"` - // QueryParams specifies HTTP query parameter matchers. Multiple match values - // are ANDed together, meaning, a request must match all the specified query - // parameters to select the route. - QueryParams []*HTTPQueryParamMatch `protobuf:"bytes,3,rep,name=query_params,json=queryParams,proto3" json:"query_params,omitempty"` - // Method specifies HTTP method matcher. When specified, this route will be - // matched only if the request has the specified method. - Method string `protobuf:"bytes,4,opt,name=method,proto3" json:"method,omitempty"` -} - -func (x *HTTPRouteMatch) Reset() { - *x = HTTPRouteMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPRouteMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPRouteMatch) ProtoMessage() {} - -func (x *HTTPRouteMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_http_route_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 HTTPRouteMatch.ProtoReflect.Descriptor instead. -func (*HTTPRouteMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{2} -} - -func (x *HTTPRouteMatch) GetPath() *HTTPPathMatch { - if x != nil { - return x.Path - } - return nil -} - -func (x *HTTPRouteMatch) GetHeaders() []*HTTPHeaderMatch { - if x != nil { - return x.Headers - } - return nil -} - -func (x *HTTPRouteMatch) GetQueryParams() []*HTTPQueryParamMatch { - if x != nil { - return x.QueryParams - } - return nil -} - -func (x *HTTPRouteMatch) GetMethod() string { - if x != nil { - return x.Method - } - return "" -} - -type HTTPPathMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Type specifies how to match against the path Value. - Type PathMatchType `protobuf:"varint,1,opt,name=type,proto3,enum=hashicorp.consul.mesh.v1alpha1.PathMatchType" json:"type,omitempty"` - // Value of the HTTP path to match against. - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *HTTPPathMatch) Reset() { - *x = HTTPPathMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPPathMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPPathMatch) ProtoMessage() {} - -func (x *HTTPPathMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[3] - 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 HTTPPathMatch.ProtoReflect.Descriptor instead. -func (*HTTPPathMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{3} -} - -func (x *HTTPPathMatch) GetType() PathMatchType { - if x != nil { - return x.Type - } - return PathMatchType_PATH_MATCH_TYPE_UNSPECIFIED -} - -func (x *HTTPPathMatch) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -type HTTPHeaderMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Type specifies how to match against the value of the header. - Type HeaderMatchType `protobuf:"varint,1,opt,name=type,proto3,enum=hashicorp.consul.mesh.v1alpha1.HeaderMatchType" json:"type,omitempty"` - // Name is the name of the HTTP Header to be matched. Name matching MUST be - // case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - // - // If multiple entries specify equivalent header names, only the first entry - // with an equivalent name MUST be considered for a match. Subsequent entries - // with an equivalent header name MUST be ignored. Due to the - // case-insensitivity of header names, “foo” and “Foo” are considered - // equivalent. - // - // When a header is repeated in an HTTP request, it is - // implementation-specific behavior as to how this is represented. Generally, - // proxies should follow the guidance from the RFC: - // https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - // processing a repeated header, with special handling for “Set-Cookie”. - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - // Value is the value of HTTP Header to be matched. - Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` - // NOTE: not in gamma; service-router compat - Invert bool `protobuf:"varint,4,opt,name=invert,proto3" json:"invert,omitempty"` -} - -func (x *HTTPHeaderMatch) Reset() { - *x = HTTPHeaderMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPHeaderMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPHeaderMatch) ProtoMessage() {} - -func (x *HTTPHeaderMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[4] - 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 HTTPHeaderMatch.ProtoReflect.Descriptor instead. -func (*HTTPHeaderMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{4} -} - -func (x *HTTPHeaderMatch) GetType() HeaderMatchType { - if x != nil { - return x.Type - } - return HeaderMatchType_HEADER_MATCH_TYPE_UNSPECIFIED -} - -func (x *HTTPHeaderMatch) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *HTTPHeaderMatch) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -func (x *HTTPHeaderMatch) GetInvert() bool { - if x != nil { - return x.Invert - } - return false -} - -type HTTPQueryParamMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Type specifies how to match against the value of the query parameter. - Type QueryParamMatchType `protobuf:"varint,1,opt,name=type,proto3,enum=hashicorp.consul.mesh.v1alpha1.QueryParamMatchType" json:"type,omitempty"` - // Name is the name of the HTTP query param to be matched. This must be an - // exact string match. (See - // https://tools.ietf.org/html/rfc7230#section-2.7.3). - // - // If multiple entries specify equivalent query param names, only the first - // entry with an equivalent name MUST be considered for a match. Subsequent - // entries with an equivalent query param name MUST be ignored. - // - // If a query param is repeated in an HTTP request, the behavior is purposely - // left undefined, since different data planes have different capabilities. - // However, it is recommended that implementations should match against the - // first value of the param if the data plane supports it, as this behavior - // is expected in other load balancing contexts outside of the Gateway API. - // - // Users SHOULD NOT route traffic based on repeated query params to guard - // themselves against potential differences in the implementations. - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - // Value is the value of HTTP query param to be matched. - Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *HTTPQueryParamMatch) Reset() { - *x = HTTPQueryParamMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPQueryParamMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPQueryParamMatch) ProtoMessage() {} - -func (x *HTTPQueryParamMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[5] - 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 HTTPQueryParamMatch.ProtoReflect.Descriptor instead. -func (*HTTPQueryParamMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{5} -} - -func (x *HTTPQueryParamMatch) GetType() QueryParamMatchType { - if x != nil { - return x.Type - } - return QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_UNSPECIFIED -} - -func (x *HTTPQueryParamMatch) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *HTTPQueryParamMatch) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -type HTTPRouteFilter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // RequestHeaderModifier defines a schema for a filter that modifies request - // headers. - RequestHeaderModifier *HTTPHeaderFilter `protobuf:"bytes,1,opt,name=request_header_modifier,json=requestHeaderModifier,proto3" json:"request_header_modifier,omitempty"` - // ResponseHeaderModifier defines a schema for a filter that modifies - // response headers. - ResponseHeaderModifier *HTTPHeaderFilter `protobuf:"bytes,2,opt,name=response_header_modifier,json=responseHeaderModifier,proto3" json:"response_header_modifier,omitempty"` - // URLRewrite defines a schema for a filter that modifies a request during - // forwarding. - UrlRewrite *HTTPURLRewriteFilter `protobuf:"bytes,5,opt,name=url_rewrite,json=urlRewrite,proto3" json:"url_rewrite,omitempty"` -} - -func (x *HTTPRouteFilter) Reset() { - *x = HTTPRouteFilter{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPRouteFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPRouteFilter) ProtoMessage() {} - -func (x *HTTPRouteFilter) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[6] - 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 HTTPRouteFilter.ProtoReflect.Descriptor instead. -func (*HTTPRouteFilter) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{6} -} - -func (x *HTTPRouteFilter) GetRequestHeaderModifier() *HTTPHeaderFilter { - if x != nil { - return x.RequestHeaderModifier - } - return nil -} - -func (x *HTTPRouteFilter) GetResponseHeaderModifier() *HTTPHeaderFilter { - if x != nil { - return x.ResponseHeaderModifier - } - return nil -} - -func (x *HTTPRouteFilter) GetUrlRewrite() *HTTPURLRewriteFilter { - if x != nil { - return x.UrlRewrite - } - return nil -} - -type HTTPHeaderFilter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Set overwrites the request with the given header (name, value) before the - // action. - Set []*HTTPHeader `protobuf:"bytes,1,rep,name=set,proto3" json:"set,omitempty"` - // Add adds the given header(s) (name, value) to the request before the - // action. It appends to any existing values associated with the header name. - Add []*HTTPHeader `protobuf:"bytes,2,rep,name=add,proto3" json:"add,omitempty"` - // Remove the given header(s) from the HTTP request before the action. The - // value of Remove is a list of HTTP header names. Note that the header names - // are case-insensitive (see - // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - Remove []string `protobuf:"bytes,3,rep,name=remove,proto3" json:"remove,omitempty"` -} - -func (x *HTTPHeaderFilter) Reset() { - *x = HTTPHeaderFilter{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPHeaderFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPHeaderFilter) ProtoMessage() {} - -func (x *HTTPHeaderFilter) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[7] - 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 HTTPHeaderFilter.ProtoReflect.Descriptor instead. -func (*HTTPHeaderFilter) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{7} -} - -func (x *HTTPHeaderFilter) GetSet() []*HTTPHeader { - if x != nil { - return x.Set - } - return nil -} - -func (x *HTTPHeaderFilter) GetAdd() []*HTTPHeader { - if x != nil { - return x.Add - } - return nil -} - -func (x *HTTPHeaderFilter) GetRemove() []string { - if x != nil { - return x.Remove - } - return nil -} - -type HTTPHeader struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *HTTPHeader) Reset() { - *x = HTTPHeader{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPHeader) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPHeader) ProtoMessage() {} - -func (x *HTTPHeader) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[8] - 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 HTTPHeader.ProtoReflect.Descriptor instead. -func (*HTTPHeader) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{8} -} - -func (x *HTTPHeader) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *HTTPHeader) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -type HTTPURLRewriteFilter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PathPrefix string `protobuf:"bytes,1,opt,name=path_prefix,json=pathPrefix,proto3" json:"path_prefix,omitempty"` -} - -func (x *HTTPURLRewriteFilter) Reset() { - *x = HTTPURLRewriteFilter{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPURLRewriteFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPURLRewriteFilter) ProtoMessage() {} - -func (x *HTTPURLRewriteFilter) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[9] - 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 HTTPURLRewriteFilter.ProtoReflect.Descriptor instead. -func (*HTTPURLRewriteFilter) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{9} -} - -func (x *HTTPURLRewriteFilter) GetPathPrefix() string { - if x != nil { - return x.PathPrefix - } - return "" -} - -type HTTPBackendRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BackendRef *BackendReference `protobuf:"bytes,1,opt,name=backend_ref,json=backendRef,proto3" json:"backend_ref,omitempty"` - // Weight specifies the proportion of requests forwarded to the referenced - // backend. This is computed as weight/(sum of all weights in this - // BackendRefs list). For non-zero values, there may be some epsilon from the - // exact proportion defined here depending on the precision an implementation - // supports. Weight is not a percentage and the sum of weights does not need - // to equal 100. - // - // If only one backend is specified and it has a weight greater than 0, 100% - // of the traffic is forwarded to that backend. If weight is set to 0, no - // traffic should be forwarded for this entry. If unspecified, weight defaults - // to 1. - Weight uint32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` - // Filters defined at this level should be executed if and only if the - // request is being forwarded to the backend defined here. - Filters []*HTTPRouteFilter `protobuf:"bytes,3,rep,name=filters,proto3" json:"filters,omitempty"` -} - -func (x *HTTPBackendRef) Reset() { - *x = HTTPBackendRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPBackendRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPBackendRef) ProtoMessage() {} - -func (x *HTTPBackendRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_http_route_proto_msgTypes[10] - 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 HTTPBackendRef.ProtoReflect.Descriptor instead. -func (*HTTPBackendRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP(), []int{10} -} - -func (x *HTTPBackendRef) GetBackendRef() *BackendReference { - if x != nil { - return x.BackendRef - } - return nil -} - -func (x *HTTPBackendRef) GetWeight() uint32 { - if x != nil { - return x.Weight - } - return 0 -} - -func (x *HTTPBackendRef) GetFilters() []*HTTPRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -var File_pbmesh_v1alpha1_http_route_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_http_route_proto_rawDesc = []byte{ - 0x0a, 0x20, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x1a, 0x1c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x70, 0x62, 0x6d, 0x65, - 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, - 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc0, 0x01, 0x0a, 0x09, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x12, 0x50, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, - 0x66, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x66, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, - 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x92, 0x03, 0x0a, 0x0d, 0x48, 0x54, 0x54, - 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x48, 0x0a, 0x07, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, - 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x6d, 0x61, 0x74, - 0x63, 0x68, 0x65, 0x73, 0x12, 0x49, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, - 0x51, 0x0a, 0x0c, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, - 0x6e, 0x64, 0x52, 0x65, 0x66, 0x52, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, - 0x66, 0x73, 0x12, 0x4d, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x73, 0x12, 0x4a, 0x0a, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x52, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0x8e, 0x02, - 0x0a, 0x0e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x12, 0x41, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x12, 0x49, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x56, - 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x0b, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0x68, - 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, - 0x41, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, - 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x98, 0x01, 0x0a, 0x0f, 0x48, 0x54, 0x54, - 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x43, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x69, - 0x6e, 0x76, 0x65, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x6e, 0x76, - 0x65, 0x72, 0x74, 0x22, 0x88, 0x01, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x47, 0x0a, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xbe, - 0x02, 0x0a, 0x0f, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x12, 0x68, 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x6a, 0x0a, 0x18, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, - 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x52, 0x16, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x55, 0x0a, 0x0b, 0x75, 0x72, 0x6c, 0x5f, - 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, - 0x54, 0x54, 0x50, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x52, 0x0a, 0x75, 0x72, 0x6c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22, - 0xa6, 0x01, 0x0a, 0x10, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x12, 0x3c, 0x0a, 0x03, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x03, 0x73, - 0x65, 0x74, 0x12, 0x3c, 0x0a, 0x03, 0x61, 0x64, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x03, 0x61, 0x64, 0x64, - 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x22, 0x36, 0x0a, 0x0a, 0x48, 0x54, 0x54, 0x50, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x37, 0x0a, 0x14, 0x48, 0x54, 0x54, 0x50, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, - 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x74, 0x68, - 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, - 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0xc6, 0x01, 0x0a, 0x0e, 0x48, 0x54, - 0x54, 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x51, 0x0a, 0x0b, - 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, - 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x49, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x73, 0x2a, 0x82, 0x01, 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x50, 0x41, 0x54, 0x48, 0x5f, 0x4d, 0x41, 0x54, - 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x50, 0x41, 0x54, 0x48, 0x5f, 0x4d, 0x41, - 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x41, 0x43, 0x54, 0x10, 0x01, - 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x41, 0x54, 0x48, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, - 0x50, 0x41, 0x54, 0x48, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x52, 0x45, 0x47, 0x45, 0x58, 0x10, 0x03, 0x2a, 0xc9, 0x01, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x48, - 0x45, 0x41, 0x44, 0x45, 0x52, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, - 0x0a, 0x17, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x41, 0x43, 0x54, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x48, - 0x45, 0x41, 0x44, 0x45, 0x52, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x52, 0x45, 0x47, 0x45, 0x58, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x48, 0x45, 0x41, 0x44, - 0x45, 0x52, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x52, - 0x45, 0x53, 0x45, 0x4e, 0x54, 0x10, 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x48, 0x45, 0x41, 0x44, 0x45, - 0x52, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x52, 0x45, - 0x46, 0x49, 0x58, 0x10, 0x04, 0x12, 0x1c, 0x0a, 0x18, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5f, - 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, 0x46, 0x46, 0x49, - 0x58, 0x10, 0x05, 0x2a, 0xa5, 0x01, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x22, 0x51, - 0x55, 0x45, 0x52, 0x59, 0x5f, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x51, 0x55, 0x45, 0x52, 0x59, 0x5f, 0x50, 0x41, 0x52, - 0x41, 0x4d, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, - 0x41, 0x43, 0x54, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x51, 0x55, 0x45, 0x52, 0x59, 0x5f, 0x50, - 0x41, 0x52, 0x41, 0x4d, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x52, 0x45, 0x47, 0x45, 0x58, 0x10, 0x02, 0x12, 0x22, 0x0a, 0x1e, 0x51, 0x55, 0x45, 0x52, 0x59, - 0x5f, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x50, 0x52, 0x45, 0x53, 0x45, 0x4e, 0x54, 0x10, 0x03, 0x42, 0x96, 0x02, 0x0a, 0x22, - 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x42, 0x0e, 0x48, 0x74, 0x74, 0x70, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, - 0x65, 0x73, 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, - 0x4d, 0xaa, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_http_route_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_http_route_proto_rawDescData = file_pbmesh_v1alpha1_http_route_proto_rawDesc -) - -func file_pbmesh_v1alpha1_http_route_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_http_route_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_http_route_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_http_route_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_http_route_proto_rawDescData -} - -var file_pbmesh_v1alpha1_http_route_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_pbmesh_v1alpha1_http_route_proto_msgTypes = make([]protoimpl.MessageInfo, 11) -var file_pbmesh_v1alpha1_http_route_proto_goTypes = []interface{}{ - (PathMatchType)(0), // 0: hashicorp.consul.mesh.v1alpha1.PathMatchType - (HeaderMatchType)(0), // 1: hashicorp.consul.mesh.v1alpha1.HeaderMatchType - (QueryParamMatchType)(0), // 2: hashicorp.consul.mesh.v1alpha1.QueryParamMatchType - (*HTTPRoute)(nil), // 3: hashicorp.consul.mesh.v1alpha1.HTTPRoute - (*HTTPRouteRule)(nil), // 4: hashicorp.consul.mesh.v1alpha1.HTTPRouteRule - (*HTTPRouteMatch)(nil), // 5: hashicorp.consul.mesh.v1alpha1.HTTPRouteMatch - (*HTTPPathMatch)(nil), // 6: hashicorp.consul.mesh.v1alpha1.HTTPPathMatch - (*HTTPHeaderMatch)(nil), // 7: hashicorp.consul.mesh.v1alpha1.HTTPHeaderMatch - (*HTTPQueryParamMatch)(nil), // 8: hashicorp.consul.mesh.v1alpha1.HTTPQueryParamMatch - (*HTTPRouteFilter)(nil), // 9: hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter - (*HTTPHeaderFilter)(nil), // 10: hashicorp.consul.mesh.v1alpha1.HTTPHeaderFilter - (*HTTPHeader)(nil), // 11: hashicorp.consul.mesh.v1alpha1.HTTPHeader - (*HTTPURLRewriteFilter)(nil), // 12: hashicorp.consul.mesh.v1alpha1.HTTPURLRewriteFilter - (*HTTPBackendRef)(nil), // 13: hashicorp.consul.mesh.v1alpha1.HTTPBackendRef - (*ParentReference)(nil), // 14: hashicorp.consul.mesh.v1alpha1.ParentReference - (*HTTPRouteTimeouts)(nil), // 15: hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts - (*HTTPRouteRetries)(nil), // 16: hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries - (*BackendReference)(nil), // 17: hashicorp.consul.mesh.v1alpha1.BackendReference -} -var file_pbmesh_v1alpha1_http_route_proto_depIdxs = []int32{ - 14, // 0: hashicorp.consul.mesh.v1alpha1.HTTPRoute.parent_refs:type_name -> hashicorp.consul.mesh.v1alpha1.ParentReference - 4, // 1: hashicorp.consul.mesh.v1alpha1.HTTPRoute.rules:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteRule - 5, // 2: hashicorp.consul.mesh.v1alpha1.HTTPRouteRule.matches:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteMatch - 9, // 3: hashicorp.consul.mesh.v1alpha1.HTTPRouteRule.filters:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter - 13, // 4: hashicorp.consul.mesh.v1alpha1.HTTPRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPBackendRef - 15, // 5: hashicorp.consul.mesh.v1alpha1.HTTPRouteRule.timeouts:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts - 16, // 6: hashicorp.consul.mesh.v1alpha1.HTTPRouteRule.retries:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries - 6, // 7: hashicorp.consul.mesh.v1alpha1.HTTPRouteMatch.path:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPPathMatch - 7, // 8: hashicorp.consul.mesh.v1alpha1.HTTPRouteMatch.headers:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPHeaderMatch - 8, // 9: hashicorp.consul.mesh.v1alpha1.HTTPRouteMatch.query_params:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPQueryParamMatch - 0, // 10: hashicorp.consul.mesh.v1alpha1.HTTPPathMatch.type:type_name -> hashicorp.consul.mesh.v1alpha1.PathMatchType - 1, // 11: hashicorp.consul.mesh.v1alpha1.HTTPHeaderMatch.type:type_name -> hashicorp.consul.mesh.v1alpha1.HeaderMatchType - 2, // 12: hashicorp.consul.mesh.v1alpha1.HTTPQueryParamMatch.type:type_name -> hashicorp.consul.mesh.v1alpha1.QueryParamMatchType - 10, // 13: hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter.request_header_modifier:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPHeaderFilter - 10, // 14: hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter.response_header_modifier:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPHeaderFilter - 12, // 15: hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter.url_rewrite:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPURLRewriteFilter - 11, // 16: hashicorp.consul.mesh.v1alpha1.HTTPHeaderFilter.set:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPHeader - 11, // 17: hashicorp.consul.mesh.v1alpha1.HTTPHeaderFilter.add:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPHeader - 17, // 18: hashicorp.consul.mesh.v1alpha1.HTTPBackendRef.backend_ref:type_name -> hashicorp.consul.mesh.v1alpha1.BackendReference - 9, // 19: hashicorp.consul.mesh.v1alpha1.HTTPBackendRef.filters:type_name -> hashicorp.consul.mesh.v1alpha1.HTTPRouteFilter - 20, // [20:20] is the sub-list for method output_type - 20, // [20:20] is the sub-list for method input_type - 20, // [20:20] is the sub-list for extension type_name - 20, // [20:20] is the sub-list for extension extendee - 0, // [0:20] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_http_route_proto_init() } -func file_pbmesh_v1alpha1_http_route_proto_init() { - if File_pbmesh_v1alpha1_http_route_proto != nil { - return - } - file_pbmesh_v1alpha1_common_proto_init() - file_pbmesh_v1alpha1_http_route_retries_proto_init() - file_pbmesh_v1alpha1_http_route_timeouts_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_http_route_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRoute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_http_route_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_http_route_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRouteMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_http_route_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPPathMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_http_route_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPHeaderMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_http_route_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPQueryParamMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_http_route_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRouteFilter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_http_route_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPHeaderFilter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_http_route_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPHeader); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_http_route_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPURLRewriteFilter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_http_route_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPBackendRef); 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_pbmesh_v1alpha1_http_route_proto_rawDesc, - NumEnums: 3, - NumMessages: 11, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_http_route_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_http_route_proto_depIdxs, - EnumInfos: file_pbmesh_v1alpha1_http_route_proto_enumTypes, - MessageInfos: file_pbmesh_v1alpha1_http_route_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_http_route_proto = out.File - file_pbmesh_v1alpha1_http_route_proto_rawDesc = nil - file_pbmesh_v1alpha1_http_route_proto_goTypes = nil - file_pbmesh_v1alpha1_http_route_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/http_route.proto b/proto-public/pbmesh/v1alpha1/http_route.proto deleted file mode 100644 index ea14176b1b7c0..0000000000000 --- a/proto-public/pbmesh/v1alpha1/http_route.proto +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1; - -import "pbmesh/v1alpha1/common.proto"; -import "pbmesh/v1alpha1/http_route_retries.proto"; -import "pbmesh/v1alpha1/http_route_timeouts.proto"; - -// NOTE: this should align to the GAMMA/gateway-api version, or at least be -// easily translatable. -// -// https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.HTTPRoute -// -// This is a Resource type. -message HTTPRoute { - // ParentRefs references the resources (usually Gateways) that a Route wants - // to be attached to. Note that the referenced parent resource needs to allow - // this for the attachment to be complete. For Gateways, that means the - // Gateway needs to allow attachment from Routes of this kind and namespace. - // - // It is invalid to reference an identical parent more than once. It is valid - // to reference multiple distinct sections within the same parent resource, - // such as 2 Listeners within a Gateway. - repeated ParentReference parent_refs = 1; - - // Hostnames are the hostnames for which this HTTPRoute should respond to requests. - repeated string hostnames = 2; - - // Rules are a list of HTTP-based routing rules that this route should - // use for constructing a routing table. - repeated HTTPRouteRule rules = 3; -} - -// HTTPRouteRule specifies the routing rules used to determine what upstream -// service an HTTP request is routed to. -message HTTPRouteRule { - // Matches specified the matching criteria used in the routing table. If a - // request matches the given HTTPMatch configuration, then traffic is routed - // to services specified in the Services field. - repeated HTTPRouteMatch matches = 1; - - repeated HTTPRouteFilter filters = 2; - - // BackendRefs defines the backend(s) where matching requests should be sent. - // - // Failure behavior here depends on how many BackendRefs are specified and - // how many are invalid. - // - // If all entries in BackendRefs are invalid, and there are also no filters - // specified in this route rule, all traffic which matches this rule MUST - // receive a 500 status code. - // - // See the HTTPBackendRef definition for the rules about what makes a single - // HTTPBackendRef invalid. - // - // When a HTTPBackendRef is invalid, 500 status codes MUST be returned for - // requests that would have otherwise been routed to an invalid backend. If - // multiple backends are specified, and some are invalid, the proportion of - // requests that would otherwise have been routed to an invalid backend MUST - // receive a 500 status code. - // - // For example, if two backends are specified with equal weights, and one is - // invalid, 50 percent of traffic must receive a 500. Implementations may - // choose how that 50 percent is determined. - repeated HTTPBackendRef backend_refs = 3; - - // ALTERNATIVE: Timeouts defines the timeouts that can be configured for an HTTP request. - HTTPRouteTimeouts timeouts = 4; - // ALTERNATIVE: - HTTPRouteRetries retries = 5; -} - -message HTTPRouteMatch { - // Path specifies a HTTP request path matcher. If this field is not - // specified, a default prefix match on the “/” path is provided. - HTTPPathMatch path = 1; - - // Headers specifies HTTP request header matchers. Multiple match values are - // ANDed together, meaning, a request must match all the specified headers to - // select the route. - repeated HTTPHeaderMatch headers = 2; - - // QueryParams specifies HTTP query parameter matchers. Multiple match values - // are ANDed together, meaning, a request must match all the specified query - // parameters to select the route. - repeated HTTPQueryParamMatch query_params = 3; - - // Method specifies HTTP method matcher. When specified, this route will be - // matched only if the request has the specified method. - string method = 4; -} - -message HTTPPathMatch { - // Type specifies how to match against the path Value. - PathMatchType type = 1; - // Value of the HTTP path to match against. - string value = 2; -} - -// PathMatchType specifies the semantics of how HTTP paths should be compared. -// Valid PathMatchType values, along with their support levels, are: -// -// PathPrefix and Exact paths must be syntactically valid: -// -// - Must begin with the / character -// - Must not contain consecutive / characters (e.g. /foo///, //). -// - Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the Accepted -// Condition for the Route to status: False, with a Reason of UnsupportedValue. -enum PathMatchType { - PATH_MATCH_TYPE_UNSPECIFIED = 0; - PATH_MATCH_TYPE_EXACT = 1; - PATH_MATCH_TYPE_PREFIX = 2; - PATH_MATCH_TYPE_REGEX = 3; -} - -message HTTPHeaderMatch { - // Type specifies how to match against the value of the header. - HeaderMatchType type = 1; - - // Name is the name of the HTTP Header to be matched. Name matching MUST be - // case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - // - // If multiple entries specify equivalent header names, only the first entry - // with an equivalent name MUST be considered for a match. Subsequent entries - // with an equivalent header name MUST be ignored. Due to the - // case-insensitivity of header names, “foo” and “Foo” are considered - // equivalent. - // - // When a header is repeated in an HTTP request, it is - // implementation-specific behavior as to how this is represented. Generally, - // proxies should follow the guidance from the RFC: - // https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - // processing a repeated header, with special handling for “Set-Cookie”. - string name = 2; - - // Value is the value of HTTP Header to be matched. - string value = 3; - - // NOTE: not in gamma; service-router compat - bool invert = 4; -} - -// HeaderMatchType specifies the semantics of how HTTP header values should be -// compared. Valid HeaderMatchType values, along with their conformance levels, -// are: -// -// Note that values may be added to this enum, implementations must ensure that -// unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the Accepted -// Condition for the Route to status: False, with a Reason of UnsupportedValue. -enum HeaderMatchType { - HEADER_MATCH_TYPE_UNSPECIFIED = 0; - HEADER_MATCH_TYPE_EXACT = 1; - HEADER_MATCH_TYPE_REGEX = 2; - // consul only after this point (service-router compat) - HEADER_MATCH_TYPE_PRESENT = 3; - HEADER_MATCH_TYPE_PREFIX = 4; - HEADER_MATCH_TYPE_SUFFIX = 5; -} - -message HTTPQueryParamMatch { - // Type specifies how to match against the value of the query parameter. - QueryParamMatchType type = 1; - - // Name is the name of the HTTP query param to be matched. This must be an - // exact string match. (See - // https://tools.ietf.org/html/rfc7230#section-2.7.3). - // - // If multiple entries specify equivalent query param names, only the first - // entry with an equivalent name MUST be considered for a match. Subsequent - // entries with an equivalent query param name MUST be ignored. - // - // If a query param is repeated in an HTTP request, the behavior is purposely - // left undefined, since different data planes have different capabilities. - // However, it is recommended that implementations should match against the - // first value of the param if the data plane supports it, as this behavior - // is expected in other load balancing contexts outside of the Gateway API. - // - // Users SHOULD NOT route traffic based on repeated query params to guard - // themselves against potential differences in the implementations. - string name = 2; - - // Value is the value of HTTP query param to be matched. - string value = 3; -} - -enum QueryParamMatchType { - QUERY_PARAM_MATCH_TYPE_UNSPECIFIED = 0; - QUERY_PARAM_MATCH_TYPE_EXACT = 1; - QUERY_PARAM_MATCH_TYPE_REGEX = 2; - // consul only after this point (service-router compat) - QUERY_PARAM_MATCH_TYPE_PRESENT = 3; -} - -message HTTPRouteFilter { - // RequestHeaderModifier defines a schema for a filter that modifies request - // headers. - HTTPHeaderFilter request_header_modifier = 1; - - // ResponseHeaderModifier defines a schema for a filter that modifies - // response headers. - HTTPHeaderFilter response_header_modifier = 2; - - // URLRewrite defines a schema for a filter that modifies a request during - // forwarding. - HTTPURLRewriteFilter url_rewrite = 5; -} - -message HTTPHeaderFilter { - // Set overwrites the request with the given header (name, value) before the - // action. - repeated HTTPHeader set = 1; - - // Add adds the given header(s) (name, value) to the request before the - // action. It appends to any existing values associated with the header name. - repeated HTTPHeader add = 2; - - // Remove the given header(s) from the HTTP request before the action. The - // value of Remove is a list of HTTP header names. Note that the header names - // are case-insensitive (see - // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - repeated string remove = 3; -} - -message HTTPHeader { - string name = 1; - string value = 2; -} - -message HTTPURLRewriteFilter { - string path_prefix = 1; -} - -message HTTPBackendRef { - BackendReference backend_ref = 1; - - // Weight specifies the proportion of requests forwarded to the referenced - // backend. This is computed as weight/(sum of all weights in this - // BackendRefs list). For non-zero values, there may be some epsilon from the - // exact proportion defined here depending on the precision an implementation - // supports. Weight is not a percentage and the sum of weights does not need - // to equal 100. - // - //If only one backend is specified and it has a weight greater than 0, 100% - //of the traffic is forwarded to that backend. If weight is set to 0, no - //traffic should be forwarded for this entry. If unspecified, weight defaults - //to 1. - uint32 weight = 2; - - // Filters defined at this level should be executed if and only if the - // request is being forwarded to the backend defined here. - repeated HTTPRouteFilter filters = 3; -} diff --git a/proto-public/pbmesh/v1alpha1/http_route_retries.pb.binary.go b/proto-public/pbmesh/v1alpha1/http_route_retries.pb.binary.go deleted file mode 100644 index b84704f0e1aa1..0000000000000 --- a/proto-public/pbmesh/v1alpha1/http_route_retries.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/http_route_retries.proto - -package meshv1alpha1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPRouteRetries) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPRouteRetries) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/http_route_retries.pb.go b/proto-public/pbmesh/v1alpha1/http_route_retries.pb.go deleted file mode 100644 index 5a34d26a3260e..0000000000000 --- a/proto-public/pbmesh/v1alpha1/http_route_retries.pb.go +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/http_route_retries.proto - -package meshv1alpha1 - -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) -) - -// ALTERNATIVE: not using policy attachment semantics -type HTTPRouteRetries struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // NumRetries is the number of times to retry the request when a retryable - // result occurs. - Number int32 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"` - // RetryOnConnectFailure allows for connection failure errors to trigger a - // retry. - OnConnectFailure bool `protobuf:"varint,2,opt,name=on_connect_failure,json=onConnectFailure,proto3" json:"on_connect_failure,omitempty"` - // RetryOn allows setting envoy specific conditions when a request should - // be automatically retried. - OnConditions []string `protobuf:"bytes,3,rep,name=on_conditions,json=onConditions,proto3" json:"on_conditions,omitempty"` - // RetryOnStatusCodes is a flat list of http response status codes that are - // eligible for retry. This again should be feasible in any reasonable proxy. - OnStatusCodes []uint32 `protobuf:"varint,4,rep,packed,name=on_status_codes,json=onStatusCodes,proto3" json:"on_status_codes,omitempty"` -} - -func (x *HTTPRouteRetries) Reset() { - *x = HTTPRouteRetries{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_http_route_retries_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPRouteRetries) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPRouteRetries) ProtoMessage() {} - -func (x *HTTPRouteRetries) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_http_route_retries_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 HTTPRouteRetries.ProtoReflect.Descriptor instead. -func (*HTTPRouteRetries) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_retries_proto_rawDescGZIP(), []int{0} -} - -func (x *HTTPRouteRetries) GetNumber() int32 { - if x != nil { - return x.Number - } - return 0 -} - -func (x *HTTPRouteRetries) GetOnConnectFailure() bool { - if x != nil { - return x.OnConnectFailure - } - return false -} - -func (x *HTTPRouteRetries) GetOnConditions() []string { - if x != nil { - return x.OnConditions - } - return nil -} - -func (x *HTTPRouteRetries) GetOnStatusCodes() []uint32 { - if x != nil { - return x.OnStatusCodes - } - return nil -} - -var File_pbmesh_v1alpha1_http_route_retries_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_http_route_retries_proto_rawDesc = []byte{ - 0x0a, 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x22, 0xa5, 0x01, 0x0a, 0x10, 0x48, - 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, - 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x10, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x46, 0x61, - 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x6e, - 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6f, 0x6e, - 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x0d, 0x52, 0x0d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, - 0x65, 0x73, 0x42, 0x9d, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x15, 0x48, 0x74, 0x74, 0x70, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x45, 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, - 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, - 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, - 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_http_route_retries_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_http_route_retries_proto_rawDescData = file_pbmesh_v1alpha1_http_route_retries_proto_rawDesc -) - -func file_pbmesh_v1alpha1_http_route_retries_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_http_route_retries_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_http_route_retries_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_http_route_retries_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_http_route_retries_proto_rawDescData -} - -var file_pbmesh_v1alpha1_http_route_retries_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmesh_v1alpha1_http_route_retries_proto_goTypes = []interface{}{ - (*HTTPRouteRetries)(nil), // 0: hashicorp.consul.mesh.v1alpha1.HTTPRouteRetries -} -var file_pbmesh_v1alpha1_http_route_retries_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_pbmesh_v1alpha1_http_route_retries_proto_init() } -func file_pbmesh_v1alpha1_http_route_retries_proto_init() { - if File_pbmesh_v1alpha1_http_route_retries_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_http_route_retries_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRouteRetries); 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_pbmesh_v1alpha1_http_route_retries_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_http_route_retries_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_http_route_retries_proto_depIdxs, - MessageInfos: file_pbmesh_v1alpha1_http_route_retries_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_http_route_retries_proto = out.File - file_pbmesh_v1alpha1_http_route_retries_proto_rawDesc = nil - file_pbmesh_v1alpha1_http_route_retries_proto_goTypes = nil - file_pbmesh_v1alpha1_http_route_retries_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/http_route_retries.proto b/proto-public/pbmesh/v1alpha1/http_route_retries.proto deleted file mode 100644 index 3ea112027abec..0000000000000 --- a/proto-public/pbmesh/v1alpha1/http_route_retries.proto +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1; - -// ALTERNATIVE: not using policy attachment semantics -message HTTPRouteRetries { - // NumRetries is the number of times to retry the request when a retryable - // result occurs. - int32 number = 1; - - // RetryOnConnectFailure allows for connection failure errors to trigger a - // retry. - bool on_connect_failure = 2; - - // RetryOn allows setting envoy specific conditions when a request should - // be automatically retried. - repeated string on_conditions = 3; - - // RetryOnStatusCodes is a flat list of http response status codes that are - // eligible for retry. This again should be feasible in any reasonable proxy. - repeated uint32 on_status_codes = 4; -} diff --git a/proto-public/pbmesh/v1alpha1/http_route_timeouts.pb.binary.go b/proto-public/pbmesh/v1alpha1/http_route_timeouts.pb.binary.go deleted file mode 100644 index cb38ff24c577f..0000000000000 --- a/proto-public/pbmesh/v1alpha1/http_route_timeouts.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/http_route_timeouts.proto - -package meshv1alpha1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPRouteTimeouts) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPRouteTimeouts) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/http_route_timeouts.pb.go b/proto-public/pbmesh/v1alpha1/http_route_timeouts.pb.go deleted file mode 100644 index 0fc421e43e5b5..0000000000000 --- a/proto-public/pbmesh/v1alpha1/http_route_timeouts.pb.go +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/http_route_timeouts.proto - -package meshv1alpha1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - 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) -) - -// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute. -// Timeout values are formatted like 1h/1m/1s/1ms as parsed by Golang time.ParseDuration -// and MUST BE >= 1ms. -// -// ALTERNATIVE: not using policy attachment semantics -type HTTPRouteTimeouts struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Request specifies the duration for processing an HTTP client request after which the - // gateway will time out if unable to send a response. - // Whether the gateway starts the timeout before or after the entire client request stream - // has been received, is implementation-dependent. - // - // For example, setting the `rules.timeouts.request` field to the value `10s` in an - // `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds - // to complete. - // - // When this field is unspecified, request timeout behavior is implementation-dependent. - Request *durationpb.Duration `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"` - // BackendRequest specifies a timeout for an individual request from the gateway - // to a backend service. Typically used in conjuction with retry configuration, - // if supported by an implementation. - // - // The value of BackendRequest defaults to and must be <= the value of Request timeout. - // - // Support: Extended - // - // TODO(rb): net-new feature - BackendRequest *durationpb.Duration `protobuf:"bytes,2,opt,name=backend_request,json=backendRequest,proto3" json:"backend_request,omitempty"` - // TODO(RB): this is a consul-only feature - Idle *durationpb.Duration `protobuf:"bytes,3,opt,name=idle,proto3" json:"idle,omitempty"` -} - -func (x *HTTPRouteTimeouts) Reset() { - *x = HTTPRouteTimeouts{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_http_route_timeouts_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPRouteTimeouts) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPRouteTimeouts) ProtoMessage() {} - -func (x *HTTPRouteTimeouts) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_http_route_timeouts_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 HTTPRouteTimeouts.ProtoReflect.Descriptor instead. -func (*HTTPRouteTimeouts) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_http_route_timeouts_proto_rawDescGZIP(), []int{0} -} - -func (x *HTTPRouteTimeouts) GetRequest() *durationpb.Duration { - if x != nil { - return x.Request - } - return nil -} - -func (x *HTTPRouteTimeouts) GetBackendRequest() *durationpb.Duration { - if x != nil { - return x.BackendRequest - } - return nil -} - -func (x *HTTPRouteTimeouts) GetIdle() *durationpb.Duration { - if x != nil { - return x.Idle - } - return nil -} - -var File_pbmesh_v1alpha1_http_route_timeouts_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_http_route_timeouts_proto_rawDesc = []byte{ - 0x0a, 0x29, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbb, 0x01, 0x0a, 0x11, - 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x73, 0x12, 0x33, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x0f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, - 0x64, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x62, 0x61, 0x63, 0x6b, - 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x04, 0x69, 0x64, - 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x69, 0x64, 0x6c, 0x65, 0x42, 0x9e, 0x02, 0x0a, 0x22, 0x63, 0x6f, - 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x42, 0x16, 0x48, 0x74, 0x74, 0x70, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, - 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, - 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, - 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, - 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_http_route_timeouts_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_http_route_timeouts_proto_rawDescData = file_pbmesh_v1alpha1_http_route_timeouts_proto_rawDesc -) - -func file_pbmesh_v1alpha1_http_route_timeouts_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_http_route_timeouts_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_http_route_timeouts_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_http_route_timeouts_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_http_route_timeouts_proto_rawDescData -} - -var file_pbmesh_v1alpha1_http_route_timeouts_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmesh_v1alpha1_http_route_timeouts_proto_goTypes = []interface{}{ - (*HTTPRouteTimeouts)(nil), // 0: hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts - (*durationpb.Duration)(nil), // 1: google.protobuf.Duration -} -var file_pbmesh_v1alpha1_http_route_timeouts_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts.request:type_name -> google.protobuf.Duration - 1, // 1: hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts.backend_request:type_name -> google.protobuf.Duration - 1, // 2: hashicorp.consul.mesh.v1alpha1.HTTPRouteTimeouts.idle:type_name -> google.protobuf.Duration - 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_pbmesh_v1alpha1_http_route_timeouts_proto_init() } -func file_pbmesh_v1alpha1_http_route_timeouts_proto_init() { - if File_pbmesh_v1alpha1_http_route_timeouts_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_http_route_timeouts_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRouteTimeouts); 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_pbmesh_v1alpha1_http_route_timeouts_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_http_route_timeouts_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_http_route_timeouts_proto_depIdxs, - MessageInfos: file_pbmesh_v1alpha1_http_route_timeouts_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_http_route_timeouts_proto = out.File - file_pbmesh_v1alpha1_http_route_timeouts_proto_rawDesc = nil - file_pbmesh_v1alpha1_http_route_timeouts_proto_goTypes = nil - file_pbmesh_v1alpha1_http_route_timeouts_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/http_route_timeouts.proto b/proto-public/pbmesh/v1alpha1/http_route_timeouts.proto deleted file mode 100644 index f33587496b552..0000000000000 --- a/proto-public/pbmesh/v1alpha1/http_route_timeouts.proto +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1; - -import "google/protobuf/duration.proto"; - -// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute. -// Timeout values are formatted like 1h/1m/1s/1ms as parsed by Golang time.ParseDuration -// and MUST BE >= 1ms. -// -// ALTERNATIVE: not using policy attachment semantics -message HTTPRouteTimeouts { - // Request specifies the duration for processing an HTTP client request after which the - // gateway will time out if unable to send a response. - // Whether the gateway starts the timeout before or after the entire client request stream - // has been received, is implementation-dependent. - // - // For example, setting the `rules.timeouts.request` field to the value `10s` in an - // `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds - // to complete. - // - // When this field is unspecified, request timeout behavior is implementation-dependent. - google.protobuf.Duration request = 1; - - // BackendRequest specifies a timeout for an individual request from the gateway - // to a backend service. Typically used in conjuction with retry configuration, - // if supported by an implementation. - // - // The value of BackendRequest defaults to and must be <= the value of Request timeout. - // - // Support: Extended - // - // TODO(rb): net-new feature - google.protobuf.Duration backend_request = 2; - - // TODO(RB): this is a consul-only feature - google.protobuf.Duration idle = 3; -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/access_logs.pb.binary.go b/proto-public/pbmesh/v1alpha1/pbproxystate/access_logs.pb.binary.go deleted file mode 100644 index 813f6d3ebb6a5..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/access_logs.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/pbproxystate/access_logs.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *AccessLogs) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *AccessLogs) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/access_logs.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/access_logs.pb.go deleted file mode 100644 index bedb5f988072f..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/access_logs.pb.go +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/pbproxystate/access_logs.proto - -package pbproxystate - -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 LogSinkType int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - LogSinkType_LOG_SINK_TYPE_DEFAULT LogSinkType = 0 - LogSinkType_LOG_SINK_TYPE_FILE LogSinkType = 1 - LogSinkType_LOG_SINK_TYPE_STDERR LogSinkType = 2 - LogSinkType_LOG_SINK_TYPE_STDOUT LogSinkType = 3 -) - -// Enum value maps for LogSinkType. -var ( - LogSinkType_name = map[int32]string{ - 0: "LOG_SINK_TYPE_DEFAULT", - 1: "LOG_SINK_TYPE_FILE", - 2: "LOG_SINK_TYPE_STDERR", - 3: "LOG_SINK_TYPE_STDOUT", - } - LogSinkType_value = map[string]int32{ - "LOG_SINK_TYPE_DEFAULT": 0, - "LOG_SINK_TYPE_FILE": 1, - "LOG_SINK_TYPE_STDERR": 2, - "LOG_SINK_TYPE_STDOUT": 3, - } -) - -func (x LogSinkType) Enum() *LogSinkType { - p := new(LogSinkType) - *p = x - return p -} - -func (x LogSinkType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (LogSinkType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_enumTypes[0].Descriptor() -} - -func (LogSinkType) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_enumTypes[0] -} - -func (x LogSinkType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use LogSinkType.Descriptor instead. -func (LogSinkType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_rawDescGZIP(), []int{0} -} - -type AccessLogs struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // enabled enables access logging. - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - // disable_listener_logs turns off just listener logs for connections rejected by Envoy because they don't - // have a matching listener filter. - DisableListenerLogs bool `protobuf:"varint,2,opt,name=disable_listener_logs,json=disableListenerLogs,proto3" json:"disable_listener_logs,omitempty"` - // type selects the output for logs: "file", "stderr". "stdout" - Type LogSinkType `protobuf:"varint,3,opt,name=type,proto3,enum=hashicorp.consul.mesh.v1alpha1.pbproxystate.LogSinkType" json:"type,omitempty"` - // path is the output file to write logs - Path string `protobuf:"bytes,4,opt,name=path,proto3" json:"path,omitempty"` - // The presence of one format string or the other implies the access log string encoding. - // Defining both is invalid. - // - // Types that are assignable to Format: - // - // *AccessLogs_Json - // *AccessLogs_Text - Format isAccessLogs_Format `protobuf_oneof:"format"` -} - -func (x *AccessLogs) Reset() { - *x = AccessLogs{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AccessLogs) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AccessLogs) ProtoMessage() {} - -func (x *AccessLogs) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_access_logs_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 AccessLogs.ProtoReflect.Descriptor instead. -func (*AccessLogs) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_rawDescGZIP(), []int{0} -} - -func (x *AccessLogs) GetEnabled() bool { - if x != nil { - return x.Enabled - } - return false -} - -func (x *AccessLogs) GetDisableListenerLogs() bool { - if x != nil { - return x.DisableListenerLogs - } - return false -} - -func (x *AccessLogs) GetType() LogSinkType { - if x != nil { - return x.Type - } - return LogSinkType_LOG_SINK_TYPE_DEFAULT -} - -func (x *AccessLogs) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (m *AccessLogs) GetFormat() isAccessLogs_Format { - if m != nil { - return m.Format - } - return nil -} - -func (x *AccessLogs) GetJson() string { - if x, ok := x.GetFormat().(*AccessLogs_Json); ok { - return x.Json - } - return "" -} - -func (x *AccessLogs) GetText() string { - if x, ok := x.GetFormat().(*AccessLogs_Text); ok { - return x.Text - } - return "" -} - -type isAccessLogs_Format interface { - isAccessLogs_Format() -} - -type AccessLogs_Json struct { - Json string `protobuf:"bytes,5,opt,name=json,proto3,oneof"` -} - -type AccessLogs_Text struct { - Text string `protobuf:"bytes,6,opt,name=text,proto3,oneof"` -} - -func (*AccessLogs_Json) isAccessLogs_Format() {} - -func (*AccessLogs_Text) isAccessLogs_Format() {} - -var File_pbmesh_v1alpha1_pbproxystate_access_logs_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_rawDesc = []byte{ - 0x0a, 0x2e, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x2b, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0xf2, 0x01, - 0x0a, 0x0a, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, - 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, - 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, - 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x4c, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x53, 0x69, 0x6e, 0x6b, 0x54, 0x79, - 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x04, - 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6a, 0x73, - 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, - 0x61, 0x74, 0x2a, 0x74, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x53, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x4f, 0x47, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, - 0x4c, 0x4f, 0x47, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, - 0x4c, 0x45, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4c, 0x4f, 0x47, 0x5f, 0x53, 0x49, 0x4e, 0x4b, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x44, 0x45, 0x52, 0x52, 0x10, 0x02, 0x12, 0x18, - 0x0a, 0x14, 0x4c, 0x4f, 0x47, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x53, 0x54, 0x44, 0x4f, 0x55, 0x54, 0x10, 0x03, 0x42, 0xdb, 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0f, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x45, 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, 0x65, 0x73, 0x68, - 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, - 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, - 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, - 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_rawDescData = file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_rawDesc -) - -func file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_rawDescData -} - -var file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_goTypes = []interface{}{ - (LogSinkType)(0), // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.LogSinkType - (*AccessLogs)(nil), // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.AccessLogs -} -var file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_depIdxs = []int32{ - 0, // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.AccessLogs.type:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LogSinkType - 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_pbmesh_v1alpha1_pbproxystate_access_logs_proto_init() } -func file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_init() { - if File_pbmesh_v1alpha1_pbproxystate_access_logs_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AccessLogs); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*AccessLogs_Json)(nil), - (*AccessLogs_Text)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_rawDesc, - NumEnums: 1, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_depIdxs, - EnumInfos: file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_enumTypes, - MessageInfos: file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_pbproxystate_access_logs_proto = out.File - file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_rawDesc = nil - file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_goTypes = nil - file_pbmesh_v1alpha1_pbproxystate_access_logs_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/access_logs.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/access_logs.proto deleted file mode 100644 index 00770c0c146e6..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/access_logs.proto +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1.pbproxystate; - -message AccessLogs { - // enabled enables access logging. - bool enabled = 1; - // disable_listener_logs turns off just listener logs for connections rejected by Envoy because they don't - // have a matching listener filter. - bool disable_listener_logs = 2; - // type selects the output for logs: "file", "stderr". "stdout" - LogSinkType type = 3; - // path is the output file to write logs - string path = 4; - // The presence of one format string or the other implies the access log string encoding. - // Defining both is invalid. - oneof format { - string json = 5; - string text = 6; - } -} - -enum LogSinkType { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - LOG_SINK_TYPE_DEFAULT = 0; - LOG_SINK_TYPE_FILE = 1; - LOG_SINK_TYPE_STDERR = 2; - LOG_SINK_TYPE_STDOUT = 3; -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/address.pb.binary.go b/proto-public/pbmesh/v1alpha1/pbproxystate/address.pb.binary.go deleted file mode 100644 index 84ba62db40830..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/address.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/pbproxystate/address.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HostPortAddress) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HostPortAddress) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *UnixSocketAddress) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *UnixSocketAddress) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/address.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/address.pb.go deleted file mode 100644 index 0afb768f4aa45..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/address.pb.go +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/pbproxystate/address.proto - -package pbproxystate - -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 HostPortAddress struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` - Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` -} - -func (x *HostPortAddress) Reset() { - *x = HostPortAddress{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_address_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HostPortAddress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HostPortAddress) ProtoMessage() {} - -func (x *HostPortAddress) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_address_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 HostPortAddress.ProtoReflect.Descriptor instead. -func (*HostPortAddress) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_address_proto_rawDescGZIP(), []int{0} -} - -func (x *HostPortAddress) GetHost() string { - if x != nil { - return x.Host - } - return "" -} - -func (x *HostPortAddress) GetPort() uint32 { - if x != nil { - return x.Port - } - return 0 -} - -type UnixSocketAddress struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // path is the file system path at which to bind a Unix domain socket listener. - Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - // mode is the Unix file mode for the socket file. It should be provided - // in the numeric notation, for example, "0600". - Mode string `protobuf:"bytes,2,opt,name=mode,proto3" json:"mode,omitempty"` -} - -func (x *UnixSocketAddress) Reset() { - *x = UnixSocketAddress{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_address_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UnixSocketAddress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UnixSocketAddress) ProtoMessage() {} - -func (x *UnixSocketAddress) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_address_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 UnixSocketAddress.ProtoReflect.Descriptor instead. -func (*UnixSocketAddress) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_address_proto_rawDescGZIP(), []int{1} -} - -func (x *UnixSocketAddress) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (x *UnixSocketAddress) GetMode() string { - if x != nil { - return x.Mode - } - return "" -} - -var File_pbmesh_v1alpha1_pbproxystate_address_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_pbproxystate_address_proto_rawDesc = []byte{ - 0x0a, 0x2a, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2b, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x39, 0x0a, 0x0f, 0x48, 0x6f, 0x73, - 0x74, 0x50, 0x6f, 0x72, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, - 0x70, 0x6f, 0x72, 0x74, 0x22, 0x3b, 0x0a, 0x11, 0x55, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, - 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, - 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, - 0x65, 0x42, 0xd8, 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, - 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0xca, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0xe2, 0x02, 0x37, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, - 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3a, 0x3a, - 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_pbproxystate_address_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_pbproxystate_address_proto_rawDescData = file_pbmesh_v1alpha1_pbproxystate_address_proto_rawDesc -) - -func file_pbmesh_v1alpha1_pbproxystate_address_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_pbproxystate_address_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_pbproxystate_address_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_pbproxystate_address_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_pbproxystate_address_proto_rawDescData -} - -var file_pbmesh_v1alpha1_pbproxystate_address_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbmesh_v1alpha1_pbproxystate_address_proto_goTypes = []interface{}{ - (*HostPortAddress)(nil), // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.HostPortAddress - (*UnixSocketAddress)(nil), // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.UnixSocketAddress -} -var file_pbmesh_v1alpha1_pbproxystate_address_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_pbmesh_v1alpha1_pbproxystate_address_proto_init() } -func file_pbmesh_v1alpha1_pbproxystate_address_proto_init() { - if File_pbmesh_v1alpha1_pbproxystate_address_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_pbproxystate_address_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HostPortAddress); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_address_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnixSocketAddress); 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_pbmesh_v1alpha1_pbproxystate_address_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_pbproxystate_address_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_pbproxystate_address_proto_depIdxs, - MessageInfos: file_pbmesh_v1alpha1_pbproxystate_address_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_pbproxystate_address_proto = out.File - file_pbmesh_v1alpha1_pbproxystate_address_proto_rawDesc = nil - file_pbmesh_v1alpha1_pbproxystate_address_proto_goTypes = nil - file_pbmesh_v1alpha1_pbproxystate_address_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/address.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/address.proto deleted file mode 100644 index 2d08199a0ecc9..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/address.proto +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1.pbproxystate; - -message HostPortAddress { - string host = 1; - uint32 port = 2; -} - -message UnixSocketAddress { - // path is the file system path at which to bind a Unix domain socket listener. - string path = 1; - - // mode is the Unix file mode for the socket file. It should be provided - // in the numeric notation, for example, "0600". - string mode = 2; -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.binary.go b/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.binary.go deleted file mode 100644 index 54087655a2c8e..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.binary.go +++ /dev/null @@ -1,258 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/pbproxystate/cluster.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Cluster) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Cluster) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *FailoverGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *FailoverGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *FailoverGroupConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *FailoverGroupConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *EndpointGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *EndpointGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DynamicEndpointGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DynamicEndpointGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *PassthroughEndpointGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *PassthroughEndpointGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DNSEndpointGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DNSEndpointGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *StaticEndpointGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *StaticEndpointGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L4WeightedClusterGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L4WeightedClusterGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L7WeightedClusterGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L7WeightedClusterGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L4WeightedDestinationCluster) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L4WeightedDestinationCluster) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L7WeightedDestinationCluster) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L7WeightedDestinationCluster) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DynamicEndpointGroupConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DynamicEndpointGroupConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LBPolicyLeastRequest) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LBPolicyLeastRequest) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LBPolicyRoundRobin) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LBPolicyRoundRobin) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LBPolicyRandom) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LBPolicyRandom) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LBPolicyRingHash) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LBPolicyRingHash) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LBPolicyMaglev) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LBPolicyMaglev) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *CircuitBreakers) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *CircuitBreakers) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *UpstreamLimits) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *UpstreamLimits) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *OutlierDetection) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *OutlierDetection) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *UpstreamConnectionOptions) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *UpstreamConnectionOptions) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *PassthroughEndpointGroupConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *PassthroughEndpointGroupConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DNSEndpointGroupConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DNSEndpointGroupConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *StaticEndpointGroupConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *StaticEndpointGroupConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.go deleted file mode 100644 index a641988f422a6..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.pb.go +++ /dev/null @@ -1,2554 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/pbproxystate/cluster.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - 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 DiscoveryType int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - DiscoveryType_DISCOVERY_TYPE_LOGICAL DiscoveryType = 0 - DiscoveryType_DISCOVERY_TYPE_STRICT DiscoveryType = 1 -) - -// Enum value maps for DiscoveryType. -var ( - DiscoveryType_name = map[int32]string{ - 0: "DISCOVERY_TYPE_LOGICAL", - 1: "DISCOVERY_TYPE_STRICT", - } - DiscoveryType_value = map[string]int32{ - "DISCOVERY_TYPE_LOGICAL": 0, - "DISCOVERY_TYPE_STRICT": 1, - } -) - -func (x DiscoveryType) Enum() *DiscoveryType { - p := new(DiscoveryType) - *p = x - return p -} - -func (x DiscoveryType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (DiscoveryType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_enumTypes[0].Descriptor() -} - -func (DiscoveryType) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_enumTypes[0] -} - -func (x DiscoveryType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use DiscoveryType.Descriptor instead. -func (DiscoveryType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{0} -} - -type Cluster struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is the name of the cluster. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // group is either a failover group or endpoint group. If this cluster needs to failover to other clusters, use the failover group. If this cluster routes directly to endpoints, use the endpoint group. - // - // Types that are assignable to Group: - // - // *Cluster_FailoverGroup - // *Cluster_EndpointGroup - Group isCluster_Group `protobuf_oneof:"group"` - // escape_hatch_cluster_json configures a user configured escape hatch cluster. - EscapeHatchClusterJson string `protobuf:"bytes,4,opt,name=escape_hatch_cluster_json,json=escapeHatchClusterJson,proto3" json:"escape_hatch_cluster_json,omitempty"` - // alt_stat_name is the name used for observability in place of cluster name if provided. - AltStatName string `protobuf:"bytes,5,opt,name=alt_stat_name,json=altStatName,proto3" json:"alt_stat_name,omitempty"` - // protocol is the local path protocol or the service protocol. - Protocol string `protobuf:"bytes,6,opt,name=protocol,proto3" json:"protocol,omitempty"` -} - -func (x *Cluster) Reset() { - *x = Cluster{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Cluster) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Cluster) ProtoMessage() {} - -func (x *Cluster) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_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 Cluster.ProtoReflect.Descriptor instead. -func (*Cluster) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{0} -} - -func (x *Cluster) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (m *Cluster) GetGroup() isCluster_Group { - if m != nil { - return m.Group - } - return nil -} - -func (x *Cluster) GetFailoverGroup() *FailoverGroup { - if x, ok := x.GetGroup().(*Cluster_FailoverGroup); ok { - return x.FailoverGroup - } - return nil -} - -func (x *Cluster) GetEndpointGroup() *EndpointGroup { - if x, ok := x.GetGroup().(*Cluster_EndpointGroup); ok { - return x.EndpointGroup - } - return nil -} - -func (x *Cluster) GetEscapeHatchClusterJson() string { - if x != nil { - return x.EscapeHatchClusterJson - } - return "" -} - -func (x *Cluster) GetAltStatName() string { - if x != nil { - return x.AltStatName - } - return "" -} - -func (x *Cluster) GetProtocol() string { - if x != nil { - return x.Protocol - } - return "" -} - -type isCluster_Group interface { - isCluster_Group() -} - -type Cluster_FailoverGroup struct { - FailoverGroup *FailoverGroup `protobuf:"bytes,2,opt,name=failover_group,json=failoverGroup,proto3,oneof"` -} - -type Cluster_EndpointGroup struct { - EndpointGroup *EndpointGroup `protobuf:"bytes,3,opt,name=endpoint_group,json=endpointGroup,proto3,oneof"` -} - -func (*Cluster_FailoverGroup) isCluster_Group() {} - -func (*Cluster_EndpointGroup) isCluster_Group() {} - -type FailoverGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // endpoint_groups is an ordered list of which groups to failover to. - EndpointGroups []*EndpointGroup `protobuf:"bytes,1,rep,name=endpoint_groups,json=endpointGroups,proto3" json:"endpoint_groups,omitempty"` - Config *FailoverGroupConfig `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` -} - -func (x *FailoverGroup) Reset() { - *x = FailoverGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FailoverGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FailoverGroup) ProtoMessage() {} - -func (x *FailoverGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_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 FailoverGroup.ProtoReflect.Descriptor instead. -func (*FailoverGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{1} -} - -func (x *FailoverGroup) GetEndpointGroups() []*EndpointGroup { - if x != nil { - return x.EndpointGroups - } - return nil -} - -func (x *FailoverGroup) GetConfig() *FailoverGroupConfig { - if x != nil { - return x.Config - } - return nil -} - -type FailoverGroupConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - UseAltStatName bool `protobuf:"varint,1,opt,name=use_alt_stat_name,json=useAltStatName,proto3" json:"use_alt_stat_name,omitempty"` - ConnectTimeout *durationpb.Duration `protobuf:"bytes,2,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` -} - -func (x *FailoverGroupConfig) Reset() { - *x = FailoverGroupConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FailoverGroupConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FailoverGroupConfig) ProtoMessage() {} - -func (x *FailoverGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_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 FailoverGroupConfig.ProtoReflect.Descriptor instead. -func (*FailoverGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{2} -} - -func (x *FailoverGroupConfig) GetUseAltStatName() bool { - if x != nil { - return x.UseAltStatName - } - return false -} - -func (x *FailoverGroupConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -type EndpointGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Group: - // - // *EndpointGroup_Dynamic - // *EndpointGroup_Static - // *EndpointGroup_Dns - // *EndpointGroup_Passthrough - Group isEndpointGroup_Group `protobuf_oneof:"group"` -} - -func (x *EndpointGroup) Reset() { - *x = EndpointGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EndpointGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EndpointGroup) ProtoMessage() {} - -func (x *EndpointGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[3] - 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 EndpointGroup.ProtoReflect.Descriptor instead. -func (*EndpointGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{3} -} - -func (m *EndpointGroup) GetGroup() isEndpointGroup_Group { - if m != nil { - return m.Group - } - return nil -} - -func (x *EndpointGroup) GetDynamic() *DynamicEndpointGroup { - if x, ok := x.GetGroup().(*EndpointGroup_Dynamic); ok { - return x.Dynamic - } - return nil -} - -func (x *EndpointGroup) GetStatic() *StaticEndpointGroup { - if x, ok := x.GetGroup().(*EndpointGroup_Static); ok { - return x.Static - } - return nil -} - -func (x *EndpointGroup) GetDns() *DNSEndpointGroup { - if x, ok := x.GetGroup().(*EndpointGroup_Dns); ok { - return x.Dns - } - return nil -} - -func (x *EndpointGroup) GetPassthrough() *PassthroughEndpointGroup { - if x, ok := x.GetGroup().(*EndpointGroup_Passthrough); ok { - return x.Passthrough - } - return nil -} - -type isEndpointGroup_Group interface { - isEndpointGroup_Group() -} - -type EndpointGroup_Dynamic struct { - // dynamic endpoint group is used to reach mesh destinations that are dynamically configured from Consul's catalog. - Dynamic *DynamicEndpointGroup `protobuf:"bytes,1,opt,name=dynamic,proto3,oneof"` -} - -type EndpointGroup_Static struct { - // static endpoint group is used to reach local app ports. - Static *StaticEndpointGroup `protobuf:"bytes,2,opt,name=static,proto3,oneof"` -} - -type EndpointGroup_Dns struct { - // dns is used to reach mesh and non-mesh destinations using a hostname. - Dns *DNSEndpointGroup `protobuf:"bytes,3,opt,name=dns,proto3,oneof"` -} - -type EndpointGroup_Passthrough struct { - // passthrough is used to reach destinations that don't have endpoints saved in Consul. - Passthrough *PassthroughEndpointGroup `protobuf:"bytes,4,opt,name=passthrough,proto3,oneof"` -} - -func (*EndpointGroup_Dynamic) isEndpointGroup_Group() {} - -func (*EndpointGroup_Static) isEndpointGroup_Group() {} - -func (*EndpointGroup_Dns) isEndpointGroup_Group() {} - -func (*EndpointGroup_Passthrough) isEndpointGroup_Group() {} - -type DynamicEndpointGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // config configures how to connect to the endpoints. - Config *DynamicEndpointGroupConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - // outbound_tls will configure what TLS information to use when connecting to an upstream. - OutboundTls *TransportSocket `protobuf:"bytes,2,opt,name=outbound_tls,json=outboundTls,proto3" json:"outbound_tls,omitempty"` -} - -func (x *DynamicEndpointGroup) Reset() { - *x = DynamicEndpointGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DynamicEndpointGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DynamicEndpointGroup) ProtoMessage() {} - -func (x *DynamicEndpointGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[4] - 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 DynamicEndpointGroup.ProtoReflect.Descriptor instead. -func (*DynamicEndpointGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{4} -} - -func (x *DynamicEndpointGroup) GetConfig() *DynamicEndpointGroupConfig { - if x != nil { - return x.Config - } - return nil -} - -func (x *DynamicEndpointGroup) GetOutboundTls() *TransportSocket { - if x != nil { - return x.OutboundTls - } - return nil -} - -type PassthroughEndpointGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // config configures how to connect to the endpoints. - Config *PassthroughEndpointGroupConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - // outbound_tls will configure what TLS information to use when connecting to an upstream. - OutboundTls *TransportSocket `protobuf:"bytes,2,opt,name=outbound_tls,json=outboundTls,proto3" json:"outbound_tls,omitempty"` -} - -func (x *PassthroughEndpointGroup) Reset() { - *x = PassthroughEndpointGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PassthroughEndpointGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PassthroughEndpointGroup) ProtoMessage() {} - -func (x *PassthroughEndpointGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[5] - 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 PassthroughEndpointGroup.ProtoReflect.Descriptor instead. -func (*PassthroughEndpointGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{5} -} - -func (x *PassthroughEndpointGroup) GetConfig() *PassthroughEndpointGroupConfig { - if x != nil { - return x.Config - } - return nil -} - -func (x *PassthroughEndpointGroup) GetOutboundTls() *TransportSocket { - if x != nil { - return x.OutboundTls - } - return nil -} - -type DNSEndpointGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // config configures how to connect to the endpoints. - Config *DNSEndpointGroupConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - // outbound_tls will configure what TLS information to use when connecting to an upstream. - OutboundTls *TransportSocket `protobuf:"bytes,2,opt,name=outbound_tls,json=outboundTls,proto3" json:"outbound_tls,omitempty"` -} - -func (x *DNSEndpointGroup) Reset() { - *x = DNSEndpointGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DNSEndpointGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DNSEndpointGroup) ProtoMessage() {} - -func (x *DNSEndpointGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[6] - 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 DNSEndpointGroup.ProtoReflect.Descriptor instead. -func (*DNSEndpointGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{6} -} - -func (x *DNSEndpointGroup) GetConfig() *DNSEndpointGroupConfig { - if x != nil { - return x.Config - } - return nil -} - -func (x *DNSEndpointGroup) GetOutboundTls() *TransportSocket { - if x != nil { - return x.OutboundTls - } - return nil -} - -// StaticEndpointGroup is used to reach local app ports. -type StaticEndpointGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // config configures how to connect to the endpoints. - Config *StaticEndpointGroupConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` -} - -func (x *StaticEndpointGroup) Reset() { - *x = StaticEndpointGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StaticEndpointGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StaticEndpointGroup) ProtoMessage() {} - -func (x *StaticEndpointGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[7] - 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 StaticEndpointGroup.ProtoReflect.Descriptor instead. -func (*StaticEndpointGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{7} -} - -func (x *StaticEndpointGroup) GetConfig() *StaticEndpointGroupConfig { - if x != nil { - return x.Config - } - return nil -} - -type L4WeightedClusterGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // clusters to route to by weight. - Clusters []*L4WeightedDestinationCluster `protobuf:"bytes,1,rep,name=clusters,proto3" json:"clusters,omitempty"` -} - -func (x *L4WeightedClusterGroup) Reset() { - *x = L4WeightedClusterGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L4WeightedClusterGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L4WeightedClusterGroup) ProtoMessage() {} - -func (x *L4WeightedClusterGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[8] - 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 L4WeightedClusterGroup.ProtoReflect.Descriptor instead. -func (*L4WeightedClusterGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{8} -} - -func (x *L4WeightedClusterGroup) GetClusters() []*L4WeightedDestinationCluster { - if x != nil { - return x.Clusters - } - return nil -} - -type L7WeightedClusterGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // clusters to route to by weight. - Clusters []*L7WeightedDestinationCluster `protobuf:"bytes,1,rep,name=clusters,proto3" json:"clusters,omitempty"` -} - -func (x *L7WeightedClusterGroup) Reset() { - *x = L7WeightedClusterGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L7WeightedClusterGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L7WeightedClusterGroup) ProtoMessage() {} - -func (x *L7WeightedClusterGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[9] - 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 L7WeightedClusterGroup.ProtoReflect.Descriptor instead. -func (*L7WeightedClusterGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{9} -} - -func (x *L7WeightedClusterGroup) GetClusters() []*L7WeightedDestinationCluster { - if x != nil { - return x.Clusters - } - return nil -} - -type L4WeightedDestinationCluster struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Weight *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=weight,proto3" json:"weight,omitempty"` -} - -func (x *L4WeightedDestinationCluster) Reset() { - *x = L4WeightedDestinationCluster{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L4WeightedDestinationCluster) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L4WeightedDestinationCluster) ProtoMessage() {} - -func (x *L4WeightedDestinationCluster) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[10] - 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 L4WeightedDestinationCluster.ProtoReflect.Descriptor instead. -func (*L4WeightedDestinationCluster) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{10} -} - -func (x *L4WeightedDestinationCluster) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *L4WeightedDestinationCluster) GetWeight() *wrapperspb.UInt32Value { - if x != nil { - return x.Weight - } - return nil -} - -type L7WeightedDestinationCluster struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Weight *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=weight,proto3" json:"weight,omitempty"` - HeaderMutations []*HeaderMutation `protobuf:"bytes,3,rep,name=header_mutations,json=headerMutations,proto3" json:"header_mutations,omitempty"` -} - -func (x *L7WeightedDestinationCluster) Reset() { - *x = L7WeightedDestinationCluster{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L7WeightedDestinationCluster) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L7WeightedDestinationCluster) ProtoMessage() {} - -func (x *L7WeightedDestinationCluster) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[11] - 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 L7WeightedDestinationCluster.ProtoReflect.Descriptor instead. -func (*L7WeightedDestinationCluster) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{11} -} - -func (x *L7WeightedDestinationCluster) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *L7WeightedDestinationCluster) GetWeight() *wrapperspb.UInt32Value { - if x != nil { - return x.Weight - } - return nil -} - -func (x *L7WeightedDestinationCluster) GetHeaderMutations() []*HeaderMutation { - if x != nil { - return x.HeaderMutations - } - return nil -} - -type DynamicEndpointGroupConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ConnectTimeout *durationpb.Duration `protobuf:"bytes,1,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` - DisablePanicThreshold bool `protobuf:"varint,2,opt,name=disable_panic_threshold,json=disablePanicThreshold,proto3" json:"disable_panic_threshold,omitempty"` - // Types that are assignable to LbPolicy: - // - // *DynamicEndpointGroupConfig_LeastRequest - // *DynamicEndpointGroupConfig_RoundRobin - // *DynamicEndpointGroupConfig_Random - // *DynamicEndpointGroupConfig_RingHash - // *DynamicEndpointGroupConfig_Maglev - LbPolicy isDynamicEndpointGroupConfig_LbPolicy `protobuf_oneof:"lb_policy"` - CircuitBreakers *CircuitBreakers `protobuf:"bytes,8,opt,name=circuit_breakers,json=circuitBreakers,proto3" json:"circuit_breakers,omitempty"` - OutlierDetection *OutlierDetection `protobuf:"bytes,9,opt,name=outlier_detection,json=outlierDetection,proto3" json:"outlier_detection,omitempty"` - UpstreamConnectionOptions *UpstreamConnectionOptions `protobuf:"bytes,10,opt,name=upstream_connection_options,json=upstreamConnectionOptions,proto3" json:"upstream_connection_options,omitempty"` - UseAltStatName bool `protobuf:"varint,11,opt,name=use_alt_stat_name,json=useAltStatName,proto3" json:"use_alt_stat_name,omitempty"` -} - -func (x *DynamicEndpointGroupConfig) Reset() { - *x = DynamicEndpointGroupConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DynamicEndpointGroupConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DynamicEndpointGroupConfig) ProtoMessage() {} - -func (x *DynamicEndpointGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[12] - 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 DynamicEndpointGroupConfig.ProtoReflect.Descriptor instead. -func (*DynamicEndpointGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{12} -} - -func (x *DynamicEndpointGroupConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetDisablePanicThreshold() bool { - if x != nil { - return x.DisablePanicThreshold - } - return false -} - -func (m *DynamicEndpointGroupConfig) GetLbPolicy() isDynamicEndpointGroupConfig_LbPolicy { - if m != nil { - return m.LbPolicy - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetLeastRequest() *LBPolicyLeastRequest { - if x, ok := x.GetLbPolicy().(*DynamicEndpointGroupConfig_LeastRequest); ok { - return x.LeastRequest - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetRoundRobin() *LBPolicyRoundRobin { - if x, ok := x.GetLbPolicy().(*DynamicEndpointGroupConfig_RoundRobin); ok { - return x.RoundRobin - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetRandom() *LBPolicyRandom { - if x, ok := x.GetLbPolicy().(*DynamicEndpointGroupConfig_Random); ok { - return x.Random - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetRingHash() *LBPolicyRingHash { - if x, ok := x.GetLbPolicy().(*DynamicEndpointGroupConfig_RingHash); ok { - return x.RingHash - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetMaglev() *LBPolicyMaglev { - if x, ok := x.GetLbPolicy().(*DynamicEndpointGroupConfig_Maglev); ok { - return x.Maglev - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetCircuitBreakers() *CircuitBreakers { - if x != nil { - return x.CircuitBreakers - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetOutlierDetection() *OutlierDetection { - if x != nil { - return x.OutlierDetection - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetUpstreamConnectionOptions() *UpstreamConnectionOptions { - if x != nil { - return x.UpstreamConnectionOptions - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetUseAltStatName() bool { - if x != nil { - return x.UseAltStatName - } - return false -} - -type isDynamicEndpointGroupConfig_LbPolicy interface { - isDynamicEndpointGroupConfig_LbPolicy() -} - -type DynamicEndpointGroupConfig_LeastRequest struct { - LeastRequest *LBPolicyLeastRequest `protobuf:"bytes,3,opt,name=least_request,json=leastRequest,proto3,oneof"` -} - -type DynamicEndpointGroupConfig_RoundRobin struct { - RoundRobin *LBPolicyRoundRobin `protobuf:"bytes,4,opt,name=round_robin,json=roundRobin,proto3,oneof"` -} - -type DynamicEndpointGroupConfig_Random struct { - Random *LBPolicyRandom `protobuf:"bytes,5,opt,name=random,proto3,oneof"` -} - -type DynamicEndpointGroupConfig_RingHash struct { - RingHash *LBPolicyRingHash `protobuf:"bytes,6,opt,name=ring_hash,json=ringHash,proto3,oneof"` -} - -type DynamicEndpointGroupConfig_Maglev struct { - Maglev *LBPolicyMaglev `protobuf:"bytes,7,opt,name=maglev,proto3,oneof"` -} - -func (*DynamicEndpointGroupConfig_LeastRequest) isDynamicEndpointGroupConfig_LbPolicy() {} - -func (*DynamicEndpointGroupConfig_RoundRobin) isDynamicEndpointGroupConfig_LbPolicy() {} - -func (*DynamicEndpointGroupConfig_Random) isDynamicEndpointGroupConfig_LbPolicy() {} - -func (*DynamicEndpointGroupConfig_RingHash) isDynamicEndpointGroupConfig_LbPolicy() {} - -func (*DynamicEndpointGroupConfig_Maglev) isDynamicEndpointGroupConfig_LbPolicy() {} - -type LBPolicyLeastRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ChoiceCount *wrapperspb.UInt32Value `protobuf:"bytes,1,opt,name=choice_count,json=choiceCount,proto3" json:"choice_count,omitempty"` -} - -func (x *LBPolicyLeastRequest) Reset() { - *x = LBPolicyLeastRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LBPolicyLeastRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LBPolicyLeastRequest) ProtoMessage() {} - -func (x *LBPolicyLeastRequest) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[13] - 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 LBPolicyLeastRequest.ProtoReflect.Descriptor instead. -func (*LBPolicyLeastRequest) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{13} -} - -func (x *LBPolicyLeastRequest) GetChoiceCount() *wrapperspb.UInt32Value { - if x != nil { - return x.ChoiceCount - } - return nil -} - -type LBPolicyRoundRobin struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *LBPolicyRoundRobin) Reset() { - *x = LBPolicyRoundRobin{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LBPolicyRoundRobin) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LBPolicyRoundRobin) ProtoMessage() {} - -func (x *LBPolicyRoundRobin) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[14] - 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 LBPolicyRoundRobin.ProtoReflect.Descriptor instead. -func (*LBPolicyRoundRobin) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{14} -} - -type LBPolicyRandom struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *LBPolicyRandom) Reset() { - *x = LBPolicyRandom{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LBPolicyRandom) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LBPolicyRandom) ProtoMessage() {} - -func (x *LBPolicyRandom) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[15] - 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 LBPolicyRandom.ProtoReflect.Descriptor instead. -func (*LBPolicyRandom) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{15} -} - -type LBPolicyRingHash struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MinimumRingSize *wrapperspb.UInt64Value `protobuf:"bytes,1,opt,name=minimum_ring_size,json=minimumRingSize,proto3" json:"minimum_ring_size,omitempty"` - MaximumRingSize *wrapperspb.UInt64Value `protobuf:"bytes,2,opt,name=maximum_ring_size,json=maximumRingSize,proto3" json:"maximum_ring_size,omitempty"` -} - -func (x *LBPolicyRingHash) Reset() { - *x = LBPolicyRingHash{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LBPolicyRingHash) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LBPolicyRingHash) ProtoMessage() {} - -func (x *LBPolicyRingHash) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[16] - 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 LBPolicyRingHash.ProtoReflect.Descriptor instead. -func (*LBPolicyRingHash) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{16} -} - -func (x *LBPolicyRingHash) GetMinimumRingSize() *wrapperspb.UInt64Value { - if x != nil { - return x.MinimumRingSize - } - return nil -} - -func (x *LBPolicyRingHash) GetMaximumRingSize() *wrapperspb.UInt64Value { - if x != nil { - return x.MaximumRingSize - } - return nil -} - -type LBPolicyMaglev struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *LBPolicyMaglev) Reset() { - *x = LBPolicyMaglev{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LBPolicyMaglev) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LBPolicyMaglev) ProtoMessage() {} - -func (x *LBPolicyMaglev) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[17] - 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 LBPolicyMaglev.ProtoReflect.Descriptor instead. -func (*LBPolicyMaglev) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{17} -} - -type CircuitBreakers struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - UpstreamLimits *UpstreamLimits `protobuf:"bytes,1,opt,name=upstream_limits,json=upstreamLimits,proto3" json:"upstream_limits,omitempty"` -} - -func (x *CircuitBreakers) Reset() { - *x = CircuitBreakers{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CircuitBreakers) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CircuitBreakers) ProtoMessage() {} - -func (x *CircuitBreakers) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[18] - 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 CircuitBreakers.ProtoReflect.Descriptor instead. -func (*CircuitBreakers) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{18} -} - -func (x *CircuitBreakers) GetUpstreamLimits() *UpstreamLimits { - if x != nil { - return x.UpstreamLimits - } - return nil -} - -type UpstreamLimits struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MaxConnections *wrapperspb.UInt32Value `protobuf:"bytes,1,opt,name=max_connections,json=maxConnections,proto3" json:"max_connections,omitempty"` - MaxPendingRequests *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=max_pending_requests,json=maxPendingRequests,proto3" json:"max_pending_requests,omitempty"` - MaxConcurrentRequests *wrapperspb.UInt32Value `protobuf:"bytes,3,opt,name=max_concurrent_requests,json=maxConcurrentRequests,proto3" json:"max_concurrent_requests,omitempty"` -} - -func (x *UpstreamLimits) Reset() { - *x = UpstreamLimits{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpstreamLimits) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpstreamLimits) ProtoMessage() {} - -func (x *UpstreamLimits) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[19] - 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 UpstreamLimits.ProtoReflect.Descriptor instead. -func (*UpstreamLimits) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{19} -} - -func (x *UpstreamLimits) GetMaxConnections() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxConnections - } - return nil -} - -func (x *UpstreamLimits) GetMaxPendingRequests() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxPendingRequests - } - return nil -} - -func (x *UpstreamLimits) GetMaxConcurrentRequests() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxConcurrentRequests - } - return nil -} - -type OutlierDetection struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Interval *durationpb.Duration `protobuf:"bytes,1,opt,name=interval,proto3" json:"interval,omitempty"` - Consecutive_5Xx *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=consecutive_5xx,json=consecutive5xx,proto3" json:"consecutive_5xx,omitempty"` - EnforcingConsecutive_5Xx *wrapperspb.UInt32Value `protobuf:"bytes,3,opt,name=enforcing_consecutive_5xx,json=enforcingConsecutive5xx,proto3" json:"enforcing_consecutive_5xx,omitempty"` - MaxEjectionPercent *wrapperspb.UInt32Value `protobuf:"bytes,4,opt,name=max_ejection_percent,json=maxEjectionPercent,proto3" json:"max_ejection_percent,omitempty"` - BaseEjectionTime *durationpb.Duration `protobuf:"bytes,5,opt,name=base_ejection_time,json=baseEjectionTime,proto3" json:"base_ejection_time,omitempty"` -} - -func (x *OutlierDetection) Reset() { - *x = OutlierDetection{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OutlierDetection) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OutlierDetection) ProtoMessage() {} - -func (x *OutlierDetection) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[20] - 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 OutlierDetection.ProtoReflect.Descriptor instead. -func (*OutlierDetection) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{20} -} - -func (x *OutlierDetection) GetInterval() *durationpb.Duration { - if x != nil { - return x.Interval - } - return nil -} - -func (x *OutlierDetection) GetConsecutive_5Xx() *wrapperspb.UInt32Value { - if x != nil { - return x.Consecutive_5Xx - } - return nil -} - -func (x *OutlierDetection) GetEnforcingConsecutive_5Xx() *wrapperspb.UInt32Value { - if x != nil { - return x.EnforcingConsecutive_5Xx - } - return nil -} - -func (x *OutlierDetection) GetMaxEjectionPercent() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxEjectionPercent - } - return nil -} - -func (x *OutlierDetection) GetBaseEjectionTime() *durationpb.Duration { - if x != nil { - return x.BaseEjectionTime - } - return nil -} - -type UpstreamConnectionOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TcpKeepaliveTime *wrapperspb.UInt32Value `protobuf:"bytes,1,opt,name=tcp_keepalive_time,json=tcpKeepaliveTime,proto3" json:"tcp_keepalive_time,omitempty"` - TcpKeepaliveInterval *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=tcp_keepalive_interval,json=tcpKeepaliveInterval,proto3" json:"tcp_keepalive_interval,omitempty"` - TcpKeepaliveProbes *wrapperspb.UInt32Value `protobuf:"bytes,3,opt,name=tcp_keepalive_probes,json=tcpKeepaliveProbes,proto3" json:"tcp_keepalive_probes,omitempty"` -} - -func (x *UpstreamConnectionOptions) Reset() { - *x = UpstreamConnectionOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpstreamConnectionOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpstreamConnectionOptions) ProtoMessage() {} - -func (x *UpstreamConnectionOptions) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[21] - 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 UpstreamConnectionOptions.ProtoReflect.Descriptor instead. -func (*UpstreamConnectionOptions) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{21} -} - -func (x *UpstreamConnectionOptions) GetTcpKeepaliveTime() *wrapperspb.UInt32Value { - if x != nil { - return x.TcpKeepaliveTime - } - return nil -} - -func (x *UpstreamConnectionOptions) GetTcpKeepaliveInterval() *wrapperspb.UInt32Value { - if x != nil { - return x.TcpKeepaliveInterval - } - return nil -} - -func (x *UpstreamConnectionOptions) GetTcpKeepaliveProbes() *wrapperspb.UInt32Value { - if x != nil { - return x.TcpKeepaliveProbes - } - return nil -} - -type PassthroughEndpointGroupConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ConnectTimeout *durationpb.Duration `protobuf:"bytes,1,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` -} - -func (x *PassthroughEndpointGroupConfig) Reset() { - *x = PassthroughEndpointGroupConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PassthroughEndpointGroupConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PassthroughEndpointGroupConfig) ProtoMessage() {} - -func (x *PassthroughEndpointGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[22] - 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 PassthroughEndpointGroupConfig.ProtoReflect.Descriptor instead. -func (*PassthroughEndpointGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{22} -} - -func (x *PassthroughEndpointGroupConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -type DNSEndpointGroupConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ConnectTimeout *durationpb.Duration `protobuf:"bytes,1,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` - DisablePanicThreshold bool `protobuf:"varint,2,opt,name=disable_panic_threshold,json=disablePanicThreshold,proto3" json:"disable_panic_threshold,omitempty"` - DiscoveryType DiscoveryType `protobuf:"varint,3,opt,name=discovery_type,json=discoveryType,proto3,enum=hashicorp.consul.mesh.v1alpha1.pbproxystate.DiscoveryType" json:"discovery_type,omitempty"` - CircuitBreakers *CircuitBreakers `protobuf:"bytes,4,opt,name=circuit_breakers,json=circuitBreakers,proto3" json:"circuit_breakers,omitempty"` - OutlierDetection *OutlierDetection `protobuf:"bytes,5,opt,name=outlier_detection,json=outlierDetection,proto3" json:"outlier_detection,omitempty"` - UpstreamConnectionOptions *UpstreamConnectionOptions `protobuf:"bytes,6,opt,name=upstream_connection_options,json=upstreamConnectionOptions,proto3" json:"upstream_connection_options,omitempty"` - UseAltStatName bool `protobuf:"varint,7,opt,name=use_alt_stat_name,json=useAltStatName,proto3" json:"use_alt_stat_name,omitempty"` -} - -func (x *DNSEndpointGroupConfig) Reset() { - *x = DNSEndpointGroupConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DNSEndpointGroupConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DNSEndpointGroupConfig) ProtoMessage() {} - -func (x *DNSEndpointGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[23] - 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 DNSEndpointGroupConfig.ProtoReflect.Descriptor instead. -func (*DNSEndpointGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{23} -} - -func (x *DNSEndpointGroupConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -func (x *DNSEndpointGroupConfig) GetDisablePanicThreshold() bool { - if x != nil { - return x.DisablePanicThreshold - } - return false -} - -func (x *DNSEndpointGroupConfig) GetDiscoveryType() DiscoveryType { - if x != nil { - return x.DiscoveryType - } - return DiscoveryType_DISCOVERY_TYPE_LOGICAL -} - -func (x *DNSEndpointGroupConfig) GetCircuitBreakers() *CircuitBreakers { - if x != nil { - return x.CircuitBreakers - } - return nil -} - -func (x *DNSEndpointGroupConfig) GetOutlierDetection() *OutlierDetection { - if x != nil { - return x.OutlierDetection - } - return nil -} - -func (x *DNSEndpointGroupConfig) GetUpstreamConnectionOptions() *UpstreamConnectionOptions { - if x != nil { - return x.UpstreamConnectionOptions - } - return nil -} - -func (x *DNSEndpointGroupConfig) GetUseAltStatName() bool { - if x != nil { - return x.UseAltStatName - } - return false -} - -type StaticEndpointGroupConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ConnectTimeout *durationpb.Duration `protobuf:"bytes,1,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` - CircuitBreakers *CircuitBreakers `protobuf:"bytes,2,opt,name=circuit_breakers,json=circuitBreakers,proto3" json:"circuit_breakers,omitempty"` -} - -func (x *StaticEndpointGroupConfig) Reset() { - *x = StaticEndpointGroupConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StaticEndpointGroupConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StaticEndpointGroupConfig) ProtoMessage() {} - -func (x *StaticEndpointGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[24] - 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 StaticEndpointGroupConfig.ProtoReflect.Descriptor instead. -func (*StaticEndpointGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP(), []int{24} -} - -func (x *StaticEndpointGroupConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -func (x *StaticEndpointGroupConfig) GetCircuitBreakers() *CircuitBreakers { - if x != nil { - return x.CircuitBreakers - } - return nil -} - -var File_pbmesh_v1alpha1_pbproxystate_cluster_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDesc = []byte{ - 0x0a, 0x2a, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2b, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, - 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x33, 0x70, 0x62, 0x6d, 0x65, 0x73, - 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, - 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x33, - 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0xeb, 0x02, 0x0a, 0x07, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x63, 0x0a, 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x5f, - 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, - 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x0d, 0x66, 0x61, 0x69, 0x6c, 0x6f, - 0x76, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x63, 0x0a, 0x0e, 0x65, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x45, - 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x0d, - 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x39, 0x0a, - 0x19, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x5f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x16, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x48, 0x61, 0x74, 0x63, 0x68, 0x43, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x6c, 0x74, 0x5f, - 0x73, 0x74, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x61, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x42, 0x07, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x22, 0xce, 0x01, 0x0a, 0x0d, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x12, 0x63, 0x0a, 0x0f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, - 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x0e, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x58, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x22, 0x84, 0x01, 0x0a, 0x13, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x0a, 0x11, 0x75, 0x73, - 0x65, 0x5f, 0x61, 0x6c, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x41, 0x6c, 0x74, 0x53, 0x74, 0x61, - 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x91, 0x03, 0x0a, 0x0d, 0x45, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x5d, 0x0a, 0x07, 0x64, - 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, - 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, - 0x00, 0x52, 0x07, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x12, 0x5a, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x45, - 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x12, 0x51, 0x0a, 0x03, 0x64, 0x6e, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x44, 0x4e, 0x53, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x48, 0x00, 0x52, 0x03, 0x64, 0x6e, 0x73, 0x12, 0x69, 0x0a, 0x0b, 0x70, 0x61, 0x73, - 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x45, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x61, 0x73, - 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, - 0x6f, 0x75, 0x67, 0x68, 0x42, 0x07, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0xd8, 0x01, - 0x0a, 0x14, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x5f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x47, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5f, 0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0b, 0x6f, 0x75, 0x74, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x6c, 0x73, 0x22, 0xe0, 0x01, 0x0a, 0x18, 0x50, 0x61, 0x73, - 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x63, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x45, - 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5f, 0x0a, 0x0c, 0x6f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0b, - 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x6c, 0x73, 0x22, 0xd0, 0x01, 0x0a, 0x10, - 0x44, 0x4e, 0x53, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x12, 0x5b, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, - 0x4e, 0x53, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5f, 0x0a, - 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x6c, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x6f, 0x63, 0x6b, 0x65, - 0x74, 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x6c, 0x73, 0x22, 0x75, - 0x0a, 0x13, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x5e, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x7f, 0x0a, 0x16, 0x4c, 0x34, 0x57, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, - 0x65, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x49, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, - 0x4c, 0x34, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x22, 0x7f, 0x0a, 0x16, 0x4c, 0x37, 0x57, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x12, 0x65, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x4c, 0x37, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x22, 0x68, 0x0a, 0x1c, 0x4c, 0x34, 0x57, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x77, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x22, 0xd0, 0x01, 0x0a, 0x1c, 0x4c, 0x37, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, - 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x66, 0x0a, 0x10, - 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x88, 0x08, 0x0a, 0x1a, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, - 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x69, 0x73, 0x61, 0x62, - 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, - 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, - 0x65, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, - 0x68, 0x0a, 0x0d, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x65, 0x61, - 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x6c, 0x65, 0x61, - 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x62, 0x0a, 0x0b, 0x72, 0x6f, 0x75, - 0x6e, 0x64, 0x5f, 0x72, 0x6f, 0x62, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x62, 0x69, 0x6e, 0x48, - 0x00, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x62, 0x69, 0x6e, 0x12, 0x55, 0x0a, - 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x48, 0x00, 0x52, 0x06, 0x72, 0x61, - 0x6e, 0x64, 0x6f, 0x6d, 0x12, 0x5c, 0x0a, 0x09, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x69, - 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x48, 0x00, 0x52, 0x08, 0x72, 0x69, 0x6e, 0x67, 0x48, 0x61, - 0x73, 0x68, 0x12, 0x55, 0x0a, 0x06, 0x6d, 0x61, 0x67, 0x6c, 0x65, 0x76, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4d, 0x61, 0x67, 0x6c, 0x65, 0x76, 0x48, - 0x00, 0x52, 0x06, 0x6d, 0x61, 0x67, 0x6c, 0x65, 0x76, 0x12, 0x67, 0x0a, 0x10, 0x63, 0x69, 0x72, - 0x63, 0x75, 0x69, 0x74, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, - 0x73, 0x52, 0x0f, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, - 0x72, 0x73, 0x12, 0x6a, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x64, 0x65, - 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x6c, - 0x69, 0x65, 0x72, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x6f, 0x75, - 0x74, 0x6c, 0x69, 0x65, 0x72, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x86, - 0x01, 0x0a, 0x1b, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x19, 0x75, 0x70, - 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x5f, 0x61, - 0x6c, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x41, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x4e, 0x61, - 0x6d, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x6c, 0x62, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, - 0x57, 0x0a, 0x14, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x0c, 0x63, 0x68, 0x6f, 0x69, 0x63, - 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0b, 0x63, 0x68, 0x6f, - 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x14, 0x0a, 0x12, 0x4c, 0x42, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x62, 0x69, 0x6e, 0x22, 0x10, - 0x0a, 0x0e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, - 0x22, 0xa6, 0x01, 0x0a, 0x10, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x69, 0x6e, - 0x67, 0x48, 0x61, 0x73, 0x68, 0x12, 0x48, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, - 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, - 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x12, - 0x48, 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, - 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, - 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, - 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x10, 0x0a, 0x0e, 0x4c, 0x42, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4d, 0x61, 0x67, 0x6c, 0x65, 0x76, 0x22, 0x77, 0x0a, 0x0f, 0x43, - 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x64, - 0x0a, 0x0f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x73, 0x52, 0x0e, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x73, 0x22, 0xfd, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, - 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4e, - 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x6d, 0x61, 0x78, 0x50, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x54, - 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, - 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x15, 0x6d, - 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x73, 0x22, 0x83, 0x03, 0x0a, 0x10, 0x4f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, - 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x08, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, - 0x12, 0x45, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, - 0x35, 0x78, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, - 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, 0x78, 0x12, 0x58, 0x0a, 0x19, 0x65, 0x6e, 0x66, 0x6f, 0x72, - 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, - 0x5f, 0x35, 0x78, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, - 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x17, 0x65, 0x6e, 0x66, 0x6f, 0x72, 0x63, - 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, - 0x78, 0x12, 0x4e, 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x6d, - 0x61, 0x78, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, - 0x74, 0x12, 0x47, 0x0a, 0x12, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x62, 0x61, 0x73, 0x65, 0x45, 0x6a, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x8b, 0x02, 0x0a, 0x19, 0x55, - 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4a, 0x0a, 0x12, 0x74, 0x63, 0x70, 0x5f, - 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x10, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, - 0x54, 0x69, 0x6d, 0x65, 0x12, 0x52, 0x0a, 0x16, 0x74, 0x63, 0x70, 0x5f, 0x6b, 0x65, 0x65, 0x70, - 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x14, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x4e, 0x0a, 0x14, 0x74, 0x63, 0x70, 0x5f, - 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, - 0x76, 0x65, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x1e, 0x50, 0x61, 0x73, 0x73, - 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x80, - 0x05, 0x0a, 0x16, 0x44, 0x4e, 0x53, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x36, 0x0a, - 0x17, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x5f, 0x74, - 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, - 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x54, 0x68, 0x72, 0x65, - 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x61, 0x0a, 0x0e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, - 0x72, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x67, 0x0a, 0x10, 0x63, 0x69, 0x72, 0x63, - 0x75, 0x69, 0x74, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, - 0x52, 0x0f, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, - 0x73, 0x12, 0x6a, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x6c, 0x69, - 0x65, 0x72, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x6f, 0x75, 0x74, - 0x6c, 0x69, 0x65, 0x72, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x86, 0x01, - 0x0a, 0x1b, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x19, 0x75, 0x70, 0x73, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x5f, 0x61, 0x6c, - 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x41, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x22, 0xc8, 0x01, 0x0a, 0x19, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x12, 0x67, 0x0a, 0x10, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x5f, 0x62, - 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x69, 0x72, 0x63, - 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x63, 0x69, 0x72, - 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x2a, 0x46, 0x0a, 0x0d, - 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, - 0x16, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x4c, 0x4f, 0x47, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x53, - 0x43, 0x4f, 0x56, 0x45, 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, - 0x43, 0x54, 0x10, 0x01, 0x42, 0xd8, 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, - 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, - 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescData = file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDesc -) - -func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDescData -} - -var file_pbmesh_v1alpha1_pbproxystate_cluster_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes = make([]protoimpl.MessageInfo, 25) -var file_pbmesh_v1alpha1_pbproxystate_cluster_proto_goTypes = []interface{}{ - (DiscoveryType)(0), // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.DiscoveryType - (*Cluster)(nil), // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.Cluster - (*FailoverGroup)(nil), // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.FailoverGroup - (*FailoverGroupConfig)(nil), // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.FailoverGroupConfig - (*EndpointGroup)(nil), // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointGroup - (*DynamicEndpointGroup)(nil), // 5: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroup - (*PassthroughEndpointGroup)(nil), // 6: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroup - (*DNSEndpointGroup)(nil), // 7: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroup - (*StaticEndpointGroup)(nil), // 8: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroup - (*L4WeightedClusterGroup)(nil), // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedClusterGroup - (*L7WeightedClusterGroup)(nil), // 10: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedClusterGroup - (*L4WeightedDestinationCluster)(nil), // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedDestinationCluster - (*L7WeightedDestinationCluster)(nil), // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedDestinationCluster - (*DynamicEndpointGroupConfig)(nil), // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig - (*LBPolicyLeastRequest)(nil), // 14: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyLeastRequest - (*LBPolicyRoundRobin)(nil), // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRoundRobin - (*LBPolicyRandom)(nil), // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRandom - (*LBPolicyRingHash)(nil), // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRingHash - (*LBPolicyMaglev)(nil), // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyMaglev - (*CircuitBreakers)(nil), // 19: hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers - (*UpstreamLimits)(nil), // 20: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits - (*OutlierDetection)(nil), // 21: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection - (*UpstreamConnectionOptions)(nil), // 22: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions - (*PassthroughEndpointGroupConfig)(nil), // 23: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroupConfig - (*DNSEndpointGroupConfig)(nil), // 24: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig - (*StaticEndpointGroupConfig)(nil), // 25: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroupConfig - (*durationpb.Duration)(nil), // 26: google.protobuf.Duration - (*TransportSocket)(nil), // 27: hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket - (*wrapperspb.UInt32Value)(nil), // 28: google.protobuf.UInt32Value - (*HeaderMutation)(nil), // 29: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation - (*wrapperspb.UInt64Value)(nil), // 30: google.protobuf.UInt64Value -} -var file_pbmesh_v1alpha1_pbproxystate_cluster_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.Cluster.failover_group:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.FailoverGroup - 4, // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.Cluster.endpoint_group:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointGroup - 4, // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.FailoverGroup.endpoint_groups:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointGroup - 3, // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.FailoverGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.FailoverGroupConfig - 26, // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.FailoverGroupConfig.connect_timeout:type_name -> google.protobuf.Duration - 5, // 5: hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointGroup.dynamic:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroup - 8, // 6: hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointGroup.static:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroup - 7, // 7: hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointGroup.dns:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroup - 6, // 8: hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointGroup.passthrough:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroup - 13, // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig - 27, // 10: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroup.outbound_tls:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket - 23, // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroupConfig - 27, // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroup.outbound_tls:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket - 24, // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig - 27, // 14: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroup.outbound_tls:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket - 25, // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroup.config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroupConfig - 11, // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedClusterGroup.clusters:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedDestinationCluster - 12, // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedClusterGroup.clusters:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedDestinationCluster - 28, // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4WeightedDestinationCluster.weight:type_name -> google.protobuf.UInt32Value - 28, // 19: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedDestinationCluster.weight:type_name -> google.protobuf.UInt32Value - 29, // 20: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedDestinationCluster.header_mutations:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation - 26, // 21: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration - 14, // 22: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.least_request:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyLeastRequest - 15, // 23: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.round_robin:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRoundRobin - 16, // 24: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.random:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRandom - 17, // 25: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.ring_hash:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRingHash - 18, // 26: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.maglev:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyMaglev - 19, // 27: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.circuit_breakers:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers - 21, // 28: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.outlier_detection:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection - 22, // 29: hashicorp.consul.mesh.v1alpha1.pbproxystate.DynamicEndpointGroupConfig.upstream_connection_options:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions - 28, // 30: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyLeastRequest.choice_count:type_name -> google.protobuf.UInt32Value - 30, // 31: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRingHash.minimum_ring_size:type_name -> google.protobuf.UInt64Value - 30, // 32: hashicorp.consul.mesh.v1alpha1.pbproxystate.LBPolicyRingHash.maximum_ring_size:type_name -> google.protobuf.UInt64Value - 20, // 33: hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers.upstream_limits:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits - 28, // 34: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits.max_connections:type_name -> google.protobuf.UInt32Value - 28, // 35: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits.max_pending_requests:type_name -> google.protobuf.UInt32Value - 28, // 36: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamLimits.max_concurrent_requests:type_name -> google.protobuf.UInt32Value - 26, // 37: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.interval:type_name -> google.protobuf.Duration - 28, // 38: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.consecutive_5xx:type_name -> google.protobuf.UInt32Value - 28, // 39: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.enforcing_consecutive_5xx:type_name -> google.protobuf.UInt32Value - 28, // 40: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.max_ejection_percent:type_name -> google.protobuf.UInt32Value - 26, // 41: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection.base_ejection_time:type_name -> google.protobuf.Duration - 28, // 42: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions.tcp_keepalive_time:type_name -> google.protobuf.UInt32Value - 28, // 43: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions.tcp_keepalive_interval:type_name -> google.protobuf.UInt32Value - 28, // 44: hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions.tcp_keepalive_probes:type_name -> google.protobuf.UInt32Value - 26, // 45: hashicorp.consul.mesh.v1alpha1.pbproxystate.PassthroughEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration - 26, // 46: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration - 0, // 47: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.discovery_type:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DiscoveryType - 19, // 48: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.circuit_breakers:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers - 21, // 49: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.outlier_detection:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.OutlierDetection - 22, // 50: hashicorp.consul.mesh.v1alpha1.pbproxystate.DNSEndpointGroupConfig.upstream_connection_options:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.UpstreamConnectionOptions - 26, // 51: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration - 19, // 52: hashicorp.consul.mesh.v1alpha1.pbproxystate.StaticEndpointGroupConfig.circuit_breakers:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CircuitBreakers - 53, // [53:53] is the sub-list for method output_type - 53, // [53:53] is the sub-list for method input_type - 53, // [53:53] is the sub-list for extension type_name - 53, // [53:53] is the sub-list for extension extendee - 0, // [0:53] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() } -func file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() { - if File_pbmesh_v1alpha1_pbproxystate_cluster_proto != nil { - return - } - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_init() - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Cluster); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FailoverGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FailoverGroupConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EndpointGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DynamicEndpointGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PassthroughEndpointGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DNSEndpointGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StaticEndpointGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L4WeightedClusterGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L7WeightedClusterGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L4WeightedDestinationCluster); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L7WeightedDestinationCluster); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DynamicEndpointGroupConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyLeastRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyRoundRobin); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyRandom); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyRingHash); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyMaglev); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CircuitBreakers); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpstreamLimits); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OutlierDetection); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpstreamConnectionOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PassthroughEndpointGroupConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DNSEndpointGroupConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StaticEndpointGroupConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*Cluster_FailoverGroup)(nil), - (*Cluster_EndpointGroup)(nil), - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[3].OneofWrappers = []interface{}{ - (*EndpointGroup_Dynamic)(nil), - (*EndpointGroup_Static)(nil), - (*EndpointGroup_Dns)(nil), - (*EndpointGroup_Passthrough)(nil), - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes[12].OneofWrappers = []interface{}{ - (*DynamicEndpointGroupConfig_LeastRequest)(nil), - (*DynamicEndpointGroupConfig_RoundRobin)(nil), - (*DynamicEndpointGroupConfig_Random)(nil), - (*DynamicEndpointGroupConfig_RingHash)(nil), - (*DynamicEndpointGroupConfig_Maglev)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDesc, - NumEnums: 1, - NumMessages: 25, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_pbproxystate_cluster_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_pbproxystate_cluster_proto_depIdxs, - EnumInfos: file_pbmesh_v1alpha1_pbproxystate_cluster_proto_enumTypes, - MessageInfos: file_pbmesh_v1alpha1_pbproxystate_cluster_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_pbproxystate_cluster_proto = out.File - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_rawDesc = nil - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_goTypes = nil - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.proto deleted file mode 100644 index 802e873401e8c..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/cluster.proto +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1.pbproxystate; - -import "google/protobuf/duration.proto"; -import "google/protobuf/wrappers.proto"; -import "pbmesh/v1alpha1/pbproxystate/header_mutations.proto"; -import "pbmesh/v1alpha1/pbproxystate/transport_socket.proto"; - -message Cluster { - // name is the name of the cluster. - string name = 1; - // group is either a failover group or endpoint group. If this cluster needs to failover to other clusters, use the failover group. If this cluster routes directly to endpoints, use the endpoint group. - oneof group { - FailoverGroup failover_group = 2; - EndpointGroup endpoint_group = 3; - } - // escape_hatch_cluster_json configures a user configured escape hatch cluster. - string escape_hatch_cluster_json = 4; - // alt_stat_name is the name used for observability in place of cluster name if provided. - string alt_stat_name = 5; - // protocol is the local path protocol or the service protocol. - string protocol = 6; -} - -message FailoverGroup { - // endpoint_groups is an ordered list of which groups to failover to. - repeated EndpointGroup endpoint_groups = 1; - FailoverGroupConfig config = 2; -} - -message FailoverGroupConfig { - bool use_alt_stat_name = 1; - google.protobuf.Duration connect_timeout = 2; -} - -message EndpointGroup { - oneof group { - // dynamic endpoint group is used to reach mesh destinations that are dynamically configured from Consul's catalog. - DynamicEndpointGroup dynamic = 1; - // static endpoint group is used to reach local app ports. - StaticEndpointGroup static = 2; - // dns is used to reach mesh and non-mesh destinations using a hostname. - DNSEndpointGroup dns = 3; - // passthrough is used to reach destinations that don't have endpoints saved in Consul. - PassthroughEndpointGroup passthrough = 4; - } -} - -message DynamicEndpointGroup { - // config configures how to connect to the endpoints. - DynamicEndpointGroupConfig config = 1; - // outbound_tls will configure what TLS information to use when connecting to an upstream. - TransportSocket outbound_tls = 2; -} - -message PassthroughEndpointGroup { - // config configures how to connect to the endpoints. - PassthroughEndpointGroupConfig config = 1; - // outbound_tls will configure what TLS information to use when connecting to an upstream. - TransportSocket outbound_tls = 2; -} - -message DNSEndpointGroup { - // config configures how to connect to the endpoints. - DNSEndpointGroupConfig config = 1; - // outbound_tls will configure what TLS information to use when connecting to an upstream. - TransportSocket outbound_tls = 2; -} - -// StaticEndpointGroup is used to reach local app ports. -message StaticEndpointGroup { - // config configures how to connect to the endpoints. - StaticEndpointGroupConfig config = 1; -} - -message L4WeightedClusterGroup { - // clusters to route to by weight. - repeated L4WeightedDestinationCluster clusters = 1; -} - -message L7WeightedClusterGroup { - // clusters to route to by weight. - repeated L7WeightedDestinationCluster clusters = 1; -} - -message L4WeightedDestinationCluster { - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - string name = 1; - google.protobuf.UInt32Value weight = 2; -} - -message L7WeightedDestinationCluster { - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - string name = 1; - google.protobuf.UInt32Value weight = 2; - repeated HeaderMutation header_mutations = 3; -} - -message DynamicEndpointGroupConfig { - google.protobuf.Duration connect_timeout = 1; - bool disable_panic_threshold = 2; - oneof lb_policy { - LBPolicyLeastRequest least_request = 3; - LBPolicyRoundRobin round_robin = 4; - LBPolicyRandom random = 5; - LBPolicyRingHash ring_hash = 6; - LBPolicyMaglev maglev = 7; - } - CircuitBreakers circuit_breakers = 8; - OutlierDetection outlier_detection = 9; - UpstreamConnectionOptions upstream_connection_options = 10; - bool use_alt_stat_name = 11; -} - -message LBPolicyLeastRequest { - google.protobuf.UInt32Value choice_count = 1; -} -message LBPolicyRoundRobin {} - -message LBPolicyRandom {} - -message LBPolicyRingHash { - google.protobuf.UInt64Value minimum_ring_size = 1; - google.protobuf.UInt64Value maximum_ring_size = 2; -} - -message LBPolicyMaglev {} - -message CircuitBreakers { - UpstreamLimits upstream_limits = 1; -} - -message UpstreamLimits { - google.protobuf.UInt32Value max_connections = 1; - google.protobuf.UInt32Value max_pending_requests = 2; - google.protobuf.UInt32Value max_concurrent_requests = 3; -} - -message OutlierDetection { - google.protobuf.Duration interval = 1; - google.protobuf.UInt32Value consecutive_5xx = 2; - google.protobuf.UInt32Value enforcing_consecutive_5xx = 3; - google.protobuf.UInt32Value max_ejection_percent = 4; - google.protobuf.Duration base_ejection_time = 5; -} - -message UpstreamConnectionOptions { - google.protobuf.UInt32Value tcp_keepalive_time = 1; - google.protobuf.UInt32Value tcp_keepalive_interval = 2; - google.protobuf.UInt32Value tcp_keepalive_probes = 3; -} - -message PassthroughEndpointGroupConfig { - google.protobuf.Duration connect_timeout = 1; -} - -message DNSEndpointGroupConfig { - google.protobuf.Duration connect_timeout = 1; - bool disable_panic_threshold = 2; - DiscoveryType discovery_type = 3; - CircuitBreakers circuit_breakers = 4; - OutlierDetection outlier_detection = 5; - UpstreamConnectionOptions upstream_connection_options = 6; - bool use_alt_stat_name = 7; -} - -enum DiscoveryType { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - DISCOVERY_TYPE_LOGICAL = 0; - DISCOVERY_TYPE_STRICT = 1; -} - -message StaticEndpointGroupConfig { - google.protobuf.Duration connect_timeout = 1; - CircuitBreakers circuit_breakers = 2; -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/endpoints.pb.binary.go b/proto-public/pbmesh/v1alpha1/pbproxystate/endpoints.pb.binary.go deleted file mode 100644 index 62f943ca762e2..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/endpoints.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/pbproxystate/endpoints.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Endpoints) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Endpoints) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Endpoint) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Endpoint) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/endpoints.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/endpoints.pb.go deleted file mode 100644 index ce14e15f722d7..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/endpoints.pb.go +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/pbproxystate/endpoints.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - 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 HealthStatus int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - HealthStatus_HEALTH_STATUS_UNKNOWN HealthStatus = 0 - HealthStatus_HEALTH_STATUS_HEALTHY HealthStatus = 1 - HealthStatus_HEALTH_STATUS_UNHEALTHY HealthStatus = 2 -) - -// Enum value maps for HealthStatus. -var ( - HealthStatus_name = map[int32]string{ - 0: "HEALTH_STATUS_UNKNOWN", - 1: "HEALTH_STATUS_HEALTHY", - 2: "HEALTH_STATUS_UNHEALTHY", - } - HealthStatus_value = map[string]int32{ - "HEALTH_STATUS_UNKNOWN": 0, - "HEALTH_STATUS_HEALTHY": 1, - "HEALTH_STATUS_UNHEALTHY": 2, - } -) - -func (x HealthStatus) Enum() *HealthStatus { - p := new(HealthStatus) - *p = x - return p -} - -func (x HealthStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (HealthStatus) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_enumTypes[0].Descriptor() -} - -func (HealthStatus) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_enumTypes[0] -} - -func (x HealthStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use HealthStatus.Descriptor instead. -func (HealthStatus) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDescGZIP(), []int{0} -} - -type Endpoints struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Endpoints []*Endpoint `protobuf:"bytes,1,rep,name=endpoints,proto3" json:"endpoints,omitempty"` -} - -func (x *Endpoints) Reset() { - *x = Endpoints{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Endpoints) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Endpoints) ProtoMessage() {} - -func (x *Endpoints) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_endpoints_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 Endpoints.ProtoReflect.Descriptor instead. -func (*Endpoints) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDescGZIP(), []int{0} -} - -func (x *Endpoints) GetEndpoints() []*Endpoint { - if x != nil { - return x.Endpoints - } - return nil -} - -type Endpoint struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Address: - // - // *Endpoint_HostPort - // *Endpoint_UnixSocket - Address isEndpoint_Address `protobuf_oneof:"address"` - HealthStatus HealthStatus `protobuf:"varint,3,opt,name=health_status,json=healthStatus,proto3,enum=hashicorp.consul.mesh.v1alpha1.pbproxystate.HealthStatus" json:"health_status,omitempty"` - LoadBalancingWeight *wrapperspb.UInt32Value `protobuf:"bytes,4,opt,name=load_balancing_weight,json=loadBalancingWeight,proto3" json:"load_balancing_weight,omitempty"` -} - -func (x *Endpoint) Reset() { - *x = Endpoint{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Endpoint) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Endpoint) ProtoMessage() {} - -func (x *Endpoint) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_endpoints_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 Endpoint.ProtoReflect.Descriptor instead. -func (*Endpoint) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDescGZIP(), []int{1} -} - -func (m *Endpoint) GetAddress() isEndpoint_Address { - if m != nil { - return m.Address - } - return nil -} - -func (x *Endpoint) GetHostPort() *HostPortAddress { - if x, ok := x.GetAddress().(*Endpoint_HostPort); ok { - return x.HostPort - } - return nil -} - -func (x *Endpoint) GetUnixSocket() *UnixSocketAddress { - if x, ok := x.GetAddress().(*Endpoint_UnixSocket); ok { - return x.UnixSocket - } - return nil -} - -func (x *Endpoint) GetHealthStatus() HealthStatus { - if x != nil { - return x.HealthStatus - } - return HealthStatus_HEALTH_STATUS_UNKNOWN -} - -func (x *Endpoint) GetLoadBalancingWeight() *wrapperspb.UInt32Value { - if x != nil { - return x.LoadBalancingWeight - } - return nil -} - -type isEndpoint_Address interface { - isEndpoint_Address() -} - -type Endpoint_HostPort struct { - HostPort *HostPortAddress `protobuf:"bytes,1,opt,name=host_port,json=hostPort,proto3,oneof"` -} - -type Endpoint_UnixSocket struct { - UnixSocket *UnixSocketAddress `protobuf:"bytes,2,opt,name=unix_socket,json=unixSocket,proto3,oneof"` -} - -func (*Endpoint_HostPort) isEndpoint_Address() {} - -func (*Endpoint_UnixSocket) isEndpoint_Address() {} - -var File_pbmesh_v1alpha1_pbproxystate_endpoints_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDesc = []byte{ - 0x0a, 0x2c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x65, - 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2b, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, - 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x70, 0x62, 0x6d, - 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x60, 0x0a, 0x09, 0x45, 0x6e, 0x64, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x73, 0x12, 0x53, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x09, - 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x22, 0x87, 0x03, 0x0a, 0x08, 0x45, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x5b, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, - 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x50, - 0x6f, 0x72, 0x74, 0x12, 0x61, 0x0a, 0x0b, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x73, 0x6f, 0x63, 0x6b, - 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, - 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x75, 0x6e, 0x69, 0x78, - 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x5e, 0x0a, 0x0d, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0c, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x50, 0x0a, 0x15, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x62, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x13, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, - 0x6e, 0x67, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x2a, 0x61, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x53, 0x54, - 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x19, - 0x0a, 0x15, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, - 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, - 0x4c, 0x54, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x48, 0x45, 0x41, - 0x4c, 0x54, 0x48, 0x59, 0x10, 0x02, 0x42, 0xda, 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0e, 0x45, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2b, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, - 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, - 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, - 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0xea, 0x02, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDescData = file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDesc -) - -func file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDescData -} - -var file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_goTypes = []interface{}{ - (HealthStatus)(0), // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.HealthStatus - (*Endpoints)(nil), // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.Endpoints - (*Endpoint)(nil), // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.Endpoint - (*HostPortAddress)(nil), // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.HostPortAddress - (*UnixSocketAddress)(nil), // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.UnixSocketAddress - (*wrapperspb.UInt32Value)(nil), // 5: google.protobuf.UInt32Value -} -var file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.Endpoints.endpoints:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.Endpoint - 3, // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.Endpoint.host_port:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HostPortAddress - 4, // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.Endpoint.unix_socket:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.UnixSocketAddress - 0, // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.Endpoint.health_status:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HealthStatus - 5, // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.Endpoint.load_balancing_weight:type_name -> google.protobuf.UInt32Value - 5, // [5:5] is the sub-list for method output_type - 5, // [5:5] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_init() } -func file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_init() { - if File_pbmesh_v1alpha1_pbproxystate_endpoints_proto != nil { - return - } - file_pbmesh_v1alpha1_pbproxystate_address_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Endpoints); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Endpoint); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*Endpoint_HostPort)(nil), - (*Endpoint_UnixSocket)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDesc, - NumEnums: 1, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_depIdxs, - EnumInfos: file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_enumTypes, - MessageInfos: file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_pbproxystate_endpoints_proto = out.File - file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_rawDesc = nil - file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_goTypes = nil - file_pbmesh_v1alpha1_pbproxystate_endpoints_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/endpoints.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/endpoints.proto deleted file mode 100644 index 28ff53b7eec1d..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/endpoints.proto +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1.pbproxystate; - -import "google/protobuf/wrappers.proto"; -import "pbmesh/v1alpha1/pbproxystate/address.proto"; - -message Endpoints { - repeated Endpoint endpoints = 1; -} - -message Endpoint { - oneof address { - HostPortAddress host_port = 1; - UnixSocketAddress unix_socket = 2; - } - HealthStatus health_status = 3; - google.protobuf.UInt32Value load_balancing_weight = 4; -} - -enum HealthStatus { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - HEALTH_STATUS_UNKNOWN = 0; - HEALTH_STATUS_HEALTHY = 1; - HEALTH_STATUS_UNHEALTHY = 2; -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/escape_hatches.pb.binary.go b/proto-public/pbmesh/v1alpha1/pbproxystate/escape_hatches.pb.binary.go deleted file mode 100644 index b684a26f32e0a..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/escape_hatches.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/pbproxystate/escape_hatches.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *EscapeHatches) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *EscapeHatches) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/escape_hatches.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/escape_hatches.pb.go deleted file mode 100644 index 9250341dbef53..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/escape_hatches.pb.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/pbproxystate/escape_hatches.proto - -package pbproxystate - -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 EscapeHatches struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // listener_tracing_json contains user provided tracing configuration. - ListenerTracingJson string `protobuf:"bytes,1,opt,name=listener_tracing_json,json=listenerTracingJson,proto3" json:"listener_tracing_json,omitempty"` -} - -func (x *EscapeHatches) Reset() { - *x = EscapeHatches{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EscapeHatches) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EscapeHatches) ProtoMessage() {} - -func (x *EscapeHatches) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_escape_hatches_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 EscapeHatches.ProtoReflect.Descriptor instead. -func (*EscapeHatches) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_rawDescGZIP(), []int{0} -} - -func (x *EscapeHatches) GetListenerTracingJson() string { - if x != nil { - return x.ListenerTracingJson - } - return "" -} - -var File_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_rawDesc = []byte{ - 0x0a, 0x31, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x65, - 0x73, 0x63, 0x61, 0x70, 0x65, 0x5f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x2b, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x22, 0x43, 0x0a, 0x0d, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x48, 0x61, 0x74, 0x63, 0x68, 0x65, - 0x73, 0x12, 0x32, 0x0a, 0x15, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x74, 0x72, - 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x13, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, - 0x67, 0x4a, 0x73, 0x6f, 0x6e, 0x42, 0xde, 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x12, 0x45, 0x73, 0x63, 0x61, 0x70, - 0x65, 0x48, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x45, 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, 0x65, 0x73, 0x68, - 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, - 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, - 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, - 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_rawDescData = file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_rawDesc -) - -func file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_rawDescData -} - -var file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_goTypes = []interface{}{ - (*EscapeHatches)(nil), // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.EscapeHatches -} -var file_pbmesh_v1alpha1_pbproxystate_escape_hatches_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_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_init() } -func file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_init() { - if File_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EscapeHatches); 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_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_depIdxs, - MessageInfos: file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto = out.File - file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_rawDesc = nil - file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_goTypes = nil - file_pbmesh_v1alpha1_pbproxystate_escape_hatches_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/escape_hatches.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/escape_hatches.proto deleted file mode 100644 index ab88711827804..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/escape_hatches.proto +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1.pbproxystate; - -message EscapeHatches { - // listener_tracing_json contains user provided tracing configuration. - string listener_tracing_json = 1; -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/header_mutations.pb.binary.go b/proto-public/pbmesh/v1alpha1/pbproxystate/header_mutations.pb.binary.go deleted file mode 100644 index 55d9155e9f7a8..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/header_mutations.pb.binary.go +++ /dev/null @@ -1,68 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/pbproxystate/header_mutations.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HeaderMutation) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HeaderMutation) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RequestHeaderAdd) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RequestHeaderAdd) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RequestHeaderRemove) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RequestHeaderRemove) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ResponseHeaderAdd) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ResponseHeaderAdd) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ResponseHeaderRemove) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ResponseHeaderRemove) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Header) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Header) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/header_mutations.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/header_mutations.pb.go deleted file mode 100644 index 71d0b5dc3c02c..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/header_mutations.pb.go +++ /dev/null @@ -1,693 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/pbproxystate/header_mutations.proto - -package pbproxystate - -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 AppendAction int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD AppendAction = 0 - AppendAction_APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD AppendAction = 1 -) - -// Enum value maps for AppendAction. -var ( - AppendAction_name = map[int32]string{ - 0: "APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD", - 1: "APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD", - } - AppendAction_value = map[string]int32{ - "APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD": 0, - "APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD": 1, - } -) - -func (x AppendAction) Enum() *AppendAction { - p := new(AppendAction) - *p = x - return p -} - -func (x AppendAction) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (AppendAction) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_enumTypes[0].Descriptor() -} - -func (AppendAction) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_enumTypes[0] -} - -func (x AppendAction) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use AppendAction.Descriptor instead. -func (AppendAction) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{0} -} - -// Note: it's nice to have this list of header mutations as opposed to configuration similar to Envoy because it -// translates more nicely from GAMMA HTTPRoute, and our existing service router config. Then xds code can handle turning -// it into envoy xds. -type HeaderMutation struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Action: - // - // *HeaderMutation_RequestHeaderAdd - // *HeaderMutation_RequestHeaderRemove - // *HeaderMutation_ResponseHeaderAdd - // *HeaderMutation_ResponseHeaderRemove - Action isHeaderMutation_Action `protobuf_oneof:"action"` -} - -func (x *HeaderMutation) Reset() { - *x = HeaderMutation{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HeaderMutation) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HeaderMutation) ProtoMessage() {} - -func (x *HeaderMutation) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_header_mutations_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 HeaderMutation.ProtoReflect.Descriptor instead. -func (*HeaderMutation) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{0} -} - -func (m *HeaderMutation) GetAction() isHeaderMutation_Action { - if m != nil { - return m.Action - } - return nil -} - -func (x *HeaderMutation) GetRequestHeaderAdd() *RequestHeaderAdd { - if x, ok := x.GetAction().(*HeaderMutation_RequestHeaderAdd); ok { - return x.RequestHeaderAdd - } - return nil -} - -func (x *HeaderMutation) GetRequestHeaderRemove() *RequestHeaderRemove { - if x, ok := x.GetAction().(*HeaderMutation_RequestHeaderRemove); ok { - return x.RequestHeaderRemove - } - return nil -} - -func (x *HeaderMutation) GetResponseHeaderAdd() *ResponseHeaderAdd { - if x, ok := x.GetAction().(*HeaderMutation_ResponseHeaderAdd); ok { - return x.ResponseHeaderAdd - } - return nil -} - -func (x *HeaderMutation) GetResponseHeaderRemove() *ResponseHeaderRemove { - if x, ok := x.GetAction().(*HeaderMutation_ResponseHeaderRemove); ok { - return x.ResponseHeaderRemove - } - return nil -} - -type isHeaderMutation_Action interface { - isHeaderMutation_Action() -} - -type HeaderMutation_RequestHeaderAdd struct { - RequestHeaderAdd *RequestHeaderAdd `protobuf:"bytes,1,opt,name=request_header_add,json=requestHeaderAdd,proto3,oneof"` -} - -type HeaderMutation_RequestHeaderRemove struct { - RequestHeaderRemove *RequestHeaderRemove `protobuf:"bytes,2,opt,name=request_header_remove,json=requestHeaderRemove,proto3,oneof"` -} - -type HeaderMutation_ResponseHeaderAdd struct { - ResponseHeaderAdd *ResponseHeaderAdd `protobuf:"bytes,3,opt,name=response_header_add,json=responseHeaderAdd,proto3,oneof"` -} - -type HeaderMutation_ResponseHeaderRemove struct { - ResponseHeaderRemove *ResponseHeaderRemove `protobuf:"bytes,4,opt,name=response_header_remove,json=responseHeaderRemove,proto3,oneof"` -} - -func (*HeaderMutation_RequestHeaderAdd) isHeaderMutation_Action() {} - -func (*HeaderMutation_RequestHeaderRemove) isHeaderMutation_Action() {} - -func (*HeaderMutation_ResponseHeaderAdd) isHeaderMutation_Action() {} - -func (*HeaderMutation_ResponseHeaderRemove) isHeaderMutation_Action() {} - -type RequestHeaderAdd struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Header *Header `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` - AppendAction AppendAction `protobuf:"varint,2,opt,name=append_action,json=appendAction,proto3,enum=hashicorp.consul.mesh.v1alpha1.pbproxystate.AppendAction" json:"append_action,omitempty"` -} - -func (x *RequestHeaderAdd) Reset() { - *x = RequestHeaderAdd{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RequestHeaderAdd) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RequestHeaderAdd) ProtoMessage() {} - -func (x *RequestHeaderAdd) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_header_mutations_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 RequestHeaderAdd.ProtoReflect.Descriptor instead. -func (*RequestHeaderAdd) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{1} -} - -func (x *RequestHeaderAdd) GetHeader() *Header { - if x != nil { - return x.Header - } - return nil -} - -func (x *RequestHeaderAdd) GetAppendAction() AppendAction { - if x != nil { - return x.AppendAction - } - return AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD -} - -type RequestHeaderRemove struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - HeaderKeys []string `protobuf:"bytes,1,rep,name=header_keys,json=headerKeys,proto3" json:"header_keys,omitempty"` -} - -func (x *RequestHeaderRemove) Reset() { - *x = RequestHeaderRemove{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RequestHeaderRemove) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RequestHeaderRemove) ProtoMessage() {} - -func (x *RequestHeaderRemove) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_header_mutations_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 RequestHeaderRemove.ProtoReflect.Descriptor instead. -func (*RequestHeaderRemove) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{2} -} - -func (x *RequestHeaderRemove) GetHeaderKeys() []string { - if x != nil { - return x.HeaderKeys - } - return nil -} - -type ResponseHeaderAdd struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Header *Header `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` - AppendAction AppendAction `protobuf:"varint,2,opt,name=append_action,json=appendAction,proto3,enum=hashicorp.consul.mesh.v1alpha1.pbproxystate.AppendAction" json:"append_action,omitempty"` -} - -func (x *ResponseHeaderAdd) Reset() { - *x = ResponseHeaderAdd{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ResponseHeaderAdd) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ResponseHeaderAdd) ProtoMessage() {} - -func (x *ResponseHeaderAdd) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[3] - 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 ResponseHeaderAdd.ProtoReflect.Descriptor instead. -func (*ResponseHeaderAdd) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{3} -} - -func (x *ResponseHeaderAdd) GetHeader() *Header { - if x != nil { - return x.Header - } - return nil -} - -func (x *ResponseHeaderAdd) GetAppendAction() AppendAction { - if x != nil { - return x.AppendAction - } - return AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD -} - -type ResponseHeaderRemove struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - HeaderKeys []string `protobuf:"bytes,1,rep,name=header_keys,json=headerKeys,proto3" json:"header_keys,omitempty"` -} - -func (x *ResponseHeaderRemove) Reset() { - *x = ResponseHeaderRemove{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ResponseHeaderRemove) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ResponseHeaderRemove) ProtoMessage() {} - -func (x *ResponseHeaderRemove) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[4] - 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 ResponseHeaderRemove.ProtoReflect.Descriptor instead. -func (*ResponseHeaderRemove) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{4} -} - -func (x *ResponseHeaderRemove) GetHeaderKeys() []string { - if x != nil { - return x.HeaderKeys - } - return nil -} - -type Header struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *Header) Reset() { - *x = Header{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Header) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Header) ProtoMessage() {} - -func (x *Header) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[5] - 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 Header.ProtoReflect.Descriptor instead. -func (*Header) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{5} -} - -func (x *Header) GetKey() string { - if x != nil { - return x.Key - } - return "" -} - -func (x *Header) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -var File_pbmesh_v1alpha1_pbproxystate_header_mutations_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDesc = []byte{ - 0x0a, 0x33, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2b, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x22, 0xee, 0x03, 0x0a, 0x0e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6d, 0x0a, 0x12, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, - 0x48, 0x00, 0x52, 0x10, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x41, 0x64, 0x64, 0x12, 0x76, 0x0a, 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, - 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x48, 0x00, 0x52, 0x13, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x70, 0x0a, 0x13, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, - 0x61, 0x64, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x48, 0x00, 0x52, 0x11, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x12, 0x79, - 0x0a, 0x16, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x48, 0x00, 0x52, 0x14, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x22, 0xbf, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x12, 0x4b, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x5e, 0x0a, 0x0d, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, - 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x41, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x36, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x1f, 0x0a, 0x0b, - 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0a, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x73, 0x22, 0xc0, 0x01, - 0x0a, 0x11, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x41, 0x64, 0x64, 0x12, 0x4b, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x12, 0x5e, 0x0a, 0x0d, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0c, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x22, 0x37, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x73, 0x22, 0x30, 0x0a, 0x06, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2a, 0x67, 0x0a, 0x0c, 0x41, - 0x70, 0x70, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x25, 0x41, - 0x50, 0x50, 0x45, 0x4e, 0x44, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x50, - 0x45, 0x4e, 0x44, 0x5f, 0x49, 0x46, 0x5f, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x5f, 0x4f, 0x52, - 0x5f, 0x41, 0x44, 0x44, 0x10, 0x00, 0x12, 0x2c, 0x0a, 0x28, 0x41, 0x50, 0x50, 0x45, 0x4e, 0x44, - 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x57, 0x52, 0x49, 0x54, - 0x45, 0x5f, 0x49, 0x46, 0x5f, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x5f, 0x4f, 0x52, 0x5f, 0x41, - 0x44, 0x44, 0x10, 0x01, 0x42, 0xe0, 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x14, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x45, 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, 0x65, 0x73, - 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, - 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, - 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, - 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescData = file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDesc -) - -func file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDescData -} - -var file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes = make([]protoimpl.MessageInfo, 6) -var file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_goTypes = []interface{}{ - (AppendAction)(0), // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.AppendAction - (*HeaderMutation)(nil), // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation - (*RequestHeaderAdd)(nil), // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.RequestHeaderAdd - (*RequestHeaderRemove)(nil), // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.RequestHeaderRemove - (*ResponseHeaderAdd)(nil), // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.ResponseHeaderAdd - (*ResponseHeaderRemove)(nil), // 5: hashicorp.consul.mesh.v1alpha1.pbproxystate.ResponseHeaderRemove - (*Header)(nil), // 6: hashicorp.consul.mesh.v1alpha1.pbproxystate.Header -} -var file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation.request_header_add:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.RequestHeaderAdd - 3, // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation.request_header_remove:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.RequestHeaderRemove - 4, // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation.response_header_add:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.ResponseHeaderAdd - 5, // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation.response_header_remove:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.ResponseHeaderRemove - 6, // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.RequestHeaderAdd.header:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.Header - 0, // 5: hashicorp.consul.mesh.v1alpha1.pbproxystate.RequestHeaderAdd.append_action:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.AppendAction - 6, // 6: hashicorp.consul.mesh.v1alpha1.pbproxystate.ResponseHeaderAdd.header:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.Header - 0, // 7: hashicorp.consul.mesh.v1alpha1.pbproxystate.ResponseHeaderAdd.append_action:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.AppendAction - 8, // [8:8] is the sub-list for method output_type - 8, // [8:8] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_init() } -func file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_init() { - if File_pbmesh_v1alpha1_pbproxystate_header_mutations_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HeaderMutation); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RequestHeaderAdd); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RequestHeaderRemove); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResponseHeaderAdd); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResponseHeaderRemove); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Header); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*HeaderMutation_RequestHeaderAdd)(nil), - (*HeaderMutation_RequestHeaderRemove)(nil), - (*HeaderMutation_ResponseHeaderAdd)(nil), - (*HeaderMutation_ResponseHeaderRemove)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDesc, - NumEnums: 1, - NumMessages: 6, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_depIdxs, - EnumInfos: file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_enumTypes, - MessageInfos: file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_pbproxystate_header_mutations_proto = out.File - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_rawDesc = nil - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_goTypes = nil - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/header_mutations.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/header_mutations.proto deleted file mode 100644 index ca3bd6ee79cc5..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/header_mutations.proto +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1.pbproxystate; - -// Note: it's nice to have this list of header mutations as opposed to configuration similar to Envoy because it -// translates more nicely from GAMMA HTTPRoute, and our existing service router config. Then xds code can handle turning -// it into envoy xds. -message HeaderMutation { - oneof action { - RequestHeaderAdd request_header_add = 1; - RequestHeaderRemove request_header_remove = 2; - ResponseHeaderAdd response_header_add = 3; - ResponseHeaderRemove response_header_remove = 4; - } -} - -message RequestHeaderAdd { - Header header = 1; - AppendAction append_action = 2; -} - -message RequestHeaderRemove { - repeated string header_keys = 1; -} - -message ResponseHeaderAdd { - Header header = 1; - AppendAction append_action = 2; -} - -message ResponseHeaderRemove { - repeated string header_keys = 1; -} - -message Header { - string key = 1; - string value = 2; -} - -enum AppendAction { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD = 0; - APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD = 1; -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/intentions.pb.binary.go b/proto-public/pbmesh/v1alpha1/pbproxystate/intentions.pb.binary.go deleted file mode 100644 index 7eb87f443f197..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/intentions.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/pbproxystate/intentions.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L7Intention) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L7Intention) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L4Intention) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L4Intention) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/intentions.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/intentions.pb.go deleted file mode 100644 index 171c5f357f375..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/intentions.pb.go +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/pbproxystate/intentions.proto - -package pbproxystate - -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 L7Intention struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *L7Intention) Reset() { - *x = L7Intention{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_intentions_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L7Intention) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L7Intention) ProtoMessage() {} - -func (x *L7Intention) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_intentions_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 L7Intention.ProtoReflect.Descriptor instead. -func (*L7Intention) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_intentions_proto_rawDescGZIP(), []int{0} -} - -type L4Intention struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *L4Intention) Reset() { - *x = L4Intention{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_intentions_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L4Intention) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L4Intention) ProtoMessage() {} - -func (x *L4Intention) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_intentions_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 L4Intention.ProtoReflect.Descriptor instead. -func (*L4Intention) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_intentions_proto_rawDescGZIP(), []int{1} -} - -var File_pbmesh_v1alpha1_pbproxystate_intentions_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_pbproxystate_intentions_proto_rawDesc = []byte{ - 0x0a, 0x2d, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x69, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x2b, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x0d, 0x0a, 0x0b, - 0x4c, 0x37, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x0d, 0x0a, 0x0b, 0x4c, - 0x34, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0xdb, 0x02, 0x0a, 0x2f, 0x63, - 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0f, - 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x45, 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, 0x65, - 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, - 0xaa, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, - 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, - 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, - 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_pbproxystate_intentions_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_pbproxystate_intentions_proto_rawDescData = file_pbmesh_v1alpha1_pbproxystate_intentions_proto_rawDesc -) - -func file_pbmesh_v1alpha1_pbproxystate_intentions_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_pbproxystate_intentions_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_pbproxystate_intentions_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_pbproxystate_intentions_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_pbproxystate_intentions_proto_rawDescData -} - -var file_pbmesh_v1alpha1_pbproxystate_intentions_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbmesh_v1alpha1_pbproxystate_intentions_proto_goTypes = []interface{}{ - (*L7Intention)(nil), // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Intention - (*L4Intention)(nil), // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4Intention -} -var file_pbmesh_v1alpha1_pbproxystate_intentions_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_pbmesh_v1alpha1_pbproxystate_intentions_proto_init() } -func file_pbmesh_v1alpha1_pbproxystate_intentions_proto_init() { - if File_pbmesh_v1alpha1_pbproxystate_intentions_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_pbproxystate_intentions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L7Intention); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_intentions_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L4Intention); 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_pbmesh_v1alpha1_pbproxystate_intentions_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_pbproxystate_intentions_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_pbproxystate_intentions_proto_depIdxs, - MessageInfos: file_pbmesh_v1alpha1_pbproxystate_intentions_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_pbproxystate_intentions_proto = out.File - file_pbmesh_v1alpha1_pbproxystate_intentions_proto_rawDesc = nil - file_pbmesh_v1alpha1_pbproxystate_intentions_proto_goTypes = nil - file_pbmesh_v1alpha1_pbproxystate_intentions_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/intentions.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/intentions.proto deleted file mode 100644 index 37f009cc30395..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/intentions.proto +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1.pbproxystate; - -message L7Intention {} - -message L4Intention {} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/listener.pb.binary.go b/proto-public/pbmesh/v1alpha1/pbproxystate/listener.pb.binary.go deleted file mode 100644 index 333fa99892e07..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/listener.pb.binary.go +++ /dev/null @@ -1,78 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/pbproxystate/listener.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Listener) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Listener) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Router) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Router) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Match) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Match) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *CidrRange) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *CidrRange) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L4Destination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L4Destination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L7Destination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L7Destination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *SNIDestination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *SNIDestination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/listener.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/listener.pb.go deleted file mode 100644 index 24c6f5fc8ce53..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/listener.pb.go +++ /dev/null @@ -1,1269 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/pbproxystate/listener.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - 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 Direction int32 - -const ( - // DIRECTION_UNSPECIFIED is used by mesh gateway listeners. - Direction_DIRECTION_UNSPECIFIED Direction = 0 - Direction_DIRECTION_INBOUND Direction = 1 - Direction_DIRECTION_OUTBOUND Direction = 2 -) - -// Enum value maps for Direction. -var ( - Direction_name = map[int32]string{ - 0: "DIRECTION_UNSPECIFIED", - 1: "DIRECTION_INBOUND", - 2: "DIRECTION_OUTBOUND", - } - Direction_value = map[string]int32{ - "DIRECTION_UNSPECIFIED": 0, - "DIRECTION_INBOUND": 1, - "DIRECTION_OUTBOUND": 2, - } -) - -func (x Direction) Enum() *Direction { - p := new(Direction) - *p = x - return p -} - -func (x Direction) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Direction) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_enumTypes[0].Descriptor() -} - -func (Direction) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_pbproxystate_listener_proto_enumTypes[0] -} - -func (x Direction) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Direction.Descriptor instead. -func (Direction) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescGZIP(), []int{0} -} - -type BalanceConnections int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - BalanceConnections_BALANCE_CONNECTIONS_DEFAULT BalanceConnections = 0 - BalanceConnections_BALANCE_CONNECTIONS_EXACT BalanceConnections = 1 -) - -// Enum value maps for BalanceConnections. -var ( - BalanceConnections_name = map[int32]string{ - 0: "BALANCE_CONNECTIONS_DEFAULT", - 1: "BALANCE_CONNECTIONS_EXACT", - } - BalanceConnections_value = map[string]int32{ - "BALANCE_CONNECTIONS_DEFAULT": 0, - "BALANCE_CONNECTIONS_EXACT": 1, - } -) - -func (x BalanceConnections) Enum() *BalanceConnections { - p := new(BalanceConnections) - *p = x - return p -} - -func (x BalanceConnections) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (BalanceConnections) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_enumTypes[1].Descriptor() -} - -func (BalanceConnections) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_pbproxystate_listener_proto_enumTypes[1] -} - -func (x BalanceConnections) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use BalanceConnections.Descriptor instead. -func (BalanceConnections) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescGZIP(), []int{1} -} - -// Capabilities map to proxy functionality to enable. These enable tproxy, l7 protocol/alpn inspection, or l4 sni/alpn inspection. -type Capability int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - Capability_CAPABILITY_TRANSPARENT Capability = 0 - Capability_CAPABILITY_L7_PROTOCOL_INSPECTION Capability = 1 - Capability_CAPABILITY_L4_TLS_INSPECTION Capability = 2 -) - -// Enum value maps for Capability. -var ( - Capability_name = map[int32]string{ - 0: "CAPABILITY_TRANSPARENT", - 1: "CAPABILITY_L7_PROTOCOL_INSPECTION", - 2: "CAPABILITY_L4_TLS_INSPECTION", - } - Capability_value = map[string]int32{ - "CAPABILITY_TRANSPARENT": 0, - "CAPABILITY_L7_PROTOCOL_INSPECTION": 1, - "CAPABILITY_L4_TLS_INSPECTION": 2, - } -) - -func (x Capability) Enum() *Capability { - p := new(Capability) - *p = x - return p -} - -func (x Capability) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Capability) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_enumTypes[2].Descriptor() -} - -func (Capability) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_pbproxystate_listener_proto_enumTypes[2] -} - -func (x Capability) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Capability.Descriptor instead. -func (Capability) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescGZIP(), []int{2} -} - -type L7Protocol int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - L7Protocol_L7_PROTOCOL_HTTP L7Protocol = 0 - L7Protocol_L7_PROTOCOL_HTTP2 L7Protocol = 1 - L7Protocol_L7_PROTOCOL_GRPC L7Protocol = 2 -) - -// Enum value maps for L7Protocol. -var ( - L7Protocol_name = map[int32]string{ - 0: "L7_PROTOCOL_HTTP", - 1: "L7_PROTOCOL_HTTP2", - 2: "L7_PROTOCOL_GRPC", - } - L7Protocol_value = map[string]int32{ - "L7_PROTOCOL_HTTP": 0, - "L7_PROTOCOL_HTTP2": 1, - "L7_PROTOCOL_GRPC": 2, - } -) - -func (x L7Protocol) Enum() *L7Protocol { - p := new(L7Protocol) - *p = x - return p -} - -func (x L7Protocol) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (L7Protocol) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_enumTypes[3].Descriptor() -} - -func (L7Protocol) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_pbproxystate_listener_proto_enumTypes[3] -} - -func (x L7Protocol) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use L7Protocol.Descriptor instead. -func (L7Protocol) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescGZIP(), []int{3} -} - -type Listener struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is the name of the listener. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // direction tells the listener the direction of traffic. - Direction Direction `protobuf:"varint,2,opt,name=direction,proto3,enum=hashicorp.consul.mesh.v1alpha1.pbproxystate.Direction" json:"direction,omitempty"` - // bind_address describes where to listen. - // - // Types that are assignable to BindAddress: - // - // *Listener_HostPort - // *Listener_UnixSocket - BindAddress isListener_BindAddress `protobuf_oneof:"bind_address"` - // routers describes how to route traffic from this listener. - Routers []*Router `protobuf:"bytes,5,rep,name=routers,proto3" json:"routers,omitempty"` - // default_router describes where to route if none of the other router matches match the connection. - DefaultRouter *Router `protobuf:"bytes,6,opt,name=default_router,json=defaultRouter,proto3" json:"default_router,omitempty"` - // capabilities describe Envoy proxy functionality to enable. These map closely to Envoy listener filters. - Capabilities []Capability `protobuf:"varint,7,rep,packed,name=capabilities,proto3,enum=hashicorp.consul.mesh.v1alpha1.pbproxystate.Capability" json:"capabilities,omitempty"` - // balance_connections configures how the listener should balance connections. - BalanceConnections BalanceConnections `protobuf:"varint,8,opt,name=balance_connections,json=balanceConnections,proto3,enum=hashicorp.consul.mesh.v1alpha1.pbproxystate.BalanceConnections" json:"balance_connections,omitempty"` - // escape_hatch_listener_json configures a user configured escape hatch listener. - EscapeHatchListener string `protobuf:"bytes,9,opt,name=escape_hatch_listener,json=escapeHatchListener,proto3" json:"escape_hatch_listener,omitempty"` - // use_escape_hatch_tracing configures whether to use the top level user configured tracing escape hatch for this listener. - UseEscapeHatchTracing bool `protobuf:"varint,10,opt,name=use_escape_hatch_tracing,json=useEscapeHatchTracing,proto3" json:"use_escape_hatch_tracing,omitempty"` -} - -func (x *Listener) Reset() { - *x = Listener{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Listener) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Listener) ProtoMessage() {} - -func (x *Listener) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_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 Listener.ProtoReflect.Descriptor instead. -func (*Listener) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescGZIP(), []int{0} -} - -func (x *Listener) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *Listener) GetDirection() Direction { - if x != nil { - return x.Direction - } - return Direction_DIRECTION_UNSPECIFIED -} - -func (m *Listener) GetBindAddress() isListener_BindAddress { - if m != nil { - return m.BindAddress - } - return nil -} - -func (x *Listener) GetHostPort() *HostPortAddress { - if x, ok := x.GetBindAddress().(*Listener_HostPort); ok { - return x.HostPort - } - return nil -} - -func (x *Listener) GetUnixSocket() *UnixSocketAddress { - if x, ok := x.GetBindAddress().(*Listener_UnixSocket); ok { - return x.UnixSocket - } - return nil -} - -func (x *Listener) GetRouters() []*Router { - if x != nil { - return x.Routers - } - return nil -} - -func (x *Listener) GetDefaultRouter() *Router { - if x != nil { - return x.DefaultRouter - } - return nil -} - -func (x *Listener) GetCapabilities() []Capability { - if x != nil { - return x.Capabilities - } - return nil -} - -func (x *Listener) GetBalanceConnections() BalanceConnections { - if x != nil { - return x.BalanceConnections - } - return BalanceConnections_BALANCE_CONNECTIONS_DEFAULT -} - -func (x *Listener) GetEscapeHatchListener() string { - if x != nil { - return x.EscapeHatchListener - } - return "" -} - -func (x *Listener) GetUseEscapeHatchTracing() bool { - if x != nil { - return x.UseEscapeHatchTracing - } - return false -} - -type isListener_BindAddress interface { - isListener_BindAddress() -} - -type Listener_HostPort struct { - HostPort *HostPortAddress `protobuf:"bytes,3,opt,name=host_port,json=hostPort,proto3,oneof"` -} - -type Listener_UnixSocket struct { - UnixSocket *UnixSocketAddress `protobuf:"bytes,4,opt,name=unix_socket,json=unixSocket,proto3,oneof"` -} - -func (*Listener_HostPort) isListener_BindAddress() {} - -func (*Listener_UnixSocket) isListener_BindAddress() {} - -type Router struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // match specifies how to match traffic coming into this listener. If the traffic matches, it will be routed to the - // destination. - Match *Match `protobuf:"bytes,1,opt,name=match,proto3" json:"match,omitempty"` - // Types that are assignable to Destination: - // - // *Router_L4 - // *Router_L7 - // *Router_Sni - Destination isRouter_Destination `protobuf_oneof:"destination"` - // inbound_tls is used by inbound listeners that terminate TLS. - InboundTls *TransportSocket `protobuf:"bytes,5,opt,name=inbound_tls,json=inboundTls,proto3" json:"inbound_tls,omitempty"` -} - -func (x *Router) Reset() { - *x = Router{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Router) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Router) ProtoMessage() {} - -func (x *Router) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_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 Router.ProtoReflect.Descriptor instead. -func (*Router) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescGZIP(), []int{1} -} - -func (x *Router) GetMatch() *Match { - if x != nil { - return x.Match - } - return nil -} - -func (m *Router) GetDestination() isRouter_Destination { - if m != nil { - return m.Destination - } - return nil -} - -func (x *Router) GetL4() *L4Destination { - if x, ok := x.GetDestination().(*Router_L4); ok { - return x.L4 - } - return nil -} - -func (x *Router) GetL7() *L7Destination { - if x, ok := x.GetDestination().(*Router_L7); ok { - return x.L7 - } - return nil -} - -func (x *Router) GetSni() *SNIDestination { - if x, ok := x.GetDestination().(*Router_Sni); ok { - return x.Sni - } - return nil -} - -func (x *Router) GetInboundTls() *TransportSocket { - if x != nil { - return x.InboundTls - } - return nil -} - -type isRouter_Destination interface { - isRouter_Destination() -} - -type Router_L4 struct { - // l4 is an l4 destination to route to, which will have a reference to a cluster. - L4 *L4Destination `protobuf:"bytes,2,opt,name=l4,proto3,oneof"` -} - -type Router_L7 struct { - // l7 is an l7 destination to route to, which will have a reference to a route. - L7 *L7Destination `protobuf:"bytes,3,opt,name=l7,proto3,oneof"` -} - -type Router_Sni struct { - // sni is an SNI destination, which means there will be no references, but the SNI name will be tied to the cluster - // name, so we should generate all clusters. - Sni *SNIDestination `protobuf:"bytes,4,opt,name=sni,proto3,oneof"` -} - -func (*Router_L4) isRouter_Destination() {} - -func (*Router_L7) isRouter_Destination() {} - -func (*Router_Sni) isRouter_Destination() {} - -type Match struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DestinationPort *wrapperspb.UInt32Value `protobuf:"bytes,1,opt,name=destination_port,json=destinationPort,proto3" json:"destination_port,omitempty"` - PrefixRanges []*CidrRange `protobuf:"bytes,2,rep,name=prefix_ranges,json=prefixRanges,proto3" json:"prefix_ranges,omitempty"` - SourcePrefixRanges []*CidrRange `protobuf:"bytes,3,rep,name=source_prefix_ranges,json=sourcePrefixRanges,proto3" json:"source_prefix_ranges,omitempty"` - // server_names matches based on SNI of the incoming request. - ServerNames []string `protobuf:"bytes,4,rep,name=server_names,json=serverNames,proto3" json:"server_names,omitempty"` -} - -func (x *Match) Reset() { - *x = Match{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Match) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Match) ProtoMessage() {} - -func (x *Match) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_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 Match.ProtoReflect.Descriptor instead. -func (*Match) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescGZIP(), []int{2} -} - -func (x *Match) GetDestinationPort() *wrapperspb.UInt32Value { - if x != nil { - return x.DestinationPort - } - return nil -} - -func (x *Match) GetPrefixRanges() []*CidrRange { - if x != nil { - return x.PrefixRanges - } - return nil -} - -func (x *Match) GetSourcePrefixRanges() []*CidrRange { - if x != nil { - return x.SourcePrefixRanges - } - return nil -} - -func (x *Match) GetServerNames() []string { - if x != nil { - return x.ServerNames - } - return nil -} - -type CidrRange struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AddressPrefix string `protobuf:"bytes,1,opt,name=address_prefix,json=addressPrefix,proto3" json:"address_prefix,omitempty"` - PrefixLen *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=prefix_len,json=prefixLen,proto3" json:"prefix_len,omitempty"` -} - -func (x *CidrRange) Reset() { - *x = CidrRange{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CidrRange) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CidrRange) ProtoMessage() {} - -func (x *CidrRange) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[3] - 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 CidrRange.ProtoReflect.Descriptor instead. -func (*CidrRange) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescGZIP(), []int{3} -} - -func (x *CidrRange) GetAddressPrefix() string { - if x != nil { - return x.AddressPrefix - } - return "" -} - -func (x *CidrRange) GetPrefixLen() *wrapperspb.UInt32Value { - if x != nil { - return x.PrefixLen - } - return nil -} - -type L4Destination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is a key in the top level clusters map. This specifies which cluster to go to in this L4 destination. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - StatPrefix string `protobuf:"bytes,2,opt,name=stat_prefix,json=statPrefix,proto3" json:"stat_prefix,omitempty"` - // intentions is a list of intentions for this destination. - Intentions []*L4Intention `protobuf:"bytes,3,rep,name=intentions,proto3" json:"intentions,omitempty"` - // add_empty_intention specifies whether to add an empty intention for this destination, when there are no other intentions specified. - AddEmptyIntention bool `protobuf:"varint,4,opt,name=add_empty_intention,json=addEmptyIntention,proto3" json:"add_empty_intention,omitempty"` - // max_inbound_connections specifies how many connections this destination can accept. - MaxInboundConnections uint64 `protobuf:"varint,5,opt,name=max_inbound_connections,json=maxInboundConnections,proto3" json:"max_inbound_connections,omitempty"` -} - -func (x *L4Destination) Reset() { - *x = L4Destination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L4Destination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L4Destination) ProtoMessage() {} - -func (x *L4Destination) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[4] - 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 L4Destination.ProtoReflect.Descriptor instead. -func (*L4Destination) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescGZIP(), []int{4} -} - -func (x *L4Destination) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *L4Destination) GetStatPrefix() string { - if x != nil { - return x.StatPrefix - } - return "" -} - -func (x *L4Destination) GetIntentions() []*L4Intention { - if x != nil { - return x.Intentions - } - return nil -} - -func (x *L4Destination) GetAddEmptyIntention() bool { - if x != nil { - return x.AddEmptyIntention - } - return false -} - -func (x *L4Destination) GetMaxInboundConnections() uint64 { - if x != nil { - return x.MaxInboundConnections - } - return 0 -} - -type L7Destination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is a key in the top level routes map. This specifies which route to go to in this L7 destination. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - StatPrefix string `protobuf:"bytes,2,opt,name=stat_prefix,json=statPrefix,proto3" json:"stat_prefix,omitempty"` - // protocol for the destination. - Protocol L7Protocol `protobuf:"varint,3,opt,name=protocol,proto3,enum=hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Protocol" json:"protocol,omitempty"` - // intentions is a list of intentions for this destination. - Intentions []*L7Intention `protobuf:"bytes,4,rep,name=intentions,proto3" json:"intentions,omitempty"` - // add_empty_intention specifies whether to add an empty intention for this destination, when there are no other intentions specified. - AddEmptyIntention bool `protobuf:"varint,5,opt,name=add_empty_intention,json=addEmptyIntention,proto3" json:"add_empty_intention,omitempty"` - // include_xfcc specifies whether to add xfcc header. - IncludeXfcc bool `protobuf:"varint,6,opt,name=include_xfcc,json=includeXfcc,proto3" json:"include_xfcc,omitempty"` - // static_route specifies whether this is a static route that is inlined in the listener filter. This is required to - // match existing xds config. - StaticRoute bool `protobuf:"varint,7,opt,name=static_route,json=staticRoute,proto3" json:"static_route,omitempty"` - // max_inbound_connections specifies how many connections this destination can accept. - MaxInboundConnections uint64 `protobuf:"varint,8,opt,name=max_inbound_connections,json=maxInboundConnections,proto3" json:"max_inbound_connections,omitempty"` -} - -func (x *L7Destination) Reset() { - *x = L7Destination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L7Destination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L7Destination) ProtoMessage() {} - -func (x *L7Destination) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[5] - 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 L7Destination.ProtoReflect.Descriptor instead. -func (*L7Destination) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescGZIP(), []int{5} -} - -func (x *L7Destination) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *L7Destination) GetStatPrefix() string { - if x != nil { - return x.StatPrefix - } - return "" -} - -func (x *L7Destination) GetProtocol() L7Protocol { - if x != nil { - return x.Protocol - } - return L7Protocol_L7_PROTOCOL_HTTP -} - -func (x *L7Destination) GetIntentions() []*L7Intention { - if x != nil { - return x.Intentions - } - return nil -} - -func (x *L7Destination) GetAddEmptyIntention() bool { - if x != nil { - return x.AddEmptyIntention - } - return false -} - -func (x *L7Destination) GetIncludeXfcc() bool { - if x != nil { - return x.IncludeXfcc - } - return false -} - -func (x *L7Destination) GetStaticRoute() bool { - if x != nil { - return x.StaticRoute - } - return false -} - -func (x *L7Destination) GetMaxInboundConnections() uint64 { - if x != nil { - return x.MaxInboundConnections - } - return 0 -} - -type SNIDestination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - StatPrefix string `protobuf:"bytes,1,opt,name=stat_prefix,json=statPrefix,proto3" json:"stat_prefix,omitempty"` -} - -func (x *SNIDestination) Reset() { - *x = SNIDestination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SNIDestination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SNIDestination) ProtoMessage() {} - -func (x *SNIDestination) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[6] - 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 SNIDestination.ProtoReflect.Descriptor instead. -func (*SNIDestination) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescGZIP(), []int{6} -} - -func (x *SNIDestination) GetStatPrefix() string { - if x != nil { - return x.StatPrefix - } - return "" -} - -var File_pbmesh_v1alpha1_pbproxystate_listener_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDesc = []byte{ - 0x0a, 0x2b, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x6c, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2b, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, - 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x70, 0x62, 0x6d, 0x65, - 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2d, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x33, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x6f, - 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xab, 0x06, 0x0a, 0x08, 0x4c, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x54, 0x0a, 0x09, 0x64, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x5b, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x48, 0x00, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x61, - 0x0a, 0x0b, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x75, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, - 0x74, 0x12, 0x4d, 0x0a, 0x07, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x73, - 0x12, 0x5a, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, - 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x0d, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x5b, 0x0a, 0x0c, - 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, - 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0c, 0x63, 0x61, 0x70, - 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x70, 0x0a, 0x13, 0x62, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x65, - 0x73, 0x63, 0x61, 0x70, 0x65, 0x5f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x65, 0x73, 0x63, 0x61, - 0x70, 0x65, 0x48, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, - 0x37, 0x0a, 0x18, 0x75, 0x73, 0x65, 0x5f, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x5f, 0x68, 0x61, - 0x74, 0x63, 0x68, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x15, 0x75, 0x73, 0x65, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x48, 0x61, 0x74, 0x63, - 0x68, 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x42, 0x0e, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xad, 0x03, 0x0a, 0x06, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x4c, 0x0a, - 0x02, 0x6c, 0x34, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x34, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x02, 0x6c, 0x34, 0x12, 0x4c, 0x0a, 0x02, 0x6c, - 0x37, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x37, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x02, 0x6c, 0x37, 0x12, 0x4f, 0x0a, 0x03, 0x73, 0x6e, 0x69, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x4e, 0x49, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x03, 0x73, 0x6e, 0x69, 0x12, 0x5d, 0x0a, 0x0b, 0x69, 0x6e, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0a, 0x69, - 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x6c, 0x73, 0x42, 0x0d, 0x0a, 0x0b, 0x64, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xba, 0x02, 0x0a, 0x05, 0x4d, 0x61, 0x74, - 0x63, 0x68, 0x12, 0x47, 0x0a, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x5b, 0x0a, 0x0d, 0x70, - 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x68, 0x0a, 0x14, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x12, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x6f, 0x0a, 0x09, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, - 0x67, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x3b, 0x0a, 0x0a, 0x70, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x09, 0x70, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x4c, 0x65, 0x6e, 0x22, 0x86, 0x02, 0x0a, 0x0d, 0x4c, 0x34, 0x44, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, - 0x73, 0x74, 0x61, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x58, 0x0a, - 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, - 0x4c, 0x34, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x61, 0x64, 0x64, 0x5f, 0x65, - 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x61, 0x64, 0x64, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x49, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x69, - 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, - 0xa1, 0x03, 0x0a, 0x0d, 0x4c, 0x37, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x70, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, - 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x53, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x37, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x58, 0x0a, 0x0a, 0x69, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x37, - 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x61, 0x64, 0x64, 0x5f, 0x65, 0x6d, 0x70, - 0x74, 0x79, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x11, 0x61, 0x64, 0x64, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, - 0x5f, 0x78, 0x66, 0x63, 0x63, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x63, - 0x6c, 0x75, 0x64, 0x65, 0x58, 0x66, 0x63, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x6d, - 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x6d, 0x61, - 0x78, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x22, 0x31, 0x0a, 0x0e, 0x53, 0x4e, 0x49, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x70, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, - 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x2a, 0x55, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, - 0x0a, 0x11, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x42, 0x4f, - 0x55, 0x4e, 0x44, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x4f, 0x55, 0x54, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x2a, 0x54, 0x0a, - 0x12, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x43, - 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, - 0x4c, 0x54, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x5f, - 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x45, 0x58, 0x41, 0x43, - 0x54, 0x10, 0x01, 0x2a, 0x71, 0x0a, 0x0a, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, - 0x54, 0x52, 0x41, 0x4e, 0x53, 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x25, 0x0a, - 0x21, 0x43, 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x4c, 0x37, 0x5f, 0x50, - 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, - 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x43, 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, 0x49, - 0x54, 0x59, 0x5f, 0x4c, 0x34, 0x5f, 0x54, 0x4c, 0x53, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x2a, 0x4f, 0x0a, 0x0a, 0x4c, 0x37, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x37, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, - 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4c, 0x37, - 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x32, 0x10, - 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x37, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, - 0x5f, 0x47, 0x52, 0x50, 0x43, 0x10, 0x02, 0x42, 0xd9, 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0d, 0x4c, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2b, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, - 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, - 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, - 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0xea, 0x02, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescData = file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDesc -) - -func file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDescData -} - -var file_pbmesh_v1alpha1_pbproxystate_listener_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_pbmesh_v1alpha1_pbproxystate_listener_proto_goTypes = []interface{}{ - (Direction)(0), // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.Direction - (BalanceConnections)(0), // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.BalanceConnections - (Capability)(0), // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.Capability - (L7Protocol)(0), // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Protocol - (*Listener)(nil), // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.Listener - (*Router)(nil), // 5: hashicorp.consul.mesh.v1alpha1.pbproxystate.Router - (*Match)(nil), // 6: hashicorp.consul.mesh.v1alpha1.pbproxystate.Match - (*CidrRange)(nil), // 7: hashicorp.consul.mesh.v1alpha1.pbproxystate.CidrRange - (*L4Destination)(nil), // 8: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4Destination - (*L7Destination)(nil), // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Destination - (*SNIDestination)(nil), // 10: hashicorp.consul.mesh.v1alpha1.pbproxystate.SNIDestination - (*HostPortAddress)(nil), // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.HostPortAddress - (*UnixSocketAddress)(nil), // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.UnixSocketAddress - (*TransportSocket)(nil), // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket - (*wrapperspb.UInt32Value)(nil), // 14: google.protobuf.UInt32Value - (*L4Intention)(nil), // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4Intention - (*L7Intention)(nil), // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Intention -} -var file_pbmesh_v1alpha1_pbproxystate_listener_proto_depIdxs = []int32{ - 0, // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.Listener.direction:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.Direction - 11, // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.Listener.host_port:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HostPortAddress - 12, // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.Listener.unix_socket:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.UnixSocketAddress - 5, // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.Listener.routers:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.Router - 5, // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.Listener.default_router:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.Router - 2, // 5: hashicorp.consul.mesh.v1alpha1.pbproxystate.Listener.capabilities:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.Capability - 1, // 6: hashicorp.consul.mesh.v1alpha1.pbproxystate.Listener.balance_connections:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.BalanceConnections - 6, // 7: hashicorp.consul.mesh.v1alpha1.pbproxystate.Router.match:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.Match - 8, // 8: hashicorp.consul.mesh.v1alpha1.pbproxystate.Router.l4:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L4Destination - 9, // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.Router.l7:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Destination - 10, // 10: hashicorp.consul.mesh.v1alpha1.pbproxystate.Router.sni:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.SNIDestination - 13, // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.Router.inbound_tls:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket - 14, // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.Match.destination_port:type_name -> google.protobuf.UInt32Value - 7, // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.Match.prefix_ranges:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CidrRange - 7, // 14: hashicorp.consul.mesh.v1alpha1.pbproxystate.Match.source_prefix_ranges:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CidrRange - 14, // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.CidrRange.prefix_len:type_name -> google.protobuf.UInt32Value - 15, // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.L4Destination.intentions:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L4Intention - 3, // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Destination.protocol:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Protocol - 16, // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Destination.intentions:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L7Intention - 19, // [19:19] is the sub-list for method output_type - 19, // [19:19] is the sub-list for method input_type - 19, // [19:19] is the sub-list for extension type_name - 19, // [19:19] is the sub-list for extension extendee - 0, // [0:19] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_pbproxystate_listener_proto_init() } -func file_pbmesh_v1alpha1_pbproxystate_listener_proto_init() { - if File_pbmesh_v1alpha1_pbproxystate_listener_proto != nil { - return - } - file_pbmesh_v1alpha1_pbproxystate_address_proto_init() - file_pbmesh_v1alpha1_pbproxystate_intentions_proto_init() - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Listener); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Router); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Match); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CidrRange); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L4Destination); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L7Destination); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SNIDestination); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*Listener_HostPort)(nil), - (*Listener_UnixSocket)(nil), - } - file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*Router_L4)(nil), - (*Router_L7)(nil), - (*Router_Sni)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDesc, - NumEnums: 4, - NumMessages: 7, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_pbproxystate_listener_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_pbproxystate_listener_proto_depIdxs, - EnumInfos: file_pbmesh_v1alpha1_pbproxystate_listener_proto_enumTypes, - MessageInfos: file_pbmesh_v1alpha1_pbproxystate_listener_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_pbproxystate_listener_proto = out.File - file_pbmesh_v1alpha1_pbproxystate_listener_proto_rawDesc = nil - file_pbmesh_v1alpha1_pbproxystate_listener_proto_goTypes = nil - file_pbmesh_v1alpha1_pbproxystate_listener_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/listener.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/listener.proto deleted file mode 100644 index d4a4dcda9f350..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/listener.proto +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1.pbproxystate; - -import "google/protobuf/wrappers.proto"; -import "pbmesh/v1alpha1/pbproxystate/address.proto"; -import "pbmesh/v1alpha1/pbproxystate/intentions.proto"; -import "pbmesh/v1alpha1/pbproxystate/transport_socket.proto"; - -message Listener { - // name is the name of the listener. - string name = 1; - // direction tells the listener the direction of traffic. - Direction direction = 2; - // bind_address describes where to listen. - oneof bind_address { - HostPortAddress host_port = 3; - UnixSocketAddress unix_socket = 4; - } - - // routers describes how to route traffic from this listener. - repeated Router routers = 5; - // default_router describes where to route if none of the other router matches match the connection. - Router default_router = 6; - // capabilities describe Envoy proxy functionality to enable. These map closely to Envoy listener filters. - repeated Capability capabilities = 7; - // balance_connections configures how the listener should balance connections. - BalanceConnections balance_connections = 8; - // escape_hatch_listener_json configures a user configured escape hatch listener. - string escape_hatch_listener = 9; - // use_escape_hatch_tracing configures whether to use the top level user configured tracing escape hatch for this listener. - bool use_escape_hatch_tracing = 10; -} - -enum Direction { - // DIRECTION_UNSPECIFIED is used by mesh gateway listeners. - DIRECTION_UNSPECIFIED = 0; - DIRECTION_INBOUND = 1; - DIRECTION_OUTBOUND = 2; -} - -enum BalanceConnections { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - BALANCE_CONNECTIONS_DEFAULT = 0; - BALANCE_CONNECTIONS_EXACT = 1; -} - -// Capabilities map to proxy functionality to enable. These enable tproxy, l7 protocol/alpn inspection, or l4 sni/alpn inspection. -enum Capability { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - CAPABILITY_TRANSPARENT = 0; - CAPABILITY_L7_PROTOCOL_INSPECTION = 1; - CAPABILITY_L4_TLS_INSPECTION = 2; -} - -message Router { - // match specifies how to match traffic coming into this listener. If the traffic matches, it will be routed to the - // destination. - Match match = 1; - oneof destination { - // l4 is an l4 destination to route to, which will have a reference to a cluster. - L4Destination l4 = 2; - // l7 is an l7 destination to route to, which will have a reference to a route. - L7Destination l7 = 3; - // sni is an SNI destination, which means there will be no references, but the SNI name will be tied to the cluster - // name, so we should generate all clusters. - SNIDestination sni = 4; - } - // inbound_tls is used by inbound listeners that terminate TLS. - TransportSocket inbound_tls = 5; -} - -message Match { - google.protobuf.UInt32Value destination_port = 1; - repeated CidrRange prefix_ranges = 2; - repeated CidrRange source_prefix_ranges = 3; - // server_names matches based on SNI of the incoming request. - repeated string server_names = 4; -} - -message CidrRange { - string address_prefix = 1; - google.protobuf.UInt32Value prefix_len = 2; -} - -message L4Destination { - // name is a key in the top level clusters map. This specifies which cluster to go to in this L4 destination. - string name = 1; - // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - string stat_prefix = 2; - // intentions is a list of intentions for this destination. - repeated L4Intention intentions = 3; - // add_empty_intention specifies whether to add an empty intention for this destination, when there are no other intentions specified. - bool add_empty_intention = 4; - // max_inbound_connections specifies how many connections this destination can accept. - uint64 max_inbound_connections = 5; -} - -message L7Destination { - // name is a key in the top level routes map. This specifies which route to go to in this L7 destination. - string name = 1; - // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - string stat_prefix = 2; - // protocol for the destination. - L7Protocol protocol = 3; - // intentions is a list of intentions for this destination. - repeated L7Intention intentions = 4; - // add_empty_intention specifies whether to add an empty intention for this destination, when there are no other intentions specified. - bool add_empty_intention = 5; - // include_xfcc specifies whether to add xfcc header. - bool include_xfcc = 6; - // static_route specifies whether this is a static route that is inlined in the listener filter. This is required to - // match existing xds config. - bool static_route = 7; - // max_inbound_connections specifies how many connections this destination can accept. - uint64 max_inbound_connections = 8; -} - -enum L7Protocol { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - L7_PROTOCOL_HTTP = 0; - L7_PROTOCOL_HTTP2 = 1; - L7_PROTOCOL_GRPC = 2; -} - -message SNIDestination { - // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - string stat_prefix = 1; -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/references.pb.binary.go b/proto-public/pbmesh/v1alpha1/pbproxystate/references.pb.binary.go deleted file mode 100644 index 5d42cb386296f..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/references.pb.binary.go +++ /dev/null @@ -1,38 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/pbproxystate/references.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LeafCertificateRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LeafCertificateRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TrustBundleRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TrustBundleRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *EndpointRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *EndpointRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/references.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/references.pb.go deleted file mode 100644 index cee7c44bc46b2..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/references.pb.go +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/pbproxystate/references.proto - -package pbproxystate - -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 LeafCertificateRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` - Partition string `protobuf:"bytes,3,opt,name=partition,proto3" json:"partition,omitempty"` - Host string `protobuf:"bytes,4,opt,name=host,proto3" json:"host,omitempty"` - Datacenter string `protobuf:"bytes,5,opt,name=datacenter,proto3" json:"datacenter,omitempty"` - DnsSan []string `protobuf:"bytes,6,rep,name=dns_san,json=dnsSan,proto3" json:"dns_san,omitempty"` -} - -func (x *LeafCertificateRef) Reset() { - *x = LeafCertificateRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_references_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LeafCertificateRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LeafCertificateRef) ProtoMessage() {} - -func (x *LeafCertificateRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_references_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 LeafCertificateRef.ProtoReflect.Descriptor instead. -func (*LeafCertificateRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_references_proto_rawDescGZIP(), []int{0} -} - -func (x *LeafCertificateRef) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *LeafCertificateRef) GetNamespace() string { - if x != nil { - return x.Namespace - } - return "" -} - -func (x *LeafCertificateRef) GetPartition() string { - if x != nil { - return x.Partition - } - return "" -} - -func (x *LeafCertificateRef) GetHost() string { - if x != nil { - return x.Host - } - return "" -} - -func (x *LeafCertificateRef) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - -func (x *LeafCertificateRef) GetDnsSan() []string { - if x != nil { - return x.DnsSan - } - return nil -} - -type TrustBundleRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Peer string `protobuf:"bytes,1,opt,name=peer,proto3" json:"peer,omitempty"` - TrustDomain string `protobuf:"bytes,2,opt,name=trust_domain,json=trustDomain,proto3" json:"trust_domain,omitempty"` -} - -func (x *TrustBundleRef) Reset() { - *x = TrustBundleRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_references_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TrustBundleRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TrustBundleRef) ProtoMessage() {} - -func (x *TrustBundleRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_references_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 TrustBundleRef.ProtoReflect.Descriptor instead. -func (*TrustBundleRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_references_proto_rawDescGZIP(), []int{1} -} - -func (x *TrustBundleRef) GetPeer() string { - if x != nil { - return x.Peer - } - return "" -} - -func (x *TrustBundleRef) GetTrustDomain() string { - if x != nil { - return x.TrustDomain - } - return "" -} - -type EndpointRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // id is the ServiceEndpoints resource id. - Id *pbresource.ID `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - // port is the name of the port in the ServiceEndpoints to generate the Endpoints from. - Port string `protobuf:"bytes,2,opt,name=port,proto3" json:"port,omitempty"` -} - -func (x *EndpointRef) Reset() { - *x = EndpointRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_references_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EndpointRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EndpointRef) ProtoMessage() {} - -func (x *EndpointRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_references_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 EndpointRef.ProtoReflect.Descriptor instead. -func (*EndpointRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_references_proto_rawDescGZIP(), []int{2} -} - -func (x *EndpointRef) GetId() *pbresource.ID { - if x != nil { - return x.Id - } - return nil -} - -func (x *EndpointRef) GetPort() string { - if x != nil { - return x.Port - } - return "" -} - -var File_pbmesh_v1alpha1_pbproxystate_references_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_pbproxystate_references_proto_rawDesc = []byte{ - 0x0a, 0x2d, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x72, - 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x2b, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 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, 0xb1, 0x01, 0x0a, 0x12, 0x4c, 0x65, 0x61, 0x66, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x66, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, - 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, - 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, - 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x6e, 0x73, 0x5f, 0x73, 0x61, 0x6e, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6e, 0x73, 0x53, 0x61, 0x6e, 0x22, 0x47, 0x0a, 0x0e, 0x54, - 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x66, 0x12, 0x12, 0x0a, - 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x65, 0x65, - 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x72, 0x75, 0x73, 0x74, 0x44, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x50, 0x0a, 0x0b, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x52, 0x65, 0x66, 0x12, 0x2d, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 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, 0x49, 0x44, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x42, 0xdb, 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0f, 0x52, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x65, 0x73, 0x68, 0x2f, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2b, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, - 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, - 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_pbproxystate_references_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_pbproxystate_references_proto_rawDescData = file_pbmesh_v1alpha1_pbproxystate_references_proto_rawDesc -) - -func file_pbmesh_v1alpha1_pbproxystate_references_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_pbproxystate_references_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_pbproxystate_references_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_pbproxystate_references_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_pbproxystate_references_proto_rawDescData -} - -var file_pbmesh_v1alpha1_pbproxystate_references_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_pbmesh_v1alpha1_pbproxystate_references_proto_goTypes = []interface{}{ - (*LeafCertificateRef)(nil), // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.LeafCertificateRef - (*TrustBundleRef)(nil), // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.TrustBundleRef - (*EndpointRef)(nil), // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointRef - (*pbresource.ID)(nil), // 3: hashicorp.consul.resource.ID -} -var file_pbmesh_v1alpha1_pbproxystate_references_proto_depIdxs = []int32{ - 3, // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointRef.id:type_name -> hashicorp.consul.resource.ID - 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_pbmesh_v1alpha1_pbproxystate_references_proto_init() } -func file_pbmesh_v1alpha1_pbproxystate_references_proto_init() { - if File_pbmesh_v1alpha1_pbproxystate_references_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_pbproxystate_references_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LeafCertificateRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_references_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TrustBundleRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_references_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EndpointRef); 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_pbmesh_v1alpha1_pbproxystate_references_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_pbproxystate_references_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_pbproxystate_references_proto_depIdxs, - MessageInfos: file_pbmesh_v1alpha1_pbproxystate_references_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_pbproxystate_references_proto = out.File - file_pbmesh_v1alpha1_pbproxystate_references_proto_rawDesc = nil - file_pbmesh_v1alpha1_pbproxystate_references_proto_goTypes = nil - file_pbmesh_v1alpha1_pbproxystate_references_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/references.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/references.proto deleted file mode 100644 index 3e2c1ddd45ca9..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/references.proto +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1.pbproxystate; - -import "pbresource/resource.proto"; - -message LeafCertificateRef { - string name = 1; - string namespace = 2; - string partition = 3; - string host = 4; - string datacenter = 5; - repeated string dns_san = 6; -} - -message TrustBundleRef { - string peer = 1; - string trust_domain = 2; -} - -message EndpointRef { - // id is the ServiceEndpoints resource id. - hashicorp.consul.resource.ID id = 1; - // port is the name of the port in the ServiceEndpoints to generate the Endpoints from. - string port = 2; -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.binary.go b/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.binary.go deleted file mode 100644 index 5d6ba14ecc912..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.binary.go +++ /dev/null @@ -1,178 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/pbproxystate/route.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Route) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Route) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *VirtualHost) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *VirtualHost) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RouteMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RouteMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *PathMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *PathMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *QueryParameterMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *QueryParameterMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HeaderMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HeaderMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RouteDestination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RouteDestination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationConfiguration) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationConfiguration) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RetryPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RetryPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TimeoutConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TimeoutConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LoadBalancerHashPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LoadBalancerHashPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *CookiePolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *CookiePolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HeaderPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HeaderPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *QueryParameterPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *QueryParameterPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ConnectionPropertiesPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ConnectionPropertiesPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationCluster) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationCluster) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.go deleted file mode 100644 index c6840dd18aaa2..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/route.pb.go +++ /dev/null @@ -1,1891 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/pbproxystate/route.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - 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 Route struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // virtual_hosts is a list of virtual hosts. A virtual host is selected based on an incoming request's host header. - VirtualHosts []*VirtualHost `protobuf:"bytes,1,rep,name=virtual_hosts,json=virtualHosts,proto3" json:"virtual_hosts,omitempty"` -} - -func (x *Route) Reset() { - *x = Route{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Route) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Route) ProtoMessage() {} - -func (x *Route) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_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 Route.ProtoReflect.Descriptor instead. -func (*Route) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{0} -} - -func (x *Route) GetVirtualHosts() []*VirtualHost { - if x != nil { - return x.VirtualHosts - } - return nil -} - -type VirtualHost struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // domains are used to match an incoming request's host header and determine which virtual host to use. - Domains []string `protobuf:"bytes,2,rep,name=domains,proto3" json:"domains,omitempty"` - // header_mutations to apply to the request when it matches this virtual host. These are applied after any headers in - // the RouteRule. - HeaderMutations []*HeaderMutation `protobuf:"bytes,3,rep,name=header_mutations,json=headerMutations,proto3" json:"header_mutations,omitempty"` - // route_rules are a list of rules to use for what to do next with this request. The first rule with a match will be - // used. - RouteRules []*RouteRule `protobuf:"bytes,4,rep,name=route_rules,json=routeRules,proto3" json:"route_rules,omitempty"` -} - -func (x *VirtualHost) Reset() { - *x = VirtualHost{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *VirtualHost) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*VirtualHost) ProtoMessage() {} - -func (x *VirtualHost) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_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 VirtualHost.ProtoReflect.Descriptor instead. -func (*VirtualHost) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{1} -} - -func (x *VirtualHost) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *VirtualHost) GetDomains() []string { - if x != nil { - return x.Domains - } - return nil -} - -func (x *VirtualHost) GetHeaderMutations() []*HeaderMutation { - if x != nil { - return x.HeaderMutations - } - return nil -} - -func (x *VirtualHost) GetRouteRules() []*RouteRule { - if x != nil { - return x.RouteRules - } - return nil -} - -type RouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // match determines how to match the request. The first match determines which destination the request will go to. - Match *RouteMatch `protobuf:"bytes,1,opt,name=match,proto3" json:"match,omitempty"` - // destination is where to send the request to. - Destination *RouteDestination `protobuf:"bytes,2,opt,name=destination,proto3" json:"destination,omitempty"` - // header_mutations to apply to the request. These are applied before the VirtualHost header mutations. - HeaderMutations []*HeaderMutation `protobuf:"bytes,3,rep,name=header_mutations,json=headerMutations,proto3" json:"header_mutations,omitempty"` -} - -func (x *RouteRule) Reset() { - *x = RouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RouteRule) ProtoMessage() {} - -func (x *RouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_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 RouteRule.ProtoReflect.Descriptor instead. -func (*RouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{2} -} - -func (x *RouteRule) GetMatch() *RouteMatch { - if x != nil { - return x.Match - } - return nil -} - -func (x *RouteRule) GetDestination() *RouteDestination { - if x != nil { - return x.Destination - } - return nil -} - -func (x *RouteRule) GetHeaderMutations() []*HeaderMutation { - if x != nil { - return x.HeaderMutations - } - return nil -} - -// RouteMatch has configuration to match a request. -type RouteMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PathMatch *PathMatch `protobuf:"bytes,1,opt,name=path_match,json=pathMatch,proto3" json:"path_match,omitempty"` - HeaderMatches []*HeaderMatch `protobuf:"bytes,2,rep,name=header_matches,json=headerMatches,proto3" json:"header_matches,omitempty"` - MethodMatches []string `protobuf:"bytes,3,rep,name=method_matches,json=methodMatches,proto3" json:"method_matches,omitempty"` - QueryParameterMatches []*QueryParameterMatch `protobuf:"bytes,4,rep,name=query_parameter_matches,json=queryParameterMatches,proto3" json:"query_parameter_matches,omitempty"` -} - -func (x *RouteMatch) Reset() { - *x = RouteMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RouteMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RouteMatch) ProtoMessage() {} - -func (x *RouteMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[3] - 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 RouteMatch.ProtoReflect.Descriptor instead. -func (*RouteMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{3} -} - -func (x *RouteMatch) GetPathMatch() *PathMatch { - if x != nil { - return x.PathMatch - } - return nil -} - -func (x *RouteMatch) GetHeaderMatches() []*HeaderMatch { - if x != nil { - return x.HeaderMatches - } - return nil -} - -func (x *RouteMatch) GetMethodMatches() []string { - if x != nil { - return x.MethodMatches - } - return nil -} - -func (x *RouteMatch) GetQueryParameterMatches() []*QueryParameterMatch { - if x != nil { - return x.QueryParameterMatches - } - return nil -} - -type PathMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to PathMatch: - // - // *PathMatch_Exact - // *PathMatch_Prefix - // *PathMatch_Regex - PathMatch isPathMatch_PathMatch `protobuf_oneof:"path_match"` -} - -func (x *PathMatch) Reset() { - *x = PathMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PathMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PathMatch) ProtoMessage() {} - -func (x *PathMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[4] - 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 PathMatch.ProtoReflect.Descriptor instead. -func (*PathMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{4} -} - -func (m *PathMatch) GetPathMatch() isPathMatch_PathMatch { - if m != nil { - return m.PathMatch - } - return nil -} - -func (x *PathMatch) GetExact() string { - if x, ok := x.GetPathMatch().(*PathMatch_Exact); ok { - return x.Exact - } - return "" -} - -func (x *PathMatch) GetPrefix() string { - if x, ok := x.GetPathMatch().(*PathMatch_Prefix); ok { - return x.Prefix - } - return "" -} - -func (x *PathMatch) GetRegex() string { - if x, ok := x.GetPathMatch().(*PathMatch_Regex); ok { - return x.Regex - } - return "" -} - -type isPathMatch_PathMatch interface { - isPathMatch_PathMatch() -} - -type PathMatch_Exact struct { - Exact string `protobuf:"bytes,1,opt,name=exact,proto3,oneof"` -} - -type PathMatch_Prefix struct { - Prefix string `protobuf:"bytes,2,opt,name=prefix,proto3,oneof"` -} - -type PathMatch_Regex struct { - Regex string `protobuf:"bytes,3,opt,name=regex,proto3,oneof"` -} - -func (*PathMatch_Exact) isPathMatch_PathMatch() {} - -func (*PathMatch_Prefix) isPathMatch_PathMatch() {} - -func (*PathMatch_Regex) isPathMatch_PathMatch() {} - -type QueryParameterMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Types that are assignable to Match: - // - // *QueryParameterMatch_Exact - // *QueryParameterMatch_Regex - // *QueryParameterMatch_Present - Match isQueryParameterMatch_Match `protobuf_oneof:"match"` -} - -func (x *QueryParameterMatch) Reset() { - *x = QueryParameterMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryParameterMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryParameterMatch) ProtoMessage() {} - -func (x *QueryParameterMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[5] - 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 QueryParameterMatch.ProtoReflect.Descriptor instead. -func (*QueryParameterMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{5} -} - -func (x *QueryParameterMatch) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (m *QueryParameterMatch) GetMatch() isQueryParameterMatch_Match { - if m != nil { - return m.Match - } - return nil -} - -func (x *QueryParameterMatch) GetExact() string { - if x, ok := x.GetMatch().(*QueryParameterMatch_Exact); ok { - return x.Exact - } - return "" -} - -func (x *QueryParameterMatch) GetRegex() string { - if x, ok := x.GetMatch().(*QueryParameterMatch_Regex); ok { - return x.Regex - } - return "" -} - -func (x *QueryParameterMatch) GetPresent() bool { - if x, ok := x.GetMatch().(*QueryParameterMatch_Present); ok { - return x.Present - } - return false -} - -type isQueryParameterMatch_Match interface { - isQueryParameterMatch_Match() -} - -type QueryParameterMatch_Exact struct { - Exact string `protobuf:"bytes,2,opt,name=exact,proto3,oneof"` -} - -type QueryParameterMatch_Regex struct { - Regex string `protobuf:"bytes,3,opt,name=regex,proto3,oneof"` -} - -type QueryParameterMatch_Present struct { - Present bool `protobuf:"varint,4,opt,name=present,proto3,oneof"` -} - -func (*QueryParameterMatch_Exact) isQueryParameterMatch_Match() {} - -func (*QueryParameterMatch_Regex) isQueryParameterMatch_Match() {} - -func (*QueryParameterMatch_Present) isQueryParameterMatch_Match() {} - -type HeaderMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Types that are assignable to Match: - // - // *HeaderMatch_Exact - // *HeaderMatch_Prefix - // *HeaderMatch_Suffix - // *HeaderMatch_Regex - // *HeaderMatch_Present - Match isHeaderMatch_Match `protobuf_oneof:"match"` - InvertMatch bool `protobuf:"varint,7,opt,name=invert_match,json=invertMatch,proto3" json:"invert_match,omitempty"` -} - -func (x *HeaderMatch) Reset() { - *x = HeaderMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HeaderMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HeaderMatch) ProtoMessage() {} - -func (x *HeaderMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[6] - 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 HeaderMatch.ProtoReflect.Descriptor instead. -func (*HeaderMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{6} -} - -func (x *HeaderMatch) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (m *HeaderMatch) GetMatch() isHeaderMatch_Match { - if m != nil { - return m.Match - } - return nil -} - -func (x *HeaderMatch) GetExact() string { - if x, ok := x.GetMatch().(*HeaderMatch_Exact); ok { - return x.Exact - } - return "" -} - -func (x *HeaderMatch) GetPrefix() string { - if x, ok := x.GetMatch().(*HeaderMatch_Prefix); ok { - return x.Prefix - } - return "" -} - -func (x *HeaderMatch) GetSuffix() string { - if x, ok := x.GetMatch().(*HeaderMatch_Suffix); ok { - return x.Suffix - } - return "" -} - -func (x *HeaderMatch) GetRegex() string { - if x, ok := x.GetMatch().(*HeaderMatch_Regex); ok { - return x.Regex - } - return "" -} - -func (x *HeaderMatch) GetPresent() bool { - if x, ok := x.GetMatch().(*HeaderMatch_Present); ok { - return x.Present - } - return false -} - -func (x *HeaderMatch) GetInvertMatch() bool { - if x != nil { - return x.InvertMatch - } - return false -} - -type isHeaderMatch_Match interface { - isHeaderMatch_Match() -} - -type HeaderMatch_Exact struct { - Exact string `protobuf:"bytes,2,opt,name=exact,proto3,oneof"` -} - -type HeaderMatch_Prefix struct { - Prefix string `protobuf:"bytes,3,opt,name=prefix,proto3,oneof"` -} - -type HeaderMatch_Suffix struct { - Suffix string `protobuf:"bytes,4,opt,name=suffix,proto3,oneof"` -} - -type HeaderMatch_Regex struct { - Regex string `protobuf:"bytes,5,opt,name=regex,proto3,oneof"` -} - -type HeaderMatch_Present struct { - Present bool `protobuf:"varint,6,opt,name=present,proto3,oneof"` -} - -func (*HeaderMatch_Exact) isHeaderMatch_Match() {} - -func (*HeaderMatch_Prefix) isHeaderMatch_Match() {} - -func (*HeaderMatch_Suffix) isHeaderMatch_Match() {} - -func (*HeaderMatch_Regex) isHeaderMatch_Match() {} - -func (*HeaderMatch_Present) isHeaderMatch_Match() {} - -// RouteDestination has configuration for where to send a request. -type RouteDestination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // destination is one or more clusters to route to. - // - // Types that are assignable to Destination: - // - // *RouteDestination_Cluster - // *RouteDestination_WeightedClusters - Destination isRouteDestination_Destination `protobuf_oneof:"destination"` - DestinationConfiguration *DestinationConfiguration `protobuf:"bytes,3,opt,name=destination_configuration,json=destinationConfiguration,proto3" json:"destination_configuration,omitempty"` -} - -func (x *RouteDestination) Reset() { - *x = RouteDestination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RouteDestination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RouteDestination) ProtoMessage() {} - -func (x *RouteDestination) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[7] - 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 RouteDestination.ProtoReflect.Descriptor instead. -func (*RouteDestination) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{7} -} - -func (m *RouteDestination) GetDestination() isRouteDestination_Destination { - if m != nil { - return m.Destination - } - return nil -} - -func (x *RouteDestination) GetCluster() *DestinationCluster { - if x, ok := x.GetDestination().(*RouteDestination_Cluster); ok { - return x.Cluster - } - return nil -} - -func (x *RouteDestination) GetWeightedClusters() *L7WeightedClusterGroup { - if x, ok := x.GetDestination().(*RouteDestination_WeightedClusters); ok { - return x.WeightedClusters - } - return nil -} - -func (x *RouteDestination) GetDestinationConfiguration() *DestinationConfiguration { - if x != nil { - return x.DestinationConfiguration - } - return nil -} - -type isRouteDestination_Destination interface { - isRouteDestination_Destination() -} - -type RouteDestination_Cluster struct { - Cluster *DestinationCluster `protobuf:"bytes,1,opt,name=cluster,proto3,oneof"` -} - -type RouteDestination_WeightedClusters struct { - WeightedClusters *L7WeightedClusterGroup `protobuf:"bytes,2,opt,name=weighted_clusters,json=weightedClusters,proto3,oneof"` -} - -func (*RouteDestination_Cluster) isRouteDestination_Destination() {} - -func (*RouteDestination_WeightedClusters) isRouteDestination_Destination() {} - -type DestinationConfiguration struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AutoHostRewrite *wrapperspb.BoolValue `protobuf:"bytes,1,opt,name=auto_host_rewrite,json=autoHostRewrite,proto3" json:"auto_host_rewrite,omitempty"` - HashPolicies []*LoadBalancerHashPolicy `protobuf:"bytes,2,rep,name=hash_policies,json=hashPolicies,proto3" json:"hash_policies,omitempty"` - TimeoutConfig *TimeoutConfig `protobuf:"bytes,3,opt,name=timeout_config,json=timeoutConfig,proto3" json:"timeout_config,omitempty"` - PrefixRewrite string `protobuf:"bytes,4,opt,name=prefix_rewrite,json=prefixRewrite,proto3" json:"prefix_rewrite,omitempty"` - RetryPolicy *RetryPolicy `protobuf:"bytes,5,opt,name=retry_policy,json=retryPolicy,proto3" json:"retry_policy,omitempty"` -} - -func (x *DestinationConfiguration) Reset() { - *x = DestinationConfiguration{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationConfiguration) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationConfiguration) ProtoMessage() {} - -func (x *DestinationConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[8] - 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 DestinationConfiguration.ProtoReflect.Descriptor instead. -func (*DestinationConfiguration) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{8} -} - -func (x *DestinationConfiguration) GetAutoHostRewrite() *wrapperspb.BoolValue { - if x != nil { - return x.AutoHostRewrite - } - return nil -} - -func (x *DestinationConfiguration) GetHashPolicies() []*LoadBalancerHashPolicy { - if x != nil { - return x.HashPolicies - } - return nil -} - -func (x *DestinationConfiguration) GetTimeoutConfig() *TimeoutConfig { - if x != nil { - return x.TimeoutConfig - } - return nil -} - -func (x *DestinationConfiguration) GetPrefixRewrite() string { - if x != nil { - return x.PrefixRewrite - } - return "" -} - -func (x *DestinationConfiguration) GetRetryPolicy() *RetryPolicy { - if x != nil { - return x.RetryPolicy - } - return nil -} - -type RetryPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RetryOn string `protobuf:"bytes,1,opt,name=retry_on,json=retryOn,proto3" json:"retry_on,omitempty"` - NumRetries *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=num_retries,json=numRetries,proto3" json:"num_retries,omitempty"` - RetriableStatusCodes []uint32 `protobuf:"varint,3,rep,packed,name=retriable_status_codes,json=retriableStatusCodes,proto3" json:"retriable_status_codes,omitempty"` -} - -func (x *RetryPolicy) Reset() { - *x = RetryPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RetryPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RetryPolicy) ProtoMessage() {} - -func (x *RetryPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[9] - 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 RetryPolicy.ProtoReflect.Descriptor instead. -func (*RetryPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{9} -} - -func (x *RetryPolicy) GetRetryOn() string { - if x != nil { - return x.RetryOn - } - return "" -} - -func (x *RetryPolicy) GetNumRetries() *wrapperspb.UInt32Value { - if x != nil { - return x.NumRetries - } - return nil -} - -func (x *RetryPolicy) GetRetriableStatusCodes() []uint32 { - if x != nil { - return x.RetriableStatusCodes - } - return nil -} - -type TimeoutConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Timeout *durationpb.Duration `protobuf:"bytes,1,opt,name=timeout,proto3" json:"timeout,omitempty"` - IdleTimeout *durationpb.Duration `protobuf:"bytes,2,opt,name=idle_timeout,json=idleTimeout,proto3" json:"idle_timeout,omitempty"` -} - -func (x *TimeoutConfig) Reset() { - *x = TimeoutConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TimeoutConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TimeoutConfig) ProtoMessage() {} - -func (x *TimeoutConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[10] - 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 TimeoutConfig.ProtoReflect.Descriptor instead. -func (*TimeoutConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{10} -} - -func (x *TimeoutConfig) GetTimeout() *durationpb.Duration { - if x != nil { - return x.Timeout - } - return nil -} - -func (x *TimeoutConfig) GetIdleTimeout() *durationpb.Duration { - if x != nil { - return x.IdleTimeout - } - return nil -} - -type LoadBalancerHashPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Policy: - // - // *LoadBalancerHashPolicy_Cookie - // *LoadBalancerHashPolicy_Header - // *LoadBalancerHashPolicy_QueryParameter - // *LoadBalancerHashPolicy_ConnectionProperties - Policy isLoadBalancerHashPolicy_Policy `protobuf_oneof:"policy"` -} - -func (x *LoadBalancerHashPolicy) Reset() { - *x = LoadBalancerHashPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LoadBalancerHashPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LoadBalancerHashPolicy) ProtoMessage() {} - -func (x *LoadBalancerHashPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[11] - 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 LoadBalancerHashPolicy.ProtoReflect.Descriptor instead. -func (*LoadBalancerHashPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{11} -} - -func (m *LoadBalancerHashPolicy) GetPolicy() isLoadBalancerHashPolicy_Policy { - if m != nil { - return m.Policy - } - return nil -} - -func (x *LoadBalancerHashPolicy) GetCookie() *CookiePolicy { - if x, ok := x.GetPolicy().(*LoadBalancerHashPolicy_Cookie); ok { - return x.Cookie - } - return nil -} - -func (x *LoadBalancerHashPolicy) GetHeader() *HeaderPolicy { - if x, ok := x.GetPolicy().(*LoadBalancerHashPolicy_Header); ok { - return x.Header - } - return nil -} - -func (x *LoadBalancerHashPolicy) GetQueryParameter() *QueryParameterPolicy { - if x, ok := x.GetPolicy().(*LoadBalancerHashPolicy_QueryParameter); ok { - return x.QueryParameter - } - return nil -} - -func (x *LoadBalancerHashPolicy) GetConnectionProperties() *ConnectionPropertiesPolicy { - if x, ok := x.GetPolicy().(*LoadBalancerHashPolicy_ConnectionProperties); ok { - return x.ConnectionProperties - } - return nil -} - -type isLoadBalancerHashPolicy_Policy interface { - isLoadBalancerHashPolicy_Policy() -} - -type LoadBalancerHashPolicy_Cookie struct { - Cookie *CookiePolicy `protobuf:"bytes,1,opt,name=cookie,proto3,oneof"` -} - -type LoadBalancerHashPolicy_Header struct { - Header *HeaderPolicy `protobuf:"bytes,2,opt,name=header,proto3,oneof"` -} - -type LoadBalancerHashPolicy_QueryParameter struct { - QueryParameter *QueryParameterPolicy `protobuf:"bytes,3,opt,name=query_parameter,json=queryParameter,proto3,oneof"` -} - -type LoadBalancerHashPolicy_ConnectionProperties struct { - ConnectionProperties *ConnectionPropertiesPolicy `protobuf:"bytes,4,opt,name=connection_properties,json=connectionProperties,proto3,oneof"` -} - -func (*LoadBalancerHashPolicy_Cookie) isLoadBalancerHashPolicy_Policy() {} - -func (*LoadBalancerHashPolicy_Header) isLoadBalancerHashPolicy_Policy() {} - -func (*LoadBalancerHashPolicy_QueryParameter) isLoadBalancerHashPolicy_Policy() {} - -func (*LoadBalancerHashPolicy_ConnectionProperties) isLoadBalancerHashPolicy_Policy() {} - -type CookiePolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Ttl *durationpb.Duration `protobuf:"bytes,2,opt,name=ttl,proto3" json:"ttl,omitempty"` - Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"` - Terminal bool `protobuf:"varint,4,opt,name=terminal,proto3" json:"terminal,omitempty"` -} - -func (x *CookiePolicy) Reset() { - *x = CookiePolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CookiePolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CookiePolicy) ProtoMessage() {} - -func (x *CookiePolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[12] - 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 CookiePolicy.ProtoReflect.Descriptor instead. -func (*CookiePolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{12} -} - -func (x *CookiePolicy) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *CookiePolicy) GetTtl() *durationpb.Duration { - if x != nil { - return x.Ttl - } - return nil -} - -func (x *CookiePolicy) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (x *CookiePolicy) GetTerminal() bool { - if x != nil { - return x.Terminal - } - return false -} - -type HeaderPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Terminal bool `protobuf:"varint,2,opt,name=terminal,proto3" json:"terminal,omitempty"` -} - -func (x *HeaderPolicy) Reset() { - *x = HeaderPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HeaderPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HeaderPolicy) ProtoMessage() {} - -func (x *HeaderPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[13] - 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 HeaderPolicy.ProtoReflect.Descriptor instead. -func (*HeaderPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{13} -} - -func (x *HeaderPolicy) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *HeaderPolicy) GetTerminal() bool { - if x != nil { - return x.Terminal - } - return false -} - -type QueryParameterPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Terminal bool `protobuf:"varint,2,opt,name=terminal,proto3" json:"terminal,omitempty"` -} - -func (x *QueryParameterPolicy) Reset() { - *x = QueryParameterPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryParameterPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryParameterPolicy) ProtoMessage() {} - -func (x *QueryParameterPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[14] - 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 QueryParameterPolicy.ProtoReflect.Descriptor instead. -func (*QueryParameterPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{14} -} - -func (x *QueryParameterPolicy) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *QueryParameterPolicy) GetTerminal() bool { - if x != nil { - return x.Terminal - } - return false -} - -type ConnectionPropertiesPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SourceIp bool `protobuf:"varint,1,opt,name=source_ip,json=sourceIp,proto3" json:"source_ip,omitempty"` - Terminal bool `protobuf:"varint,2,opt,name=terminal,proto3" json:"terminal,omitempty"` -} - -func (x *ConnectionPropertiesPolicy) Reset() { - *x = ConnectionPropertiesPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ConnectionPropertiesPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConnectionPropertiesPolicy) ProtoMessage() {} - -func (x *ConnectionPropertiesPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[15] - 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 ConnectionPropertiesPolicy.ProtoReflect.Descriptor instead. -func (*ConnectionPropertiesPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{15} -} - -func (x *ConnectionPropertiesPolicy) GetSourceIp() bool { - if x != nil { - return x.SourceIp - } - return false -} - -func (x *ConnectionPropertiesPolicy) GetTerminal() bool { - if x != nil { - return x.Terminal - } - return false -} - -type DestinationCluster struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` -} - -func (x *DestinationCluster) Reset() { - *x = DestinationCluster{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationCluster) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationCluster) ProtoMessage() {} - -func (x *DestinationCluster) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[16] - 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 DestinationCluster.ProtoReflect.Descriptor instead. -func (*DestinationCluster) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP(), []int{16} -} - -func (x *DestinationCluster) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -var File_pbmesh_v1alpha1_pbproxystate_route_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDesc = []byte{ - 0x0a, 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x72, - 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2b, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x33, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x66, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x12, 0x5d, 0x0a, 0x0d, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x73, - 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x48, 0x6f, - 0x73, 0x74, 0x52, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x48, 0x6f, 0x73, 0x74, 0x73, - 0x22, 0xfc, 0x01, 0x0a, 0x0b, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x48, 0x6f, 0x73, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x66, - 0x0a, 0x10, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x57, 0x0a, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, - 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, - 0x75, 0x6c, 0x65, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x22, - 0xa3, 0x02, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x4d, 0x0a, - 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x5f, 0x0a, 0x0b, - 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x66, 0x0a, - 0x10, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe5, 0x02, 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x12, 0x55, 0x0a, 0x0a, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x74, - 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x52, 0x09, 0x70, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x5f, 0x0a, 0x0e, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x0d, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x65, 0x73, 0x12, 0x78, 0x0a, 0x17, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x70, 0x61, 0x72, - 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, - 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x15, 0x71, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0x63, 0x0a, - 0x09, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x78, - 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, 0x78, 0x61, - 0x63, 0x74, 0x12, 0x18, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x05, - 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x72, - 0x65, 0x67, 0x65, 0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x74, - 0x63, 0x68, 0x22, 0x7e, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x65, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, - 0x05, 0x65, 0x78, 0x61, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, - 0x65, 0x78, 0x61, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x12, 0x1a, 0x0a, - 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, - 0x52, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x6d, 0x61, 0x74, - 0x63, 0x68, 0x22, 0xcd, 0x01, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, - 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x78, 0x61, 0x63, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, 0x78, 0x61, 0x63, 0x74, 0x12, 0x18, - 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, - 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x18, 0x0a, 0x06, 0x73, 0x75, 0x66, 0x66, - 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x73, 0x75, 0x66, 0x66, - 0x69, 0x78, 0x12, 0x16, 0x0a, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x12, 0x1a, 0x0a, 0x07, 0x70, 0x72, - 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x70, - 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, - 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, - 0x76, 0x65, 0x72, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x42, 0x07, 0x0a, 0x05, 0x6d, 0x61, 0x74, - 0x63, 0x68, 0x22, 0xf7, 0x02, 0x0a, 0x10, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x12, 0x72, 0x0a, 0x11, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, - 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x37, - 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x10, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x82, 0x01, 0x0a, 0x19, 0x64, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0d, 0x0a, - 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb3, 0x03, 0x0a, - 0x18, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x11, 0x61, 0x75, 0x74, - 0x6f, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x0f, 0x61, 0x75, 0x74, 0x6f, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, - 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x72, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0c, 0x68, - 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x61, 0x0a, 0x0e, 0x74, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, - 0x0a, 0x0e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, - 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x5b, 0x0a, 0x0c, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x22, 0x9d, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x6f, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x12, 0x3d, 0x0a, - 0x0b, 0x6e, 0x75, 0x6d, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x0a, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x16, - 0x72, 0x65, 0x74, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x14, 0x72, 0x65, - 0x74, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, - 0x65, 0x73, 0x22, 0x82, 0x01, 0x0a, 0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x33, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x3c, 0x0a, 0x0c, 0x69, 0x64, 0x6c, - 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x69, 0x64, 0x6c, 0x65, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0xba, 0x03, 0x0a, 0x16, 0x4c, 0x6f, 0x61, 0x64, - 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x12, 0x53, 0x0a, 0x06, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x48, 0x00, 0x52, - 0x06, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x12, 0x53, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x6c, 0x0a, 0x0f, - 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x48, 0x00, 0x52, 0x0e, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x7e, 0x0a, 0x15, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, - 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x47, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x48, 0x00, 0x52, 0x14, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x42, 0x08, 0x0a, 0x06, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x22, 0x7f, 0x0a, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x03, 0x74, 0x74, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x3e, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x46, 0x0a, 0x14, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x55, 0x0a, - 0x1a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, - 0x72, 0x74, 0x69, 0x65, 0x73, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x72, 0x6d, - 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x72, 0x6d, - 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x28, 0x0a, 0x12, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0xd6, - 0x02, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x42, 0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x45, 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, 0x65, 0x73, - 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, - 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, - 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, - 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescData = file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDesc -) - -func file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDescData -} - -var file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes = make([]protoimpl.MessageInfo, 17) -var file_pbmesh_v1alpha1_pbproxystate_route_proto_goTypes = []interface{}{ - (*Route)(nil), // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.Route - (*VirtualHost)(nil), // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.VirtualHost - (*RouteRule)(nil), // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteRule - (*RouteMatch)(nil), // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteMatch - (*PathMatch)(nil), // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.PathMatch - (*QueryParameterMatch)(nil), // 5: hashicorp.consul.mesh.v1alpha1.pbproxystate.QueryParameterMatch - (*HeaderMatch)(nil), // 6: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMatch - (*RouteDestination)(nil), // 7: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteDestination - (*DestinationConfiguration)(nil), // 8: hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationConfiguration - (*RetryPolicy)(nil), // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.RetryPolicy - (*TimeoutConfig)(nil), // 10: hashicorp.consul.mesh.v1alpha1.pbproxystate.TimeoutConfig - (*LoadBalancerHashPolicy)(nil), // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.LoadBalancerHashPolicy - (*CookiePolicy)(nil), // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.CookiePolicy - (*HeaderPolicy)(nil), // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderPolicy - (*QueryParameterPolicy)(nil), // 14: hashicorp.consul.mesh.v1alpha1.pbproxystate.QueryParameterPolicy - (*ConnectionPropertiesPolicy)(nil), // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.ConnectionPropertiesPolicy - (*DestinationCluster)(nil), // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationCluster - (*HeaderMutation)(nil), // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation - (*L7WeightedClusterGroup)(nil), // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedClusterGroup - (*wrapperspb.BoolValue)(nil), // 19: google.protobuf.BoolValue - (*wrapperspb.UInt32Value)(nil), // 20: google.protobuf.UInt32Value - (*durationpb.Duration)(nil), // 21: google.protobuf.Duration -} -var file_pbmesh_v1alpha1_pbproxystate_route_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.Route.virtual_hosts:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.VirtualHost - 17, // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.VirtualHost.header_mutations:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation - 2, // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.VirtualHost.route_rules:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteRule - 3, // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteRule.match:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteMatch - 7, // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteRule.destination:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteDestination - 17, // 5: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteRule.header_mutations:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMutation - 4, // 6: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteMatch.path_match:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.PathMatch - 6, // 7: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteMatch.header_matches:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderMatch - 5, // 8: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteMatch.query_parameter_matches:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.QueryParameterMatch - 16, // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteDestination.cluster:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationCluster - 18, // 10: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteDestination.weighted_clusters:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.L7WeightedClusterGroup - 8, // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.RouteDestination.destination_configuration:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationConfiguration - 19, // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationConfiguration.auto_host_rewrite:type_name -> google.protobuf.BoolValue - 11, // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationConfiguration.hash_policies:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LoadBalancerHashPolicy - 10, // 14: hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationConfiguration.timeout_config:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TimeoutConfig - 9, // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.DestinationConfiguration.retry_policy:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.RetryPolicy - 20, // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.RetryPolicy.num_retries:type_name -> google.protobuf.UInt32Value - 21, // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.TimeoutConfig.timeout:type_name -> google.protobuf.Duration - 21, // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.TimeoutConfig.idle_timeout:type_name -> google.protobuf.Duration - 12, // 19: hashicorp.consul.mesh.v1alpha1.pbproxystate.LoadBalancerHashPolicy.cookie:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.CookiePolicy - 13, // 20: hashicorp.consul.mesh.v1alpha1.pbproxystate.LoadBalancerHashPolicy.header:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.HeaderPolicy - 14, // 21: hashicorp.consul.mesh.v1alpha1.pbproxystate.LoadBalancerHashPolicy.query_parameter:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.QueryParameterPolicy - 15, // 22: hashicorp.consul.mesh.v1alpha1.pbproxystate.LoadBalancerHashPolicy.connection_properties:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.ConnectionPropertiesPolicy - 21, // 23: hashicorp.consul.mesh.v1alpha1.pbproxystate.CookiePolicy.ttl:type_name -> google.protobuf.Duration - 24, // [24:24] is the sub-list for method output_type - 24, // [24:24] is the sub-list for method input_type - 24, // [24:24] is the sub-list for extension type_name - 24, // [24:24] is the sub-list for extension extendee - 0, // [0:24] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_pbproxystate_route_proto_init() } -func file_pbmesh_v1alpha1_pbproxystate_route_proto_init() { - if File_pbmesh_v1alpha1_pbproxystate_route_proto != nil { - return - } - file_pbmesh_v1alpha1_pbproxystate_cluster_proto_init() - file_pbmesh_v1alpha1_pbproxystate_header_mutations_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Route); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*VirtualHost); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RouteMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PathMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryParameterMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HeaderMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RouteDestination); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationConfiguration); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RetryPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TimeoutConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LoadBalancerHashPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CookiePolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HeaderPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryParameterPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConnectionPropertiesPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationCluster); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[4].OneofWrappers = []interface{}{ - (*PathMatch_Exact)(nil), - (*PathMatch_Prefix)(nil), - (*PathMatch_Regex)(nil), - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[5].OneofWrappers = []interface{}{ - (*QueryParameterMatch_Exact)(nil), - (*QueryParameterMatch_Regex)(nil), - (*QueryParameterMatch_Present)(nil), - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[6].OneofWrappers = []interface{}{ - (*HeaderMatch_Exact)(nil), - (*HeaderMatch_Prefix)(nil), - (*HeaderMatch_Suffix)(nil), - (*HeaderMatch_Regex)(nil), - (*HeaderMatch_Present)(nil), - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[7].OneofWrappers = []interface{}{ - (*RouteDestination_Cluster)(nil), - (*RouteDestination_WeightedClusters)(nil), - } - file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes[11].OneofWrappers = []interface{}{ - (*LoadBalancerHashPolicy_Cookie)(nil), - (*LoadBalancerHashPolicy_Header)(nil), - (*LoadBalancerHashPolicy_QueryParameter)(nil), - (*LoadBalancerHashPolicy_ConnectionProperties)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDesc, - NumEnums: 0, - NumMessages: 17, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_pbproxystate_route_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_pbproxystate_route_proto_depIdxs, - MessageInfos: file_pbmesh_v1alpha1_pbproxystate_route_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_pbproxystate_route_proto = out.File - file_pbmesh_v1alpha1_pbproxystate_route_proto_rawDesc = nil - file_pbmesh_v1alpha1_pbproxystate_route_proto_goTypes = nil - file_pbmesh_v1alpha1_pbproxystate_route_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/route.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/route.proto deleted file mode 100644 index 2ec10f3737d16..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/route.proto +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1.pbproxystate; - -import "google/protobuf/duration.proto"; -import "google/protobuf/wrappers.proto"; -import "pbmesh/v1alpha1/pbproxystate/cluster.proto"; -import "pbmesh/v1alpha1/pbproxystate/header_mutations.proto"; - -message Route { - // virtual_hosts is a list of virtual hosts. A virtual host is selected based on an incoming request's host header. - repeated VirtualHost virtual_hosts = 1; -} - -message VirtualHost { - string name = 1; - // domains are used to match an incoming request's host header and determine which virtual host to use. - repeated string domains = 2; - // header_mutations to apply to the request when it matches this virtual host. These are applied after any headers in - // the RouteRule. - repeated HeaderMutation header_mutations = 3; - // route_rules are a list of rules to use for what to do next with this request. The first rule with a match will be - // used. - repeated RouteRule route_rules = 4; -} - -message RouteRule { - // match determines how to match the request. The first match determines which destination the request will go to. - RouteMatch match = 1; - // destination is where to send the request to. - RouteDestination destination = 2; - // header_mutations to apply to the request. These are applied before the VirtualHost header mutations. - repeated HeaderMutation header_mutations = 3; -} - -// RouteMatch has configuration to match a request. -message RouteMatch { - PathMatch path_match = 1; - repeated HeaderMatch header_matches = 2; - repeated string method_matches = 3; - repeated QueryParameterMatch query_parameter_matches = 4; -} - -message PathMatch { - oneof path_match { - string exact = 1; - string prefix = 2; - string regex = 3; - } -} - -message QueryParameterMatch { - string name = 1; - oneof match { - string exact = 2; - string regex = 3; - bool present = 4; - } -} - -message HeaderMatch { - string name = 1; - oneof match { - string exact = 2; - string prefix = 3; - string suffix = 4; - string regex = 5; - bool present = 6; - } - bool invert_match = 7; -} - -// RouteDestination has configuration for where to send a request. -message RouteDestination { - // destination is one or more clusters to route to. - oneof destination { - DestinationCluster cluster = 1; - L7WeightedClusterGroup weighted_clusters = 2; - } - DestinationConfiguration destination_configuration = 3; -} - -message DestinationConfiguration { - google.protobuf.BoolValue auto_host_rewrite = 1; - repeated LoadBalancerHashPolicy hash_policies = 2; - TimeoutConfig timeout_config = 3; - string prefix_rewrite = 4; - RetryPolicy retry_policy = 5; -} - -message RetryPolicy { - string retry_on = 1; - google.protobuf.UInt32Value num_retries = 2; - repeated uint32 retriable_status_codes = 3; -} - -message TimeoutConfig { - google.protobuf.Duration timeout = 1; - google.protobuf.Duration idle_timeout = 2; -} - -message LoadBalancerHashPolicy { - oneof policy { - CookiePolicy cookie = 1; - HeaderPolicy header = 2; - QueryParameterPolicy query_parameter = 3; - ConnectionPropertiesPolicy connection_properties = 4; - } -} - -message CookiePolicy { - string name = 1; - google.protobuf.Duration ttl = 2; - string path = 3; - bool terminal = 4; -} -message HeaderPolicy { - string name = 1; - bool terminal = 2; -} -message QueryParameterPolicy { - string name = 1; - bool terminal = 2; -} -message ConnectionPropertiesPolicy { - bool source_ip = 1; - bool terminal = 2; -} - -message DestinationCluster { - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - string name = 1; -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/transport_socket.pb.binary.go b/proto-public/pbmesh/v1alpha1/pbproxystate/transport_socket.pb.binary.go deleted file mode 100644 index c659541c92149..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/transport_socket.pb.binary.go +++ /dev/null @@ -1,138 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/pbproxystate/transport_socket.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TLS) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TLS) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TransportSocket) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TransportSocket) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InboundMeshMTLS) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InboundMeshMTLS) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *OutboundMeshMTLS) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *OutboundMeshMTLS) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InboundNonMeshTLS) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InboundNonMeshTLS) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *OutboundNonMeshTLS) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *OutboundNonMeshTLS) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *MeshInboundValidationContext) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *MeshInboundValidationContext) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *MeshOutboundValidationContext) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *MeshOutboundValidationContext) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *NonMeshOutboundValidationContext) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *NonMeshOutboundValidationContext) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *SDSCertificate) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *SDSCertificate) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TLSParameters) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TLSParameters) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LeafCertificate) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LeafCertificate) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TrustBundle) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TrustBundle) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/transport_socket.pb.go b/proto-public/pbmesh/v1alpha1/pbproxystate/transport_socket.pb.go deleted file mode 100644 index 816ddb717b0c6..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/transport_socket.pb.go +++ /dev/null @@ -1,1505 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/pbproxystate/transport_socket.proto - -package pbproxystate - -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 TLSVersion int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - TLSVersion_TLS_VERSION_AUTO TLSVersion = 0 - TLSVersion_TLS_VERSION_1_0 TLSVersion = 1 - TLSVersion_TLS_VERSION_1_1 TLSVersion = 2 - TLSVersion_TLS_VERSION_1_2 TLSVersion = 3 - TLSVersion_TLS_VERSION_1_3 TLSVersion = 4 - TLSVersion_TLS_VERSION_INVALID TLSVersion = 5 - TLSVersion_TLS_VERSION_UNSPECIFIED TLSVersion = 6 -) - -// Enum value maps for TLSVersion. -var ( - TLSVersion_name = map[int32]string{ - 0: "TLS_VERSION_AUTO", - 1: "TLS_VERSION_1_0", - 2: "TLS_VERSION_1_1", - 3: "TLS_VERSION_1_2", - 4: "TLS_VERSION_1_3", - 5: "TLS_VERSION_INVALID", - 6: "TLS_VERSION_UNSPECIFIED", - } - TLSVersion_value = map[string]int32{ - "TLS_VERSION_AUTO": 0, - "TLS_VERSION_1_0": 1, - "TLS_VERSION_1_1": 2, - "TLS_VERSION_1_2": 3, - "TLS_VERSION_1_3": 4, - "TLS_VERSION_INVALID": 5, - "TLS_VERSION_UNSPECIFIED": 6, - } -) - -func (x TLSVersion) Enum() *TLSVersion { - p := new(TLSVersion) - *p = x - return p -} - -func (x TLSVersion) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (TLSVersion) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_enumTypes[0].Descriptor() -} - -func (TLSVersion) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_enumTypes[0] -} - -func (x TLSVersion) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use TLSVersion.Descriptor instead. -func (TLSVersion) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{0} -} - -type TLSCipherSuite int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256 TLSCipherSuite = 0 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305 TLSCipherSuite = 1 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256 TLSCipherSuite = 2 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305 TLSCipherSuite = 3 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA TLSCipherSuite = 4 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA TLSCipherSuite = 5 - TLSCipherSuite_TLS_CIPHER_SUITE_AES128_GCM_SHA256 TLSCipherSuite = 6 - TLSCipherSuite_TLS_CIPHER_SUITE_AES128_SHA TLSCipherSuite = 7 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384 TLSCipherSuite = 8 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384 TLSCipherSuite = 9 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA TLSCipherSuite = 10 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA TLSCipherSuite = 11 - TLSCipherSuite_TLS_CIPHER_SUITE_AES256_GCM_SHA384 TLSCipherSuite = 12 - TLSCipherSuite_TLS_CIPHER_SUITE_AES256_SHA TLSCipherSuite = 13 -) - -// Enum value maps for TLSCipherSuite. -var ( - TLSCipherSuite_name = map[int32]string{ - 0: "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256", - 1: "TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305", - 2: "TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256", - 3: "TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305", - 4: "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA", - 5: "TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA", - 6: "TLS_CIPHER_SUITE_AES128_GCM_SHA256", - 7: "TLS_CIPHER_SUITE_AES128_SHA", - 8: "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384", - 9: "TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384", - 10: "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA", - 11: "TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA", - 12: "TLS_CIPHER_SUITE_AES256_GCM_SHA384", - 13: "TLS_CIPHER_SUITE_AES256_SHA", - } - TLSCipherSuite_value = map[string]int32{ - "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256": 0, - "TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305": 1, - "TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256": 2, - "TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305": 3, - "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA": 4, - "TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA": 5, - "TLS_CIPHER_SUITE_AES128_GCM_SHA256": 6, - "TLS_CIPHER_SUITE_AES128_SHA": 7, - "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384": 8, - "TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384": 9, - "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA": 10, - "TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA": 11, - "TLS_CIPHER_SUITE_AES256_GCM_SHA384": 12, - "TLS_CIPHER_SUITE_AES256_SHA": 13, - } -) - -func (x TLSCipherSuite) Enum() *TLSCipherSuite { - p := new(TLSCipherSuite) - *p = x - return p -} - -func (x TLSCipherSuite) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (TLSCipherSuite) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_enumTypes[1].Descriptor() -} - -func (TLSCipherSuite) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_enumTypes[1] -} - -func (x TLSCipherSuite) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use TLSCipherSuite.Descriptor instead. -func (TLSCipherSuite) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{1} -} - -type TLS struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // inbound_tls_parameters has default TLS parameter configuration for inbound connections. These can be overridden per - // transport socket. - InboundTlsParameters *TLSParameters `protobuf:"bytes,1,opt,name=inbound_tls_parameters,json=inboundTlsParameters,proto3" json:"inbound_tls_parameters,omitempty"` - // outbound_tls_parameters has default TLS parameter configuration for inbound connections. These can be overridden per transport socket. - OutboundTlsParameters *TLSParameters `protobuf:"bytes,2,opt,name=outbound_tls_parameters,json=outboundTlsParameters,proto3" json:"outbound_tls_parameters,omitempty"` -} - -func (x *TLS) Reset() { - *x = TLS{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TLS) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TLS) ProtoMessage() {} - -func (x *TLS) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_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 TLS.ProtoReflect.Descriptor instead. -func (*TLS) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{0} -} - -func (x *TLS) GetInboundTlsParameters() *TLSParameters { - if x != nil { - return x.InboundTlsParameters - } - return nil -} - -func (x *TLS) GetOutboundTlsParameters() *TLSParameters { - if x != nil { - return x.OutboundTlsParameters - } - return nil -} - -type TransportSocket struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name of the transport socket - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Types that are assignable to ConnectionTls: - // - // *TransportSocket_InboundMesh - // *TransportSocket_OutboundMesh - // *TransportSocket_InboundNonMesh - // *TransportSocket_OutboundNonMesh - ConnectionTls isTransportSocket_ConnectionTls `protobuf_oneof:"connection_tls"` - // tls_parameters can override any top level tls parameters that are configured. - TlsParameters *TLSParameters `protobuf:"bytes,6,opt,name=tls_parameters,json=tlsParameters,proto3" json:"tls_parameters,omitempty"` - AlpnProtocols []string `protobuf:"bytes,7,rep,name=alpn_protocols,json=alpnProtocols,proto3" json:"alpn_protocols,omitempty"` -} - -func (x *TransportSocket) Reset() { - *x = TransportSocket{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TransportSocket) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TransportSocket) ProtoMessage() {} - -func (x *TransportSocket) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_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 TransportSocket.ProtoReflect.Descriptor instead. -func (*TransportSocket) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{1} -} - -func (x *TransportSocket) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (m *TransportSocket) GetConnectionTls() isTransportSocket_ConnectionTls { - if m != nil { - return m.ConnectionTls - } - return nil -} - -func (x *TransportSocket) GetInboundMesh() *InboundMeshMTLS { - if x, ok := x.GetConnectionTls().(*TransportSocket_InboundMesh); ok { - return x.InboundMesh - } - return nil -} - -func (x *TransportSocket) GetOutboundMesh() *OutboundMeshMTLS { - if x, ok := x.GetConnectionTls().(*TransportSocket_OutboundMesh); ok { - return x.OutboundMesh - } - return nil -} - -func (x *TransportSocket) GetInboundNonMesh() *InboundNonMeshTLS { - if x, ok := x.GetConnectionTls().(*TransportSocket_InboundNonMesh); ok { - return x.InboundNonMesh - } - return nil -} - -func (x *TransportSocket) GetOutboundNonMesh() *OutboundNonMeshTLS { - if x, ok := x.GetConnectionTls().(*TransportSocket_OutboundNonMesh); ok { - return x.OutboundNonMesh - } - return nil -} - -func (x *TransportSocket) GetTlsParameters() *TLSParameters { - if x != nil { - return x.TlsParameters - } - return nil -} - -func (x *TransportSocket) GetAlpnProtocols() []string { - if x != nil { - return x.AlpnProtocols - } - return nil -} - -type isTransportSocket_ConnectionTls interface { - isTransportSocket_ConnectionTls() -} - -type TransportSocket_InboundMesh struct { - // inbound_mesh is for incoming connections FROM the mesh. - InboundMesh *InboundMeshMTLS `protobuf:"bytes,2,opt,name=inbound_mesh,json=inboundMesh,proto3,oneof"` -} - -type TransportSocket_OutboundMesh struct { - // outbound_mesh is for outbound connections TO mesh destinations. - OutboundMesh *OutboundMeshMTLS `protobuf:"bytes,3,opt,name=outbound_mesh,json=outboundMesh,proto3,oneof"` -} - -type TransportSocket_InboundNonMesh struct { - // inbound_non_mesh is for incoming connections FROM non mesh. - InboundNonMesh *InboundNonMeshTLS `protobuf:"bytes,4,opt,name=inbound_non_mesh,json=inboundNonMesh,proto3,oneof"` -} - -type TransportSocket_OutboundNonMesh struct { - // outbound_non_mesh is for outbound connections TO non mesh destinations. - OutboundNonMesh *OutboundNonMeshTLS `protobuf:"bytes,5,opt,name=outbound_non_mesh,json=outboundNonMesh,proto3,oneof"` -} - -func (*TransportSocket_InboundMesh) isTransportSocket_ConnectionTls() {} - -func (*TransportSocket_OutboundMesh) isTransportSocket_ConnectionTls() {} - -func (*TransportSocket_InboundNonMesh) isTransportSocket_ConnectionTls() {} - -func (*TransportSocket_OutboundNonMesh) isTransportSocket_ConnectionTls() {} - -type InboundMeshMTLS struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // identity_key is UUID key to use to look up the leaf certificate in ProxyState to present for incoming connections. - IdentityKey string `protobuf:"bytes,1,opt,name=identity_key,json=identityKey,proto3" json:"identity_key,omitempty"` - // validation_context has what is needed to validate incoming connections. - ValidationContext *MeshInboundValidationContext `protobuf:"bytes,2,opt,name=validation_context,json=validationContext,proto3" json:"validation_context,omitempty"` -} - -func (x *InboundMeshMTLS) Reset() { - *x = InboundMeshMTLS{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InboundMeshMTLS) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InboundMeshMTLS) ProtoMessage() {} - -func (x *InboundMeshMTLS) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_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 InboundMeshMTLS.ProtoReflect.Descriptor instead. -func (*InboundMeshMTLS) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{2} -} - -func (x *InboundMeshMTLS) GetIdentityKey() string { - if x != nil { - return x.IdentityKey - } - return "" -} - -func (x *InboundMeshMTLS) GetValidationContext() *MeshInboundValidationContext { - if x != nil { - return x.ValidationContext - } - return nil -} - -type OutboundMeshMTLS struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // identity_key is UUID key to use to look up the leaf certificate in ProxyState when connecting to destinations. - IdentityKey string `protobuf:"bytes,1,opt,name=identity_key,json=identityKey,proto3" json:"identity_key,omitempty"` - // validation_context has what is needed to validate the destination. - ValidationContext *MeshOutboundValidationContext `protobuf:"bytes,2,opt,name=validation_context,json=validationContext,proto3" json:"validation_context,omitempty"` - // sni to use when connecting to the destination. - Sni string `protobuf:"bytes,3,opt,name=sni,proto3" json:"sni,omitempty"` -} - -func (x *OutboundMeshMTLS) Reset() { - *x = OutboundMeshMTLS{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OutboundMeshMTLS) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OutboundMeshMTLS) ProtoMessage() {} - -func (x *OutboundMeshMTLS) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[3] - 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 OutboundMeshMTLS.ProtoReflect.Descriptor instead. -func (*OutboundMeshMTLS) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{3} -} - -func (x *OutboundMeshMTLS) GetIdentityKey() string { - if x != nil { - return x.IdentityKey - } - return "" -} - -func (x *OutboundMeshMTLS) GetValidationContext() *MeshOutboundValidationContext { - if x != nil { - return x.ValidationContext - } - return nil -} - -func (x *OutboundMeshMTLS) GetSni() string { - if x != nil { - return x.Sni - } - return "" -} - -type InboundNonMeshTLS struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // identity is the reference to the leaf certificate to present for incoming connections. - // - // Types that are assignable to Identity: - // - // *InboundNonMeshTLS_LeafKey - // *InboundNonMeshTLS_Sds - Identity isInboundNonMeshTLS_Identity `protobuf_oneof:"identity"` -} - -func (x *InboundNonMeshTLS) Reset() { - *x = InboundNonMeshTLS{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InboundNonMeshTLS) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InboundNonMeshTLS) ProtoMessage() {} - -func (x *InboundNonMeshTLS) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[4] - 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 InboundNonMeshTLS.ProtoReflect.Descriptor instead. -func (*InboundNonMeshTLS) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{4} -} - -func (m *InboundNonMeshTLS) GetIdentity() isInboundNonMeshTLS_Identity { - if m != nil { - return m.Identity - } - return nil -} - -func (x *InboundNonMeshTLS) GetLeafKey() string { - if x, ok := x.GetIdentity().(*InboundNonMeshTLS_LeafKey); ok { - return x.LeafKey - } - return "" -} - -func (x *InboundNonMeshTLS) GetSds() *SDSCertificate { - if x, ok := x.GetIdentity().(*InboundNonMeshTLS_Sds); ok { - return x.Sds - } - return nil -} - -type isInboundNonMeshTLS_Identity interface { - isInboundNonMeshTLS_Identity() -} - -type InboundNonMeshTLS_LeafKey struct { - // leaf_key is the UUID key to use to look up the leaf certificate in the ProxyState leaf certificate map. - LeafKey string `protobuf:"bytes,1,opt,name=leaf_key,json=leafKey,proto3,oneof"` -} - -type InboundNonMeshTLS_Sds struct { - // sds refers to certificates retrieved via Envoy SDS. - Sds *SDSCertificate `protobuf:"bytes,2,opt,name=sds,proto3,oneof"` -} - -func (*InboundNonMeshTLS_LeafKey) isInboundNonMeshTLS_Identity() {} - -func (*InboundNonMeshTLS_Sds) isInboundNonMeshTLS_Identity() {} - -type OutboundNonMeshTLS struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // cert_file is a filename for a certificate to present for outbound connections. - CertFile string `protobuf:"bytes,1,opt,name=cert_file,json=certFile,proto3" json:"cert_file,omitempty"` - // key_file is a filename for a key for outbound connections. - KeyFile string `protobuf:"bytes,2,opt,name=key_file,json=keyFile,proto3" json:"key_file,omitempty"` - // validation_context has what is needed to validate the destination. - ValidationContext *NonMeshOutboundValidationContext `protobuf:"bytes,3,opt,name=validation_context,json=validationContext,proto3" json:"validation_context,omitempty"` -} - -func (x *OutboundNonMeshTLS) Reset() { - *x = OutboundNonMeshTLS{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OutboundNonMeshTLS) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OutboundNonMeshTLS) ProtoMessage() {} - -func (x *OutboundNonMeshTLS) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[5] - 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 OutboundNonMeshTLS.ProtoReflect.Descriptor instead. -func (*OutboundNonMeshTLS) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{5} -} - -func (x *OutboundNonMeshTLS) GetCertFile() string { - if x != nil { - return x.CertFile - } - return "" -} - -func (x *OutboundNonMeshTLS) GetKeyFile() string { - if x != nil { - return x.KeyFile - } - return "" -} - -func (x *OutboundNonMeshTLS) GetValidationContext() *NonMeshOutboundValidationContext { - if x != nil { - return x.ValidationContext - } - return nil -} - -type MeshInboundValidationContext struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // trust_bundle_peer_name_keys is which trust bundles to use for validating incoming connections. If this workload is exported - // to peers, the incoming connection could be from a different peer, requiring that trust bundle to validate the - // connection. These could be local or peered trust bundles. This will be a key in the trust bundle map. - TrustBundlePeerNameKeys []string `protobuf:"bytes,1,rep,name=trust_bundle_peer_name_keys,json=trustBundlePeerNameKeys,proto3" json:"trust_bundle_peer_name_keys,omitempty"` -} - -func (x *MeshInboundValidationContext) Reset() { - *x = MeshInboundValidationContext{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MeshInboundValidationContext) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MeshInboundValidationContext) ProtoMessage() {} - -func (x *MeshInboundValidationContext) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[6] - 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 MeshInboundValidationContext.ProtoReflect.Descriptor instead. -func (*MeshInboundValidationContext) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{6} -} - -func (x *MeshInboundValidationContext) GetTrustBundlePeerNameKeys() []string { - if x != nil { - return x.TrustBundlePeerNameKeys - } - return nil -} - -type MeshOutboundValidationContext struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // trust_bundle_peer_name_key is which trust bundle to use for the destination. It could be the local or a peer's trust bundle. - // This will be a key in the trust bundle map. - TrustBundlePeerNameKey string `protobuf:"bytes,1,opt,name=trust_bundle_peer_name_key,json=trustBundlePeerNameKey,proto3" json:"trust_bundle_peer_name_key,omitempty"` - // spiffe_ids is one or more spiffe IDs to validate. - SpiffeIds []string `protobuf:"bytes,2,rep,name=spiffe_ids,json=spiffeIds,proto3" json:"spiffe_ids,omitempty"` -} - -func (x *MeshOutboundValidationContext) Reset() { - *x = MeshOutboundValidationContext{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MeshOutboundValidationContext) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MeshOutboundValidationContext) ProtoMessage() {} - -func (x *MeshOutboundValidationContext) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[7] - 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 MeshOutboundValidationContext.ProtoReflect.Descriptor instead. -func (*MeshOutboundValidationContext) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{7} -} - -func (x *MeshOutboundValidationContext) GetTrustBundlePeerNameKey() string { - if x != nil { - return x.TrustBundlePeerNameKey - } - return "" -} - -func (x *MeshOutboundValidationContext) GetSpiffeIds() []string { - if x != nil { - return x.SpiffeIds - } - return nil -} - -type NonMeshOutboundValidationContext struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ca_file is a filename for a ca for outbound connections to validate the destination. - CaFile string `protobuf:"bytes,1,opt,name=ca_file,json=caFile,proto3" json:"ca_file,omitempty"` -} - -func (x *NonMeshOutboundValidationContext) Reset() { - *x = NonMeshOutboundValidationContext{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NonMeshOutboundValidationContext) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NonMeshOutboundValidationContext) ProtoMessage() {} - -func (x *NonMeshOutboundValidationContext) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[8] - 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 NonMeshOutboundValidationContext.ProtoReflect.Descriptor instead. -func (*NonMeshOutboundValidationContext) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{8} -} - -func (x *NonMeshOutboundValidationContext) GetCaFile() string { - if x != nil { - return x.CaFile - } - return "" -} - -type SDSCertificate struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ClusterName string `protobuf:"bytes,1,opt,name=cluster_name,json=clusterName,proto3" json:"cluster_name,omitempty"` - CertResource string `protobuf:"bytes,2,opt,name=cert_resource,json=certResource,proto3" json:"cert_resource,omitempty"` -} - -func (x *SDSCertificate) Reset() { - *x = SDSCertificate{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SDSCertificate) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SDSCertificate) ProtoMessage() {} - -func (x *SDSCertificate) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[9] - 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 SDSCertificate.ProtoReflect.Descriptor instead. -func (*SDSCertificate) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{9} -} - -func (x *SDSCertificate) GetClusterName() string { - if x != nil { - return x.ClusterName - } - return "" -} - -func (x *SDSCertificate) GetCertResource() string { - if x != nil { - return x.CertResource - } - return "" -} - -type TLSParameters struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MinVersion TLSVersion `protobuf:"varint,1,opt,name=min_version,json=minVersion,proto3,enum=hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSVersion" json:"min_version,omitempty"` - MaxVersion TLSVersion `protobuf:"varint,2,opt,name=max_version,json=maxVersion,proto3,enum=hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSVersion" json:"max_version,omitempty"` - CipherSuites []TLSCipherSuite `protobuf:"varint,3,rep,packed,name=cipher_suites,json=cipherSuites,proto3,enum=hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSCipherSuite" json:"cipher_suites,omitempty"` -} - -func (x *TLSParameters) Reset() { - *x = TLSParameters{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TLSParameters) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TLSParameters) ProtoMessage() {} - -func (x *TLSParameters) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[10] - 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 TLSParameters.ProtoReflect.Descriptor instead. -func (*TLSParameters) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{10} -} - -func (x *TLSParameters) GetMinVersion() TLSVersion { - if x != nil { - return x.MinVersion - } - return TLSVersion_TLS_VERSION_AUTO -} - -func (x *TLSParameters) GetMaxVersion() TLSVersion { - if x != nil { - return x.MaxVersion - } - return TLSVersion_TLS_VERSION_AUTO -} - -func (x *TLSParameters) GetCipherSuites() []TLSCipherSuite { - if x != nil { - return x.CipherSuites - } - return nil -} - -type LeafCertificate struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Cert string `protobuf:"bytes,1,opt,name=cert,proto3" json:"cert,omitempty"` - Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` -} - -func (x *LeafCertificate) Reset() { - *x = LeafCertificate{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LeafCertificate) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LeafCertificate) ProtoMessage() {} - -func (x *LeafCertificate) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[11] - 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 LeafCertificate.ProtoReflect.Descriptor instead. -func (*LeafCertificate) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{11} -} - -func (x *LeafCertificate) GetCert() string { - if x != nil { - return x.Cert - } - return "" -} - -func (x *LeafCertificate) GetKey() string { - if x != nil { - return x.Key - } - return "" -} - -type TrustBundle struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TrustDomain string `protobuf:"bytes,1,opt,name=trust_domain,json=trustDomain,proto3" json:"trust_domain,omitempty"` - Roots []string `protobuf:"bytes,2,rep,name=roots,proto3" json:"roots,omitempty"` -} - -func (x *TrustBundle) Reset() { - *x = TrustBundle{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TrustBundle) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TrustBundle) ProtoMessage() {} - -func (x *TrustBundle) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[12] - 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 TrustBundle.ProtoReflect.Descriptor instead. -func (*TrustBundle) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{12} -} - -func (x *TrustBundle) GetTrustDomain() string { - if x != nil { - return x.TrustDomain - } - return "" -} - -func (x *TrustBundle) GetRoots() []string { - if x != nil { - return x.Roots - } - return nil -} - -var File_pbmesh_v1alpha1_pbproxystate_transport_socket_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDesc = []byte{ - 0x0a, 0x33, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x74, - 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2b, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x22, 0xeb, 0x01, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x70, 0x0a, 0x16, 0x69, 0x6e, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x4c, 0x53, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x14, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, - 0x6c, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x72, 0x0a, 0x17, - 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x70, 0x61, 0x72, - 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x4c, 0x53, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x15, 0x6f, 0x75, 0x74, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x54, 0x6c, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, - 0x22, 0xe5, 0x04, 0x0a, 0x0f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x6f, - 0x63, 0x6b, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x61, 0x0a, 0x0c, 0x69, 0x6e, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x49, 0x6e, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, 0x4d, 0x54, 0x4c, 0x53, 0x48, 0x00, 0x52, 0x0b, - 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, 0x12, 0x64, 0x0a, 0x0d, 0x6f, - 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, 0x4d, 0x54, 0x4c, - 0x53, 0x48, 0x00, 0x52, 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4d, 0x65, 0x73, - 0x68, 0x12, 0x6a, 0x0a, 0x10, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x6e, 0x6f, 0x6e, - 0x5f, 0x6d, 0x65, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x4e, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x54, 0x4c, 0x53, 0x48, 0x00, 0x52, 0x0e, 0x69, - 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4e, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x12, 0x6d, 0x0a, - 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x6e, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, - 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4e, - 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x54, 0x4c, 0x53, 0x48, 0x00, 0x52, 0x0f, 0x6f, 0x75, 0x74, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4e, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x12, 0x61, 0x0a, 0x0e, - 0x74, 0x6c, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x54, 0x4c, 0x53, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, - 0x52, 0x0d, 0x74, 0x6c, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, - 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x70, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x6c, 0x70, 0x6e, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x10, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6c, 0x73, 0x22, 0xae, 0x01, 0x0a, 0x0f, 0x49, 0x6e, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, 0x4d, 0x54, 0x4c, 0x53, 0x12, 0x21, 0x0a, 0x0c, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4b, 0x65, 0x79, 0x12, - 0x78, 0x0a, 0x12, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x49, 0x6e, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xc2, 0x01, 0x0a, 0x10, 0x4f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, 0x4d, 0x54, 0x4c, 0x53, 0x12, 0x21, - 0x0a, 0x0c, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4b, 0x65, - 0x79, 0x12, 0x79, 0x0a, 0x12, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4a, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x68, - 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x10, 0x0a, 0x03, - 0x73, 0x6e, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x6e, 0x69, 0x22, 0x8d, - 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4e, 0x6f, 0x6e, 0x4d, 0x65, 0x73, - 0x68, 0x54, 0x4c, 0x53, 0x12, 0x1b, 0x0a, 0x08, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x6c, 0x65, 0x61, 0x66, 0x4b, 0x65, - 0x79, 0x12, 0x4f, 0x0a, 0x03, 0x73, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x44, 0x53, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x03, 0x73, - 0x64, 0x73, 0x42, 0x0a, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0xca, - 0x01, 0x0a, 0x12, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4e, 0x6f, 0x6e, 0x4d, 0x65, - 0x73, 0x68, 0x54, 0x4c, 0x53, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x66, 0x69, - 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x65, 0x72, 0x74, 0x46, 0x69, - 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x7c, 0x0a, - 0x12, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4d, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4e, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x4f, - 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x5c, 0x0a, 0x1c, 0x4d, - 0x65, 0x73, 0x68, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x3c, 0x0a, 0x1b, 0x74, - 0x72, 0x75, 0x73, 0x74, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x70, 0x65, 0x65, 0x72, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x17, 0x74, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x50, 0x65, 0x65, - 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x22, 0x7a, 0x0a, 0x1d, 0x4d, 0x65, 0x73, - 0x68, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x3a, 0x0a, 0x1a, 0x74, 0x72, - 0x75, 0x73, 0x74, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, - 0x74, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x50, 0x65, 0x65, 0x72, 0x4e, - 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x70, 0x69, 0x66, 0x66, 0x65, - 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x73, 0x70, 0x69, 0x66, - 0x66, 0x65, 0x49, 0x64, 0x73, 0x22, 0x3b, 0x0a, 0x20, 0x4e, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x68, - 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x61, 0x5f, - 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x46, 0x69, - 0x6c, 0x65, 0x22, 0x58, 0x0a, 0x0e, 0x53, 0x44, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x65, 0x72, 0x74, 0x5f, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x63, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xa5, 0x02, 0x0a, - 0x0d, 0x54, 0x4c, 0x53, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x58, - 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6d, 0x69, - 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x58, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x37, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x4c, 0x53, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x60, 0x0a, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, - 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x4c, 0x53, 0x43, 0x69, 0x70, 0x68, 0x65, - 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x52, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, - 0x69, 0x74, 0x65, 0x73, 0x22, 0x37, 0x0a, 0x0f, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x46, 0x0a, - 0x0b, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x0c, - 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x74, 0x72, 0x75, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, - 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, - 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x2a, 0xac, 0x01, 0x0a, 0x0a, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x4c, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, - 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x55, 0x54, 0x4f, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x4c, - 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x5f, 0x30, 0x10, 0x01, 0x12, - 0x13, 0x0a, 0x0f, 0x54, 0x4c, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x31, - 0x5f, 0x31, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x4c, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, - 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x5f, 0x32, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x4c, 0x53, - 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x5f, 0x33, 0x10, 0x04, 0x12, 0x17, - 0x0a, 0x13, 0x54, 0x4c, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, - 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x05, 0x12, 0x1b, 0x0a, 0x17, 0x54, 0x4c, 0x53, 0x5f, 0x56, - 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x06, 0x2a, 0x84, 0x05, 0x0a, 0x0e, 0x54, 0x4c, 0x53, 0x43, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x32, 0x0a, 0x2e, 0x54, 0x4c, 0x53, 0x5f, 0x43, - 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, - 0x45, 0x5f, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x41, 0x45, 0x53, 0x31, 0x32, 0x38, 0x5f, 0x47, - 0x43, 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x00, 0x12, 0x32, 0x0a, 0x2e, 0x54, - 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, - 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x43, 0x48, 0x41, 0x43, - 0x48, 0x41, 0x32, 0x30, 0x5f, 0x50, 0x4f, 0x4c, 0x59, 0x31, 0x33, 0x30, 0x35, 0x10, 0x01, 0x12, - 0x30, 0x0a, 0x2c, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, - 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x41, 0x45, - 0x53, 0x31, 0x32, 0x38, 0x5f, 0x47, 0x43, 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, - 0x02, 0x12, 0x30, 0x0a, 0x2c, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, - 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x52, 0x53, 0x41, 0x5f, - 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x50, 0x4f, 0x4c, 0x59, 0x31, 0x33, 0x30, - 0x35, 0x10, 0x03, 0x12, 0x2b, 0x0a, 0x27, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, - 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x45, 0x43, - 0x44, 0x53, 0x41, 0x5f, 0x41, 0x45, 0x53, 0x31, 0x32, 0x38, 0x5f, 0x53, 0x48, 0x41, 0x10, 0x04, - 0x12, 0x29, 0x0a, 0x25, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, - 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x41, - 0x45, 0x53, 0x31, 0x32, 0x38, 0x5f, 0x53, 0x48, 0x41, 0x10, 0x05, 0x12, 0x26, 0x0a, 0x22, 0x54, - 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, - 0x41, 0x45, 0x53, 0x31, 0x32, 0x38, 0x5f, 0x47, 0x43, 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, - 0x36, 0x10, 0x06, 0x12, 0x1f, 0x0a, 0x1b, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, - 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x41, 0x45, 0x53, 0x31, 0x32, 0x38, 0x5f, 0x53, - 0x48, 0x41, 0x10, 0x07, 0x12, 0x32, 0x0a, 0x2e, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, - 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x45, - 0x43, 0x44, 0x53, 0x41, 0x5f, 0x41, 0x45, 0x53, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x43, 0x4d, 0x5f, - 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x08, 0x12, 0x30, 0x0a, 0x2c, 0x54, 0x4c, 0x53, 0x5f, - 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, - 0x48, 0x45, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x41, 0x45, 0x53, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x43, - 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x09, 0x12, 0x2b, 0x0a, 0x27, 0x54, 0x4c, - 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, - 0x43, 0x44, 0x48, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x41, 0x45, 0x53, 0x32, 0x35, - 0x36, 0x5f, 0x53, 0x48, 0x41, 0x10, 0x0a, 0x12, 0x29, 0x0a, 0x25, 0x54, 0x4c, 0x53, 0x5f, 0x43, - 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, - 0x45, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x41, 0x45, 0x53, 0x32, 0x35, 0x36, 0x5f, 0x53, 0x48, 0x41, - 0x10, 0x0b, 0x12, 0x26, 0x0a, 0x22, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, - 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x41, 0x45, 0x53, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x43, - 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x0c, 0x12, 0x1f, 0x0a, 0x1b, 0x54, 0x4c, - 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x41, - 0x45, 0x53, 0x32, 0x35, 0x36, 0x5f, 0x53, 0x48, 0x41, 0x10, 0x0d, 0x42, 0xe0, 0x02, 0x0a, 0x2f, - 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, - 0x14, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, - 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0xe2, 0x02, 0x37, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2f, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescData = file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDesc -) - -func file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDescData -} - -var file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes = make([]protoimpl.MessageInfo, 13) -var file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_goTypes = []interface{}{ - (TLSVersion)(0), // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSVersion - (TLSCipherSuite)(0), // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSCipherSuite - (*TLS)(nil), // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.TLS - (*TransportSocket)(nil), // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket - (*InboundMeshMTLS)(nil), // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.InboundMeshMTLS - (*OutboundMeshMTLS)(nil), // 5: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutboundMeshMTLS - (*InboundNonMeshTLS)(nil), // 6: hashicorp.consul.mesh.v1alpha1.pbproxystate.InboundNonMeshTLS - (*OutboundNonMeshTLS)(nil), // 7: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutboundNonMeshTLS - (*MeshInboundValidationContext)(nil), // 8: hashicorp.consul.mesh.v1alpha1.pbproxystate.MeshInboundValidationContext - (*MeshOutboundValidationContext)(nil), // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.MeshOutboundValidationContext - (*NonMeshOutboundValidationContext)(nil), // 10: hashicorp.consul.mesh.v1alpha1.pbproxystate.NonMeshOutboundValidationContext - (*SDSCertificate)(nil), // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.SDSCertificate - (*TLSParameters)(nil), // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSParameters - (*LeafCertificate)(nil), // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.LeafCertificate - (*TrustBundle)(nil), // 14: hashicorp.consul.mesh.v1alpha1.pbproxystate.TrustBundle -} -var file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_depIdxs = []int32{ - 12, // 0: hashicorp.consul.mesh.v1alpha1.pbproxystate.TLS.inbound_tls_parameters:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSParameters - 12, // 1: hashicorp.consul.mesh.v1alpha1.pbproxystate.TLS.outbound_tls_parameters:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSParameters - 4, // 2: hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket.inbound_mesh:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.InboundMeshMTLS - 5, // 3: hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket.outbound_mesh:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.OutboundMeshMTLS - 6, // 4: hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket.inbound_non_mesh:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.InboundNonMeshTLS - 7, // 5: hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket.outbound_non_mesh:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.OutboundNonMeshTLS - 12, // 6: hashicorp.consul.mesh.v1alpha1.pbproxystate.TransportSocket.tls_parameters:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSParameters - 8, // 7: hashicorp.consul.mesh.v1alpha1.pbproxystate.InboundMeshMTLS.validation_context:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.MeshInboundValidationContext - 9, // 8: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutboundMeshMTLS.validation_context:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.MeshOutboundValidationContext - 11, // 9: hashicorp.consul.mesh.v1alpha1.pbproxystate.InboundNonMeshTLS.sds:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.SDSCertificate - 10, // 10: hashicorp.consul.mesh.v1alpha1.pbproxystate.OutboundNonMeshTLS.validation_context:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.NonMeshOutboundValidationContext - 0, // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSParameters.min_version:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSVersion - 0, // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSParameters.max_version:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSVersion - 1, // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSParameters.cipher_suites:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TLSCipherSuite - 14, // [14:14] is the sub-list for method output_type - 14, // [14:14] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_init() } -func file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_init() { - if File_pbmesh_v1alpha1_pbproxystate_transport_socket_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TLS); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransportSocket); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InboundMeshMTLS); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OutboundMeshMTLS); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InboundNonMeshTLS); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OutboundNonMeshTLS); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MeshInboundValidationContext); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MeshOutboundValidationContext); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NonMeshOutboundValidationContext); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SDSCertificate); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TLSParameters); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LeafCertificate); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TrustBundle); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*TransportSocket_InboundMesh)(nil), - (*TransportSocket_OutboundMesh)(nil), - (*TransportSocket_InboundNonMesh)(nil), - (*TransportSocket_OutboundNonMesh)(nil), - } - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes[4].OneofWrappers = []interface{}{ - (*InboundNonMeshTLS_LeafKey)(nil), - (*InboundNonMeshTLS_Sds)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDesc, - NumEnums: 2, - NumMessages: 13, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_depIdxs, - EnumInfos: file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_enumTypes, - MessageInfos: file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_pbproxystate_transport_socket_proto = out.File - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_rawDesc = nil - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_goTypes = nil - file_pbmesh_v1alpha1_pbproxystate_transport_socket_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/pbproxystate/transport_socket.proto b/proto-public/pbmesh/v1alpha1/pbproxystate/transport_socket.proto deleted file mode 100644 index 4d191ba580dd8..0000000000000 --- a/proto-public/pbmesh/v1alpha1/pbproxystate/transport_socket.proto +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1.pbproxystate; - -message TLS { - // inbound_tls_parameters has default TLS parameter configuration for inbound connections. These can be overridden per - // transport socket. - TLSParameters inbound_tls_parameters = 1; - // outbound_tls_parameters has default TLS parameter configuration for inbound connections. These can be overridden per transport socket. - TLSParameters outbound_tls_parameters = 2; -} - -message TransportSocket { - // name of the transport socket - string name = 1; - oneof connection_tls { - // inbound_mesh is for incoming connections FROM the mesh. - InboundMeshMTLS inbound_mesh = 2; - // outbound_mesh is for outbound connections TO mesh destinations. - OutboundMeshMTLS outbound_mesh = 3; - // inbound_non_mesh is for incoming connections FROM non mesh. - InboundNonMeshTLS inbound_non_mesh = 4; - // outbound_non_mesh is for outbound connections TO non mesh destinations. - OutboundNonMeshTLS outbound_non_mesh = 5; - } - // tls_parameters can override any top level tls parameters that are configured. - TLSParameters tls_parameters = 6; - repeated string alpn_protocols = 7; -} - -message InboundMeshMTLS { - // identity_key is UUID key to use to look up the leaf certificate in ProxyState to present for incoming connections. - string identity_key = 1; - // validation_context has what is needed to validate incoming connections. - MeshInboundValidationContext validation_context = 2; -} - -message OutboundMeshMTLS { - // identity_key is UUID key to use to look up the leaf certificate in ProxyState when connecting to destinations. - string identity_key = 1; - // validation_context has what is needed to validate the destination. - MeshOutboundValidationContext validation_context = 2; - // sni to use when connecting to the destination. - string sni = 3; -} - -message InboundNonMeshTLS { - // identity is the reference to the leaf certificate to present for incoming connections. - oneof identity { - // leaf_key is the UUID key to use to look up the leaf certificate in the ProxyState leaf certificate map. - string leaf_key = 1; - // sds refers to certificates retrieved via Envoy SDS. - SDSCertificate sds = 2; - } -} - -message OutboundNonMeshTLS { - // cert_file is a filename for a certificate to present for outbound connections. - string cert_file = 1; - // key_file is a filename for a key for outbound connections. - string key_file = 2; - // validation_context has what is needed to validate the destination. - NonMeshOutboundValidationContext validation_context = 3; -} - -message MeshInboundValidationContext { - // trust_bundle_peer_name_keys is which trust bundles to use for validating incoming connections. If this workload is exported - // to peers, the incoming connection could be from a different peer, requiring that trust bundle to validate the - // connection. These could be local or peered trust bundles. This will be a key in the trust bundle map. - repeated string trust_bundle_peer_name_keys = 1; -} - -message MeshOutboundValidationContext { - // trust_bundle_peer_name_key is which trust bundle to use for the destination. It could be the local or a peer's trust bundle. - // This will be a key in the trust bundle map. - string trust_bundle_peer_name_key = 1; - // spiffe_ids is one or more spiffe IDs to validate. - repeated string spiffe_ids = 2; -} - -message NonMeshOutboundValidationContext { - // ca_file is a filename for a ca for outbound connections to validate the destination. - string ca_file = 1; -} - -message SDSCertificate { - string cluster_name = 1; - string cert_resource = 2; -} - -message TLSParameters { - TLSVersion min_version = 1; - TLSVersion max_version = 2; - repeated TLSCipherSuite cipher_suites = 3; -} - -message LeafCertificate { - string cert = 1; - string key = 2; -} - -message TrustBundle { - string trust_domain = 1; - repeated string roots = 2; -} - -enum TLSVersion { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - TLS_VERSION_AUTO = 0; - TLS_VERSION_1_0 = 1; - TLS_VERSION_1_1 = 2; - TLS_VERSION_1_2 = 3; - TLS_VERSION_1_3 = 4; - TLS_VERSION_INVALID = 5; - TLS_VERSION_UNSPECIFIED = 6; -} - -enum TLSCipherSuite { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256 = 0; - TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305 = 1; - TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256 = 2; - TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305 = 3; - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA = 4; - TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA = 5; - TLS_CIPHER_SUITE_AES128_GCM_SHA256 = 6; - TLS_CIPHER_SUITE_AES128_SHA = 7; - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384 = 8; - TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384 = 9; - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA = 10; - TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA = 11; - TLS_CIPHER_SUITE_AES256_GCM_SHA384 = 12; - TLS_CIPHER_SUITE_AES256_SHA = 13; -} diff --git a/proto-public/pbmesh/v1alpha1/proxy_configuration.pb.binary.go b/proto-public/pbmesh/v1alpha1/proxy.pb.binary.go similarity index 67% rename from proto-public/pbmesh/v1alpha1/proxy_configuration.pb.binary.go rename to proto-public/pbmesh/v1alpha1/proxy.pb.binary.go index bb706d5da3d66..f39ae6afec843 100644 --- a/proto-public/pbmesh/v1alpha1/proxy_configuration.pb.binary.go +++ b/proto-public/pbmesh/v1alpha1/proxy.pb.binary.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/proxy_configuration.proto +// source: pbmesh/v1alpha1/proxy.proto package meshv1alpha1 @@ -46,23 +46,3 @@ func (msg *BootstrapConfig) MarshalBinary() ([]byte, error) { func (msg *BootstrapConfig) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *AccessLogsConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *AccessLogsConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *EnvoyExtension) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *EnvoyExtension) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/proxy.pb.go b/proto-public/pbmesh/v1alpha1/proxy.pb.go new file mode 100644 index 0000000000000..b6ef2edf873bd --- /dev/null +++ b/proto-public/pbmesh/v1alpha1/proxy.pb.go @@ -0,0 +1,816 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc (unknown) +// source: pbmesh/v1alpha1/proxy.proto + +package meshv1alpha1 + +import ( + v1alpha1 "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + structpb "google.golang.org/protobuf/types/known/structpb" + 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 ProxyMode int32 + +const ( + // ProxyModeDefault represents no specific mode and should + // be used to indicate that a different layer of the configuration + // chain should take precedence + // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX + ProxyMode_PROXY_MODE_DEFAULT ProxyMode = 0 + // ProxyModeTransparent represents that inbound and outbound application + // traffic is being captured and redirected through the proxy. + ProxyMode_PROXY_MODE_TRANSPARENT ProxyMode = 1 + // ProxyModeDirect represents that the proxy's listeners must be dialed directly + // by the local application and other proxies. + ProxyMode_PROXY_MODE_DIRECT ProxyMode = 2 +) + +// Enum value maps for ProxyMode. +var ( + ProxyMode_name = map[int32]string{ + 0: "PROXY_MODE_DEFAULT", + 1: "PROXY_MODE_TRANSPARENT", + 2: "PROXY_MODE_DIRECT", + } + ProxyMode_value = map[string]int32{ + "PROXY_MODE_DEFAULT": 0, + "PROXY_MODE_TRANSPARENT": 1, + "PROXY_MODE_DIRECT": 2, + } +) + +func (x ProxyMode) Enum() *ProxyMode { + p := new(ProxyMode) + *p = x + return p +} + +func (x ProxyMode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ProxyMode) Descriptor() protoreflect.EnumDescriptor { + return file_pbmesh_v1alpha1_proxy_proto_enumTypes[0].Descriptor() +} + +func (ProxyMode) Type() protoreflect.EnumType { + return &file_pbmesh_v1alpha1_proxy_proto_enumTypes[0] +} + +func (x ProxyMode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ProxyMode.Descriptor instead. +func (ProxyMode) EnumDescriptor() ([]byte, []int) { + return file_pbmesh_v1alpha1_proxy_proto_rawDescGZIP(), []int{0} +} + +type ProxyConfiguration struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Selection of workloads this proxy configuration should apply to. + // These can be prefixes or specific workload names. + Workloads *v1alpha1.WorkloadSelector `protobuf:"bytes,1,opt,name=workloads,proto3" json:"workloads,omitempty"` + // dynamic_config is the configuration that could be changed + // dynamically (i.e. without needing restart). + DynamicConfig *DynamicConfig `protobuf:"bytes,2,opt,name=dynamic_config,json=dynamicConfig,proto3" json:"dynamic_config,omitempty"` + // bootstrap_config is the configuration that requires proxies + // to be restarted to be applied. + BootstrapConfig *BootstrapConfig `protobuf:"bytes,3,opt,name=bootstrap_config,json=bootstrapConfig,proto3" json:"bootstrap_config,omitempty"` + // deprecated: prevent usage when using v2 APIs directly. + // needed for backwards compatibility + // + // Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. + OpaqueConfig *structpb.Struct `protobuf:"bytes,4,opt,name=opaque_config,json=opaqueConfig,proto3" json:"opaque_config,omitempty"` +} + +func (x *ProxyConfiguration) Reset() { + *x = ProxyConfiguration{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmesh_v1alpha1_proxy_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ProxyConfiguration) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProxyConfiguration) ProtoMessage() {} + +func (x *ProxyConfiguration) ProtoReflect() protoreflect.Message { + mi := &file_pbmesh_v1alpha1_proxy_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 ProxyConfiguration.ProtoReflect.Descriptor instead. +func (*ProxyConfiguration) Descriptor() ([]byte, []int) { + return file_pbmesh_v1alpha1_proxy_proto_rawDescGZIP(), []int{0} +} + +func (x *ProxyConfiguration) GetWorkloads() *v1alpha1.WorkloadSelector { + if x != nil { + return x.Workloads + } + return nil +} + +func (x *ProxyConfiguration) GetDynamicConfig() *DynamicConfig { + if x != nil { + return x.DynamicConfig + } + return nil +} + +func (x *ProxyConfiguration) GetBootstrapConfig() *BootstrapConfig { + if x != nil { + return x.BootstrapConfig + } + return nil +} + +// Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. +func (x *ProxyConfiguration) GetOpaqueConfig() *structpb.Struct { + if x != nil { + return x.OpaqueConfig + } + return nil +} + +type DynamicConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // mode indicates the proxy's mode. This will default to 'transparent'. + Mode ProxyMode `protobuf:"varint,1,opt,name=mode,proto3,enum=hashicorp.consul.mesh.v1alpha1.ProxyMode" json:"mode,omitempty"` + TransparentProxy *TransparentProxy `protobuf:"bytes,2,opt,name=transparent_proxy,json=transparentProxy,proto3" json:"transparent_proxy,omitempty"` + // local_connection is the configuration that should be used + // to connect to the local application provided per-port. + // The map keys should correspond to port names on the workload. + LocalConnection map[string]*ConnectionConfig `protobuf:"bytes,3,rep,name=local_connection,json=localConnection,proto3" json:"local_connection,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // inbound_connections configures inbound connections to the proxy. + InboundConnections *InboundConnectionsConfig `protobuf:"bytes,4,opt,name=inbound_connections,json=inboundConnections,proto3" json:"inbound_connections,omitempty"` + MeshGatewayMode MeshGatewayMode `protobuf:"varint,5,opt,name=mesh_gateway_mode,json=meshGatewayMode,proto3,enum=hashicorp.consul.mesh.v1alpha1.MeshGatewayMode" json:"mesh_gateway_mode,omitempty"` + ExposeConfig *ExposeConfig `protobuf:"bytes,6,opt,name=expose_config,json=exposeConfig,proto3" json:"expose_config,omitempty"` + PublicListenerJson string `protobuf:"bytes,7,opt,name=public_listener_json,json=publicListenerJson,proto3" json:"public_listener_json,omitempty"` + ListenerTracingJson string `protobuf:"bytes,8,opt,name=listener_tracing_json,json=listenerTracingJson,proto3" json:"listener_tracing_json,omitempty"` + LocalClusterJson string `protobuf:"bytes,9,opt,name=local_cluster_json,json=localClusterJson,proto3" json:"local_cluster_json,omitempty"` + // deprecated: + // local_workload_address, local_workload_port, and local_workload_socket_path + // are deprecated and are only needed for migration of existing resources. + // + // Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. + LocalWorkloadAddress string `protobuf:"bytes,10,opt,name=local_workload_address,json=localWorkloadAddress,proto3" json:"local_workload_address,omitempty"` + // Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. + LocalWorkloadPort uint32 `protobuf:"varint,11,opt,name=local_workload_port,json=localWorkloadPort,proto3" json:"local_workload_port,omitempty"` + // Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. + LocalWorkloadSocketPath string `protobuf:"bytes,12,opt,name=local_workload_socket_path,json=localWorkloadSocketPath,proto3" json:"local_workload_socket_path,omitempty"` +} + +func (x *DynamicConfig) Reset() { + *x = DynamicConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmesh_v1alpha1_proxy_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DynamicConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DynamicConfig) ProtoMessage() {} + +func (x *DynamicConfig) ProtoReflect() protoreflect.Message { + mi := &file_pbmesh_v1alpha1_proxy_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 DynamicConfig.ProtoReflect.Descriptor instead. +func (*DynamicConfig) Descriptor() ([]byte, []int) { + return file_pbmesh_v1alpha1_proxy_proto_rawDescGZIP(), []int{1} +} + +func (x *DynamicConfig) GetMode() ProxyMode { + if x != nil { + return x.Mode + } + return ProxyMode_PROXY_MODE_DEFAULT +} + +func (x *DynamicConfig) GetTransparentProxy() *TransparentProxy { + if x != nil { + return x.TransparentProxy + } + return nil +} + +func (x *DynamicConfig) GetLocalConnection() map[string]*ConnectionConfig { + if x != nil { + return x.LocalConnection + } + return nil +} + +func (x *DynamicConfig) GetInboundConnections() *InboundConnectionsConfig { + if x != nil { + return x.InboundConnections + } + return nil +} + +func (x *DynamicConfig) GetMeshGatewayMode() MeshGatewayMode { + if x != nil { + return x.MeshGatewayMode + } + return MeshGatewayMode_MESH_GATEWAY_MODE_UNSPECIFIED +} + +func (x *DynamicConfig) GetExposeConfig() *ExposeConfig { + if x != nil { + return x.ExposeConfig + } + return nil +} + +func (x *DynamicConfig) GetPublicListenerJson() string { + if x != nil { + return x.PublicListenerJson + } + return "" +} + +func (x *DynamicConfig) GetListenerTracingJson() string { + if x != nil { + return x.ListenerTracingJson + } + return "" +} + +func (x *DynamicConfig) GetLocalClusterJson() string { + if x != nil { + return x.LocalClusterJson + } + return "" +} + +// Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. +func (x *DynamicConfig) GetLocalWorkloadAddress() string { + if x != nil { + return x.LocalWorkloadAddress + } + return "" +} + +// Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. +func (x *DynamicConfig) GetLocalWorkloadPort() uint32 { + if x != nil { + return x.LocalWorkloadPort + } + return 0 +} + +// Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. +func (x *DynamicConfig) GetLocalWorkloadSocketPath() string { + if x != nil { + return x.LocalWorkloadSocketPath + } + return "" +} + +type TransparentProxy struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // outbound_listener_port is the port for the proxy's outbound listener. + // This defaults to 15001. + OutboundListenerPort uint32 `protobuf:"varint,1,opt,name=outbound_listener_port,json=outboundListenerPort,proto3" json:"outbound_listener_port,omitempty"` + // dialed_directly indicates whether this proxy should be dialed using original destination IP + // in the connection rather than load balance between all endpoints. + DialedDirectly bool `protobuf:"varint,2,opt,name=dialed_directly,json=dialedDirectly,proto3" json:"dialed_directly,omitempty"` +} + +func (x *TransparentProxy) Reset() { + *x = TransparentProxy{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmesh_v1alpha1_proxy_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransparentProxy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransparentProxy) ProtoMessage() {} + +func (x *TransparentProxy) ProtoReflect() protoreflect.Message { + mi := &file_pbmesh_v1alpha1_proxy_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 TransparentProxy.ProtoReflect.Descriptor instead. +func (*TransparentProxy) Descriptor() ([]byte, []int) { + return file_pbmesh_v1alpha1_proxy_proto_rawDescGZIP(), []int{2} +} + +func (x *TransparentProxy) GetOutboundListenerPort() uint32 { + if x != nil { + return x.OutboundListenerPort + } + return 0 +} + +func (x *TransparentProxy) GetDialedDirectly() bool { + if x != nil { + return x.DialedDirectly + } + return false +} + +// BootstrapConfig is equivalent to configuration defined +// in our docs. +type BootstrapConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + StatsdUrl string `protobuf:"bytes,1,opt,name=statsd_url,json=statsdUrl,proto3" json:"statsd_url,omitempty"` + DogstatsdUrl string `protobuf:"bytes,2,opt,name=dogstatsd_url,json=dogstatsdUrl,proto3" json:"dogstatsd_url,omitempty"` + StatsTags []string `protobuf:"bytes,3,rep,name=stats_tags,json=statsTags,proto3" json:"stats_tags,omitempty"` + PrometheusBindAddr string `protobuf:"bytes,4,opt,name=prometheus_bind_addr,json=prometheusBindAddr,proto3" json:"prometheus_bind_addr,omitempty"` + StatsBindAddr string `protobuf:"bytes,5,opt,name=stats_bind_addr,json=statsBindAddr,proto3" json:"stats_bind_addr,omitempty"` + ReadyBindAddr string `protobuf:"bytes,6,opt,name=ready_bind_addr,json=readyBindAddr,proto3" json:"ready_bind_addr,omitempty"` + OverrideJsonTpl string `protobuf:"bytes,7,opt,name=override_json_tpl,json=overrideJsonTpl,proto3" json:"override_json_tpl,omitempty"` + StaticClustersJson string `protobuf:"bytes,8,opt,name=static_clusters_json,json=staticClustersJson,proto3" json:"static_clusters_json,omitempty"` + StaticListenersJson string `protobuf:"bytes,9,opt,name=static_listeners_json,json=staticListenersJson,proto3" json:"static_listeners_json,omitempty"` + StatsSinksJson string `protobuf:"bytes,10,opt,name=stats_sinks_json,json=statsSinksJson,proto3" json:"stats_sinks_json,omitempty"` + StatsConfigJson string `protobuf:"bytes,11,opt,name=stats_config_json,json=statsConfigJson,proto3" json:"stats_config_json,omitempty"` + StatsFlushInterval string `protobuf:"bytes,12,opt,name=stats_flush_interval,json=statsFlushInterval,proto3" json:"stats_flush_interval,omitempty"` + TracingConfigJson string `protobuf:"bytes,13,opt,name=tracing_config_json,json=tracingConfigJson,proto3" json:"tracing_config_json,omitempty"` +} + +func (x *BootstrapConfig) Reset() { + *x = BootstrapConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmesh_v1alpha1_proxy_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BootstrapConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BootstrapConfig) ProtoMessage() {} + +func (x *BootstrapConfig) ProtoReflect() protoreflect.Message { + mi := &file_pbmesh_v1alpha1_proxy_proto_msgTypes[3] + 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 BootstrapConfig.ProtoReflect.Descriptor instead. +func (*BootstrapConfig) Descriptor() ([]byte, []int) { + return file_pbmesh_v1alpha1_proxy_proto_rawDescGZIP(), []int{3} +} + +func (x *BootstrapConfig) GetStatsdUrl() string { + if x != nil { + return x.StatsdUrl + } + return "" +} + +func (x *BootstrapConfig) GetDogstatsdUrl() string { + if x != nil { + return x.DogstatsdUrl + } + return "" +} + +func (x *BootstrapConfig) GetStatsTags() []string { + if x != nil { + return x.StatsTags + } + return nil +} + +func (x *BootstrapConfig) GetPrometheusBindAddr() string { + if x != nil { + return x.PrometheusBindAddr + } + return "" +} + +func (x *BootstrapConfig) GetStatsBindAddr() string { + if x != nil { + return x.StatsBindAddr + } + return "" +} + +func (x *BootstrapConfig) GetReadyBindAddr() string { + if x != nil { + return x.ReadyBindAddr + } + return "" +} + +func (x *BootstrapConfig) GetOverrideJsonTpl() string { + if x != nil { + return x.OverrideJsonTpl + } + return "" +} + +func (x *BootstrapConfig) GetStaticClustersJson() string { + if x != nil { + return x.StaticClustersJson + } + return "" +} + +func (x *BootstrapConfig) GetStaticListenersJson() string { + if x != nil { + return x.StaticListenersJson + } + return "" +} + +func (x *BootstrapConfig) GetStatsSinksJson() string { + if x != nil { + return x.StatsSinksJson + } + return "" +} + +func (x *BootstrapConfig) GetStatsConfigJson() string { + if x != nil { + return x.StatsConfigJson + } + return "" +} + +func (x *BootstrapConfig) GetStatsFlushInterval() string { + if x != nil { + return x.StatsFlushInterval + } + return "" +} + +func (x *BootstrapConfig) GetTracingConfigJson() string { + if x != nil { + return x.TracingConfigJson + } + return "" +} + +var File_pbmesh_v1alpha1_proxy_proto protoreflect.FileDescriptor + +var file_pbmesh_v1alpha1_proxy_proto_rawDesc = []byte{ + 0x0a, 0x1b, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1c, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, + 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x70, 0x62, 0x63, + 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, + 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, + 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x1c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, + 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, + 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdb, 0x02, + 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x51, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, + 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x77, 0x6f, + 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, 0x54, 0x0a, 0x0e, 0x64, 0x79, 0x6e, 0x61, 0x6d, + 0x69, 0x63, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, + 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5a, 0x0a, + 0x10, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, + 0x61, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0f, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, + 0x72, 0x61, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x40, 0x0a, 0x0d, 0x6f, 0x70, 0x61, + 0x71, 0x75, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0c, 0x6f, + 0x70, 0x61, 0x71, 0x75, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xf0, 0x07, 0x0a, 0x0d, + 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, + 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, + 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, + 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x5d, 0x0a, 0x11, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x78, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x52, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x6d, 0x0a, 0x10, 0x6c, + 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x69, 0x0a, 0x13, 0x69, 0x6e, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x12, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5b, 0x0a, 0x11, 0x6d, 0x65, 0x73, 0x68, 0x5f, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, + 0x65, 0x52, 0x0f, 0x6d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, + 0x64, 0x65, 0x12, 0x51, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, + 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x12, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4c, 0x69, 0x73, 0x74, 0x65, + 0x6e, 0x65, 0x72, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x15, 0x6c, 0x69, 0x73, 0x74, 0x65, + 0x6e, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, + 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x6c, + 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6a, 0x73, 0x6f, + 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x16, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x14, 0x6c, + 0x6f, 0x63, 0x61, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x32, 0x0a, 0x13, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x77, 0x6f, 0x72, + 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, + 0x42, 0x02, 0x18, 0x01, 0x52, 0x11, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x6c, + 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x3f, 0x0a, 0x1a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, + 0x17, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x6f, + 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x1a, 0x74, 0x0a, 0x14, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x71, + 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, + 0x78, 0x79, 0x12, 0x34, 0x0a, 0x16, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x6c, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x14, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, + 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x69, 0x61, 0x6c, + 0x65, 0x64, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0e, 0x64, 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, + 0x79, 0x22, 0xc0, 0x04, 0x0a, 0x0f, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, 0x5f, + 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x73, + 0x64, 0x55, 0x72, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x6f, 0x67, 0x73, 0x74, 0x61, 0x74, 0x73, + 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x6f, 0x67, + 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, 0x55, 0x72, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, + 0x74, 0x73, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x73, + 0x74, 0x61, 0x74, 0x73, 0x54, 0x61, 0x67, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x72, 0x6f, 0x6d, + 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, + 0x75, 0x73, 0x42, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x74, + 0x61, 0x74, 0x73, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x42, 0x69, 0x6e, 0x64, 0x41, 0x64, + 0x64, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x62, 0x69, 0x6e, 0x64, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x61, + 0x64, 0x79, 0x42, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x74, 0x70, 0x6c, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x4a, + 0x73, 0x6f, 0x6e, 0x54, 0x70, 0x6c, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, + 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x73, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x63, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x5f, 0x6a, 0x73, 0x6f, + 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x4c, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, + 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x53, 0x69, 0x6e, + 0x6b, 0x73, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4a, 0x73, + 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x66, 0x6c, 0x75, 0x73, + 0x68, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x12, 0x73, 0x74, 0x61, 0x74, 0x73, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x11, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x4a, 0x73, 0x6f, 0x6e, 0x2a, 0x56, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, + 0x65, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, + 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x52, 0x4f, + 0x58, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x50, 0x41, 0x52, + 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x4d, + 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x02, 0x42, 0x92, 0x02, 0x0a, + 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x42, 0x0a, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x45, 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, 0x65, + 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, + 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, + 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, + 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pbmesh_v1alpha1_proxy_proto_rawDescOnce sync.Once + file_pbmesh_v1alpha1_proxy_proto_rawDescData = file_pbmesh_v1alpha1_proxy_proto_rawDesc +) + +func file_pbmesh_v1alpha1_proxy_proto_rawDescGZIP() []byte { + file_pbmesh_v1alpha1_proxy_proto_rawDescOnce.Do(func() { + file_pbmesh_v1alpha1_proxy_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_proxy_proto_rawDescData) + }) + return file_pbmesh_v1alpha1_proxy_proto_rawDescData +} + +var file_pbmesh_v1alpha1_proxy_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_pbmesh_v1alpha1_proxy_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_pbmesh_v1alpha1_proxy_proto_goTypes = []interface{}{ + (ProxyMode)(0), // 0: hashicorp.consul.mesh.v1alpha1.ProxyMode + (*ProxyConfiguration)(nil), // 1: hashicorp.consul.mesh.v1alpha1.ProxyConfiguration + (*DynamicConfig)(nil), // 2: hashicorp.consul.mesh.v1alpha1.DynamicConfig + (*TransparentProxy)(nil), // 3: hashicorp.consul.mesh.v1alpha1.TransparentProxy + (*BootstrapConfig)(nil), // 4: hashicorp.consul.mesh.v1alpha1.BootstrapConfig + nil, // 5: hashicorp.consul.mesh.v1alpha1.DynamicConfig.LocalConnectionEntry + (*v1alpha1.WorkloadSelector)(nil), // 6: hashicorp.consul.catalog.v1alpha1.WorkloadSelector + (*structpb.Struct)(nil), // 7: google.protobuf.Struct + (*InboundConnectionsConfig)(nil), // 8: hashicorp.consul.mesh.v1alpha1.InboundConnectionsConfig + (MeshGatewayMode)(0), // 9: hashicorp.consul.mesh.v1alpha1.MeshGatewayMode + (*ExposeConfig)(nil), // 10: hashicorp.consul.mesh.v1alpha1.ExposeConfig + (*ConnectionConfig)(nil), // 11: hashicorp.consul.mesh.v1alpha1.ConnectionConfig +} +var file_pbmesh_v1alpha1_proxy_proto_depIdxs = []int32{ + 6, // 0: hashicorp.consul.mesh.v1alpha1.ProxyConfiguration.workloads:type_name -> hashicorp.consul.catalog.v1alpha1.WorkloadSelector + 2, // 1: hashicorp.consul.mesh.v1alpha1.ProxyConfiguration.dynamic_config:type_name -> hashicorp.consul.mesh.v1alpha1.DynamicConfig + 4, // 2: hashicorp.consul.mesh.v1alpha1.ProxyConfiguration.bootstrap_config:type_name -> hashicorp.consul.mesh.v1alpha1.BootstrapConfig + 7, // 3: hashicorp.consul.mesh.v1alpha1.ProxyConfiguration.opaque_config:type_name -> google.protobuf.Struct + 0, // 4: hashicorp.consul.mesh.v1alpha1.DynamicConfig.mode:type_name -> hashicorp.consul.mesh.v1alpha1.ProxyMode + 3, // 5: hashicorp.consul.mesh.v1alpha1.DynamicConfig.transparent_proxy:type_name -> hashicorp.consul.mesh.v1alpha1.TransparentProxy + 5, // 6: hashicorp.consul.mesh.v1alpha1.DynamicConfig.local_connection:type_name -> hashicorp.consul.mesh.v1alpha1.DynamicConfig.LocalConnectionEntry + 8, // 7: hashicorp.consul.mesh.v1alpha1.DynamicConfig.inbound_connections:type_name -> hashicorp.consul.mesh.v1alpha1.InboundConnectionsConfig + 9, // 8: hashicorp.consul.mesh.v1alpha1.DynamicConfig.mesh_gateway_mode:type_name -> hashicorp.consul.mesh.v1alpha1.MeshGatewayMode + 10, // 9: hashicorp.consul.mesh.v1alpha1.DynamicConfig.expose_config:type_name -> hashicorp.consul.mesh.v1alpha1.ExposeConfig + 11, // 10: hashicorp.consul.mesh.v1alpha1.DynamicConfig.LocalConnectionEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.ConnectionConfig + 11, // [11:11] is the sub-list for method output_type + 11, // [11:11] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name +} + +func init() { file_pbmesh_v1alpha1_proxy_proto_init() } +func file_pbmesh_v1alpha1_proxy_proto_init() { + if File_pbmesh_v1alpha1_proxy_proto != nil { + return + } + file_pbmesh_v1alpha1_connection_proto_init() + file_pbmesh_v1alpha1_expose_proto_init() + file_pbmesh_v1alpha1_routing_proto_init() + if !protoimpl.UnsafeEnabled { + file_pbmesh_v1alpha1_proxy_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ProxyConfiguration); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbmesh_v1alpha1_proxy_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DynamicConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbmesh_v1alpha1_proxy_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransparentProxy); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbmesh_v1alpha1_proxy_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BootstrapConfig); 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_pbmesh_v1alpha1_proxy_proto_rawDesc, + NumEnums: 1, + NumMessages: 5, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pbmesh_v1alpha1_proxy_proto_goTypes, + DependencyIndexes: file_pbmesh_v1alpha1_proxy_proto_depIdxs, + EnumInfos: file_pbmesh_v1alpha1_proxy_proto_enumTypes, + MessageInfos: file_pbmesh_v1alpha1_proxy_proto_msgTypes, + }.Build() + File_pbmesh_v1alpha1_proxy_proto = out.File + file_pbmesh_v1alpha1_proxy_proto_rawDesc = nil + file_pbmesh_v1alpha1_proxy_proto_goTypes = nil + file_pbmesh_v1alpha1_proxy_proto_depIdxs = nil +} diff --git a/proto-public/pbmesh/v1alpha1/proxy_configuration.proto b/proto-public/pbmesh/v1alpha1/proxy.proto similarity index 60% rename from proto-public/pbmesh/v1alpha1/proxy_configuration.proto rename to proto-public/pbmesh/v1alpha1/proxy.proto index c20ff3d47c44e..06ebecbf4abac 100644 --- a/proto-public/pbmesh/v1alpha1/proxy_configuration.proto +++ b/proto-public/pbmesh/v1alpha1/proxy.proto @@ -11,7 +11,6 @@ import "pbmesh/v1alpha1/connection.proto"; import "pbmesh/v1alpha1/expose.proto"; import "pbmesh/v1alpha1/routing.proto"; -// This is a Resource type. message ProxyConfiguration { // Selection of workloads this proxy configuration should apply to. // These can be prefixes or specific workload names. @@ -36,35 +35,28 @@ message DynamicConfig { TransparentProxy transparent_proxy = 2; - MutualTLSMode mutual_tls_mode = 3; - // local_connection is the configuration that should be used // to connect to the local application provided per-port. // The map keys should correspond to port names on the workload. - map local_connection = 4; + map local_connection = 3; // inbound_connections configures inbound connections to the proxy. - InboundConnectionsConfig inbound_connections = 5; - - MeshGatewayMode mesh_gateway_mode = 6; - - ExposeConfig expose_config = 7; + InboundConnectionsConfig inbound_connections = 4; - // AccessLogs configures the output and format of Envoy access logs - AccessLogsConfig access_logs = 8; + MeshGatewayMode mesh_gateway_mode = 5; - repeated EnvoyExtension envoy_extensions = 9; + ExposeConfig expose_config = 6; - string public_listener_json = 10; - string listener_tracing_json = 11; - string local_cluster_json = 12; + string public_listener_json = 7; + string listener_tracing_json = 8; + string local_cluster_json = 9; // deprecated: // local_workload_address, local_workload_port, and local_workload_socket_path // are deprecated and are only needed for migration of existing resources. - string local_workload_address = 13 [deprecated = true]; - uint32 local_workload_port = 14 [deprecated = true]; - string local_workload_socket_path = 15 [deprecated = true]; + string local_workload_address = 10 [deprecated = true]; + uint32 local_workload_port = 11 [deprecated = true]; + string local_workload_socket_path = 12 [deprecated = true]; } message TransparentProxy { @@ -110,49 +102,3 @@ enum ProxyMode { // by the local application and other proxies. PROXY_MODE_DIRECT = 2; } - -// AccessLogsConfig contains the associated default settings for all Envoy -// instances within the datacenter or partition -message AccessLogsConfig { - // Enabled turns off all access logging - bool enabled = 1; - - // DisableListenerLogs turns off just listener logs for connections rejected by Envoy because they don't - // have a matching listener filter. - bool disable_listener_logs = 2; - - // Type selects the output for logs: "file", "stderr". "stdout" - LogSinkType type = 3; - - // Path is the output file to write logs - string path = 4; - - // The presence of one format string or the other implies the access log string encoding. - // Defining Both is invalid. - string json_format = 5; - string text_format = 6; -} - -enum LogSinkType { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - LOG_SINK_TYPE_DEFAULT = 0; - LOG_SINK_TYPE_FILE = 1; - LOG_SINK_TYPE_STDERR = 2; - LOG_SINK_TYPE_STDOUT = 3; -} - -// EnvoyExtension has configuration for an extension that patches Envoy resources. -message EnvoyExtension { - string name = 1; - bool required = 2; - google.protobuf.Struct arguments = 3; - string consul_version = 4; - string envoy_version = 5; -} - -enum MutualTLSMode { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - MUTUAL_TLS_MODE_DEFAULT = 0; - MUTUAL_TLS_MODE_STRICT = 1; - MUTUAL_TLS_MODE_PERMISSIVE = 2; -} diff --git a/proto-public/pbmesh/v1alpha1/proxy_configuration.pb.go b/proto-public/pbmesh/v1alpha1/proxy_configuration.pb.go deleted file mode 100644 index 0072714553dad..0000000000000 --- a/proto-public/pbmesh/v1alpha1/proxy_configuration.pb.go +++ /dev/null @@ -1,1214 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/proxy_configuration.proto - -package meshv1alpha1 - -import ( - v1alpha1 "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - structpb "google.golang.org/protobuf/types/known/structpb" - 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 ProxyMode int32 - -const ( - // ProxyModeDefault represents no specific mode and should - // be used to indicate that a different layer of the configuration - // chain should take precedence - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - ProxyMode_PROXY_MODE_DEFAULT ProxyMode = 0 - // ProxyModeTransparent represents that inbound and outbound application - // traffic is being captured and redirected through the proxy. - ProxyMode_PROXY_MODE_TRANSPARENT ProxyMode = 1 - // ProxyModeDirect represents that the proxy's listeners must be dialed directly - // by the local application and other proxies. - ProxyMode_PROXY_MODE_DIRECT ProxyMode = 2 -) - -// Enum value maps for ProxyMode. -var ( - ProxyMode_name = map[int32]string{ - 0: "PROXY_MODE_DEFAULT", - 1: "PROXY_MODE_TRANSPARENT", - 2: "PROXY_MODE_DIRECT", - } - ProxyMode_value = map[string]int32{ - "PROXY_MODE_DEFAULT": 0, - "PROXY_MODE_TRANSPARENT": 1, - "PROXY_MODE_DIRECT": 2, - } -) - -func (x ProxyMode) Enum() *ProxyMode { - p := new(ProxyMode) - *p = x - return p -} - -func (x ProxyMode) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ProxyMode) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_proxy_configuration_proto_enumTypes[0].Descriptor() -} - -func (ProxyMode) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_proxy_configuration_proto_enumTypes[0] -} - -func (x ProxyMode) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ProxyMode.Descriptor instead. -func (ProxyMode) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescGZIP(), []int{0} -} - -type LogSinkType int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - LogSinkType_LOG_SINK_TYPE_DEFAULT LogSinkType = 0 - LogSinkType_LOG_SINK_TYPE_FILE LogSinkType = 1 - LogSinkType_LOG_SINK_TYPE_STDERR LogSinkType = 2 - LogSinkType_LOG_SINK_TYPE_STDOUT LogSinkType = 3 -) - -// Enum value maps for LogSinkType. -var ( - LogSinkType_name = map[int32]string{ - 0: "LOG_SINK_TYPE_DEFAULT", - 1: "LOG_SINK_TYPE_FILE", - 2: "LOG_SINK_TYPE_STDERR", - 3: "LOG_SINK_TYPE_STDOUT", - } - LogSinkType_value = map[string]int32{ - "LOG_SINK_TYPE_DEFAULT": 0, - "LOG_SINK_TYPE_FILE": 1, - "LOG_SINK_TYPE_STDERR": 2, - "LOG_SINK_TYPE_STDOUT": 3, - } -) - -func (x LogSinkType) Enum() *LogSinkType { - p := new(LogSinkType) - *p = x - return p -} - -func (x LogSinkType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (LogSinkType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_proxy_configuration_proto_enumTypes[1].Descriptor() -} - -func (LogSinkType) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_proxy_configuration_proto_enumTypes[1] -} - -func (x LogSinkType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use LogSinkType.Descriptor instead. -func (LogSinkType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescGZIP(), []int{1} -} - -type MutualTLSMode int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - MutualTLSMode_MUTUAL_TLS_MODE_DEFAULT MutualTLSMode = 0 - MutualTLSMode_MUTUAL_TLS_MODE_STRICT MutualTLSMode = 1 - MutualTLSMode_MUTUAL_TLS_MODE_PERMISSIVE MutualTLSMode = 2 -) - -// Enum value maps for MutualTLSMode. -var ( - MutualTLSMode_name = map[int32]string{ - 0: "MUTUAL_TLS_MODE_DEFAULT", - 1: "MUTUAL_TLS_MODE_STRICT", - 2: "MUTUAL_TLS_MODE_PERMISSIVE", - } - MutualTLSMode_value = map[string]int32{ - "MUTUAL_TLS_MODE_DEFAULT": 0, - "MUTUAL_TLS_MODE_STRICT": 1, - "MUTUAL_TLS_MODE_PERMISSIVE": 2, - } -) - -func (x MutualTLSMode) Enum() *MutualTLSMode { - p := new(MutualTLSMode) - *p = x - return p -} - -func (x MutualTLSMode) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (MutualTLSMode) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v1alpha1_proxy_configuration_proto_enumTypes[2].Descriptor() -} - -func (MutualTLSMode) Type() protoreflect.EnumType { - return &file_pbmesh_v1alpha1_proxy_configuration_proto_enumTypes[2] -} - -func (x MutualTLSMode) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use MutualTLSMode.Descriptor instead. -func (MutualTLSMode) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescGZIP(), []int{2} -} - -// This is a Resource type. -type ProxyConfiguration struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Selection of workloads this proxy configuration should apply to. - // These can be prefixes or specific workload names. - Workloads *v1alpha1.WorkloadSelector `protobuf:"bytes,1,opt,name=workloads,proto3" json:"workloads,omitempty"` - // dynamic_config is the configuration that could be changed - // dynamically (i.e. without needing restart). - DynamicConfig *DynamicConfig `protobuf:"bytes,2,opt,name=dynamic_config,json=dynamicConfig,proto3" json:"dynamic_config,omitempty"` - // bootstrap_config is the configuration that requires proxies - // to be restarted to be applied. - BootstrapConfig *BootstrapConfig `protobuf:"bytes,3,opt,name=bootstrap_config,json=bootstrapConfig,proto3" json:"bootstrap_config,omitempty"` - // deprecated: prevent usage when using v2 APIs directly. - // needed for backwards compatibility - // - // Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy_configuration.proto. - OpaqueConfig *structpb.Struct `protobuf:"bytes,4,opt,name=opaque_config,json=opaqueConfig,proto3" json:"opaque_config,omitempty"` -} - -func (x *ProxyConfiguration) Reset() { - *x = ProxyConfiguration{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProxyConfiguration) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProxyConfiguration) ProtoMessage() {} - -func (x *ProxyConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_proxy_configuration_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 ProxyConfiguration.ProtoReflect.Descriptor instead. -func (*ProxyConfiguration) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescGZIP(), []int{0} -} - -func (x *ProxyConfiguration) GetWorkloads() *v1alpha1.WorkloadSelector { - if x != nil { - return x.Workloads - } - return nil -} - -func (x *ProxyConfiguration) GetDynamicConfig() *DynamicConfig { - if x != nil { - return x.DynamicConfig - } - return nil -} - -func (x *ProxyConfiguration) GetBootstrapConfig() *BootstrapConfig { - if x != nil { - return x.BootstrapConfig - } - return nil -} - -// Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy_configuration.proto. -func (x *ProxyConfiguration) GetOpaqueConfig() *structpb.Struct { - if x != nil { - return x.OpaqueConfig - } - return nil -} - -type DynamicConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // mode indicates the proxy's mode. This will default to 'transparent'. - Mode ProxyMode `protobuf:"varint,1,opt,name=mode,proto3,enum=hashicorp.consul.mesh.v1alpha1.ProxyMode" json:"mode,omitempty"` - TransparentProxy *TransparentProxy `protobuf:"bytes,2,opt,name=transparent_proxy,json=transparentProxy,proto3" json:"transparent_proxy,omitempty"` - MutualTlsMode MutualTLSMode `protobuf:"varint,3,opt,name=mutual_tls_mode,json=mutualTlsMode,proto3,enum=hashicorp.consul.mesh.v1alpha1.MutualTLSMode" json:"mutual_tls_mode,omitempty"` - // local_connection is the configuration that should be used - // to connect to the local application provided per-port. - // The map keys should correspond to port names on the workload. - LocalConnection map[string]*ConnectionConfig `protobuf:"bytes,4,rep,name=local_connection,json=localConnection,proto3" json:"local_connection,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // inbound_connections configures inbound connections to the proxy. - InboundConnections *InboundConnectionsConfig `protobuf:"bytes,5,opt,name=inbound_connections,json=inboundConnections,proto3" json:"inbound_connections,omitempty"` - MeshGatewayMode MeshGatewayMode `protobuf:"varint,6,opt,name=mesh_gateway_mode,json=meshGatewayMode,proto3,enum=hashicorp.consul.mesh.v1alpha1.MeshGatewayMode" json:"mesh_gateway_mode,omitempty"` - ExposeConfig *ExposeConfig `protobuf:"bytes,7,opt,name=expose_config,json=exposeConfig,proto3" json:"expose_config,omitempty"` - // AccessLogs configures the output and format of Envoy access logs - AccessLogs *AccessLogsConfig `protobuf:"bytes,8,opt,name=access_logs,json=accessLogs,proto3" json:"access_logs,omitempty"` - EnvoyExtensions []*EnvoyExtension `protobuf:"bytes,9,rep,name=envoy_extensions,json=envoyExtensions,proto3" json:"envoy_extensions,omitempty"` - PublicListenerJson string `protobuf:"bytes,10,opt,name=public_listener_json,json=publicListenerJson,proto3" json:"public_listener_json,omitempty"` - ListenerTracingJson string `protobuf:"bytes,11,opt,name=listener_tracing_json,json=listenerTracingJson,proto3" json:"listener_tracing_json,omitempty"` - LocalClusterJson string `protobuf:"bytes,12,opt,name=local_cluster_json,json=localClusterJson,proto3" json:"local_cluster_json,omitempty"` - // deprecated: - // local_workload_address, local_workload_port, and local_workload_socket_path - // are deprecated and are only needed for migration of existing resources. - // - // Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy_configuration.proto. - LocalWorkloadAddress string `protobuf:"bytes,13,opt,name=local_workload_address,json=localWorkloadAddress,proto3" json:"local_workload_address,omitempty"` - // Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy_configuration.proto. - LocalWorkloadPort uint32 `protobuf:"varint,14,opt,name=local_workload_port,json=localWorkloadPort,proto3" json:"local_workload_port,omitempty"` - // Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy_configuration.proto. - LocalWorkloadSocketPath string `protobuf:"bytes,15,opt,name=local_workload_socket_path,json=localWorkloadSocketPath,proto3" json:"local_workload_socket_path,omitempty"` -} - -func (x *DynamicConfig) Reset() { - *x = DynamicConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DynamicConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DynamicConfig) ProtoMessage() {} - -func (x *DynamicConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_proxy_configuration_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 DynamicConfig.ProtoReflect.Descriptor instead. -func (*DynamicConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescGZIP(), []int{1} -} - -func (x *DynamicConfig) GetMode() ProxyMode { - if x != nil { - return x.Mode - } - return ProxyMode_PROXY_MODE_DEFAULT -} - -func (x *DynamicConfig) GetTransparentProxy() *TransparentProxy { - if x != nil { - return x.TransparentProxy - } - return nil -} - -func (x *DynamicConfig) GetMutualTlsMode() MutualTLSMode { - if x != nil { - return x.MutualTlsMode - } - return MutualTLSMode_MUTUAL_TLS_MODE_DEFAULT -} - -func (x *DynamicConfig) GetLocalConnection() map[string]*ConnectionConfig { - if x != nil { - return x.LocalConnection - } - return nil -} - -func (x *DynamicConfig) GetInboundConnections() *InboundConnectionsConfig { - if x != nil { - return x.InboundConnections - } - return nil -} - -func (x *DynamicConfig) GetMeshGatewayMode() MeshGatewayMode { - if x != nil { - return x.MeshGatewayMode - } - return MeshGatewayMode_MESH_GATEWAY_MODE_UNSPECIFIED -} - -func (x *DynamicConfig) GetExposeConfig() *ExposeConfig { - if x != nil { - return x.ExposeConfig - } - return nil -} - -func (x *DynamicConfig) GetAccessLogs() *AccessLogsConfig { - if x != nil { - return x.AccessLogs - } - return nil -} - -func (x *DynamicConfig) GetEnvoyExtensions() []*EnvoyExtension { - if x != nil { - return x.EnvoyExtensions - } - return nil -} - -func (x *DynamicConfig) GetPublicListenerJson() string { - if x != nil { - return x.PublicListenerJson - } - return "" -} - -func (x *DynamicConfig) GetListenerTracingJson() string { - if x != nil { - return x.ListenerTracingJson - } - return "" -} - -func (x *DynamicConfig) GetLocalClusterJson() string { - if x != nil { - return x.LocalClusterJson - } - return "" -} - -// Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy_configuration.proto. -func (x *DynamicConfig) GetLocalWorkloadAddress() string { - if x != nil { - return x.LocalWorkloadAddress - } - return "" -} - -// Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy_configuration.proto. -func (x *DynamicConfig) GetLocalWorkloadPort() uint32 { - if x != nil { - return x.LocalWorkloadPort - } - return 0 -} - -// Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy_configuration.proto. -func (x *DynamicConfig) GetLocalWorkloadSocketPath() string { - if x != nil { - return x.LocalWorkloadSocketPath - } - return "" -} - -type TransparentProxy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // outbound_listener_port is the port for the proxy's outbound listener. - // This defaults to 15001. - OutboundListenerPort uint32 `protobuf:"varint,1,opt,name=outbound_listener_port,json=outboundListenerPort,proto3" json:"outbound_listener_port,omitempty"` - // dialed_directly indicates whether this proxy should be dialed using original destination IP - // in the connection rather than load balance between all endpoints. - DialedDirectly bool `protobuf:"varint,2,opt,name=dialed_directly,json=dialedDirectly,proto3" json:"dialed_directly,omitempty"` -} - -func (x *TransparentProxy) Reset() { - *x = TransparentProxy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TransparentProxy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TransparentProxy) ProtoMessage() {} - -func (x *TransparentProxy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_proxy_configuration_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 TransparentProxy.ProtoReflect.Descriptor instead. -func (*TransparentProxy) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescGZIP(), []int{2} -} - -func (x *TransparentProxy) GetOutboundListenerPort() uint32 { - if x != nil { - return x.OutboundListenerPort - } - return 0 -} - -func (x *TransparentProxy) GetDialedDirectly() bool { - if x != nil { - return x.DialedDirectly - } - return false -} - -// BootstrapConfig is equivalent to configuration defined -// in our docs. -type BootstrapConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - StatsdUrl string `protobuf:"bytes,1,opt,name=statsd_url,json=statsdUrl,proto3" json:"statsd_url,omitempty"` - DogstatsdUrl string `protobuf:"bytes,2,opt,name=dogstatsd_url,json=dogstatsdUrl,proto3" json:"dogstatsd_url,omitempty"` - StatsTags []string `protobuf:"bytes,3,rep,name=stats_tags,json=statsTags,proto3" json:"stats_tags,omitempty"` - PrometheusBindAddr string `protobuf:"bytes,4,opt,name=prometheus_bind_addr,json=prometheusBindAddr,proto3" json:"prometheus_bind_addr,omitempty"` - StatsBindAddr string `protobuf:"bytes,5,opt,name=stats_bind_addr,json=statsBindAddr,proto3" json:"stats_bind_addr,omitempty"` - ReadyBindAddr string `protobuf:"bytes,6,opt,name=ready_bind_addr,json=readyBindAddr,proto3" json:"ready_bind_addr,omitempty"` - OverrideJsonTpl string `protobuf:"bytes,7,opt,name=override_json_tpl,json=overrideJsonTpl,proto3" json:"override_json_tpl,omitempty"` - StaticClustersJson string `protobuf:"bytes,8,opt,name=static_clusters_json,json=staticClustersJson,proto3" json:"static_clusters_json,omitempty"` - StaticListenersJson string `protobuf:"bytes,9,opt,name=static_listeners_json,json=staticListenersJson,proto3" json:"static_listeners_json,omitempty"` - StatsSinksJson string `protobuf:"bytes,10,opt,name=stats_sinks_json,json=statsSinksJson,proto3" json:"stats_sinks_json,omitempty"` - StatsConfigJson string `protobuf:"bytes,11,opt,name=stats_config_json,json=statsConfigJson,proto3" json:"stats_config_json,omitempty"` - StatsFlushInterval string `protobuf:"bytes,12,opt,name=stats_flush_interval,json=statsFlushInterval,proto3" json:"stats_flush_interval,omitempty"` - TracingConfigJson string `protobuf:"bytes,13,opt,name=tracing_config_json,json=tracingConfigJson,proto3" json:"tracing_config_json,omitempty"` -} - -func (x *BootstrapConfig) Reset() { - *x = BootstrapConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BootstrapConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BootstrapConfig) ProtoMessage() {} - -func (x *BootstrapConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[3] - 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 BootstrapConfig.ProtoReflect.Descriptor instead. -func (*BootstrapConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescGZIP(), []int{3} -} - -func (x *BootstrapConfig) GetStatsdUrl() string { - if x != nil { - return x.StatsdUrl - } - return "" -} - -func (x *BootstrapConfig) GetDogstatsdUrl() string { - if x != nil { - return x.DogstatsdUrl - } - return "" -} - -func (x *BootstrapConfig) GetStatsTags() []string { - if x != nil { - return x.StatsTags - } - return nil -} - -func (x *BootstrapConfig) GetPrometheusBindAddr() string { - if x != nil { - return x.PrometheusBindAddr - } - return "" -} - -func (x *BootstrapConfig) GetStatsBindAddr() string { - if x != nil { - return x.StatsBindAddr - } - return "" -} - -func (x *BootstrapConfig) GetReadyBindAddr() string { - if x != nil { - return x.ReadyBindAddr - } - return "" -} - -func (x *BootstrapConfig) GetOverrideJsonTpl() string { - if x != nil { - return x.OverrideJsonTpl - } - return "" -} - -func (x *BootstrapConfig) GetStaticClustersJson() string { - if x != nil { - return x.StaticClustersJson - } - return "" -} - -func (x *BootstrapConfig) GetStaticListenersJson() string { - if x != nil { - return x.StaticListenersJson - } - return "" -} - -func (x *BootstrapConfig) GetStatsSinksJson() string { - if x != nil { - return x.StatsSinksJson - } - return "" -} - -func (x *BootstrapConfig) GetStatsConfigJson() string { - if x != nil { - return x.StatsConfigJson - } - return "" -} - -func (x *BootstrapConfig) GetStatsFlushInterval() string { - if x != nil { - return x.StatsFlushInterval - } - return "" -} - -func (x *BootstrapConfig) GetTracingConfigJson() string { - if x != nil { - return x.TracingConfigJson - } - return "" -} - -// AccessLogsConfig contains the associated default settings for all Envoy -// instances within the datacenter or partition -type AccessLogsConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Enabled turns off all access logging - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - // DisableListenerLogs turns off just listener logs for connections rejected by Envoy because they don't - // have a matching listener filter. - DisableListenerLogs bool `protobuf:"varint,2,opt,name=disable_listener_logs,json=disableListenerLogs,proto3" json:"disable_listener_logs,omitempty"` - // Type selects the output for logs: "file", "stderr". "stdout" - Type LogSinkType `protobuf:"varint,3,opt,name=type,proto3,enum=hashicorp.consul.mesh.v1alpha1.LogSinkType" json:"type,omitempty"` - // Path is the output file to write logs - Path string `protobuf:"bytes,4,opt,name=path,proto3" json:"path,omitempty"` - // The presence of one format string or the other implies the access log string encoding. - // Defining Both is invalid. - JsonFormat string `protobuf:"bytes,5,opt,name=json_format,json=jsonFormat,proto3" json:"json_format,omitempty"` - TextFormat string `protobuf:"bytes,6,opt,name=text_format,json=textFormat,proto3" json:"text_format,omitempty"` -} - -func (x *AccessLogsConfig) Reset() { - *x = AccessLogsConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AccessLogsConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AccessLogsConfig) ProtoMessage() {} - -func (x *AccessLogsConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[4] - 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 AccessLogsConfig.ProtoReflect.Descriptor instead. -func (*AccessLogsConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescGZIP(), []int{4} -} - -func (x *AccessLogsConfig) GetEnabled() bool { - if x != nil { - return x.Enabled - } - return false -} - -func (x *AccessLogsConfig) GetDisableListenerLogs() bool { - if x != nil { - return x.DisableListenerLogs - } - return false -} - -func (x *AccessLogsConfig) GetType() LogSinkType { - if x != nil { - return x.Type - } - return LogSinkType_LOG_SINK_TYPE_DEFAULT -} - -func (x *AccessLogsConfig) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (x *AccessLogsConfig) GetJsonFormat() string { - if x != nil { - return x.JsonFormat - } - return "" -} - -func (x *AccessLogsConfig) GetTextFormat() string { - if x != nil { - return x.TextFormat - } - return "" -} - -// EnvoyExtension has configuration for an extension that patches Envoy resources. -type EnvoyExtension struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Required bool `protobuf:"varint,2,opt,name=required,proto3" json:"required,omitempty"` - Arguments *structpb.Struct `protobuf:"bytes,3,opt,name=arguments,proto3" json:"arguments,omitempty"` - ConsulVersion string `protobuf:"bytes,4,opt,name=consul_version,json=consulVersion,proto3" json:"consul_version,omitempty"` - EnvoyVersion string `protobuf:"bytes,5,opt,name=envoy_version,json=envoyVersion,proto3" json:"envoy_version,omitempty"` -} - -func (x *EnvoyExtension) Reset() { - *x = EnvoyExtension{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EnvoyExtension) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EnvoyExtension) ProtoMessage() {} - -func (x *EnvoyExtension) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[5] - 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 EnvoyExtension.ProtoReflect.Descriptor instead. -func (*EnvoyExtension) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescGZIP(), []int{5} -} - -func (x *EnvoyExtension) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *EnvoyExtension) GetRequired() bool { - if x != nil { - return x.Required - } - return false -} - -func (x *EnvoyExtension) GetArguments() *structpb.Struct { - if x != nil { - return x.Arguments - } - return nil -} - -func (x *EnvoyExtension) GetConsulVersion() string { - if x != nil { - return x.ConsulVersion - } - return "" -} - -func (x *EnvoyExtension) GetEnvoyVersion() string { - if x != nil { - return x.EnvoyVersion - } - return "" -} - -var File_pbmesh_v1alpha1_proxy_configuration_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_proxy_configuration_proto_rawDesc = []byte{ - 0x0a, 0x29, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x70, 0x62, 0x63, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x73, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x70, 0x62, - 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, - 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x70, 0x62, - 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x72, 0x6f, - 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdb, 0x02, 0x0a, 0x12, - 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x51, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, - 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, - 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, 0x54, 0x0a, 0x0e, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, - 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, - 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x64, 0x79, - 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5a, 0x0a, 0x10, 0x62, - 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0f, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, - 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x40, 0x0a, 0x0d, 0x6f, 0x70, 0x61, 0x71, 0x75, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0c, 0x6f, 0x70, 0x61, - 0x71, 0x75, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xf5, 0x09, 0x0a, 0x0d, 0x44, 0x79, - 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, 0x04, 0x6d, - 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x5d, 0x0a, 0x11, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x52, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x55, 0x0a, 0x0f, 0x6d, 0x75, 0x74, - 0x75, 0x61, 0x6c, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, - 0x65, 0x52, 0x0d, 0x6d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x6c, 0x73, 0x4d, 0x6f, 0x64, 0x65, - 0x12, 0x6d, 0x0a, 0x10, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x79, 0x6e, 0x61, - 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x69, 0x0a, 0x13, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x12, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5b, 0x0a, 0x11, 0x6d, 0x65, - 0x73, 0x68, 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0f, 0x6d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x51, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x51, 0x0a, 0x0b, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x59, 0x0a, - 0x10, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, - 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, - 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4c, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x15, 0x6c, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x6a, - 0x73, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x6c, 0x69, 0x73, 0x74, 0x65, - 0x6e, 0x65, 0x72, 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x2c, - 0x0a, 0x12, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, - 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x16, - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, - 0x52, 0x14, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x32, 0x0a, 0x13, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, - 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x0e, 0x20, - 0x01, 0x28, 0x0d, 0x42, 0x02, 0x18, 0x01, 0x52, 0x11, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x57, 0x6f, - 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x3f, 0x0a, 0x1a, 0x6c, 0x6f, - 0x63, 0x61, 0x6c, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, - 0x18, 0x01, 0x52, 0x17, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, - 0x64, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x1a, 0x74, 0x0a, 0x14, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x22, 0x71, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x34, 0x0a, 0x16, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x64, - 0x69, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x64, 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, - 0x63, 0x74, 0x6c, 0x79, 0x22, 0xc0, 0x04, 0x0a, 0x0f, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, - 0x61, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, - 0x73, 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, - 0x61, 0x74, 0x73, 0x64, 0x55, 0x72, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x6f, 0x67, 0x73, 0x74, - 0x61, 0x74, 0x73, 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x64, 0x6f, 0x67, 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, 0x55, 0x72, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, - 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x73, 0x54, 0x61, 0x67, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x70, - 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x70, 0x72, 0x6f, 0x6d, 0x65, - 0x74, 0x68, 0x65, 0x75, 0x73, 0x42, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x12, 0x26, 0x0a, - 0x0f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x42, 0x69, 0x6e, - 0x64, 0x41, 0x64, 0x64, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x62, - 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x72, 0x65, 0x61, 0x64, 0x79, 0x42, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x12, 0x2a, 0x0a, - 0x11, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x74, - 0x70, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x4a, 0x73, 0x6f, 0x6e, 0x54, 0x70, 0x6c, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x63, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x6a, 0x73, 0x6f, - 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x15, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x5f, - 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x63, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x4a, 0x73, 0x6f, 0x6e, 0x12, - 0x28, 0x0a, 0x10, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x73, 0x5f, 0x6a, - 0x73, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x73, - 0x53, 0x69, 0x6e, 0x6b, 0x73, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x74, 0x61, - 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x66, - 0x6c, 0x75, 0x73, 0x68, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x74, 0x61, 0x74, 0x73, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x63, 0x69, - 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x4a, 0x73, 0x6f, 0x6e, 0x22, 0xf7, 0x01, 0x0a, 0x10, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, - 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, - 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, - 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x3f, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x53, 0x69, 0x6e, - 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, - 0x1f, 0x0a, 0x0b, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6a, 0x73, 0x6f, 0x6e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, - 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x22, 0xc3, 0x01, 0x0a, 0x0e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x5f, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x6e, 0x76, 0x6f, 0x79, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2a, 0x56, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x4d, 0x4f, - 0x44, 0x45, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, - 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, - 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x50, 0x52, 0x4f, 0x58, - 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x02, 0x2a, - 0x74, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x53, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, - 0x0a, 0x15, 0x4c, 0x4f, 0x47, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x4f, 0x47, - 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, - 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4c, 0x4f, 0x47, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x53, 0x54, 0x44, 0x45, 0x52, 0x52, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x4c, - 0x4f, 0x47, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x44, - 0x4f, 0x55, 0x54, 0x10, 0x03, 0x2a, 0x68, 0x0a, 0x0d, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, - 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x55, 0x54, 0x55, 0x41, 0x4c, - 0x5f, 0x54, 0x4c, 0x53, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, - 0x54, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x4d, 0x55, 0x54, 0x55, 0x41, 0x4c, 0x5f, 0x54, 0x4c, - 0x53, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x43, 0x54, 0x10, 0x01, 0x12, - 0x1e, 0x0a, 0x1a, 0x4d, 0x55, 0x54, 0x55, 0x41, 0x4c, 0x5f, 0x54, 0x4c, 0x53, 0x5f, 0x4d, 0x4f, - 0x44, 0x45, 0x5f, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x56, 0x45, 0x10, 0x02, 0x42, - 0x9f, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x17, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x45, 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, 0x65, - 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, - 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, - 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescData = file_pbmesh_v1alpha1_proxy_configuration_proto_rawDesc -) - -func file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_proxy_configuration_proto_rawDescData -} - -var file_pbmesh_v1alpha1_proxy_configuration_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_pbmesh_v1alpha1_proxy_configuration_proto_goTypes = []interface{}{ - (ProxyMode)(0), // 0: hashicorp.consul.mesh.v1alpha1.ProxyMode - (LogSinkType)(0), // 1: hashicorp.consul.mesh.v1alpha1.LogSinkType - (MutualTLSMode)(0), // 2: hashicorp.consul.mesh.v1alpha1.MutualTLSMode - (*ProxyConfiguration)(nil), // 3: hashicorp.consul.mesh.v1alpha1.ProxyConfiguration - (*DynamicConfig)(nil), // 4: hashicorp.consul.mesh.v1alpha1.DynamicConfig - (*TransparentProxy)(nil), // 5: hashicorp.consul.mesh.v1alpha1.TransparentProxy - (*BootstrapConfig)(nil), // 6: hashicorp.consul.mesh.v1alpha1.BootstrapConfig - (*AccessLogsConfig)(nil), // 7: hashicorp.consul.mesh.v1alpha1.AccessLogsConfig - (*EnvoyExtension)(nil), // 8: hashicorp.consul.mesh.v1alpha1.EnvoyExtension - nil, // 9: hashicorp.consul.mesh.v1alpha1.DynamicConfig.LocalConnectionEntry - (*v1alpha1.WorkloadSelector)(nil), // 10: hashicorp.consul.catalog.v1alpha1.WorkloadSelector - (*structpb.Struct)(nil), // 11: google.protobuf.Struct - (*InboundConnectionsConfig)(nil), // 12: hashicorp.consul.mesh.v1alpha1.InboundConnectionsConfig - (MeshGatewayMode)(0), // 13: hashicorp.consul.mesh.v1alpha1.MeshGatewayMode - (*ExposeConfig)(nil), // 14: hashicorp.consul.mesh.v1alpha1.ExposeConfig - (*ConnectionConfig)(nil), // 15: hashicorp.consul.mesh.v1alpha1.ConnectionConfig -} -var file_pbmesh_v1alpha1_proxy_configuration_proto_depIdxs = []int32{ - 10, // 0: hashicorp.consul.mesh.v1alpha1.ProxyConfiguration.workloads:type_name -> hashicorp.consul.catalog.v1alpha1.WorkloadSelector - 4, // 1: hashicorp.consul.mesh.v1alpha1.ProxyConfiguration.dynamic_config:type_name -> hashicorp.consul.mesh.v1alpha1.DynamicConfig - 6, // 2: hashicorp.consul.mesh.v1alpha1.ProxyConfiguration.bootstrap_config:type_name -> hashicorp.consul.mesh.v1alpha1.BootstrapConfig - 11, // 3: hashicorp.consul.mesh.v1alpha1.ProxyConfiguration.opaque_config:type_name -> google.protobuf.Struct - 0, // 4: hashicorp.consul.mesh.v1alpha1.DynamicConfig.mode:type_name -> hashicorp.consul.mesh.v1alpha1.ProxyMode - 5, // 5: hashicorp.consul.mesh.v1alpha1.DynamicConfig.transparent_proxy:type_name -> hashicorp.consul.mesh.v1alpha1.TransparentProxy - 2, // 6: hashicorp.consul.mesh.v1alpha1.DynamicConfig.mutual_tls_mode:type_name -> hashicorp.consul.mesh.v1alpha1.MutualTLSMode - 9, // 7: hashicorp.consul.mesh.v1alpha1.DynamicConfig.local_connection:type_name -> hashicorp.consul.mesh.v1alpha1.DynamicConfig.LocalConnectionEntry - 12, // 8: hashicorp.consul.mesh.v1alpha1.DynamicConfig.inbound_connections:type_name -> hashicorp.consul.mesh.v1alpha1.InboundConnectionsConfig - 13, // 9: hashicorp.consul.mesh.v1alpha1.DynamicConfig.mesh_gateway_mode:type_name -> hashicorp.consul.mesh.v1alpha1.MeshGatewayMode - 14, // 10: hashicorp.consul.mesh.v1alpha1.DynamicConfig.expose_config:type_name -> hashicorp.consul.mesh.v1alpha1.ExposeConfig - 7, // 11: hashicorp.consul.mesh.v1alpha1.DynamicConfig.access_logs:type_name -> hashicorp.consul.mesh.v1alpha1.AccessLogsConfig - 8, // 12: hashicorp.consul.mesh.v1alpha1.DynamicConfig.envoy_extensions:type_name -> hashicorp.consul.mesh.v1alpha1.EnvoyExtension - 1, // 13: hashicorp.consul.mesh.v1alpha1.AccessLogsConfig.type:type_name -> hashicorp.consul.mesh.v1alpha1.LogSinkType - 11, // 14: hashicorp.consul.mesh.v1alpha1.EnvoyExtension.arguments:type_name -> google.protobuf.Struct - 15, // 15: hashicorp.consul.mesh.v1alpha1.DynamicConfig.LocalConnectionEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.ConnectionConfig - 16, // [16:16] is the sub-list for method output_type - 16, // [16:16] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_proxy_configuration_proto_init() } -func file_pbmesh_v1alpha1_proxy_configuration_proto_init() { - if File_pbmesh_v1alpha1_proxy_configuration_proto != nil { - return - } - file_pbmesh_v1alpha1_connection_proto_init() - file_pbmesh_v1alpha1_expose_proto_init() - file_pbmesh_v1alpha1_routing_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProxyConfiguration); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DynamicConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransparentProxy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BootstrapConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AccessLogsConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EnvoyExtension); 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_pbmesh_v1alpha1_proxy_configuration_proto_rawDesc, - NumEnums: 3, - NumMessages: 7, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_proxy_configuration_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_proxy_configuration_proto_depIdxs, - EnumInfos: file_pbmesh_v1alpha1_proxy_configuration_proto_enumTypes, - MessageInfos: file_pbmesh_v1alpha1_proxy_configuration_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_proxy_configuration_proto = out.File - file_pbmesh_v1alpha1_proxy_configuration_proto_rawDesc = nil - file_pbmesh_v1alpha1_proxy_configuration_proto_goTypes = nil - file_pbmesh_v1alpha1_proxy_configuration_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/proxy_state.pb.binary.go b/proto-public/pbmesh/v1alpha1/proxy_state.pb.binary.go deleted file mode 100644 index 747ffba080448..0000000000000 --- a/proto-public/pbmesh/v1alpha1/proxy_state.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/proxy_state.proto - -package meshv1alpha1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ProxyStateTemplate) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ProxyStateTemplate) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ProxyState) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ProxyState) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/proxy_state.pb.go b/proto-public/pbmesh/v1alpha1/proxy_state.pb.go deleted file mode 100644 index 59337a5fffbce..0000000000000 --- a/proto-public/pbmesh/v1alpha1/proxy_state.pb.go +++ /dev/null @@ -1,563 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/proxy_state.proto - -package meshv1alpha1 - -import ( - pbproxystate "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1/pbproxystate" - 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 ProxyStateTemplate struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // proxy_state is the partially filled out ProxyState resource. The Endpoints, LeafCertificates and TrustBundles fields will need filling in after the resource is stored. - ProxyState *ProxyState `protobuf:"bytes,1,opt,name=proxy_state,json=proxyState,proto3" json:"proxy_state,omitempty"` - // required_endpoints is a map of arbitrary string names to endpoint refs that need fetching by the proxy state controller. - RequiredEndpoints map[string]*pbproxystate.EndpointRef `protobuf:"bytes,2,rep,name=required_endpoints,json=requiredEndpoints,proto3" json:"required_endpoints,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // required_leaf_certificates is a map of arbitrary string names to leaf certificates that need fetching/generation by the proxy state controller. - RequiredLeafCertificates map[string]*pbproxystate.LeafCertificateRef `protobuf:"bytes,3,rep,name=required_leaf_certificates,json=requiredLeafCertificates,proto3" json:"required_leaf_certificates,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // required_trust_bundles is a map of arbitrary string names to trust bundle refs that need fetching by the proxy state controller. - RequiredTrustBundles map[string]*pbproxystate.TrustBundleRef `protobuf:"bytes,4,rep,name=required_trust_bundles,json=requiredTrustBundles,proto3" json:"required_trust_bundles,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *ProxyStateTemplate) Reset() { - *x = ProxyStateTemplate{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_proxy_state_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProxyStateTemplate) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProxyStateTemplate) ProtoMessage() {} - -func (x *ProxyStateTemplate) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_proxy_state_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 ProxyStateTemplate.ProtoReflect.Descriptor instead. -func (*ProxyStateTemplate) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_proxy_state_proto_rawDescGZIP(), []int{0} -} - -func (x *ProxyStateTemplate) GetProxyState() *ProxyState { - if x != nil { - return x.ProxyState - } - return nil -} - -func (x *ProxyStateTemplate) GetRequiredEndpoints() map[string]*pbproxystate.EndpointRef { - if x != nil { - return x.RequiredEndpoints - } - return nil -} - -func (x *ProxyStateTemplate) GetRequiredLeafCertificates() map[string]*pbproxystate.LeafCertificateRef { - if x != nil { - return x.RequiredLeafCertificates - } - return nil -} - -func (x *ProxyStateTemplate) GetRequiredTrustBundles() map[string]*pbproxystate.TrustBundleRef { - if x != nil { - return x.RequiredTrustBundles - } - return nil -} - -type ProxyState struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // identity is a reference to the identity of the workload this proxy is for. - Identity *pbresource.Reference `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` - // listeners is a list of listeners for this proxy. - Listeners []*pbproxystate.Listener `protobuf:"bytes,2,rep,name=listeners,proto3" json:"listeners,omitempty"` - // clusters is a map from cluster name to clusters. The keys are referenced from listeners or routes. - Clusters map[string]*pbproxystate.Cluster `protobuf:"bytes,3,rep,name=clusters,proto3" json:"clusters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // routes is a map from route name to routes. The keys are referenced from listeners. - Routes map[string]*pbproxystate.Route `protobuf:"bytes,4,rep,name=routes,proto3" json:"routes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // endpoints is a map from cluster name to endpoints. - Endpoints map[string]*pbproxystate.Endpoints `protobuf:"bytes,5,rep,name=endpoints,proto3" json:"endpoints,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // leaf certificates is a map from UUID to leaf certificates. - LeafCertificates map[string]*pbproxystate.LeafCertificate `protobuf:"bytes,6,rep,name=leaf_certificates,json=leafCertificates,proto3" json:"leaf_certificates,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // trust bundles is a map from peer name to trust bundles. - TrustBundles map[string]*pbproxystate.TrustBundle `protobuf:"bytes,7,rep,name=trust_bundles,json=trustBundles,proto3" json:"trust_bundles,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // tls has TLS configuration for this proxy. - Tls *pbproxystate.TLS `protobuf:"bytes,8,opt,name=tls,proto3" json:"tls,omitempty"` - // intention_default_allow is the default action for intentions. This determines how the Envoy RBAC filters are generated. - IntentionDefaultAllow bool `protobuf:"varint,9,opt,name=intention_default_allow,json=intentionDefaultAllow,proto3" json:"intention_default_allow,omitempty"` - // escape defines top level escape hatches. These are user configured json strings that configure an entire piece of listener or cluster Envoy configuration. - Escape *pbproxystate.EscapeHatches `protobuf:"bytes,10,opt,name=escape,proto3" json:"escape,omitempty"` - // access_logs configures access logging for this proxy. - AccessLogs *pbproxystate.AccessLogs `protobuf:"bytes,11,opt,name=access_logs,json=accessLogs,proto3" json:"access_logs,omitempty"` -} - -func (x *ProxyState) Reset() { - *x = ProxyState{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_proxy_state_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProxyState) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProxyState) ProtoMessage() {} - -func (x *ProxyState) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_proxy_state_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 ProxyState.ProtoReflect.Descriptor instead. -func (*ProxyState) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_proxy_state_proto_rawDescGZIP(), []int{1} -} - -func (x *ProxyState) GetIdentity() *pbresource.Reference { - if x != nil { - return x.Identity - } - return nil -} - -func (x *ProxyState) GetListeners() []*pbproxystate.Listener { - if x != nil { - return x.Listeners - } - return nil -} - -func (x *ProxyState) GetClusters() map[string]*pbproxystate.Cluster { - if x != nil { - return x.Clusters - } - return nil -} - -func (x *ProxyState) GetRoutes() map[string]*pbproxystate.Route { - if x != nil { - return x.Routes - } - return nil -} - -func (x *ProxyState) GetEndpoints() map[string]*pbproxystate.Endpoints { - if x != nil { - return x.Endpoints - } - return nil -} - -func (x *ProxyState) GetLeafCertificates() map[string]*pbproxystate.LeafCertificate { - if x != nil { - return x.LeafCertificates - } - return nil -} - -func (x *ProxyState) GetTrustBundles() map[string]*pbproxystate.TrustBundle { - if x != nil { - return x.TrustBundles - } - return nil -} - -func (x *ProxyState) GetTls() *pbproxystate.TLS { - if x != nil { - return x.Tls - } - return nil -} - -func (x *ProxyState) GetIntentionDefaultAllow() bool { - if x != nil { - return x.IntentionDefaultAllow - } - return false -} - -func (x *ProxyState) GetEscape() *pbproxystate.EscapeHatches { - if x != nil { - return x.Escape - } - return nil -} - -func (x *ProxyState) GetAccessLogs() *pbproxystate.AccessLogs { - if x != nil { - return x.AccessLogs - } - return nil -} - -var File_pbmesh_v1alpha1_proxy_state_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_proxy_state_proto_rawDesc = []byte{ - 0x0a, 0x21, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x1a, 0x2e, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x2c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x65, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x31, 0x70, - 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x65, 0x73, 0x63, 0x61, - 0x70, 0x65, 0x5f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x2b, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x6c, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2d, 0x70, - 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x72, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x28, 0x70, 0x62, - 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x33, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 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, 0x87, 0x07, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x4b, 0x0a, - 0x0b, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x78, 0x0a, 0x12, 0x72, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x11, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x1a, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, - 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x50, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x18, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x82, 0x01, 0x0a, 0x16, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, - 0x65, 0x64, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x54, 0x72, - 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x1a, 0x7e, 0x0a, 0x16, 0x52, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x8c, 0x01, 0x0a, 0x1d, 0x52, - 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x55, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x65, 0x61, 0x66, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x66, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x84, 0x01, 0x0a, 0x19, 0x52, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x51, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x52, 0x65, 0x66, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0xf5, 0x0b, 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, - 0x40, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 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, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x12, 0x53, 0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x6c, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x54, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x4e, 0x0a, 0x06, - 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, - 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x57, 0x0a, 0x09, - 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x45, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x6d, 0x0a, 0x11, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x63, 0x65, - 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x65, 0x61, - 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x10, 0x6c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x73, 0x12, 0x61, 0x0a, 0x0d, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x62, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, - 0x64, 0x6c, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x74, 0x72, 0x75, 0x73, 0x74, - 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x03, 0x74, 0x6c, 0x73, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x54, 0x4c, 0x53, 0x52, 0x03, 0x74, 0x6c, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x69, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x69, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x6c, - 0x6c, 0x6f, 0x77, 0x12, 0x52, 0x0a, 0x06, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x48, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x52, - 0x06, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x12, 0x58, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, - 0x73, 0x1a, 0x71, 0x0a, 0x0d, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6d, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x48, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x1a, 0x74, 0x0a, 0x0e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x81, 0x01, 0x0a, 0x15, 0x4c, 0x65, - 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x52, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x79, 0x0a, - 0x11, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x97, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, - 0x0f, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x45, 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, - 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, - 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, - 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_proxy_state_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_proxy_state_proto_rawDescData = file_pbmesh_v1alpha1_proxy_state_proto_rawDesc -) - -func file_pbmesh_v1alpha1_proxy_state_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_proxy_state_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_proxy_state_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_proxy_state_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_proxy_state_proto_rawDescData -} - -var file_pbmesh_v1alpha1_proxy_state_proto_msgTypes = make([]protoimpl.MessageInfo, 10) -var file_pbmesh_v1alpha1_proxy_state_proto_goTypes = []interface{}{ - (*ProxyStateTemplate)(nil), // 0: hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate - (*ProxyState)(nil), // 1: hashicorp.consul.mesh.v1alpha1.ProxyState - nil, // 2: hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate.RequiredEndpointsEntry - nil, // 3: hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate.RequiredLeafCertificatesEntry - nil, // 4: hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate.RequiredTrustBundlesEntry - nil, // 5: hashicorp.consul.mesh.v1alpha1.ProxyState.ClustersEntry - nil, // 6: hashicorp.consul.mesh.v1alpha1.ProxyState.RoutesEntry - nil, // 7: hashicorp.consul.mesh.v1alpha1.ProxyState.EndpointsEntry - nil, // 8: hashicorp.consul.mesh.v1alpha1.ProxyState.LeafCertificatesEntry - nil, // 9: hashicorp.consul.mesh.v1alpha1.ProxyState.TrustBundlesEntry - (*pbresource.Reference)(nil), // 10: hashicorp.consul.resource.Reference - (*pbproxystate.Listener)(nil), // 11: hashicorp.consul.mesh.v1alpha1.pbproxystate.Listener - (*pbproxystate.TLS)(nil), // 12: hashicorp.consul.mesh.v1alpha1.pbproxystate.TLS - (*pbproxystate.EscapeHatches)(nil), // 13: hashicorp.consul.mesh.v1alpha1.pbproxystate.EscapeHatches - (*pbproxystate.AccessLogs)(nil), // 14: hashicorp.consul.mesh.v1alpha1.pbproxystate.AccessLogs - (*pbproxystate.EndpointRef)(nil), // 15: hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointRef - (*pbproxystate.LeafCertificateRef)(nil), // 16: hashicorp.consul.mesh.v1alpha1.pbproxystate.LeafCertificateRef - (*pbproxystate.TrustBundleRef)(nil), // 17: hashicorp.consul.mesh.v1alpha1.pbproxystate.TrustBundleRef - (*pbproxystate.Cluster)(nil), // 18: hashicorp.consul.mesh.v1alpha1.pbproxystate.Cluster - (*pbproxystate.Route)(nil), // 19: hashicorp.consul.mesh.v1alpha1.pbproxystate.Route - (*pbproxystate.Endpoints)(nil), // 20: hashicorp.consul.mesh.v1alpha1.pbproxystate.Endpoints - (*pbproxystate.LeafCertificate)(nil), // 21: hashicorp.consul.mesh.v1alpha1.pbproxystate.LeafCertificate - (*pbproxystate.TrustBundle)(nil), // 22: hashicorp.consul.mesh.v1alpha1.pbproxystate.TrustBundle -} -var file_pbmesh_v1alpha1_proxy_state_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate.proxy_state:type_name -> hashicorp.consul.mesh.v1alpha1.ProxyState - 2, // 1: hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate.required_endpoints:type_name -> hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate.RequiredEndpointsEntry - 3, // 2: hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate.required_leaf_certificates:type_name -> hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate.RequiredLeafCertificatesEntry - 4, // 3: hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate.required_trust_bundles:type_name -> hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate.RequiredTrustBundlesEntry - 10, // 4: hashicorp.consul.mesh.v1alpha1.ProxyState.identity:type_name -> hashicorp.consul.resource.Reference - 11, // 5: hashicorp.consul.mesh.v1alpha1.ProxyState.listeners:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.Listener - 5, // 6: hashicorp.consul.mesh.v1alpha1.ProxyState.clusters:type_name -> hashicorp.consul.mesh.v1alpha1.ProxyState.ClustersEntry - 6, // 7: hashicorp.consul.mesh.v1alpha1.ProxyState.routes:type_name -> hashicorp.consul.mesh.v1alpha1.ProxyState.RoutesEntry - 7, // 8: hashicorp.consul.mesh.v1alpha1.ProxyState.endpoints:type_name -> hashicorp.consul.mesh.v1alpha1.ProxyState.EndpointsEntry - 8, // 9: hashicorp.consul.mesh.v1alpha1.ProxyState.leaf_certificates:type_name -> hashicorp.consul.mesh.v1alpha1.ProxyState.LeafCertificatesEntry - 9, // 10: hashicorp.consul.mesh.v1alpha1.ProxyState.trust_bundles:type_name -> hashicorp.consul.mesh.v1alpha1.ProxyState.TrustBundlesEntry - 12, // 11: hashicorp.consul.mesh.v1alpha1.ProxyState.tls:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TLS - 13, // 12: hashicorp.consul.mesh.v1alpha1.ProxyState.escape:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.EscapeHatches - 14, // 13: hashicorp.consul.mesh.v1alpha1.ProxyState.access_logs:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.AccessLogs - 15, // 14: hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate.RequiredEndpointsEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.EndpointRef - 16, // 15: hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate.RequiredLeafCertificatesEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LeafCertificateRef - 17, // 16: hashicorp.consul.mesh.v1alpha1.ProxyStateTemplate.RequiredTrustBundlesEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TrustBundleRef - 18, // 17: hashicorp.consul.mesh.v1alpha1.ProxyState.ClustersEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.Cluster - 19, // 18: hashicorp.consul.mesh.v1alpha1.ProxyState.RoutesEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.Route - 20, // 19: hashicorp.consul.mesh.v1alpha1.ProxyState.EndpointsEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.Endpoints - 21, // 20: hashicorp.consul.mesh.v1alpha1.ProxyState.LeafCertificatesEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.LeafCertificate - 22, // 21: hashicorp.consul.mesh.v1alpha1.ProxyState.TrustBundlesEntry.value:type_name -> hashicorp.consul.mesh.v1alpha1.pbproxystate.TrustBundle - 22, // [22:22] is the sub-list for method output_type - 22, // [22:22] is the sub-list for method input_type - 22, // [22:22] is the sub-list for extension type_name - 22, // [22:22] is the sub-list for extension extendee - 0, // [0:22] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_proxy_state_proto_init() } -func file_pbmesh_v1alpha1_proxy_state_proto_init() { - if File_pbmesh_v1alpha1_proxy_state_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_proxy_state_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProxyStateTemplate); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_proxy_state_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProxyState); 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_pbmesh_v1alpha1_proxy_state_proto_rawDesc, - NumEnums: 0, - NumMessages: 10, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_proxy_state_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_proxy_state_proto_depIdxs, - MessageInfos: file_pbmesh_v1alpha1_proxy_state_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_proxy_state_proto = out.File - file_pbmesh_v1alpha1_proxy_state_proto_rawDesc = nil - file_pbmesh_v1alpha1_proxy_state_proto_goTypes = nil - file_pbmesh_v1alpha1_proxy_state_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/proxy_state.proto b/proto-public/pbmesh/v1alpha1/proxy_state.proto deleted file mode 100644 index a97b54ddc4100..0000000000000 --- a/proto-public/pbmesh/v1alpha1/proxy_state.proto +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1; - -import "pbmesh/v1alpha1/pbproxystate/access_logs.proto"; -import "pbmesh/v1alpha1/pbproxystate/cluster.proto"; -import "pbmesh/v1alpha1/pbproxystate/endpoints.proto"; -import "pbmesh/v1alpha1/pbproxystate/escape_hatches.proto"; -import "pbmesh/v1alpha1/pbproxystate/listener.proto"; -import "pbmesh/v1alpha1/pbproxystate/references.proto"; -import "pbmesh/v1alpha1/pbproxystate/route.proto"; -import "pbmesh/v1alpha1/pbproxystate/transport_socket.proto"; -import "pbresource/resource.proto"; - -message ProxyStateTemplate { - // proxy_state is the partially filled out ProxyState resource. The Endpoints, LeafCertificates and TrustBundles fields will need filling in after the resource is stored. - ProxyState proxy_state = 1; - - // required_endpoints is a map of arbitrary string names to endpoint refs that need fetching by the proxy state controller. - map required_endpoints = 2; - - // required_leaf_certificates is a map of arbitrary string names to leaf certificates that need fetching/generation by the proxy state controller. - map required_leaf_certificates = 3; - - // required_trust_bundles is a map of arbitrary string names to trust bundle refs that need fetching by the proxy state controller. - map required_trust_bundles = 4; -} - -message ProxyState { - // identity is a reference to the identity of the workload this proxy is for. - hashicorp.consul.resource.Reference identity = 1; - // listeners is a list of listeners for this proxy. - repeated pbproxystate.Listener listeners = 2; - // clusters is a map from cluster name to clusters. The keys are referenced from listeners or routes. - map clusters = 3; - // routes is a map from route name to routes. The keys are referenced from listeners. - map routes = 4; - // endpoints is a map from cluster name to endpoints. - map endpoints = 5; - // leaf certificates is a map from UUID to leaf certificates. - map leaf_certificates = 6; - // trust bundles is a map from peer name to trust bundles. - map trust_bundles = 7; - // tls has TLS configuration for this proxy. - pbproxystate.TLS tls = 8; - // intention_default_allow is the default action for intentions. This determines how the Envoy RBAC filters are generated. - bool intention_default_allow = 9; - // escape defines top level escape hatches. These are user configured json strings that configure an entire piece of listener or cluster Envoy configuration. - pbproxystate.EscapeHatches escape = 10; - // access_logs configures access logging for this proxy. - pbproxystate.AccessLogs access_logs = 11; -} diff --git a/proto-public/pbmesh/v1alpha1/tcp_route.pb.binary.go b/proto-public/pbmesh/v1alpha1/tcp_route.pb.binary.go deleted file mode 100644 index 6a7885b9ca72b..0000000000000 --- a/proto-public/pbmesh/v1alpha1/tcp_route.pb.binary.go +++ /dev/null @@ -1,38 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/tcp_route.proto - -package meshv1alpha1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TCPRoute) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TCPRoute) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TCPRouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TCPRouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TCPBackendRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TCPBackendRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/tcp_route.pb.go b/proto-public/pbmesh/v1alpha1/tcp_route.pb.go deleted file mode 100644 index 6a8cf5700fc4d..0000000000000 --- a/proto-public/pbmesh/v1alpha1/tcp_route.pb.go +++ /dev/null @@ -1,362 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/tcp_route.proto - -package meshv1alpha1 - -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) -) - -// NOTE: this should align to the GAMMA/gateway-api version, or at least be -// easily translatable. -// -// https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.TCPRoute -// -// This is a Resource type. -type TCPRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ParentRefs references the resources (usually Gateways) that a Route wants - // to be attached to. Note that the referenced parent resource needs to allow - // this for the attachment to be complete. For Gateways, that means the - // Gateway needs to allow attachment from Routes of this kind and namespace. - // - // It is invalid to reference an identical parent more than once. It is valid - // to reference multiple distinct sections within the same parent resource, - // such as 2 Listeners within a Gateway. - ParentRefs []*ParentReference `protobuf:"bytes,1,rep,name=parent_refs,json=parentRefs,proto3" json:"parent_refs,omitempty"` - // Rules are a list of TCP matchers and actions. - Rules []*TCPRouteRule `protobuf:"bytes,2,rep,name=rules,proto3" json:"rules,omitempty"` -} - -func (x *TCPRoute) Reset() { - *x = TCPRoute{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_tcp_route_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TCPRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TCPRoute) ProtoMessage() {} - -func (x *TCPRoute) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_tcp_route_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 TCPRoute.ProtoReflect.Descriptor instead. -func (*TCPRoute) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_tcp_route_proto_rawDescGZIP(), []int{0} -} - -func (x *TCPRoute) GetParentRefs() []*ParentReference { - if x != nil { - return x.ParentRefs - } - return nil -} - -func (x *TCPRoute) GetRules() []*TCPRouteRule { - if x != nil { - return x.Rules - } - return nil -} - -type TCPRouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // BackendRefs defines the backend(s) where matching requests should be sent. - // If unspecified or invalid (refers to a non-existent resource or a Service - // with no endpoints), the underlying implementation MUST actively reject - // connection attempts to this backend. Connection rejections must respect - // weight; if an invalid backend is requested to have 80% of connections, - // then 80% of connections must be rejected instead. - BackendRefs []*TCPBackendRef `protobuf:"bytes,1,rep,name=backend_refs,json=backendRefs,proto3" json:"backend_refs,omitempty"` -} - -func (x *TCPRouteRule) Reset() { - *x = TCPRouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_tcp_route_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TCPRouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TCPRouteRule) ProtoMessage() {} - -func (x *TCPRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_tcp_route_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 TCPRouteRule.ProtoReflect.Descriptor instead. -func (*TCPRouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_tcp_route_proto_rawDescGZIP(), []int{1} -} - -func (x *TCPRouteRule) GetBackendRefs() []*TCPBackendRef { - if x != nil { - return x.BackendRefs - } - return nil -} - -type TCPBackendRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BackendRef *BackendReference `protobuf:"bytes,1,opt,name=backend_ref,json=backendRef,proto3" json:"backend_ref,omitempty"` - // Weight specifies the proportion of requests forwarded to the referenced - // backend. This is computed as weight/(sum of all weights in this - // BackendRefs list). For non-zero values, there may be some epsilon from the - // exact proportion defined here depending on the precision an implementation - // supports. Weight is not a percentage and the sum of weights does not need - // to equal 100. - // - // If only one backend is specified and it has a weight greater than 0, 100% - // of the traffic is forwarded to that backend. If weight is set to 0, no - // traffic should be forwarded for this entry. If unspecified, weight defaults - // to 1. - Weight uint32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` -} - -func (x *TCPBackendRef) Reset() { - *x = TCPBackendRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_tcp_route_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TCPBackendRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TCPBackendRef) ProtoMessage() {} - -func (x *TCPBackendRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_tcp_route_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 TCPBackendRef.ProtoReflect.Descriptor instead. -func (*TCPBackendRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_tcp_route_proto_rawDescGZIP(), []int{2} -} - -func (x *TCPBackendRef) GetBackendRef() *BackendReference { - if x != nil { - return x.BackendRef - } - return nil -} - -func (x *TCPBackendRef) GetWeight() uint32 { - if x != nil { - return x.Weight - } - return 0 -} - -var File_pbmesh_v1alpha1_tcp_route_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_tcp_route_proto_rawDesc = []byte{ - 0x0a, 0x1f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x74, 0x63, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x1a, 0x1c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xa0, 0x01, 0x0a, 0x08, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x50, 0x0a, 0x0b, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x73, 0x12, 0x42, - 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, - 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, - 0x65, 0x73, 0x22, 0x60, 0x0a, 0x0c, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, - 0x6c, 0x65, 0x12, 0x50, 0x0a, 0x0c, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, - 0x66, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x43, 0x50, 0x42, 0x61, 0x63, - 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x52, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, - 0x52, 0x65, 0x66, 0x73, 0x22, 0x7a, 0x0a, 0x0d, 0x54, 0x43, 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, - 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x51, 0x0a, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, - 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, - 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x62, 0x61, - 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x42, 0x95, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0d, 0x54, 0x63, 0x70, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, - 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, - 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, - 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_tcp_route_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_tcp_route_proto_rawDescData = file_pbmesh_v1alpha1_tcp_route_proto_rawDesc -) - -func file_pbmesh_v1alpha1_tcp_route_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_tcp_route_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_tcp_route_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_tcp_route_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_tcp_route_proto_rawDescData -} - -var file_pbmesh_v1alpha1_tcp_route_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_pbmesh_v1alpha1_tcp_route_proto_goTypes = []interface{}{ - (*TCPRoute)(nil), // 0: hashicorp.consul.mesh.v1alpha1.TCPRoute - (*TCPRouteRule)(nil), // 1: hashicorp.consul.mesh.v1alpha1.TCPRouteRule - (*TCPBackendRef)(nil), // 2: hashicorp.consul.mesh.v1alpha1.TCPBackendRef - (*ParentReference)(nil), // 3: hashicorp.consul.mesh.v1alpha1.ParentReference - (*BackendReference)(nil), // 4: hashicorp.consul.mesh.v1alpha1.BackendReference -} -var file_pbmesh_v1alpha1_tcp_route_proto_depIdxs = []int32{ - 3, // 0: hashicorp.consul.mesh.v1alpha1.TCPRoute.parent_refs:type_name -> hashicorp.consul.mesh.v1alpha1.ParentReference - 1, // 1: hashicorp.consul.mesh.v1alpha1.TCPRoute.rules:type_name -> hashicorp.consul.mesh.v1alpha1.TCPRouteRule - 2, // 2: hashicorp.consul.mesh.v1alpha1.TCPRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v1alpha1.TCPBackendRef - 4, // 3: hashicorp.consul.mesh.v1alpha1.TCPBackendRef.backend_ref:type_name -> hashicorp.consul.mesh.v1alpha1.BackendReference - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_tcp_route_proto_init() } -func file_pbmesh_v1alpha1_tcp_route_proto_init() { - if File_pbmesh_v1alpha1_tcp_route_proto != nil { - return - } - file_pbmesh_v1alpha1_common_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_tcp_route_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TCPRoute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_tcp_route_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TCPRouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_tcp_route_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TCPBackendRef); 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_pbmesh_v1alpha1_tcp_route_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_tcp_route_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_tcp_route_proto_depIdxs, - MessageInfos: file_pbmesh_v1alpha1_tcp_route_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_tcp_route_proto = out.File - file_pbmesh_v1alpha1_tcp_route_proto_rawDesc = nil - file_pbmesh_v1alpha1_tcp_route_proto_goTypes = nil - file_pbmesh_v1alpha1_tcp_route_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/tcp_route.proto b/proto-public/pbmesh/v1alpha1/tcp_route.proto deleted file mode 100644 index 0a6c974c046b6..0000000000000 --- a/proto-public/pbmesh/v1alpha1/tcp_route.proto +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1; - -import "pbmesh/v1alpha1/common.proto"; - -// NOTE: this should align to the GAMMA/gateway-api version, or at least be -// easily translatable. -// -// https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.TCPRoute -// -// This is a Resource type. -message TCPRoute { - // ParentRefs references the resources (usually Gateways) that a Route wants - // to be attached to. Note that the referenced parent resource needs to allow - // this for the attachment to be complete. For Gateways, that means the - // Gateway needs to allow attachment from Routes of this kind and namespace. - // - // It is invalid to reference an identical parent more than once. It is valid - // to reference multiple distinct sections within the same parent resource, - // such as 2 Listeners within a Gateway. - repeated ParentReference parent_refs = 1; - - // Rules are a list of TCP matchers and actions. - repeated TCPRouteRule rules = 2; -} - -message TCPRouteRule { - // BackendRefs defines the backend(s) where matching requests should be sent. - // If unspecified or invalid (refers to a non-existent resource or a Service - // with no endpoints), the underlying implementation MUST actively reject - // connection attempts to this backend. Connection rejections must respect - // weight; if an invalid backend is requested to have 80% of connections, - // then 80% of connections must be rejected instead. - repeated TCPBackendRef backend_refs = 1; -} - -message TCPBackendRef { - BackendReference backend_ref = 1; - - // Weight specifies the proportion of requests forwarded to the referenced - // backend. This is computed as weight/(sum of all weights in this - // BackendRefs list). For non-zero values, there may be some epsilon from the - // exact proportion defined here depending on the precision an implementation - // supports. Weight is not a percentage and the sum of weights does not need - // to equal 100. - // - //If only one backend is specified and it has a weight greater than 0, 100% - //of the traffic is forwarded to that backend. If weight is set to 0, no - //traffic should be forwarded for this entry. If unspecified, weight defaults - //to 1. - uint32 weight = 2; -} diff --git a/proto-public/pbmesh/v1alpha1/upstreams.pb.binary.go b/proto-public/pbmesh/v1alpha1/upstreams.pb.binary.go index d67b41e3a9d0e..cc8214e75a687 100644 --- a/proto-public/pbmesh/v1alpha1/upstreams.pb.binary.go +++ b/proto-public/pbmesh/v1alpha1/upstreams.pb.binary.go @@ -28,12 +28,12 @@ func (msg *Upstream) UnmarshalBinary(b []byte) error { } // MarshalBinary implements encoding.BinaryMarshaler -func (msg *IPPortAddress) MarshalBinary() ([]byte, error) { +func (msg *TCPAddress) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) } // UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *IPPortAddress) UnmarshalBinary(b []byte) error { +func (msg *TCPAddress) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } @@ -56,3 +56,33 @@ func (msg *PreparedQueryUpstream) MarshalBinary() ([]byte, error) { func (msg *PreparedQueryUpstream) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *UpstreamConfig) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *UpstreamConfig) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *UpstreamLimits) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *UpstreamLimits) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *PassiveHealthCheck) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *PassiveHealthCheck) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} diff --git a/proto-public/pbmesh/v1alpha1/upstreams.pb.go b/proto-public/pbmesh/v1alpha1/upstreams.pb.go index e8e9e4f9cf89e..575fe43006e46 100644 --- a/proto-public/pbmesh/v1alpha1/upstreams.pb.go +++ b/proto-public/pbmesh/v1alpha1/upstreams.pb.go @@ -14,6 +14,7 @@ import ( pbresource "github.com/hashicorp/consul/proto-public/pbresource" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + durationpb "google.golang.org/protobuf/types/known/durationpb" reflect "reflect" sync "sync" ) @@ -32,12 +33,10 @@ type Upstreams struct { // Selection of workloads these upstreams should apply to. // These can be prefixes or specific workload names. - Workloads *v1alpha1.WorkloadSelector `protobuf:"bytes,1,opt,name=workloads,proto3" json:"workloads,omitempty"` - // upstreams is the list of explicit upstreams to define for the selected workloads. - Upstreams []*Upstream `protobuf:"bytes,2,rep,name=upstreams,proto3" json:"upstreams,omitempty"` - // pq_upstreams is the list of prepared query upstreams. This field is not supported directly in v2 - // and should only be used for migration reasons. - PqUpstreams []*PreparedQueryUpstream `protobuf:"bytes,3,rep,name=pq_upstreams,json=pqUpstreams,proto3" json:"pq_upstreams,omitempty"` + Workloads *v1alpha1.WorkloadSelector `protobuf:"bytes,1,opt,name=workloads,proto3" json:"workloads,omitempty"` + Upstreams []*Upstream `protobuf:"bytes,2,rep,name=upstreams,proto3" json:"upstreams,omitempty"` + PqUpstreams []*PreparedQueryUpstream `protobuf:"bytes,3,rep,name=pq_upstreams,json=pqUpstreams,proto3" json:"pq_upstreams,omitempty"` + UpstreamConfig *UpstreamConfig `protobuf:"bytes,4,opt,name=upstream_config,json=upstreamConfig,proto3" json:"upstream_config,omitempty"` } func (x *Upstreams) Reset() { @@ -93,26 +92,27 @@ func (x *Upstreams) GetPqUpstreams() []*PreparedQueryUpstream { return nil } +func (x *Upstreams) GetUpstreamConfig() *UpstreamConfig { + if x != nil { + return x.UpstreamConfig + } + return nil +} + type Upstream struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // destination_ref is the reference to an upstream service. This has to be pbcatalog.Service type. - DestinationRef *pbresource.Reference `protobuf:"bytes,1,opt,name=destination_ref,json=destinationRef,proto3" json:"destination_ref,omitempty"` - // destination_port is the port name of the upstream service. This should be the name - // of the service's target port. - DestinationPort string `protobuf:"bytes,2,opt,name=destination_port,json=destinationPort,proto3" json:"destination_port,omitempty"` - // datacenter is the datacenter for where this upstream service lives. - Datacenter string `protobuf:"bytes,3,opt,name=datacenter,proto3" json:"datacenter,omitempty"` - // listen_addr is the address where Envoy will listen for requests to this upstream. - // It can provided either as an ip:port or as a Unix domain socket. - // + DestinationRef *pbresource.ID `protobuf:"bytes,1,opt,name=destination_ref,json=destinationRef,proto3" json:"destination_ref,omitempty"` + DestinationPort string `protobuf:"bytes,2,opt,name=destination_port,json=destinationPort,proto3" json:"destination_port,omitempty"` + Datacenter string `protobuf:"bytes,3,opt,name=datacenter,proto3" json:"datacenter,omitempty"` // Types that are assignable to ListenAddr: // - // *Upstream_IpPort + // *Upstream_Tcp // *Upstream_Unix - ListenAddr isUpstream_ListenAddr `protobuf_oneof:"listen_addr"` + ListenAddr isUpstream_ListenAddr `protobuf_oneof:"listen_addr"` + UpstreamConfig *UpstreamConfig `protobuf:"bytes,7,opt,name=upstream_config,json=upstreamConfig,proto3" json:"upstream_config,omitempty"` } func (x *Upstream) Reset() { @@ -147,7 +147,7 @@ func (*Upstream) Descriptor() ([]byte, []int) { return file_pbmesh_v1alpha1_upstreams_proto_rawDescGZIP(), []int{1} } -func (x *Upstream) GetDestinationRef() *pbresource.Reference { +func (x *Upstream) GetDestinationRef() *pbresource.ID { if x != nil { return x.DestinationRef } @@ -175,9 +175,9 @@ func (m *Upstream) GetListenAddr() isUpstream_ListenAddr { return nil } -func (x *Upstream) GetIpPort() *IPPortAddress { - if x, ok := x.GetListenAddr().(*Upstream_IpPort); ok { - return x.IpPort +func (x *Upstream) GetTcp() *TCPAddress { + if x, ok := x.GetListenAddr().(*Upstream_Tcp); ok { + return x.Tcp } return nil } @@ -189,35 +189,40 @@ func (x *Upstream) GetUnix() *UnixSocketAddress { return nil } +func (x *Upstream) GetUpstreamConfig() *UpstreamConfig { + if x != nil { + return x.UpstreamConfig + } + return nil +} + type isUpstream_ListenAddr interface { isUpstream_ListenAddr() } -type Upstream_IpPort struct { - IpPort *IPPortAddress `protobuf:"bytes,4,opt,name=ip_port,json=ipPort,proto3,oneof"` +type Upstream_Tcp struct { + Tcp *TCPAddress `protobuf:"bytes,4,opt,name=tcp,proto3,oneof"` } type Upstream_Unix struct { Unix *UnixSocketAddress `protobuf:"bytes,5,opt,name=unix,proto3,oneof"` } -func (*Upstream_IpPort) isUpstream_ListenAddr() {} +func (*Upstream_Tcp) isUpstream_ListenAddr() {} func (*Upstream_Unix) isUpstream_ListenAddr() {} -type IPPortAddress struct { +type TCPAddress struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // ip is an IPv4 or an IPv6 address. - Ip string `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"` - // port is the port number. + Ip string `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"` Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` } -func (x *IPPortAddress) Reset() { - *x = IPPortAddress{} +func (x *TCPAddress) Reset() { + *x = TCPAddress{} if protoimpl.UnsafeEnabled { mi := &file_pbmesh_v1alpha1_upstreams_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -225,13 +230,13 @@ func (x *IPPortAddress) Reset() { } } -func (x *IPPortAddress) String() string { +func (x *TCPAddress) String() string { return protoimpl.X.MessageStringOf(x) } -func (*IPPortAddress) ProtoMessage() {} +func (*TCPAddress) ProtoMessage() {} -func (x *IPPortAddress) ProtoReflect() protoreflect.Message { +func (x *TCPAddress) ProtoReflect() protoreflect.Message { mi := &file_pbmesh_v1alpha1_upstreams_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -243,19 +248,19 @@ func (x *IPPortAddress) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use IPPortAddress.ProtoReflect.Descriptor instead. -func (*IPPortAddress) Descriptor() ([]byte, []int) { +// Deprecated: Use TCPAddress.ProtoReflect.Descriptor instead. +func (*TCPAddress) Descriptor() ([]byte, []int) { return file_pbmesh_v1alpha1_upstreams_proto_rawDescGZIP(), []int{2} } -func (x *IPPortAddress) GetIp() string { +func (x *TCPAddress) GetIp() string { if x != nil { return x.Ip } return "" } -func (x *IPPortAddress) GetPort() uint32 { +func (x *TCPAddress) GetPort() uint32 { if x != nil { return x.Port } @@ -267,10 +272,7 @@ type UnixSocketAddress struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // path is the file system path at which to bind a Unix domain socket listener. Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - // mode is the Unix file mode for the socket file. It should be provided - // in the numeric notation, for example, "0600". Mode string `protobuf:"bytes,2,opt,name=mode,proto3" json:"mode,omitempty"` } @@ -325,13 +327,8 @@ type PreparedQueryUpstream struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // name is the name of the prepared query to use as an upstream. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // datacenter is the datacenter for where this upstream service lives. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Datacenter string `protobuf:"bytes,2,opt,name=datacenter,proto3" json:"datacenter,omitempty"` - // listen_addr is the address where Envoy will listen for requests to this upstream. - // It can provided either as an ip:port or as a Unix domain socket. - // // Types that are assignable to ListenAddr: // // *PreparedQueryUpstream_Tcp @@ -393,7 +390,7 @@ func (m *PreparedQueryUpstream) GetListenAddr() isPreparedQueryUpstream_ListenAd return nil } -func (x *PreparedQueryUpstream) GetTcp() *IPPortAddress { +func (x *PreparedQueryUpstream) GetTcp() *TCPAddress { if x, ok := x.GetListenAddr().(*PreparedQueryUpstream_Tcp); ok { return x.Tcp } @@ -419,7 +416,7 @@ type isPreparedQueryUpstream_ListenAddr interface { } type PreparedQueryUpstream_Tcp struct { - Tcp *IPPortAddress `protobuf:"bytes,4,opt,name=tcp,proto3,oneof"` + Tcp *TCPAddress `protobuf:"bytes,4,opt,name=tcp,proto3,oneof"` } type PreparedQueryUpstream_Unix struct { @@ -430,6 +427,229 @@ func (*PreparedQueryUpstream_Tcp) isPreparedQueryUpstream_ListenAddr() {} func (*PreparedQueryUpstream_Unix) isPreparedQueryUpstream_ListenAddr() {} +type UpstreamConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ConnectTimeoutMs uint64 `protobuf:"varint,2,opt,name=connect_timeout_ms,json=connectTimeoutMs,proto3" json:"connect_timeout_ms,omitempty"` + Limits *UpstreamLimits `protobuf:"bytes,3,opt,name=limits,proto3" json:"limits,omitempty"` + PassiveHealthCheck *PassiveHealthCheck `protobuf:"bytes,4,opt,name=passive_health_check,json=passiveHealthCheck,proto3" json:"passive_health_check,omitempty"` + BalanceInboundConnections BalanceInboundConnections `protobuf:"varint,5,opt,name=balance_inbound_connections,json=balanceInboundConnections,proto3,enum=hashicorp.consul.mesh.v1alpha1.BalanceInboundConnections" json:"balance_inbound_connections,omitempty"` + MeshGatewayMode MeshGatewayMode `protobuf:"varint,6,opt,name=mesh_gateway_mode,json=meshGatewayMode,proto3,enum=hashicorp.consul.mesh.v1alpha1.MeshGatewayMode" json:"mesh_gateway_mode,omitempty"` +} + +func (x *UpstreamConfig) Reset() { + *x = UpstreamConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmesh_v1alpha1_upstreams_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpstreamConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpstreamConfig) ProtoMessage() {} + +func (x *UpstreamConfig) ProtoReflect() protoreflect.Message { + mi := &file_pbmesh_v1alpha1_upstreams_proto_msgTypes[5] + 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 UpstreamConfig.ProtoReflect.Descriptor instead. +func (*UpstreamConfig) Descriptor() ([]byte, []int) { + return file_pbmesh_v1alpha1_upstreams_proto_rawDescGZIP(), []int{5} +} + +func (x *UpstreamConfig) GetConnectTimeoutMs() uint64 { + if x != nil { + return x.ConnectTimeoutMs + } + return 0 +} + +func (x *UpstreamConfig) GetLimits() *UpstreamLimits { + if x != nil { + return x.Limits + } + return nil +} + +func (x *UpstreamConfig) GetPassiveHealthCheck() *PassiveHealthCheck { + if x != nil { + return x.PassiveHealthCheck + } + return nil +} + +func (x *UpstreamConfig) GetBalanceInboundConnections() BalanceInboundConnections { + if x != nil { + return x.BalanceInboundConnections + } + return BalanceInboundConnections_BALANCE_INBOUND_CONNECTIONS_DEFAULT +} + +func (x *UpstreamConfig) GetMeshGatewayMode() MeshGatewayMode { + if x != nil { + return x.MeshGatewayMode + } + return MeshGatewayMode_MESH_GATEWAY_MODE_UNSPECIFIED +} + +// UpstreamLimits describes the limits that are associated with a specific +// upstream of a service instance. +type UpstreamLimits struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // MaxConnections is the maximum number of connections the local proxy can + // make to the upstream service. + MaxConnections int32 `protobuf:"varint,1,opt,name=max_connections,json=maxConnections,proto3" json:"max_connections,omitempty"` + // MaxPendingRequests is the maximum number of requests that will be queued + // waiting for an available connection. This is mostly applicable to HTTP/1.1 + // clusters since all HTTP/2 requests are streamed over a single + // connection. + MaxPendingRequests int32 `protobuf:"varint,2,opt,name=max_pending_requests,json=maxPendingRequests,proto3" json:"max_pending_requests,omitempty"` + // MaxConcurrentRequests is the maximum number of in-flight requests that will be allowed + // to the upstream cluster at a point in time. This is mostly applicable to HTTP/2 + // clusters since all HTTP/1.1 requests are limited by MaxConnections. + MaxConcurrentRequests int32 `protobuf:"varint,3,opt,name=max_concurrent_requests,json=maxConcurrentRequests,proto3" json:"max_concurrent_requests,omitempty"` +} + +func (x *UpstreamLimits) Reset() { + *x = UpstreamLimits{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmesh_v1alpha1_upstreams_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpstreamLimits) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpstreamLimits) ProtoMessage() {} + +func (x *UpstreamLimits) ProtoReflect() protoreflect.Message { + mi := &file_pbmesh_v1alpha1_upstreams_proto_msgTypes[6] + 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 UpstreamLimits.ProtoReflect.Descriptor instead. +func (*UpstreamLimits) Descriptor() ([]byte, []int) { + return file_pbmesh_v1alpha1_upstreams_proto_rawDescGZIP(), []int{6} +} + +func (x *UpstreamLimits) GetMaxConnections() int32 { + if x != nil { + return x.MaxConnections + } + return 0 +} + +func (x *UpstreamLimits) GetMaxPendingRequests() int32 { + if x != nil { + return x.MaxPendingRequests + } + return 0 +} + +func (x *UpstreamLimits) GetMaxConcurrentRequests() int32 { + if x != nil { + return x.MaxConcurrentRequests + } + return 0 +} + +type PassiveHealthCheck struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Interval between health check analysis sweeps. Each sweep may remove + // hosts or return hosts to the pool. + Interval *durationpb.Duration `protobuf:"bytes,1,opt,name=interval,proto3" json:"interval,omitempty"` + // MaxFailures is the count of consecutive failures that results in a host + // being removed from the pool. + MaxFailures uint32 `protobuf:"varint,2,opt,name=max_failures,json=maxFailures,proto3" json:"max_failures,omitempty"` + // EnforcingConsecutive5xx is the % chance that a host will be actually ejected + // when an outlier status is detected through consecutive 5xx. + // This setting can be used to disable ejection or to ramp it up slowly. Defaults to 100. + EnforcingConsecutive_5Xx uint32 `protobuf:"varint,3,opt,name=enforcing_consecutive_5xx,json=enforcingConsecutive5xx,proto3" json:"enforcing_consecutive_5xx,omitempty"` +} + +func (x *PassiveHealthCheck) Reset() { + *x = PassiveHealthCheck{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmesh_v1alpha1_upstreams_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PassiveHealthCheck) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PassiveHealthCheck) ProtoMessage() {} + +func (x *PassiveHealthCheck) ProtoReflect() protoreflect.Message { + mi := &file_pbmesh_v1alpha1_upstreams_proto_msgTypes[7] + 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 PassiveHealthCheck.ProtoReflect.Descriptor instead. +func (*PassiveHealthCheck) Descriptor() ([]byte, []int) { + return file_pbmesh_v1alpha1_upstreams_proto_rawDescGZIP(), []int{7} +} + +func (x *PassiveHealthCheck) GetInterval() *durationpb.Duration { + if x != nil { + return x.Interval + } + return nil +} + +func (x *PassiveHealthCheck) GetMaxFailures() uint32 { + if x != nil { + return x.MaxFailures + } + return 0 +} + +func (x *PassiveHealthCheck) GetEnforcingConsecutive_5Xx() uint32 { + if x != nil { + return x.EnforcingConsecutive_5Xx + } + return 0 +} + var File_pbmesh_v1alpha1_upstreams_proto protoreflect.FileDescriptor var file_pbmesh_v1alpha1_upstreams_proto_rawDesc = []byte{ @@ -437,95 +657,158 @@ var file_pbmesh_v1alpha1_upstreams_proto_rawDesc = []byte{ 0x31, 0x2f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x1a, 0x21, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, + 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x1a, 0x21, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2d, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x5f, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, - 0x02, 0x0a, 0x09, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x51, 0x0a, 0x09, - 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, - 0x46, 0x0a, 0x09, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x09, 0x75, 0x70, - 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x58, 0x0a, 0x0c, 0x70, 0x71, 0x5f, 0x75, 0x70, - 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, - 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x55, 0x70, 0x73, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x52, 0x0b, 0x70, 0x71, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x73, 0x22, 0xc6, 0x02, 0x0a, 0x08, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x4d, - 0x0a, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x0e, 0x64, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x12, 0x29, 0x0a, - 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x72, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, - 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, - 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x07, 0x69, 0x70, 0x5f, 0x70, - 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 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, 0xd9, 0x02, 0x0a, 0x09, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x51, + 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, + 0x73, 0x12, 0x46, 0x0a, 0x09, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x09, + 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x58, 0x0a, 0x0c, 0x70, 0x71, 0x5f, + 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x55, 0x70, + 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x0b, 0x70, 0x71, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x73, 0x12, 0x57, 0x0a, 0x0f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, + 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x75, 0x70, + 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x8e, 0x03, 0x0a, + 0x08, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x46, 0x0a, 0x0f, 0x64, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1d, 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, 0x49, + 0x44, 0x52, 0x0e, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x66, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, + 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x03, + 0x74, 0x63, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x50, 0x50, 0x6f, 0x72, - 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x06, 0x69, 0x70, 0x50, 0x6f, - 0x72, 0x74, 0x12, 0x47, 0x0a, 0x04, 0x75, 0x6e, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x04, 0x75, 0x6e, 0x69, 0x78, 0x42, 0x0d, 0x0a, 0x0b, 0x6c, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x22, 0x33, 0x0a, 0x0d, 0x49, 0x50, - 0x50, 0x6f, 0x72, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x43, 0x50, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x03, 0x74, 0x63, 0x70, 0x12, 0x47, 0x0a, 0x04, + 0x75, 0x6e, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, + 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x6e, 0x69, 0x78, + 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, + 0x04, 0x75, 0x6e, 0x69, 0x78, 0x12, 0x57, 0x0a, 0x0f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, + 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x0d, + 0x0a, 0x0b, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x22, 0x30, 0x0a, + 0x0a, 0x54, 0x43, 0x50, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x3b, 0x0a, 0x11, 0x55, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0xbf, 0x02, 0x0a, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0xbc, 0x02, 0x0a, 0x15, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x03, 0x74, 0x63, - 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x03, 0x74, 0x63, + 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x50, 0x50, 0x6f, 0x72, 0x74, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x03, 0x74, 0x63, 0x70, 0x12, 0x47, 0x0a, - 0x04, 0x75, 0x6e, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x6e, 0x69, - 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, - 0x52, 0x04, 0x75, 0x6e, 0x69, 0x78, 0x12, 0x57, 0x0a, 0x0f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x43, 0x50, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x03, 0x74, 0x63, 0x70, 0x12, 0x47, 0x0a, 0x04, 0x75, 0x6e, + 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x53, 0x6f, + 0x63, 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x04, 0x75, + 0x6e, 0x69, 0x78, 0x12, 0x57, 0x0a, 0x0f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, + 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x75, 0x70, + 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x0d, 0x0a, 0x0b, + 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x22, 0xc4, 0x03, 0x0a, 0x0e, + 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2c, + 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, + 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x46, 0x0a, 0x06, + 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, + 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, 0x6c, 0x69, + 0x6d, 0x69, 0x74, 0x73, 0x12, 0x64, 0x0a, 0x14, 0x70, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x5f, + 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x12, 0x70, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x79, 0x0a, 0x1b, 0x62, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x0e, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, - 0x0d, 0x0a, 0x0b, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x42, 0x96, - 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, - 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, - 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x19, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5b, 0x0a, 0x11, 0x6d, 0x65, 0x73, 0x68, 0x5f, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, + 0x65, 0x52, 0x0f, 0x6d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, + 0x64, 0x65, 0x22, 0xa3, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, + 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, + 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, + 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x6d, 0x61, + 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, + 0x12, 0x36, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, 0xaa, 0x01, 0x0a, 0x12, 0x50, 0x61, 0x73, + 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, + 0x35, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x66, 0x61, + 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6d, 0x61, + 0x78, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x65, 0x6e, 0x66, + 0x6f, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, + 0x76, 0x65, 0x5f, 0x35, 0x78, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x17, 0x65, 0x6e, + 0x66, 0x6f, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, + 0x76, 0x65, 0x35, 0x78, 0x78, 0x42, 0x96, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, + 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0e, 0x55, 0x70, + 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, + 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, 0x65, 0x73, 0x68, 0x2f, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1e, 0x48, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, + 0x65, 0x73, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, + 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, + 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, + 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -540,32 +823,44 @@ func file_pbmesh_v1alpha1_upstreams_proto_rawDescGZIP() []byte { return file_pbmesh_v1alpha1_upstreams_proto_rawDescData } -var file_pbmesh_v1alpha1_upstreams_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_pbmesh_v1alpha1_upstreams_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_pbmesh_v1alpha1_upstreams_proto_goTypes = []interface{}{ (*Upstreams)(nil), // 0: hashicorp.consul.mesh.v1alpha1.Upstreams (*Upstream)(nil), // 1: hashicorp.consul.mesh.v1alpha1.Upstream - (*IPPortAddress)(nil), // 2: hashicorp.consul.mesh.v1alpha1.IPPortAddress + (*TCPAddress)(nil), // 2: hashicorp.consul.mesh.v1alpha1.TCPAddress (*UnixSocketAddress)(nil), // 3: hashicorp.consul.mesh.v1alpha1.UnixSocketAddress (*PreparedQueryUpstream)(nil), // 4: hashicorp.consul.mesh.v1alpha1.PreparedQueryUpstream - (*v1alpha1.WorkloadSelector)(nil), // 5: hashicorp.consul.catalog.v1alpha1.WorkloadSelector - (*pbresource.Reference)(nil), // 6: hashicorp.consul.resource.Reference - (*UpstreamConfig)(nil), // 7: hashicorp.consul.mesh.v1alpha1.UpstreamConfig + (*UpstreamConfig)(nil), // 5: hashicorp.consul.mesh.v1alpha1.UpstreamConfig + (*UpstreamLimits)(nil), // 6: hashicorp.consul.mesh.v1alpha1.UpstreamLimits + (*PassiveHealthCheck)(nil), // 7: hashicorp.consul.mesh.v1alpha1.PassiveHealthCheck + (*v1alpha1.WorkloadSelector)(nil), // 8: hashicorp.consul.catalog.v1alpha1.WorkloadSelector + (*pbresource.ID)(nil), // 9: hashicorp.consul.resource.ID + (BalanceInboundConnections)(0), // 10: hashicorp.consul.mesh.v1alpha1.BalanceInboundConnections + (MeshGatewayMode)(0), // 11: hashicorp.consul.mesh.v1alpha1.MeshGatewayMode + (*durationpb.Duration)(nil), // 12: google.protobuf.Duration } var file_pbmesh_v1alpha1_upstreams_proto_depIdxs = []int32{ - 5, // 0: hashicorp.consul.mesh.v1alpha1.Upstreams.workloads:type_name -> hashicorp.consul.catalog.v1alpha1.WorkloadSelector - 1, // 1: hashicorp.consul.mesh.v1alpha1.Upstreams.upstreams:type_name -> hashicorp.consul.mesh.v1alpha1.Upstream - 4, // 2: hashicorp.consul.mesh.v1alpha1.Upstreams.pq_upstreams:type_name -> hashicorp.consul.mesh.v1alpha1.PreparedQueryUpstream - 6, // 3: hashicorp.consul.mesh.v1alpha1.Upstream.destination_ref:type_name -> hashicorp.consul.resource.Reference - 2, // 4: hashicorp.consul.mesh.v1alpha1.Upstream.ip_port:type_name -> hashicorp.consul.mesh.v1alpha1.IPPortAddress - 3, // 5: hashicorp.consul.mesh.v1alpha1.Upstream.unix:type_name -> hashicorp.consul.mesh.v1alpha1.UnixSocketAddress - 2, // 6: hashicorp.consul.mesh.v1alpha1.PreparedQueryUpstream.tcp:type_name -> hashicorp.consul.mesh.v1alpha1.IPPortAddress - 3, // 7: hashicorp.consul.mesh.v1alpha1.PreparedQueryUpstream.unix:type_name -> hashicorp.consul.mesh.v1alpha1.UnixSocketAddress - 7, // 8: hashicorp.consul.mesh.v1alpha1.PreparedQueryUpstream.upstream_config:type_name -> hashicorp.consul.mesh.v1alpha1.UpstreamConfig - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 8, // 0: hashicorp.consul.mesh.v1alpha1.Upstreams.workloads:type_name -> hashicorp.consul.catalog.v1alpha1.WorkloadSelector + 1, // 1: hashicorp.consul.mesh.v1alpha1.Upstreams.upstreams:type_name -> hashicorp.consul.mesh.v1alpha1.Upstream + 4, // 2: hashicorp.consul.mesh.v1alpha1.Upstreams.pq_upstreams:type_name -> hashicorp.consul.mesh.v1alpha1.PreparedQueryUpstream + 5, // 3: hashicorp.consul.mesh.v1alpha1.Upstreams.upstream_config:type_name -> hashicorp.consul.mesh.v1alpha1.UpstreamConfig + 9, // 4: hashicorp.consul.mesh.v1alpha1.Upstream.destination_ref:type_name -> hashicorp.consul.resource.ID + 2, // 5: hashicorp.consul.mesh.v1alpha1.Upstream.tcp:type_name -> hashicorp.consul.mesh.v1alpha1.TCPAddress + 3, // 6: hashicorp.consul.mesh.v1alpha1.Upstream.unix:type_name -> hashicorp.consul.mesh.v1alpha1.UnixSocketAddress + 5, // 7: hashicorp.consul.mesh.v1alpha1.Upstream.upstream_config:type_name -> hashicorp.consul.mesh.v1alpha1.UpstreamConfig + 2, // 8: hashicorp.consul.mesh.v1alpha1.PreparedQueryUpstream.tcp:type_name -> hashicorp.consul.mesh.v1alpha1.TCPAddress + 3, // 9: hashicorp.consul.mesh.v1alpha1.PreparedQueryUpstream.unix:type_name -> hashicorp.consul.mesh.v1alpha1.UnixSocketAddress + 5, // 10: hashicorp.consul.mesh.v1alpha1.PreparedQueryUpstream.upstream_config:type_name -> hashicorp.consul.mesh.v1alpha1.UpstreamConfig + 6, // 11: hashicorp.consul.mesh.v1alpha1.UpstreamConfig.limits:type_name -> hashicorp.consul.mesh.v1alpha1.UpstreamLimits + 7, // 12: hashicorp.consul.mesh.v1alpha1.UpstreamConfig.passive_health_check:type_name -> hashicorp.consul.mesh.v1alpha1.PassiveHealthCheck + 10, // 13: hashicorp.consul.mesh.v1alpha1.UpstreamConfig.balance_inbound_connections:type_name -> hashicorp.consul.mesh.v1alpha1.BalanceInboundConnections + 11, // 14: hashicorp.consul.mesh.v1alpha1.UpstreamConfig.mesh_gateway_mode:type_name -> hashicorp.consul.mesh.v1alpha1.MeshGatewayMode + 12, // 15: hashicorp.consul.mesh.v1alpha1.PassiveHealthCheck.interval:type_name -> google.protobuf.Duration + 16, // [16:16] is the sub-list for method output_type + 16, // [16:16] is the sub-list for method input_type + 16, // [16:16] is the sub-list for extension type_name + 16, // [16:16] is the sub-list for extension extendee + 0, // [0:16] is the sub-list for field type_name } func init() { file_pbmesh_v1alpha1_upstreams_proto_init() } @@ -573,7 +868,8 @@ func file_pbmesh_v1alpha1_upstreams_proto_init() { if File_pbmesh_v1alpha1_upstreams_proto != nil { return } - file_pbmesh_v1alpha1_upstreams_configuration_proto_init() + file_pbmesh_v1alpha1_connection_proto_init() + file_pbmesh_v1alpha1_routing_proto_init() if !protoimpl.UnsafeEnabled { file_pbmesh_v1alpha1_upstreams_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Upstreams); i { @@ -600,7 +896,7 @@ func file_pbmesh_v1alpha1_upstreams_proto_init() { } } file_pbmesh_v1alpha1_upstreams_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IPPortAddress); i { + switch v := v.(*TCPAddress); i { case 0: return &v.state case 1: @@ -635,9 +931,45 @@ func file_pbmesh_v1alpha1_upstreams_proto_init() { return nil } } + file_pbmesh_v1alpha1_upstreams_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpstreamConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbmesh_v1alpha1_upstreams_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpstreamLimits); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbmesh_v1alpha1_upstreams_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PassiveHealthCheck); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_pbmesh_v1alpha1_upstreams_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*Upstream_IpPort)(nil), + (*Upstream_Tcp)(nil), (*Upstream_Unix)(nil), } file_pbmesh_v1alpha1_upstreams_proto_msgTypes[4].OneofWrappers = []interface{}{ @@ -650,7 +982,7 @@ func file_pbmesh_v1alpha1_upstreams_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pbmesh_v1alpha1_upstreams_proto_rawDesc, NumEnums: 0, - NumMessages: 5, + NumMessages: 8, NumExtensions: 0, NumServices: 0, }, diff --git a/proto-public/pbmesh/v1alpha1/upstreams.proto b/proto-public/pbmesh/v1alpha1/upstreams.proto index a78d8c3f97929..9239bac774b8e 100644 --- a/proto-public/pbmesh/v1alpha1/upstreams.proto +++ b/proto-public/pbmesh/v1alpha1/upstreams.proto @@ -5,8 +5,10 @@ syntax = "proto3"; package hashicorp.consul.mesh.v1alpha1; +import "google/protobuf/duration.proto"; import "pbcatalog/v1alpha1/selector.proto"; -import "pbmesh/v1alpha1/upstreams_configuration.proto"; +import "pbmesh/v1alpha1/connection.proto"; +import "pbmesh/v1alpha1/routing.proto"; import "pbresource/resource.proto"; message Upstreams { @@ -14,63 +16,85 @@ message Upstreams { // These can be prefixes or specific workload names. hashicorp.consul.catalog.v1alpha1.WorkloadSelector workloads = 1; - // upstreams is the list of explicit upstreams to define for the selected workloads. repeated Upstream upstreams = 2; - - // pq_upstreams is the list of prepared query upstreams. This field is not supported directly in v2 - // and should only be used for migration reasons. repeated PreparedQueryUpstream pq_upstreams = 3; + + UpstreamConfig upstream_config = 4; } message Upstream { - // destination_ref is the reference to an upstream service. This has to be pbcatalog.Service type. - hashicorp.consul.resource.Reference destination_ref = 1; - - // destination_port is the port name of the upstream service. This should be the name - // of the service's target port. + hashicorp.consul.resource.ID destination_ref = 1; string destination_port = 2; - - // datacenter is the datacenter for where this upstream service lives. string datacenter = 3; - // listen_addr is the address where Envoy will listen for requests to this upstream. - // It can provided either as an ip:port or as a Unix domain socket. oneof listen_addr { - IPPortAddress ip_port = 4; + TCPAddress tcp = 4; UnixSocketAddress unix = 5; } + + UpstreamConfig upstream_config = 7; } -message IPPortAddress { - // ip is an IPv4 or an IPv6 address. +message TCPAddress { string ip = 1; - - // port is the port number. uint32 port = 2; } message UnixSocketAddress { - // path is the file system path at which to bind a Unix domain socket listener. string path = 1; - - // mode is the Unix file mode for the socket file. It should be provided - // in the numeric notation, for example, "0600". string mode = 2; } message PreparedQueryUpstream { - // name is the name of the prepared query to use as an upstream. string name = 1; - - // datacenter is the datacenter for where this upstream service lives. string datacenter = 2; - // listen_addr is the address where Envoy will listen for requests to this upstream. - // It can provided either as an ip:port or as a Unix domain socket. oneof listen_addr { - IPPortAddress tcp = 4; + TCPAddress tcp = 4; UnixSocketAddress unix = 5; } UpstreamConfig upstream_config = 6; } + +message UpstreamConfig { + uint64 connect_timeout_ms = 2; + UpstreamLimits limits = 3; + PassiveHealthCheck passive_health_check = 4; + BalanceInboundConnections balance_inbound_connections = 5; + MeshGatewayMode mesh_gateway_mode = 6; +} + +// UpstreamLimits describes the limits that are associated with a specific +// upstream of a service instance. +message UpstreamLimits { + // MaxConnections is the maximum number of connections the local proxy can + // make to the upstream service. + int32 max_connections = 1; + + // MaxPendingRequests is the maximum number of requests that will be queued + // waiting for an available connection. This is mostly applicable to HTTP/1.1 + // clusters since all HTTP/2 requests are streamed over a single + // connection. + int32 max_pending_requests = 2; + + // MaxConcurrentRequests is the maximum number of in-flight requests that will be allowed + // to the upstream cluster at a point in time. This is mostly applicable to HTTP/2 + // clusters since all HTTP/1.1 requests are limited by MaxConnections. + int32 max_concurrent_requests = 3; +} + +message PassiveHealthCheck { + // Interval between health check analysis sweeps. Each sweep may remove + // hosts or return hosts to the pool. + google.protobuf.Duration interval = 1; + + // MaxFailures is the count of consecutive failures that results in a host + // being removed from the pool. + uint32 max_failures = 2; + + // EnforcingConsecutive5xx is the % chance that a host will be actually ejected + // when an outlier status is detected through consecutive 5xx. + // This setting can be used to disable ejection or to ramp it up slowly. Defaults to 100. + uint32 enforcing_consecutive_5xx = 3; +} diff --git a/proto-public/pbmesh/v1alpha1/upstreams_configuration.pb.binary.go b/proto-public/pbmesh/v1alpha1/upstreams_configuration.pb.binary.go deleted file mode 100644 index f4a5db2813244..0000000000000 --- a/proto-public/pbmesh/v1alpha1/upstreams_configuration.pb.binary.go +++ /dev/null @@ -1,58 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v1alpha1/upstreams_configuration.proto - -package meshv1alpha1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *UpstreamsConfiguration) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *UpstreamsConfiguration) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *UpstreamConfigOverrides) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *UpstreamConfigOverrides) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *UpstreamConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *UpstreamConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *UpstreamLimits) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *UpstreamLimits) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *PassiveHealthCheck) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *PassiveHealthCheck) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v1alpha1/upstreams_configuration.pb.go b/proto-public/pbmesh/v1alpha1/upstreams_configuration.pb.go deleted file mode 100644 index 61f9709cdcd11..0000000000000 --- a/proto-public/pbmesh/v1alpha1/upstreams_configuration.pb.go +++ /dev/null @@ -1,695 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v1alpha1/upstreams_configuration.proto - -package meshv1alpha1 - -import ( - v1alpha1 "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" - pbresource "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - 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 UpstreamsConfiguration struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Selection of workloads these upstreams should apply to. - // These can be prefixes or specific workload names. - Workloads *v1alpha1.WorkloadSelector `protobuf:"bytes,1,opt,name=workloads,proto3" json:"workloads,omitempty"` - // default_config applies to all upstreams for the workloads selected by this resource. - DefaultConfig *UpstreamConfig `protobuf:"bytes,2,opt,name=default_config,json=defaultConfig,proto3" json:"default_config,omitempty"` - // config_overrides provides per-upstream or per-upstream-port config overrides. - ConfigOverrides []*UpstreamConfigOverrides `protobuf:"bytes,3,rep,name=config_overrides,json=configOverrides,proto3" json:"config_overrides,omitempty"` -} - -func (x *UpstreamsConfiguration) Reset() { - *x = UpstreamsConfiguration{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpstreamsConfiguration) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpstreamsConfiguration) ProtoMessage() {} - -func (x *UpstreamsConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_upstreams_configuration_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 UpstreamsConfiguration.ProtoReflect.Descriptor instead. -func (*UpstreamsConfiguration) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDescGZIP(), []int{0} -} - -func (x *UpstreamsConfiguration) GetWorkloads() *v1alpha1.WorkloadSelector { - if x != nil { - return x.Workloads - } - return nil -} - -func (x *UpstreamsConfiguration) GetDefaultConfig() *UpstreamConfig { - if x != nil { - return x.DefaultConfig - } - return nil -} - -func (x *UpstreamsConfiguration) GetConfigOverrides() []*UpstreamConfigOverrides { - if x != nil { - return x.ConfigOverrides - } - return nil -} - -// UpstreamConfigOverrides allow to override upstream configuration per destination_ref/port/datacenter. -// In that sense, those three fields (destination_ref, destination_port and datacenter) are treated -// sort of like map keys and config is a like a map value for that key. -type UpstreamConfigOverrides struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // destination_ref is the reference to an upstream service that this configuration applies to. - // This has to be pbcatalog.Service type. - DestinationRef *pbresource.Reference `protobuf:"bytes,1,opt,name=destination_ref,json=destinationRef,proto3" json:"destination_ref,omitempty"` - // destination_port is the port name of the upstream service. This should be the name - // of the service's target port. If not provided, this configuration will apply to all ports of an upstream. - DestinationPort string `protobuf:"bytes,2,opt,name=destination_port,json=destinationPort,proto3" json:"destination_port,omitempty"` - // datacenter is the datacenter for where this upstream service lives. - Datacenter string `protobuf:"bytes,3,opt,name=datacenter,proto3" json:"datacenter,omitempty"` - // config is the configuration that should apply to this upstream. - Config *UpstreamConfig `protobuf:"bytes,4,opt,name=config,proto3" json:"config,omitempty"` -} - -func (x *UpstreamConfigOverrides) Reset() { - *x = UpstreamConfigOverrides{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpstreamConfigOverrides) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpstreamConfigOverrides) ProtoMessage() {} - -func (x *UpstreamConfigOverrides) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_upstreams_configuration_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 UpstreamConfigOverrides.ProtoReflect.Descriptor instead. -func (*UpstreamConfigOverrides) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDescGZIP(), []int{1} -} - -func (x *UpstreamConfigOverrides) GetDestinationRef() *pbresource.Reference { - if x != nil { - return x.DestinationRef - } - return nil -} - -func (x *UpstreamConfigOverrides) GetDestinationPort() string { - if x != nil { - return x.DestinationPort - } - return "" -} - -func (x *UpstreamConfigOverrides) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - -func (x *UpstreamConfigOverrides) GetConfig() *UpstreamConfig { - if x != nil { - return x.Config - } - return nil -} - -type UpstreamConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // protocol overrides upstream's port protocol. If no port for an upstream is specified - // or if used in the default configuration, this protocol will be used for all ports - // or for all ports of all upstreams respectively. - Protocol v1alpha1.Protocol `protobuf:"varint,1,opt,name=protocol,proto3,enum=hashicorp.consul.catalog.v1alpha1.Protocol" json:"protocol,omitempty"` - // connect_timeout is the timeout used when making a new - // connection to this upstream. Defaults to 5 seconds if not set. - ConnectTimeout *durationpb.Duration `protobuf:"bytes,2,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` - // limits are the set of limits that are applied to the proxy for a specific upstream. - Limits *UpstreamLimits `protobuf:"bytes,3,opt,name=limits,proto3" json:"limits,omitempty"` - // passive_health_check configuration determines how upstream proxy instances will - // be monitored for removal from the load balancing pool. - PassiveHealthCheck *PassiveHealthCheck `protobuf:"bytes,4,opt,name=passive_health_check,json=passiveHealthCheck,proto3" json:"passive_health_check,omitempty"` - // balance_outbound_connections indicates how the proxy should attempt to distribute - // connections across worker threads. - BalanceOutboundConnections BalanceConnections `protobuf:"varint,5,opt,name=balance_outbound_connections,json=balanceOutboundConnections,proto3,enum=hashicorp.consul.mesh.v1alpha1.BalanceConnections" json:"balance_outbound_connections,omitempty"` - // MeshGatewayMode is the Mesh Gateway routing mode. - MeshGatewayMode MeshGatewayMode `protobuf:"varint,6,opt,name=mesh_gateway_mode,json=meshGatewayMode,proto3,enum=hashicorp.consul.mesh.v1alpha1.MeshGatewayMode" json:"mesh_gateway_mode,omitempty"` -} - -func (x *UpstreamConfig) Reset() { - *x = UpstreamConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpstreamConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpstreamConfig) ProtoMessage() {} - -func (x *UpstreamConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_upstreams_configuration_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 UpstreamConfig.ProtoReflect.Descriptor instead. -func (*UpstreamConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDescGZIP(), []int{2} -} - -func (x *UpstreamConfig) GetProtocol() v1alpha1.Protocol { - if x != nil { - return x.Protocol - } - return v1alpha1.Protocol(0) -} - -func (x *UpstreamConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -func (x *UpstreamConfig) GetLimits() *UpstreamLimits { - if x != nil { - return x.Limits - } - return nil -} - -func (x *UpstreamConfig) GetPassiveHealthCheck() *PassiveHealthCheck { - if x != nil { - return x.PassiveHealthCheck - } - return nil -} - -func (x *UpstreamConfig) GetBalanceOutboundConnections() BalanceConnections { - if x != nil { - return x.BalanceOutboundConnections - } - return BalanceConnections_BALANCE_CONNECTIONS_DEFAULT -} - -func (x *UpstreamConfig) GetMeshGatewayMode() MeshGatewayMode { - if x != nil { - return x.MeshGatewayMode - } - return MeshGatewayMode_MESH_GATEWAY_MODE_UNSPECIFIED -} - -// UpstreamLimits describes the limits that are associated with a specific -// upstream of a service instance. -type UpstreamLimits struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // max_connections is the maximum number of connections the local proxy can - // make to the upstream service. - MaxConnections *wrapperspb.UInt32Value `protobuf:"bytes,1,opt,name=max_connections,json=maxConnections,proto3" json:"max_connections,omitempty"` - // max_pending_requests is the maximum number of requests that will be queued - // waiting for an available connection. This is mostly applicable to HTTP/1.1 - // clusters since all HTTP/2 requests are streamed over a single - // connection. - MaxPendingRequests *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=max_pending_requests,json=maxPendingRequests,proto3" json:"max_pending_requests,omitempty"` - // max_concurrent_requests is the maximum number of in-flight requests that will be allowed - // to the upstream cluster at a point in time. This is mostly applicable to HTTP/2 - // clusters since all HTTP/1.1 requests are limited by MaxConnections. - MaxConcurrentRequests *wrapperspb.UInt32Value `protobuf:"bytes,3,opt,name=max_concurrent_requests,json=maxConcurrentRequests,proto3" json:"max_concurrent_requests,omitempty"` -} - -func (x *UpstreamLimits) Reset() { - *x = UpstreamLimits{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpstreamLimits) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpstreamLimits) ProtoMessage() {} - -func (x *UpstreamLimits) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes[3] - 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 UpstreamLimits.ProtoReflect.Descriptor instead. -func (*UpstreamLimits) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDescGZIP(), []int{3} -} - -func (x *UpstreamLimits) GetMaxConnections() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxConnections - } - return nil -} - -func (x *UpstreamLimits) GetMaxPendingRequests() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxPendingRequests - } - return nil -} - -func (x *UpstreamLimits) GetMaxConcurrentRequests() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxConcurrentRequests - } - return nil -} - -type PassiveHealthCheck struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // interval between health check analysis sweeps. Each sweep may remove - // hosts or return hosts to the pool. - Interval *durationpb.Duration `protobuf:"bytes,1,opt,name=interval,proto3" json:"interval,omitempty"` - // max_failures is the count of consecutive failures that results in a host - // being removed from the pool. - MaxFailures uint32 `protobuf:"varint,2,opt,name=max_failures,json=maxFailures,proto3" json:"max_failures,omitempty"` - // enforcing_consecutive_5xx is the % chance that a host will be actually ejected - // when an outlier status is detected through consecutive 5xx. - // This setting can be used to disable ejection or to ramp it up slowly. Defaults to 100. - EnforcingConsecutive_5Xx uint32 `protobuf:"varint,3,opt,name=enforcing_consecutive_5xx,json=enforcingConsecutive5xx,proto3" json:"enforcing_consecutive_5xx,omitempty"` -} - -func (x *PassiveHealthCheck) Reset() { - *x = PassiveHealthCheck{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PassiveHealthCheck) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PassiveHealthCheck) ProtoMessage() {} - -func (x *PassiveHealthCheck) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes[4] - 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 PassiveHealthCheck.ProtoReflect.Descriptor instead. -func (*PassiveHealthCheck) Descriptor() ([]byte, []int) { - return file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDescGZIP(), []int{4} -} - -func (x *PassiveHealthCheck) GetInterval() *durationpb.Duration { - if x != nil { - return x.Interval - } - return nil -} - -func (x *PassiveHealthCheck) GetMaxFailures() uint32 { - if x != nil { - return x.MaxFailures - } - return 0 -} - -func (x *PassiveHealthCheck) GetEnforcingConsecutive_5Xx() uint32 { - if x != nil { - return x.EnforcingConsecutive_5Xx - } - return 0 -} - -var File_pbmesh_v1alpha1_upstreams_configuration_proto protoreflect.FileDescriptor - -var file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDesc = []byte{ - 0x0a, 0x2d, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x1e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, - 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x21, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x21, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, - 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, 0xa6, 0x02, 0x0a, 0x16, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x51, 0x0a, 0x09, - 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, - 0x55, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x62, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x22, 0xfb, 0x01, 0x0a, 0x17, 0x55, - 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x4d, 0x0a, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x0e, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x72, 0x74, - 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x12, 0x46, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x9e, 0x04, 0x0a, 0x0e, 0x55, 0x70, 0x73, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x47, 0x0a, 0x08, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x46, 0x0a, 0x06, 0x6c, 0x69, 0x6d, 0x69, - 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, - 0x12, 0x64, 0x0a, 0x14, 0x70, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x52, 0x12, 0x70, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x74, 0x0a, 0x1c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x1a, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5b, 0x0a, 0x11, - 0x6d, 0x65, 0x73, 0x68, 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x6d, 0x6f, 0x64, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0f, 0x6d, 0x65, 0x73, 0x68, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0xfd, 0x01, 0x0a, 0x0e, 0x55, 0x70, - 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0f, - 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x4e, 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x12, 0x6d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x73, 0x12, 0x54, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, 0xaa, 0x01, 0x0a, 0x12, 0x50, 0x61, - 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x12, 0x35, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x66, - 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6d, - 0x61, 0x78, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x65, 0x6e, - 0x66, 0x6f, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x76, 0x65, 0x5f, 0x35, 0x78, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x17, 0x65, - 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x76, 0x65, 0x35, 0x78, 0x78, 0x42, 0xa3, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x1b, 0x55, - 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1e, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, - 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1e, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, - 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x2a, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, - 0x65, 0x73, 0x68, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, - 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDescOnce sync.Once - file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDescData = file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDesc -) - -func file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDescGZIP() []byte { - file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDescOnce.Do(func() { - file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDescData) - }) - return file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDescData -} - -var file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_pbmesh_v1alpha1_upstreams_configuration_proto_goTypes = []interface{}{ - (*UpstreamsConfiguration)(nil), // 0: hashicorp.consul.mesh.v1alpha1.UpstreamsConfiguration - (*UpstreamConfigOverrides)(nil), // 1: hashicorp.consul.mesh.v1alpha1.UpstreamConfigOverrides - (*UpstreamConfig)(nil), // 2: hashicorp.consul.mesh.v1alpha1.UpstreamConfig - (*UpstreamLimits)(nil), // 3: hashicorp.consul.mesh.v1alpha1.UpstreamLimits - (*PassiveHealthCheck)(nil), // 4: hashicorp.consul.mesh.v1alpha1.PassiveHealthCheck - (*v1alpha1.WorkloadSelector)(nil), // 5: hashicorp.consul.catalog.v1alpha1.WorkloadSelector - (*pbresource.Reference)(nil), // 6: hashicorp.consul.resource.Reference - (v1alpha1.Protocol)(0), // 7: hashicorp.consul.catalog.v1alpha1.Protocol - (*durationpb.Duration)(nil), // 8: google.protobuf.Duration - (BalanceConnections)(0), // 9: hashicorp.consul.mesh.v1alpha1.BalanceConnections - (MeshGatewayMode)(0), // 10: hashicorp.consul.mesh.v1alpha1.MeshGatewayMode - (*wrapperspb.UInt32Value)(nil), // 11: google.protobuf.UInt32Value -} -var file_pbmesh_v1alpha1_upstreams_configuration_proto_depIdxs = []int32{ - 5, // 0: hashicorp.consul.mesh.v1alpha1.UpstreamsConfiguration.workloads:type_name -> hashicorp.consul.catalog.v1alpha1.WorkloadSelector - 2, // 1: hashicorp.consul.mesh.v1alpha1.UpstreamsConfiguration.default_config:type_name -> hashicorp.consul.mesh.v1alpha1.UpstreamConfig - 1, // 2: hashicorp.consul.mesh.v1alpha1.UpstreamsConfiguration.config_overrides:type_name -> hashicorp.consul.mesh.v1alpha1.UpstreamConfigOverrides - 6, // 3: hashicorp.consul.mesh.v1alpha1.UpstreamConfigOverrides.destination_ref:type_name -> hashicorp.consul.resource.Reference - 2, // 4: hashicorp.consul.mesh.v1alpha1.UpstreamConfigOverrides.config:type_name -> hashicorp.consul.mesh.v1alpha1.UpstreamConfig - 7, // 5: hashicorp.consul.mesh.v1alpha1.UpstreamConfig.protocol:type_name -> hashicorp.consul.catalog.v1alpha1.Protocol - 8, // 6: hashicorp.consul.mesh.v1alpha1.UpstreamConfig.connect_timeout:type_name -> google.protobuf.Duration - 3, // 7: hashicorp.consul.mesh.v1alpha1.UpstreamConfig.limits:type_name -> hashicorp.consul.mesh.v1alpha1.UpstreamLimits - 4, // 8: hashicorp.consul.mesh.v1alpha1.UpstreamConfig.passive_health_check:type_name -> hashicorp.consul.mesh.v1alpha1.PassiveHealthCheck - 9, // 9: hashicorp.consul.mesh.v1alpha1.UpstreamConfig.balance_outbound_connections:type_name -> hashicorp.consul.mesh.v1alpha1.BalanceConnections - 10, // 10: hashicorp.consul.mesh.v1alpha1.UpstreamConfig.mesh_gateway_mode:type_name -> hashicorp.consul.mesh.v1alpha1.MeshGatewayMode - 11, // 11: hashicorp.consul.mesh.v1alpha1.UpstreamLimits.max_connections:type_name -> google.protobuf.UInt32Value - 11, // 12: hashicorp.consul.mesh.v1alpha1.UpstreamLimits.max_pending_requests:type_name -> google.protobuf.UInt32Value - 11, // 13: hashicorp.consul.mesh.v1alpha1.UpstreamLimits.max_concurrent_requests:type_name -> google.protobuf.UInt32Value - 8, // 14: hashicorp.consul.mesh.v1alpha1.PassiveHealthCheck.interval:type_name -> google.protobuf.Duration - 15, // [15:15] is the sub-list for method output_type - 15, // [15:15] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name -} - -func init() { file_pbmesh_v1alpha1_upstreams_configuration_proto_init() } -func file_pbmesh_v1alpha1_upstreams_configuration_proto_init() { - if File_pbmesh_v1alpha1_upstreams_configuration_proto != nil { - return - } - file_pbmesh_v1alpha1_connection_proto_init() - file_pbmesh_v1alpha1_routing_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpstreamsConfiguration); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpstreamConfigOverrides); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpstreamConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpstreamLimits); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PassiveHealthCheck); 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_pbmesh_v1alpha1_upstreams_configuration_proto_rawDesc, - NumEnums: 0, - NumMessages: 5, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v1alpha1_upstreams_configuration_proto_goTypes, - DependencyIndexes: file_pbmesh_v1alpha1_upstreams_configuration_proto_depIdxs, - MessageInfos: file_pbmesh_v1alpha1_upstreams_configuration_proto_msgTypes, - }.Build() - File_pbmesh_v1alpha1_upstreams_configuration_proto = out.File - file_pbmesh_v1alpha1_upstreams_configuration_proto_rawDesc = nil - file_pbmesh_v1alpha1_upstreams_configuration_proto_goTypes = nil - file_pbmesh_v1alpha1_upstreams_configuration_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v1alpha1/upstreams_configuration.proto b/proto-public/pbmesh/v1alpha1/upstreams_configuration.proto deleted file mode 100644 index 81bbbf5f82691..0000000000000 --- a/proto-public/pbmesh/v1alpha1/upstreams_configuration.proto +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v1alpha1; - -import "google/protobuf/duration.proto"; -import "google/protobuf/wrappers.proto"; -import "pbcatalog/v1alpha1/protocol.proto"; -import "pbcatalog/v1alpha1/selector.proto"; -import "pbmesh/v1alpha1/connection.proto"; -import "pbmesh/v1alpha1/routing.proto"; -import "pbresource/resource.proto"; - -message UpstreamsConfiguration { - // Selection of workloads these upstreams should apply to. - // These can be prefixes or specific workload names. - hashicorp.consul.catalog.v1alpha1.WorkloadSelector workloads = 1; - - // default_config applies to all upstreams for the workloads selected by this resource. - UpstreamConfig default_config = 2; - - // config_overrides provides per-upstream or per-upstream-port config overrides. - repeated UpstreamConfigOverrides config_overrides = 3; -} - -// UpstreamConfigOverrides allow to override upstream configuration per destination_ref/port/datacenter. -// In that sense, those three fields (destination_ref, destination_port and datacenter) are treated -// sort of like map keys and config is a like a map value for that key. -message UpstreamConfigOverrides { - // destination_ref is the reference to an upstream service that this configuration applies to. - // This has to be pbcatalog.Service type. - hashicorp.consul.resource.Reference destination_ref = 1; - - // destination_port is the port name of the upstream service. This should be the name - // of the service's target port. If not provided, this configuration will apply to all ports of an upstream. - string destination_port = 2; - - // datacenter is the datacenter for where this upstream service lives. - string datacenter = 3; - - // config is the configuration that should apply to this upstream. - UpstreamConfig config = 4; -} - -message UpstreamConfig { - // protocol overrides upstream's port protocol. If no port for an upstream is specified - // or if used in the default configuration, this protocol will be used for all ports - // or for all ports of all upstreams respectively. - hashicorp.consul.catalog.v1alpha1.Protocol protocol = 1; - - // connect_timeout is the timeout used when making a new - // connection to this upstream. Defaults to 5 seconds if not set. - google.protobuf.Duration connect_timeout = 2; - - // limits are the set of limits that are applied to the proxy for a specific upstream. - UpstreamLimits limits = 3; - - // passive_health_check configuration determines how upstream proxy instances will - // be monitored for removal from the load balancing pool. - PassiveHealthCheck passive_health_check = 4; - - // balance_outbound_connections indicates how the proxy should attempt to distribute - // connections across worker threads. - BalanceConnections balance_outbound_connections = 5; - - // MeshGatewayMode is the Mesh Gateway routing mode. - MeshGatewayMode mesh_gateway_mode = 6; -} - -// UpstreamLimits describes the limits that are associated with a specific -// upstream of a service instance. -message UpstreamLimits { - // max_connections is the maximum number of connections the local proxy can - // make to the upstream service. - google.protobuf.UInt32Value max_connections = 1; - - // max_pending_requests is the maximum number of requests that will be queued - // waiting for an available connection. This is mostly applicable to HTTP/1.1 - // clusters since all HTTP/2 requests are streamed over a single - // connection. - google.protobuf.UInt32Value max_pending_requests = 2; - - // max_concurrent_requests is the maximum number of in-flight requests that will be allowed - // to the upstream cluster at a point in time. This is mostly applicable to HTTP/2 - // clusters since all HTTP/1.1 requests are limited by MaxConnections. - google.protobuf.UInt32Value max_concurrent_requests = 3; -} - -message PassiveHealthCheck { - // interval between health check analysis sweeps. Each sweep may remove - // hosts or return hosts to the pool. - google.protobuf.Duration interval = 1; - - // max_failures is the count of consecutive failures that results in a host - // being removed from the pool. - uint32 max_failures = 2; - - // enforcing_consecutive_5xx is the % chance that a host will be actually ejected - // when an outlier status is detected through consecutive 5xx. - // This setting can be used to disable ejection or to ramp it up slowly. Defaults to 100. - uint32 enforcing_consecutive_5xx = 3; -} diff --git a/proto-public/pbmesh/v1alpha1/xroute_addons.go b/proto-public/pbmesh/v1alpha1/xroute_addons.go deleted file mode 100644 index e85177d5160eb..0000000000000 --- a/proto-public/pbmesh/v1alpha1/xroute_addons.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package meshv1alpha1 - -// GetUnderlyingBackendRefs will collect BackendReferences from all rules and -// bundle them up in one slice, unwrapping the HTTP-specifics in the process. -// -// This implements an XRouteWithRefs interface in the internal/mesh package. -// -// NOTE: no deduplication occurs. -func (x *HTTPRoute) GetUnderlyingBackendRefs() []*BackendReference { - if x == nil { - return nil - } - - estimate := 0 - for _, rule := range x.Rules { - estimate += len(rule.BackendRefs) - } - - backendRefs := make([]*BackendReference, 0, estimate) - for _, rule := range x.Rules { - for _, backendRef := range rule.BackendRefs { - backendRefs = append(backendRefs, backendRef.BackendRef) - } - } - return backendRefs -} - -// GetUnderlyingBackendRefs will collect BackendReferences from all rules and -// bundle them up in one slice, unwrapping the GRPC-specifics in the process. -// -// This implements an XRouteWithRefs interface in the internal/mesh package. -// -// NOTE: no deduplication occurs. -func (x *GRPCRoute) GetUnderlyingBackendRefs() []*BackendReference { - if x == nil { - return nil - } - - estimate := 0 - for _, rule := range x.Rules { - estimate += len(rule.BackendRefs) - } - - backendRefs := make([]*BackendReference, 0, estimate) - for _, rule := range x.Rules { - for _, backendRef := range rule.BackendRefs { - backendRefs = append(backendRefs, backendRef.BackendRef) - } - } - return backendRefs -} - -// GetUnderlyingBackendRefs will collect BackendReferences from all rules and -// bundle them up in one slice, unwrapping the TCP-specifics in the process. -// -// This implements an XRouteWithRefs interface in the internal/mesh package. -// -// NOTE: no deduplication occurs. -func (x *TCPRoute) GetUnderlyingBackendRefs() []*BackendReference { - if x == nil { - return nil - } - - estimate := 0 - for _, rule := range x.Rules { - estimate += len(rule.BackendRefs) - } - - backendRefs := make([]*BackendReference, 0, estimate) - - for _, rule := range x.Rules { - for _, backendRef := range rule.BackendRefs { - backendRefs = append(backendRefs, backendRef.BackendRef) - } - } - return backendRefs -} - -// IsHashBased returns true if the policy is a hash-based policy such as maglev -// or ring hash. -func (p LoadBalancerPolicy) IsHashBased() bool { - switch p { - case LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH: - return true - } - return false -} diff --git a/proto-public/pbmesh/v1alpha1/xroute_addons_test.go b/proto-public/pbmesh/v1alpha1/xroute_addons_test.go deleted file mode 100644 index ce15282de825d..0000000000000 --- a/proto-public/pbmesh/v1alpha1/xroute_addons_test.go +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package meshv1alpha1 - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/proto" - - pbresource "github.com/hashicorp/consul/proto-public/pbresource" -) - -type routeWithAddons interface { - proto.Message - GetUnderlyingBackendRefs() []*BackendReference -} - -func TestXRoute_GetUnderlyingBackendRefs(t *testing.T) { - type testcase struct { - route routeWithAddons - expect []*BackendReference - } - - run := func(t *testing.T, tc testcase) { - got := tc.route.GetUnderlyingBackendRefs() - require.ElementsMatch(t, stringifyList(tc.expect), stringifyList(got)) - } - - cases := map[string]testcase{ - "http: nil": { - route: (*HTTPRoute)(nil), - }, - "grpc: nil": { - route: (*GRPCRoute)(nil), - }, - "tcp: nil": { - route: (*TCPRoute)(nil), - }, - "http: kitchen sink": { - route: &HTTPRoute{ - Rules: []*HTTPRouteRule{ - {BackendRefs: []*HTTPBackendRef{ - {BackendRef: newBackendRef("aa")}, - }}, - {BackendRefs: []*HTTPBackendRef{ - {BackendRef: newBackendRef("bb")}, - }}, - {BackendRefs: []*HTTPBackendRef{ - {BackendRef: newBackendRef("cc")}, - {BackendRef: newBackendRef("dd")}, - }}, - {BackendRefs: []*HTTPBackendRef{ - {BackendRef: newBackendRef("ee")}, - {BackendRef: newBackendRef("ff")}, - }}, - }, - }, - expect: []*BackendReference{ - newBackendRef("aa"), - newBackendRef("bb"), - newBackendRef("cc"), - newBackendRef("dd"), - newBackendRef("ee"), - newBackendRef("ff"), - }, - }, - "grpc: kitchen sink": { - route: &GRPCRoute{ - Rules: []*GRPCRouteRule{ - {BackendRefs: []*GRPCBackendRef{ - {BackendRef: newBackendRef("aa")}, - }}, - {BackendRefs: []*GRPCBackendRef{ - {BackendRef: newBackendRef("bb")}, - }}, - {BackendRefs: []*GRPCBackendRef{ - {BackendRef: newBackendRef("cc")}, - {BackendRef: newBackendRef("dd")}, - }}, - {BackendRefs: []*GRPCBackendRef{ - {BackendRef: newBackendRef("ee")}, - {BackendRef: newBackendRef("ff")}, - }}, - }, - }, - expect: []*BackendReference{ - newBackendRef("aa"), - newBackendRef("bb"), - newBackendRef("cc"), - newBackendRef("dd"), - newBackendRef("ee"), - newBackendRef("ff"), - }, - }, - "tcp: kitchen sink": { - route: &TCPRoute{ - Rules: []*TCPRouteRule{ - {BackendRefs: []*TCPBackendRef{ - {BackendRef: newBackendRef("aa")}, - }}, - {BackendRefs: []*TCPBackendRef{ - {BackendRef: newBackendRef("bb")}, - }}, - {BackendRefs: []*TCPBackendRef{ - {BackendRef: newBackendRef("cc")}, - {BackendRef: newBackendRef("dd")}, - }}, - {BackendRefs: []*TCPBackendRef{ - {BackendRef: newBackendRef("ee")}, - {BackendRef: newBackendRef("ff")}, - }}, - }, - }, - expect: []*BackendReference{ - newBackendRef("aa"), - newBackendRef("bb"), - newBackendRef("cc"), - newBackendRef("dd"), - newBackendRef("ee"), - newBackendRef("ff"), - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func protoToString[V proto.Message](pb V) string { - m := protojson.MarshalOptions{ - Indent: " ", - } - gotJSON, err := m.Marshal(pb) - if err != nil { - return "" - } - return string(gotJSON) -} - -func newRouteRef(name string) *pbresource.Reference { - return &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "fake", - GroupVersion: "v1alpha1", - Kind: "fake", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: name, - } -} - -func newBackendRef(name string) *BackendReference { - return &BackendReference{ - Ref: newRouteRef(name), - } -} - -func stringifyList[V proto.Message](list []V) []string { - out := make([]string, 0, len(list)) - for _, item := range list { - out = append(out, protoToString(item)) - } - return out -} diff --git a/proto/buf.gen.yaml b/proto/buf.gen.yaml index efb9703b10bae..e8a1a956ab869 100644 --- a/proto/buf.gen.yaml +++ b/proto/buf.gen.yaml @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 version: v1 managed: diff --git a/proto/buf.yaml b/proto/buf.yaml index d367418c824b0..de63034c3c1be 100644 --- a/proto/buf.yaml +++ b/proto/buf.yaml @@ -1,9 +1,7 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 version: v1 -deps: - - buf.build/hashicorp/consul lint: use: - DEFAULT diff --git a/proto/private/pbacl/acl.go b/proto/private/pbacl/acl.go index 5c9cc6285e6c7..3d3b8de5204a3 100644 --- a/proto/private/pbacl/acl.go +++ b/proto/private/pbacl/acl.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbacl diff --git a/proto/private/pbacl/acl.pb.go b/proto/private/pbacl/acl.pb.go index f6aa5c3418cf2..e8d0719e8d6bf 100644 --- a/proto/private/pbacl/acl.pb.go +++ b/proto/private/pbacl/acl.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: diff --git a/proto/private/pbacl/acl.proto b/proto/private/pbacl/acl.proto index 0fa9ecd89dc6a..4a96f2671c319 100644 --- a/proto/private/pbacl/acl.proto +++ b/proto/private/pbacl/acl.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; diff --git a/proto/private/pbautoconf/auto_config.go b/proto/private/pbautoconf/auto_config.go index 39d37d1dc8b0f..e2de2f18d9cc5 100644 --- a/proto/private/pbautoconf/auto_config.go +++ b/proto/private/pbautoconf/auto_config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbautoconf diff --git a/proto/private/pbautoconf/auto_config.pb.go b/proto/private/pbautoconf/auto_config.pb.go index a9b4c2c891682..55da1b07f9720 100644 --- a/proto/private/pbautoconf/auto_config.pb.go +++ b/proto/private/pbautoconf/auto_config.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: diff --git a/proto/private/pbautoconf/auto_config.proto b/proto/private/pbautoconf/auto_config.proto index a0f4440d79047..a167107655939 100644 --- a/proto/private/pbautoconf/auto_config.proto +++ b/proto/private/pbautoconf/auto_config.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; diff --git a/proto/private/pbautoconf/auto_config_ce.go b/proto/private/pbautoconf/auto_config_ce.go index 032ca67ba3c79..1cab31f171c3f 100644 --- a/proto/private/pbautoconf/auto_config_ce.go +++ b/proto/private/pbautoconf/auto_config_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/proto/private/pbcommon/common.go b/proto/private/pbcommon/common.go index ecf935d75f142..e05c0a970a886 100644 --- a/proto/private/pbcommon/common.go +++ b/proto/private/pbcommon/common.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbcommon diff --git a/proto/private/pbcommon/common.pb.go b/proto/private/pbcommon/common.pb.go index fc6928184132d..dd6240ad85e9e 100644 --- a/proto/private/pbcommon/common.pb.go +++ b/proto/private/pbcommon/common.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: diff --git a/proto/private/pbcommon/common.proto b/proto/private/pbcommon/common.proto index 2296dc69d628a..a86aa2dde53d1 100644 --- a/proto/private/pbcommon/common.proto +++ b/proto/private/pbcommon/common.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; diff --git a/proto/private/pbcommon/common_ce.go b/proto/private/pbcommon/common_ce.go index 94aef583a1a23..c0ce9b27f8503 100644 --- a/proto/private/pbcommon/common_ce.go +++ b/proto/private/pbcommon/common_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/proto/private/pbcommon/convert_pbstruct.go b/proto/private/pbcommon/convert_pbstruct.go index f21d9a40ed49d..e48dce9ae6e0b 100644 --- a/proto/private/pbcommon/convert_pbstruct.go +++ b/proto/private/pbcommon/convert_pbstruct.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbcommon diff --git a/proto/private/pbcommon/convert_pbstruct_test.go b/proto/private/pbcommon/convert_pbstruct_test.go index 82f52c6992884..543129fdfd2fd 100644 --- a/proto/private/pbcommon/convert_pbstruct_test.go +++ b/proto/private/pbcommon/convert_pbstruct_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbcommon diff --git a/proto/private/pbconfig/config.pb.go b/proto/private/pbconfig/config.pb.go index ce8e43c7ce912..61c394944f7a5 100644 --- a/proto/private/pbconfig/config.pb.go +++ b/proto/private/pbconfig/config.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: diff --git a/proto/private/pbconfig/config.proto b/proto/private/pbconfig/config.proto index 96a0f1cae04e5..79b4a3669e8b2 100644 --- a/proto/private/pbconfig/config.proto +++ b/proto/private/pbconfig/config.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; diff --git a/proto/private/pbconfigentry/config_entry.gen.go b/proto/private/pbconfigentry/config_entry.gen.go index 61238fc91d802..ca75146af425e 100644 --- a/proto/private/pbconfigentry/config_entry.gen.go +++ b/proto/private/pbconfigentry/config_entry.gen.go @@ -53,16 +53,6 @@ func APIGatewayListenerToStructs(s *APIGatewayListener, t *structs.APIGatewayLis if s.TLS != nil { APIGatewayTLSConfigurationToStructs(s.TLS, &t.TLS) } - if s.Override != nil { - var x structs.APIGatewayPolicy - APIGatewayPolicyToStructs(s.Override, &x) - t.Override = &x - } - if s.Default != nil { - var x structs.APIGatewayPolicy - APIGatewayPolicyToStructs(s.Default, &x) - t.Default = &x - } } func APIGatewayListenerFromStructs(t *structs.APIGatewayListener, s *APIGatewayListener) { if s == nil { @@ -77,28 +67,6 @@ func APIGatewayListenerFromStructs(t *structs.APIGatewayListener, s *APIGatewayL APIGatewayTLSConfigurationFromStructs(&t.TLS, &x) s.TLS = &x } - if t.Override != nil { - var x APIGatewayPolicy - APIGatewayPolicyFromStructs(t.Override, &x) - s.Override = &x - } - if t.Default != nil { - var x APIGatewayPolicy - APIGatewayPolicyFromStructs(t.Default, &x) - s.Default = &x - } -} -func APIGatewayPolicyToStructs(s *APIGatewayPolicy, t *structs.APIGatewayPolicy) { - if s == nil { - return - } - t.JWT = gwJWTRequirementToStructs(s.JWT) -} -func APIGatewayPolicyFromStructs(t *structs.APIGatewayPolicy, s *APIGatewayPolicy) { - if s == nil { - return - } - s.JWT = gwJWTRequirementFromStructs(t.JWT) } func APIGatewayTLSConfigurationToStructs(s *APIGatewayTLSConfiguration, t *structs.APIGatewayTLSConfiguration) { if s == nil { @@ -401,17 +369,6 @@ func HTTPFiltersToStructs(s *HTTPFilters, t *structs.HTTPFilters) { URLRewriteToStructs(s.URLRewrite, &x) t.URLRewrite = &x } - if s.RetryFilter != nil { - var x structs.RetryFilter - RetryFilterToStructs(s.RetryFilter, &x) - t.RetryFilter = &x - } - if s.TimeoutFilter != nil { - var x structs.TimeoutFilter - TimeoutFilterToStructs(s.TimeoutFilter, &x) - t.TimeoutFilter = &x - } - t.JWT = routeJWTFilterToStructs(s.JWT) } func HTTPFiltersFromStructs(t *structs.HTTPFilters, s *HTTPFilters) { if s == nil { @@ -432,17 +389,6 @@ func HTTPFiltersFromStructs(t *structs.HTTPFilters, s *HTTPFilters) { URLRewriteFromStructs(t.URLRewrite, &x) s.URLRewrite = &x } - if t.RetryFilter != nil { - var x RetryFilter - RetryFilterFromStructs(t.RetryFilter, &x) - s.RetryFilter = &x - } - if t.TimeoutFilter != nil { - var x TimeoutFilter - TimeoutFilterFromStructs(t.TimeoutFilter, &x) - s.TimeoutFilter = &x - } - s.JWT = routeJWTFilterFromStructs(t.JWT) } func HTTPHeaderFilterToStructs(s *HTTPHeaderFilter, t *structs.HTTPHeaderFilter) { if s == nil { @@ -938,58 +884,6 @@ func InlineCertificateFromStructs(t *structs.InlineCertificateConfigEntry, s *In s.PrivateKey = t.PrivateKey s.Meta = t.Meta } -func InstanceLevelRateLimitsToStructs(s *InstanceLevelRateLimits, t *structs.InstanceLevelRateLimits) { - if s == nil { - return - } - t.RequestsPerSecond = int(s.RequestsPerSecond) - t.RequestsMaxBurst = int(s.RequestsMaxBurst) - { - t.Routes = make([]structs.InstanceLevelRouteRateLimits, len(s.Routes)) - for i := range s.Routes { - if s.Routes[i] != nil { - InstanceLevelRouteRateLimitsToStructs(s.Routes[i], &t.Routes[i]) - } - } - } -} -func InstanceLevelRateLimitsFromStructs(t *structs.InstanceLevelRateLimits, s *InstanceLevelRateLimits) { - if s == nil { - return - } - s.RequestsPerSecond = uint32(t.RequestsPerSecond) - s.RequestsMaxBurst = uint32(t.RequestsMaxBurst) - { - s.Routes = make([]*InstanceLevelRouteRateLimits, len(t.Routes)) - for i := range t.Routes { - { - var x InstanceLevelRouteRateLimits - InstanceLevelRouteRateLimitsFromStructs(&t.Routes[i], &x) - s.Routes[i] = &x - } - } - } -} -func InstanceLevelRouteRateLimitsToStructs(s *InstanceLevelRouteRateLimits, t *structs.InstanceLevelRouteRateLimits) { - if s == nil { - return - } - t.PathExact = s.PathExact - t.PathPrefix = s.PathPrefix - t.PathRegex = s.PathRegex - t.RequestsPerSecond = int(s.RequestsPerSecond) - t.RequestsMaxBurst = int(s.RequestsMaxBurst) -} -func InstanceLevelRouteRateLimitsFromStructs(t *structs.InstanceLevelRouteRateLimits, s *InstanceLevelRouteRateLimits) { - if s == nil { - return - } - s.PathExact = t.PathExact - s.PathPrefix = t.PathPrefix - s.PathRegex = t.PathRegex - s.RequestsPerSecond = uint32(t.RequestsPerSecond) - s.RequestsMaxBurst = uint32(t.RequestsMaxBurst) -} func IntentionHTTPHeaderPermissionToStructs(s *IntentionHTTPHeaderPermission, t *structs.IntentionHTTPHeaderPermission) { if s == nil { return @@ -1700,24 +1594,6 @@ func PeeringMeshConfigFromStructs(t *structs.PeeringMeshConfig, s *PeeringMeshCo } s.PeerThroughMeshGateways = t.PeerThroughMeshGateways } -func RateLimitsToStructs(s *RateLimits, t *structs.RateLimits) { - if s == nil { - return - } - if s.InstanceLevel != nil { - InstanceLevelRateLimitsToStructs(s.InstanceLevel, &t.InstanceLevel) - } -} -func RateLimitsFromStructs(t *structs.RateLimits, s *RateLimits) { - if s == nil { - return - } - { - var x InstanceLevelRateLimits - InstanceLevelRateLimitsFromStructs(&t.InstanceLevel, &x) - s.InstanceLevel = &x - } -} func RemoteJWKSToStructs(s *RemoteJWKS, t *structs.RemoteJWKS) { if s == nil { return @@ -1774,24 +1650,6 @@ func ResourceReferenceFromStructs(t *structs.ResourceReference, s *ResourceRefer s.SectionName = t.SectionName s.EnterpriseMeta = enterpriseMetaFromStructs(t.EnterpriseMeta) } -func RetryFilterToStructs(s *RetryFilter, t *structs.RetryFilter) { - if s == nil { - return - } - t.NumRetries = &s.NumRetries - t.RetryOn = s.RetryOn - t.RetryOnStatusCodes = s.RetryOnStatusCodes - t.RetryOnConnectFailure = &s.RetryOnConnectFailure -} -func RetryFilterFromStructs(t *structs.RetryFilter, s *RetryFilter) { - if s == nil { - return - } - s.NumRetries = *t.NumRetries - s.RetryOn = t.RetryOn - s.RetryOnStatusCodes = t.RetryOnStatusCodes - s.RetryOnConnectFailure = *t.RetryOnConnectFailure -} func RetryPolicyBackOffToStructs(s *RetryPolicyBackOff, t *structs.RetryPolicyBackOff) { if s == nil { return @@ -1903,11 +1761,6 @@ func ServiceDefaultsToStructs(s *ServiceDefaults, t *structs.ServiceConfigEntry) t.LocalConnectTimeoutMs = int(s.LocalConnectTimeoutMs) t.LocalRequestTimeoutMs = int(s.LocalRequestTimeoutMs) t.BalanceInboundConnections = s.BalanceInboundConnections - if s.RateLimits != nil { - var x structs.RateLimits - RateLimitsToStructs(s.RateLimits, &x) - t.RateLimits = &x - } t.EnvoyExtensions = EnvoyExtensionsToStructs(s.EnvoyExtensions) t.Meta = s.Meta } @@ -1948,11 +1801,6 @@ func ServiceDefaultsFromStructs(t *structs.ServiceConfigEntry, s *ServiceDefault s.LocalConnectTimeoutMs = int32(t.LocalConnectTimeoutMs) s.LocalRequestTimeoutMs = int32(t.LocalRequestTimeoutMs) s.BalanceInboundConnections = t.BalanceInboundConnections - if t.RateLimits != nil { - var x RateLimits - RateLimitsFromStructs(t.RateLimits, &x) - s.RateLimits = &x - } s.EnvoyExtensions = EnvoyExtensionsFromStructs(t.EnvoyExtensions) s.Meta = t.Meta } @@ -2376,20 +2224,6 @@ func TCPServiceFromStructs(t *structs.TCPService, s *TCPService) { s.Name = t.Name s.EnterpriseMeta = enterpriseMetaFromStructs(t.EnterpriseMeta) } -func TimeoutFilterToStructs(s *TimeoutFilter, t *structs.TimeoutFilter) { - if s == nil { - return - } - t.RequestTimeout = structs.DurationFromProto(s.RequestTimeout) - t.IdleTimeout = structs.DurationFromProto(s.IdleTimeout) -} -func TimeoutFilterFromStructs(t *structs.TimeoutFilter, s *TimeoutFilter) { - if s == nil { - return - } - s.RequestTimeout = structs.DurationToProto(t.RequestTimeout) - s.IdleTimeout = structs.DurationToProto(t.IdleTimeout) -} func TransparentProxyConfigToStructs(s *TransparentProxyConfig, t *structs.TransparentProxyConfig) { if s == nil { return diff --git a/proto/private/pbconfigentry/config_entry.go b/proto/private/pbconfigentry/config_entry.go index 8ddfde8cccfb9..705c87d0131ef 100644 --- a/proto/private/pbconfigentry/config_entry.go +++ b/proto/private/pbconfigentry/config_entry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbconfigentry diff --git a/proto/private/pbconfigentry/config_entry.pb.binary.go b/proto/private/pbconfigentry/config_entry.pb.binary.go index 9d8e6dc970223..bd9bac6c7e762 100644 --- a/proto/private/pbconfigentry/config_entry.pb.binary.go +++ b/proto/private/pbconfigentry/config_entry.pb.binary.go @@ -457,36 +457,6 @@ func (msg *DestinationConfig) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RateLimits) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RateLimits) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InstanceLevelRateLimits) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InstanceLevelRateLimits) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InstanceLevelRouteRateLimits) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InstanceLevelRouteRateLimits) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - // MarshalBinary implements encoding.BinaryMarshaler func (msg *APIGateway) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) @@ -537,46 +507,6 @@ func (msg *APIGatewayTLSConfiguration) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *APIGatewayPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *APIGatewayPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *APIGatewayJWTRequirement) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *APIGatewayJWTRequirement) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *APIGatewayJWTProvider) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *APIGatewayJWTProvider) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *APIGatewayJWTClaimVerification) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *APIGatewayJWTClaimVerification) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - // MarshalBinary implements encoding.BinaryMarshaler func (msg *ResourceReference) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) @@ -697,36 +627,6 @@ func (msg *URLRewrite) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RetryFilter) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RetryFilter) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TimeoutFilter) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TimeoutFilter) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *JWTFilter) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *JWTFilter) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - // MarshalBinary implements encoding.BinaryMarshaler func (msg *HTTPHeaderFilter) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) diff --git a/proto/private/pbconfigentry/config_entry.pb.go b/proto/private/pbconfigentry/config_entry.pb.go index 2369142dddf8f..2977d593f824c 100644 --- a/proto/private/pbconfigentry/config_entry.pb.go +++ b/proto/private/pbconfigentry/config_entry.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: @@ -3475,7 +3475,6 @@ type ServiceDefaults struct { // mog: func-to=int func-from=int32 LocalRequestTimeoutMs int32 `protobuf:"varint,11,opt,name=LocalRequestTimeoutMs,proto3" json:"LocalRequestTimeoutMs,omitempty"` BalanceInboundConnections string `protobuf:"bytes,12,opt,name=BalanceInboundConnections,proto3" json:"BalanceInboundConnections,omitempty"` - RateLimits *RateLimits `protobuf:"bytes,16,opt,name=RateLimits,proto3" json:"RateLimits,omitempty"` Meta map[string]string `protobuf:"bytes,13,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // mog: func-to=EnvoyExtensionsToStructs func-from=EnvoyExtensionsFromStructs EnvoyExtensions []*pbcommon.EnvoyExtension `protobuf:"bytes,14,rep,name=EnvoyExtensions,proto3" json:"EnvoyExtensions,omitempty"` @@ -3599,13 +3598,6 @@ func (x *ServiceDefaults) GetBalanceInboundConnections() string { return "" } -func (x *ServiceDefaults) GetRateLimits() *RateLimits { - if x != nil { - return x.RateLimits - } - return nil -} - func (x *ServiceDefaults) GetMeta() map[string]string { if x != nil { return x.Meta @@ -4301,214 +4293,6 @@ func (x *DestinationConfig) GetPort() int32 { return 0 } -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.RateLimits -// output=config_entry.gen.go -// name=Structs -type RateLimits struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - InstanceLevel *InstanceLevelRateLimits `protobuf:"bytes,1,opt,name=InstanceLevel,proto3" json:"InstanceLevel,omitempty"` -} - -func (x *RateLimits) Reset() { - *x = RateLimits{} - if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[45] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RateLimits) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RateLimits) ProtoMessage() {} - -func (x *RateLimits) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[45] - 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 RateLimits.ProtoReflect.Descriptor instead. -func (*RateLimits) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{45} -} - -func (x *RateLimits) GetInstanceLevel() *InstanceLevelRateLimits { - if x != nil { - return x.InstanceLevel - } - return nil -} - -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.InstanceLevelRateLimits -// output=config_entry.gen.go -// name=Structs -type InstanceLevelRateLimits struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // mog: func-to=int func-from=uint32 - RequestsPerSecond uint32 `protobuf:"varint,1,opt,name=RequestsPerSecond,proto3" json:"RequestsPerSecond,omitempty"` - // mog: func-to=int func-from=uint32 - RequestsMaxBurst uint32 `protobuf:"varint,2,opt,name=RequestsMaxBurst,proto3" json:"RequestsMaxBurst,omitempty"` - Routes []*InstanceLevelRouteRateLimits `protobuf:"bytes,3,rep,name=Routes,proto3" json:"Routes,omitempty"` -} - -func (x *InstanceLevelRateLimits) Reset() { - *x = InstanceLevelRateLimits{} - if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[46] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InstanceLevelRateLimits) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InstanceLevelRateLimits) ProtoMessage() {} - -func (x *InstanceLevelRateLimits) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[46] - 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 InstanceLevelRateLimits.ProtoReflect.Descriptor instead. -func (*InstanceLevelRateLimits) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{46} -} - -func (x *InstanceLevelRateLimits) GetRequestsPerSecond() uint32 { - if x != nil { - return x.RequestsPerSecond - } - return 0 -} - -func (x *InstanceLevelRateLimits) GetRequestsMaxBurst() uint32 { - if x != nil { - return x.RequestsMaxBurst - } - return 0 -} - -func (x *InstanceLevelRateLimits) GetRoutes() []*InstanceLevelRouteRateLimits { - if x != nil { - return x.Routes - } - return nil -} - -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.InstanceLevelRouteRateLimits -// output=config_entry.gen.go -// name=Structs -type InstanceLevelRouteRateLimits struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PathExact string `protobuf:"bytes,1,opt,name=PathExact,proto3" json:"PathExact,omitempty"` - PathPrefix string `protobuf:"bytes,2,opt,name=PathPrefix,proto3" json:"PathPrefix,omitempty"` - PathRegex string `protobuf:"bytes,3,opt,name=PathRegex,proto3" json:"PathRegex,omitempty"` - // mog: func-to=int func-from=uint32 - RequestsPerSecond uint32 `protobuf:"varint,4,opt,name=RequestsPerSecond,proto3" json:"RequestsPerSecond,omitempty"` - // mog: func-to=int func-from=uint32 - RequestsMaxBurst uint32 `protobuf:"varint,5,opt,name=RequestsMaxBurst,proto3" json:"RequestsMaxBurst,omitempty"` -} - -func (x *InstanceLevelRouteRateLimits) Reset() { - *x = InstanceLevelRouteRateLimits{} - if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[47] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InstanceLevelRouteRateLimits) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InstanceLevelRouteRateLimits) ProtoMessage() {} - -func (x *InstanceLevelRouteRateLimits) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[47] - 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 InstanceLevelRouteRateLimits.ProtoReflect.Descriptor instead. -func (*InstanceLevelRouteRateLimits) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{47} -} - -func (x *InstanceLevelRouteRateLimits) GetPathExact() string { - if x != nil { - return x.PathExact - } - return "" -} - -func (x *InstanceLevelRouteRateLimits) GetPathPrefix() string { - if x != nil { - return x.PathPrefix - } - return "" -} - -func (x *InstanceLevelRouteRateLimits) GetPathRegex() string { - if x != nil { - return x.PathRegex - } - return "" -} - -func (x *InstanceLevelRouteRateLimits) GetRequestsPerSecond() uint32 { - if x != nil { - return x.RequestsPerSecond - } - return 0 -} - -func (x *InstanceLevelRouteRateLimits) GetRequestsMaxBurst() uint32 { - if x != nil { - return x.RequestsMaxBurst - } - return 0 -} - // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.APIGatewayConfigEntry @@ -4528,7 +4312,7 @@ type APIGateway struct { func (x *APIGateway) Reset() { *x = APIGateway{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[48] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4541,7 +4325,7 @@ func (x *APIGateway) String() string { func (*APIGateway) ProtoMessage() {} func (x *APIGateway) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[48] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4554,7 +4338,7 @@ func (x *APIGateway) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGateway.ProtoReflect.Descriptor instead. func (*APIGateway) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{48} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{45} } func (x *APIGateway) GetMeta() map[string]string { @@ -4594,7 +4378,7 @@ type Status struct { func (x *Status) Reset() { *x = Status{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[49] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4607,7 +4391,7 @@ func (x *Status) String() string { func (*Status) ProtoMessage() {} func (x *Status) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[49] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4620,7 +4404,7 @@ func (x *Status) ProtoReflect() protoreflect.Message { // Deprecated: Use Status.ProtoReflect.Descriptor instead. func (*Status) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{49} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{46} } func (x *Status) GetConditions() []*Condition { @@ -4652,7 +4436,7 @@ type Condition struct { func (x *Condition) Reset() { *x = Condition{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[50] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4665,7 +4449,7 @@ func (x *Condition) String() string { func (*Condition) ProtoMessage() {} func (x *Condition) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[50] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4678,7 +4462,7 @@ func (x *Condition) ProtoReflect() protoreflect.Message { // Deprecated: Use Condition.ProtoReflect.Descriptor instead. func (*Condition) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{50} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{47} } func (x *Condition) GetType() string { @@ -4740,14 +4524,12 @@ type APIGatewayListener struct { // mog: func-to=apiGatewayProtocolToStructs func-from=apiGatewayProtocolFromStructs Protocol APIGatewayListenerProtocol `protobuf:"varint,4,opt,name=Protocol,proto3,enum=hashicorp.consul.internal.configentry.APIGatewayListenerProtocol" json:"Protocol,omitempty"` TLS *APIGatewayTLSConfiguration `protobuf:"bytes,5,opt,name=TLS,proto3" json:"TLS,omitempty"` - Override *APIGatewayPolicy `protobuf:"bytes,6,opt,name=Override,proto3" json:"Override,omitempty"` - Default *APIGatewayPolicy `protobuf:"bytes,7,opt,name=Default,proto3" json:"Default,omitempty"` } func (x *APIGatewayListener) Reset() { *x = APIGatewayListener{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[51] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4760,7 +4542,7 @@ func (x *APIGatewayListener) String() string { func (*APIGatewayListener) ProtoMessage() {} func (x *APIGatewayListener) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[51] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4773,7 +4555,7 @@ func (x *APIGatewayListener) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayListener.ProtoReflect.Descriptor instead. func (*APIGatewayListener) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{51} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{48} } func (x *APIGatewayListener) GetName() string { @@ -4811,20 +4593,6 @@ func (x *APIGatewayListener) GetTLS() *APIGatewayTLSConfiguration { return nil } -func (x *APIGatewayListener) GetOverride() *APIGatewayPolicy { - if x != nil { - return x.Override - } - return nil -} - -func (x *APIGatewayListener) GetDefault() *APIGatewayPolicy { - if x != nil { - return x.Default - } - return nil -} - // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.APIGatewayTLSConfiguration @@ -4847,7 +4615,7 @@ type APIGatewayTLSConfiguration struct { func (x *APIGatewayTLSConfiguration) Reset() { *x = APIGatewayTLSConfiguration{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[52] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4860,7 +4628,7 @@ func (x *APIGatewayTLSConfiguration) String() string { func (*APIGatewayTLSConfiguration) ProtoMessage() {} func (x *APIGatewayTLSConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[52] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4873,7 +4641,7 @@ func (x *APIGatewayTLSConfiguration) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayTLSConfiguration.ProtoReflect.Descriptor instead. func (*APIGatewayTLSConfiguration) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{52} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{49} } func (x *APIGatewayTLSConfiguration) GetCertificates() []*ResourceReference { @@ -4906,35 +4674,38 @@ func (x *APIGatewayTLSConfiguration) GetCipherSuites() []string { // mog annotation: // -// target=github.com/hashicorp/consul/agent/structs.APIGatewayPolicy +// target=github.com/hashicorp/consul/agent/structs.ResourceReference // output=config_entry.gen.go // name=Structs -type APIGatewayPolicy struct { +type ResourceReference struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // mog: func-to=gwJWTRequirementToStructs func-from=gwJWTRequirementFromStructs - JWT *APIGatewayJWTRequirement `protobuf:"bytes,1,opt,name=JWT,proto3" json:"JWT,omitempty"` + Kind string `protobuf:"bytes,1,opt,name=Kind,proto3" json:"Kind,omitempty"` + Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` + SectionName string `protobuf:"bytes,3,opt,name=SectionName,proto3" json:"SectionName,omitempty"` + // mog: func-to=enterpriseMetaToStructs func-from=enterpriseMetaFromStructs + EnterpriseMeta *pbcommon.EnterpriseMeta `protobuf:"bytes,4,opt,name=EnterpriseMeta,proto3" json:"EnterpriseMeta,omitempty"` } -func (x *APIGatewayPolicy) Reset() { - *x = APIGatewayPolicy{} +func (x *ResourceReference) Reset() { + *x = ResourceReference{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[53] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *APIGatewayPolicy) String() string { +func (x *ResourceReference) String() string { return protoimpl.X.MessageStringOf(x) } -func (*APIGatewayPolicy) ProtoMessage() {} +func (*ResourceReference) ProtoMessage() {} -func (x *APIGatewayPolicy) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[53] +func (x *ResourceReference) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4945,271 +4716,58 @@ func (x *APIGatewayPolicy) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use APIGatewayPolicy.ProtoReflect.Descriptor instead. -func (*APIGatewayPolicy) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{53} +// Deprecated: Use ResourceReference.ProtoReflect.Descriptor instead. +func (*ResourceReference) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{50} } -func (x *APIGatewayPolicy) GetJWT() *APIGatewayJWTRequirement { +func (x *ResourceReference) GetKind() string { if x != nil { - return x.JWT + return x.Kind + } + return "" +} + +func (x *ResourceReference) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ResourceReference) GetSectionName() string { + if x != nil { + return x.SectionName + } + return "" +} + +func (x *ResourceReference) GetEnterpriseMeta() *pbcommon.EnterpriseMeta { + if x != nil { + return x.EnterpriseMeta } return nil } -type APIGatewayJWTRequirement struct { +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.BoundAPIGatewayConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +type BoundAPIGateway struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Providers []*APIGatewayJWTProvider `protobuf:"bytes,1,rep,name=Providers,proto3" json:"Providers,omitempty"` + Meta map[string]string `protobuf:"bytes,1,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Listeners []*BoundAPIGatewayListener `protobuf:"bytes,2,rep,name=Listeners,proto3" json:"Listeners,omitempty"` } -func (x *APIGatewayJWTRequirement) Reset() { - *x = APIGatewayJWTRequirement{} +func (x *BoundAPIGateway) Reset() { + *x = BoundAPIGateway{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[54] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *APIGatewayJWTRequirement) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*APIGatewayJWTRequirement) ProtoMessage() {} - -func (x *APIGatewayJWTRequirement) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[54] - 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 APIGatewayJWTRequirement.ProtoReflect.Descriptor instead. -func (*APIGatewayJWTRequirement) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{54} -} - -func (x *APIGatewayJWTRequirement) GetProviders() []*APIGatewayJWTProvider { - if x != nil { - return x.Providers - } - return nil -} - -type APIGatewayJWTProvider struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` - VerifyClaims []*APIGatewayJWTClaimVerification `protobuf:"bytes,2,rep,name=VerifyClaims,proto3" json:"VerifyClaims,omitempty"` -} - -func (x *APIGatewayJWTProvider) Reset() { - *x = APIGatewayJWTProvider{} - if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[55] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *APIGatewayJWTProvider) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*APIGatewayJWTProvider) ProtoMessage() {} - -func (x *APIGatewayJWTProvider) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[55] - 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 APIGatewayJWTProvider.ProtoReflect.Descriptor instead. -func (*APIGatewayJWTProvider) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{55} -} - -func (x *APIGatewayJWTProvider) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *APIGatewayJWTProvider) GetVerifyClaims() []*APIGatewayJWTClaimVerification { - if x != nil { - return x.VerifyClaims - } - return nil -} - -type APIGatewayJWTClaimVerification struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Path []string `protobuf:"bytes,1,rep,name=Path,proto3" json:"Path,omitempty"` - Value string `protobuf:"bytes,2,opt,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *APIGatewayJWTClaimVerification) Reset() { - *x = APIGatewayJWTClaimVerification{} - if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[56] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *APIGatewayJWTClaimVerification) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*APIGatewayJWTClaimVerification) ProtoMessage() {} - -func (x *APIGatewayJWTClaimVerification) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[56] - 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 APIGatewayJWTClaimVerification.ProtoReflect.Descriptor instead. -func (*APIGatewayJWTClaimVerification) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{56} -} - -func (x *APIGatewayJWTClaimVerification) GetPath() []string { - if x != nil { - return x.Path - } - return nil -} - -func (x *APIGatewayJWTClaimVerification) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.ResourceReference -// output=config_entry.gen.go -// name=Structs -type ResourceReference struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Kind string `protobuf:"bytes,1,opt,name=Kind,proto3" json:"Kind,omitempty"` - Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` - SectionName string `protobuf:"bytes,3,opt,name=SectionName,proto3" json:"SectionName,omitempty"` - // mog: func-to=enterpriseMetaToStructs func-from=enterpriseMetaFromStructs - EnterpriseMeta *pbcommon.EnterpriseMeta `protobuf:"bytes,4,opt,name=EnterpriseMeta,proto3" json:"EnterpriseMeta,omitempty"` -} - -func (x *ResourceReference) Reset() { - *x = ResourceReference{} - if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[57] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ResourceReference) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ResourceReference) ProtoMessage() {} - -func (x *ResourceReference) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[57] - 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 ResourceReference.ProtoReflect.Descriptor instead. -func (*ResourceReference) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{57} -} - -func (x *ResourceReference) GetKind() string { - if x != nil { - return x.Kind - } - return "" -} - -func (x *ResourceReference) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *ResourceReference) GetSectionName() string { - if x != nil { - return x.SectionName - } - return "" -} - -func (x *ResourceReference) GetEnterpriseMeta() *pbcommon.EnterpriseMeta { - if x != nil { - return x.EnterpriseMeta - } - return nil -} - -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.BoundAPIGatewayConfigEntry -// output=config_entry.gen.go -// name=Structs -// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta -type BoundAPIGateway struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta map[string]string `protobuf:"bytes,1,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Listeners []*BoundAPIGatewayListener `protobuf:"bytes,2,rep,name=Listeners,proto3" json:"Listeners,omitempty"` -} - -func (x *BoundAPIGateway) Reset() { - *x = BoundAPIGateway{} - if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[58] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5222,7 +4780,7 @@ func (x *BoundAPIGateway) String() string { func (*BoundAPIGateway) ProtoMessage() {} func (x *BoundAPIGateway) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[58] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5235,7 +4793,7 @@ func (x *BoundAPIGateway) ProtoReflect() protoreflect.Message { // Deprecated: Use BoundAPIGateway.ProtoReflect.Descriptor instead. func (*BoundAPIGateway) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{58} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{51} } func (x *BoundAPIGateway) GetMeta() map[string]string { @@ -5270,7 +4828,7 @@ type BoundAPIGatewayListener struct { func (x *BoundAPIGatewayListener) Reset() { *x = BoundAPIGatewayListener{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[59] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5283,7 +4841,7 @@ func (x *BoundAPIGatewayListener) String() string { func (*BoundAPIGatewayListener) ProtoMessage() {} func (x *BoundAPIGatewayListener) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[59] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5296,7 +4854,7 @@ func (x *BoundAPIGatewayListener) ProtoReflect() protoreflect.Message { // Deprecated: Use BoundAPIGatewayListener.ProtoReflect.Descriptor instead. func (*BoundAPIGatewayListener) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{59} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{52} } func (x *BoundAPIGatewayListener) GetName() string { @@ -5339,7 +4897,7 @@ type InlineCertificate struct { func (x *InlineCertificate) Reset() { *x = InlineCertificate{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[60] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5352,7 +4910,7 @@ func (x *InlineCertificate) String() string { func (*InlineCertificate) ProtoMessage() {} func (x *InlineCertificate) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[60] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5365,7 +4923,7 @@ func (x *InlineCertificate) ProtoReflect() protoreflect.Message { // Deprecated: Use InlineCertificate.ProtoReflect.Descriptor instead. func (*InlineCertificate) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{60} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{53} } func (x *InlineCertificate) GetMeta() map[string]string { @@ -5410,7 +4968,7 @@ type HTTPRoute struct { func (x *HTTPRoute) Reset() { *x = HTTPRoute{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[61] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5423,7 +4981,7 @@ func (x *HTTPRoute) String() string { func (*HTTPRoute) ProtoMessage() {} func (x *HTTPRoute) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[61] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5436,7 +4994,7 @@ func (x *HTTPRoute) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPRoute.ProtoReflect.Descriptor instead. func (*HTTPRoute) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{61} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{54} } func (x *HTTPRoute) GetMeta() map[string]string { @@ -5492,7 +5050,7 @@ type HTTPRouteRule struct { func (x *HTTPRouteRule) Reset() { *x = HTTPRouteRule{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[62] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5505,7 +5063,7 @@ func (x *HTTPRouteRule) String() string { func (*HTTPRouteRule) ProtoMessage() {} func (x *HTTPRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[62] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5518,7 +5076,7 @@ func (x *HTTPRouteRule) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPRouteRule.ProtoReflect.Descriptor instead. func (*HTTPRouteRule) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{62} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{55} } func (x *HTTPRouteRule) GetFilters() *HTTPFilters { @@ -5562,7 +5120,7 @@ type HTTPMatch struct { func (x *HTTPMatch) Reset() { *x = HTTPMatch{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[63] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5575,7 +5133,7 @@ func (x *HTTPMatch) String() string { func (*HTTPMatch) ProtoMessage() {} func (x *HTTPMatch) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[63] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5588,7 +5146,7 @@ func (x *HTTPMatch) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPMatch.ProtoReflect.Descriptor instead. func (*HTTPMatch) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{63} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{56} } func (x *HTTPMatch) GetHeaders() []*HTTPHeaderMatch { @@ -5638,7 +5196,7 @@ type HTTPHeaderMatch struct { func (x *HTTPHeaderMatch) Reset() { *x = HTTPHeaderMatch{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[64] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5651,7 +5209,7 @@ func (x *HTTPHeaderMatch) String() string { func (*HTTPHeaderMatch) ProtoMessage() {} func (x *HTTPHeaderMatch) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[64] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5664,7 +5222,7 @@ func (x *HTTPHeaderMatch) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPHeaderMatch.ProtoReflect.Descriptor instead. func (*HTTPHeaderMatch) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{64} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{57} } func (x *HTTPHeaderMatch) GetMatch() HTTPHeaderMatchType { @@ -5706,7 +5264,7 @@ type HTTPPathMatch struct { func (x *HTTPPathMatch) Reset() { *x = HTTPPathMatch{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[65] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5719,7 +5277,7 @@ func (x *HTTPPathMatch) String() string { func (*HTTPPathMatch) ProtoMessage() {} func (x *HTTPPathMatch) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[65] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5732,7 +5290,7 @@ func (x *HTTPPathMatch) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPPathMatch.ProtoReflect.Descriptor instead. func (*HTTPPathMatch) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{65} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{58} } func (x *HTTPPathMatch) GetMatch() HTTPPathMatchType { @@ -5768,7 +5326,7 @@ type HTTPQueryMatch struct { func (x *HTTPQueryMatch) Reset() { *x = HTTPQueryMatch{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[66] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5781,7 +5339,7 @@ func (x *HTTPQueryMatch) String() string { func (*HTTPQueryMatch) ProtoMessage() {} func (x *HTTPQueryMatch) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[66] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5794,7 +5352,7 @@ func (x *HTTPQueryMatch) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPQueryMatch.ProtoReflect.Descriptor instead. func (*HTTPQueryMatch) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{66} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{59} } func (x *HTTPQueryMatch) GetMatch() HTTPQueryMatchType { @@ -5828,18 +5386,14 @@ type HTTPFilters struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Headers []*HTTPHeaderFilter `protobuf:"bytes,1,rep,name=Headers,proto3" json:"Headers,omitempty"` - URLRewrite *URLRewrite `protobuf:"bytes,2,opt,name=URLRewrite,proto3" json:"URLRewrite,omitempty"` - RetryFilter *RetryFilter `protobuf:"bytes,3,opt,name=RetryFilter,proto3" json:"RetryFilter,omitempty"` - TimeoutFilter *TimeoutFilter `protobuf:"bytes,4,opt,name=TimeoutFilter,proto3" json:"TimeoutFilter,omitempty"` - // mog: func-to=routeJWTFilterToStructs func-from=routeJWTFilterFromStructs - JWT *JWTFilter `protobuf:"bytes,5,opt,name=JWT,proto3" json:"JWT,omitempty"` + Headers []*HTTPHeaderFilter `protobuf:"bytes,1,rep,name=Headers,proto3" json:"Headers,omitempty"` + URLRewrite *URLRewrite `protobuf:"bytes,2,opt,name=URLRewrite,proto3" json:"URLRewrite,omitempty"` } func (x *HTTPFilters) Reset() { *x = HTTPFilters{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[67] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5852,7 +5406,7 @@ func (x *HTTPFilters) String() string { func (*HTTPFilters) ProtoMessage() {} func (x *HTTPFilters) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[67] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5865,7 +5419,7 @@ func (x *HTTPFilters) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPFilters.ProtoReflect.Descriptor instead. func (*HTTPFilters) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{67} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{60} } func (x *HTTPFilters) GetHeaders() []*HTTPHeaderFilter { @@ -5882,27 +5436,6 @@ func (x *HTTPFilters) GetURLRewrite() *URLRewrite { return nil } -func (x *HTTPFilters) GetRetryFilter() *RetryFilter { - if x != nil { - return x.RetryFilter - } - return nil -} - -func (x *HTTPFilters) GetTimeoutFilter() *TimeoutFilter { - if x != nil { - return x.TimeoutFilter - } - return nil -} - -func (x *HTTPFilters) GetJWT() *JWTFilter { - if x != nil { - return x.JWT - } - return nil -} - // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.URLRewrite @@ -5919,7 +5452,7 @@ type URLRewrite struct { func (x *URLRewrite) Reset() { *x = URLRewrite{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[68] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5932,7 +5465,7 @@ func (x *URLRewrite) String() string { func (*URLRewrite) ProtoMessage() {} func (x *URLRewrite) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[68] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[61] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5945,7 +5478,7 @@ func (x *URLRewrite) ProtoReflect() protoreflect.Message { // Deprecated: Use URLRewrite.ProtoReflect.Descriptor instead. func (*URLRewrite) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{68} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{61} } func (x *URLRewrite) GetPath() string { @@ -5955,191 +5488,6 @@ func (x *URLRewrite) GetPath() string { return "" } -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.RetryFilter -// output=config_entry.gen.go -// name=Structs -type RetryFilter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - NumRetries uint32 `protobuf:"varint,1,opt,name=NumRetries,proto3" json:"NumRetries,omitempty"` - RetryOn []string `protobuf:"bytes,2,rep,name=RetryOn,proto3" json:"RetryOn,omitempty"` - RetryOnStatusCodes []uint32 `protobuf:"varint,3,rep,packed,name=RetryOnStatusCodes,proto3" json:"RetryOnStatusCodes,omitempty"` - RetryOnConnectFailure bool `protobuf:"varint,4,opt,name=RetryOnConnectFailure,proto3" json:"RetryOnConnectFailure,omitempty"` -} - -func (x *RetryFilter) Reset() { - *x = RetryFilter{} - if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[69] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RetryFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RetryFilter) ProtoMessage() {} - -func (x *RetryFilter) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[69] - 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 RetryFilter.ProtoReflect.Descriptor instead. -func (*RetryFilter) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{69} -} - -func (x *RetryFilter) GetNumRetries() uint32 { - if x != nil { - return x.NumRetries - } - return 0 -} - -func (x *RetryFilter) GetRetryOn() []string { - if x != nil { - return x.RetryOn - } - return nil -} - -func (x *RetryFilter) GetRetryOnStatusCodes() []uint32 { - if x != nil { - return x.RetryOnStatusCodes - } - return nil -} - -func (x *RetryFilter) GetRetryOnConnectFailure() bool { - if x != nil { - return x.RetryOnConnectFailure - } - return false -} - -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.TimeoutFilter -// output=config_entry.gen.go -// name=Structs -type TimeoutFilter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto - RequestTimeout *durationpb.Duration `protobuf:"bytes,1,opt,name=RequestTimeout,proto3" json:"RequestTimeout,omitempty"` - // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto - IdleTimeout *durationpb.Duration `protobuf:"bytes,2,opt,name=IdleTimeout,proto3" json:"IdleTimeout,omitempty"` -} - -func (x *TimeoutFilter) Reset() { - *x = TimeoutFilter{} - if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[70] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TimeoutFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TimeoutFilter) ProtoMessage() {} - -func (x *TimeoutFilter) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[70] - 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 TimeoutFilter.ProtoReflect.Descriptor instead. -func (*TimeoutFilter) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{70} -} - -func (x *TimeoutFilter) GetRequestTimeout() *durationpb.Duration { - if x != nil { - return x.RequestTimeout - } - return nil -} - -func (x *TimeoutFilter) GetIdleTimeout() *durationpb.Duration { - if x != nil { - return x.IdleTimeout - } - return nil -} - -type JWTFilter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Providers []*APIGatewayJWTProvider `protobuf:"bytes,1,rep,name=Providers,proto3" json:"Providers,omitempty"` -} - -func (x *JWTFilter) Reset() { - *x = JWTFilter{} - if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[71] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *JWTFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*JWTFilter) ProtoMessage() {} - -func (x *JWTFilter) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[71] - 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 JWTFilter.ProtoReflect.Descriptor instead. -func (*JWTFilter) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{71} -} - -func (x *JWTFilter) GetProviders() []*APIGatewayJWTProvider { - if x != nil { - return x.Providers - } - return nil -} - // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.HTTPHeaderFilter @@ -6158,7 +5506,7 @@ type HTTPHeaderFilter struct { func (x *HTTPHeaderFilter) Reset() { *x = HTTPHeaderFilter{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[72] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6171,7 +5519,7 @@ func (x *HTTPHeaderFilter) String() string { func (*HTTPHeaderFilter) ProtoMessage() {} func (x *HTTPHeaderFilter) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[72] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6184,7 +5532,7 @@ func (x *HTTPHeaderFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPHeaderFilter.ProtoReflect.Descriptor instead. func (*HTTPHeaderFilter) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{72} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{62} } func (x *HTTPHeaderFilter) GetAdd() map[string]string { @@ -6229,7 +5577,7 @@ type HTTPService struct { func (x *HTTPService) Reset() { *x = HTTPService{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[73] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6242,7 +5590,7 @@ func (x *HTTPService) String() string { func (*HTTPService) ProtoMessage() {} func (x *HTTPService) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[73] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[63] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6255,7 +5603,7 @@ func (x *HTTPService) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPService.ProtoReflect.Descriptor instead. func (*HTTPService) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{73} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{63} } func (x *HTTPService) GetName() string { @@ -6306,7 +5654,7 @@ type TCPRoute struct { func (x *TCPRoute) Reset() { *x = TCPRoute{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[74] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6319,7 +5667,7 @@ func (x *TCPRoute) String() string { func (*TCPRoute) ProtoMessage() {} func (x *TCPRoute) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[74] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[64] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6332,7 +5680,7 @@ func (x *TCPRoute) ProtoReflect() protoreflect.Message { // Deprecated: Use TCPRoute.ProtoReflect.Descriptor instead. func (*TCPRoute) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{74} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{64} } func (x *TCPRoute) GetMeta() map[string]string { @@ -6381,7 +5729,7 @@ type TCPService struct { func (x *TCPService) Reset() { *x = TCPService{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[75] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6394,7 +5742,7 @@ func (x *TCPService) String() string { func (*TCPService) ProtoMessage() {} func (x *TCPService) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[75] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[65] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6407,7 +5755,7 @@ func (x *TCPService) ProtoReflect() protoreflect.Message { // Deprecated: Use TCPService.ProtoReflect.Descriptor instead. func (*TCPService) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{75} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{65} } func (x *TCPService) GetName() string { @@ -6447,7 +5795,7 @@ type SamenessGroup struct { func (x *SamenessGroup) Reset() { *x = SamenessGroup{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[76] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6460,7 +5808,7 @@ func (x *SamenessGroup) String() string { func (*SamenessGroup) ProtoMessage() {} func (x *SamenessGroup) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[76] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[66] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6473,7 +5821,7 @@ func (x *SamenessGroup) ProtoReflect() protoreflect.Message { // Deprecated: Use SamenessGroup.ProtoReflect.Descriptor instead. func (*SamenessGroup) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{76} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{66} } func (x *SamenessGroup) GetName() string { @@ -6535,7 +5883,7 @@ type SamenessGroupMember struct { func (x *SamenessGroupMember) Reset() { *x = SamenessGroupMember{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[77] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6548,7 +5896,7 @@ func (x *SamenessGroupMember) String() string { func (*SamenessGroupMember) ProtoMessage() {} func (x *SamenessGroupMember) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[77] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[67] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6561,7 +5909,7 @@ func (x *SamenessGroupMember) ProtoReflect() protoreflect.Message { // Deprecated: Use SamenessGroupMember.ProtoReflect.Descriptor instead. func (*SamenessGroupMember) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{77} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{67} } func (x *SamenessGroupMember) GetPartition() string { @@ -6603,7 +5951,7 @@ type JWTProvider struct { func (x *JWTProvider) Reset() { *x = JWTProvider{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[78] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6616,7 +5964,7 @@ func (x *JWTProvider) String() string { func (*JWTProvider) ProtoMessage() {} func (x *JWTProvider) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[78] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[68] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6629,7 +5977,7 @@ func (x *JWTProvider) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTProvider.ProtoReflect.Descriptor instead. func (*JWTProvider) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{78} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{68} } func (x *JWTProvider) GetJSONWebKeySet() *JSONWebKeySet { @@ -6705,7 +6053,7 @@ type JSONWebKeySet struct { func (x *JSONWebKeySet) Reset() { *x = JSONWebKeySet{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[79] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6718,7 +6066,7 @@ func (x *JSONWebKeySet) String() string { func (*JSONWebKeySet) ProtoMessage() {} func (x *JSONWebKeySet) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[79] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[69] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6731,7 +6079,7 @@ func (x *JSONWebKeySet) ProtoReflect() protoreflect.Message { // Deprecated: Use JSONWebKeySet.ProtoReflect.Descriptor instead. func (*JSONWebKeySet) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{79} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{69} } func (x *JSONWebKeySet) GetLocal() *LocalJWKS { @@ -6765,7 +6113,7 @@ type LocalJWKS struct { func (x *LocalJWKS) Reset() { *x = LocalJWKS{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[80] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6778,7 +6126,7 @@ func (x *LocalJWKS) String() string { func (*LocalJWKS) ProtoMessage() {} func (x *LocalJWKS) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[80] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[70] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6791,7 +6139,7 @@ func (x *LocalJWKS) ProtoReflect() protoreflect.Message { // Deprecated: Use LocalJWKS.ProtoReflect.Descriptor instead. func (*LocalJWKS) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{80} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{70} } func (x *LocalJWKS) GetJWKS() string { @@ -6831,7 +6179,7 @@ type RemoteJWKS struct { func (x *RemoteJWKS) Reset() { *x = RemoteJWKS{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[81] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6844,7 +6192,7 @@ func (x *RemoteJWKS) String() string { func (*RemoteJWKS) ProtoMessage() {} func (x *RemoteJWKS) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[81] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[71] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6857,7 +6205,7 @@ func (x *RemoteJWKS) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoteJWKS.ProtoReflect.Descriptor instead. func (*RemoteJWKS) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{81} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{71} } func (x *RemoteJWKS) GetURI() string { @@ -6921,7 +6269,7 @@ type JWKSCluster struct { func (x *JWKSCluster) Reset() { *x = JWKSCluster{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[82] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6934,7 +6282,7 @@ func (x *JWKSCluster) String() string { func (*JWKSCluster) ProtoMessage() {} func (x *JWKSCluster) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[82] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[72] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6947,7 +6295,7 @@ func (x *JWKSCluster) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSCluster.ProtoReflect.Descriptor instead. func (*JWKSCluster) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{82} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{72} } func (x *JWKSCluster) GetDiscoveryType() string { @@ -6988,7 +6336,7 @@ type JWKSTLSCertificate struct { func (x *JWKSTLSCertificate) Reset() { *x = JWKSTLSCertificate{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[83] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7001,7 +6349,7 @@ func (x *JWKSTLSCertificate) String() string { func (*JWKSTLSCertificate) ProtoMessage() {} func (x *JWKSTLSCertificate) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[83] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[73] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7014,7 +6362,7 @@ func (x *JWKSTLSCertificate) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSTLSCertificate.ProtoReflect.Descriptor instead. func (*JWKSTLSCertificate) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{83} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{73} } func (x *JWKSTLSCertificate) GetCaCertificateProviderInstance() *JWKSTLSCertProviderInstance { @@ -7048,7 +6396,7 @@ type JWKSTLSCertProviderInstance struct { func (x *JWKSTLSCertProviderInstance) Reset() { *x = JWKSTLSCertProviderInstance{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[84] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7061,7 +6409,7 @@ func (x *JWKSTLSCertProviderInstance) String() string { func (*JWKSTLSCertProviderInstance) ProtoMessage() {} func (x *JWKSTLSCertProviderInstance) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[84] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[74] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7074,7 +6422,7 @@ func (x *JWKSTLSCertProviderInstance) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSTLSCertProviderInstance.ProtoReflect.Descriptor instead. func (*JWKSTLSCertProviderInstance) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{84} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{74} } func (x *JWKSTLSCertProviderInstance) GetInstanceName() string { @@ -7110,7 +6458,7 @@ type JWKSTLSCertTrustedCA struct { func (x *JWKSTLSCertTrustedCA) Reset() { *x = JWKSTLSCertTrustedCA{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[85] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7123,7 +6471,7 @@ func (x *JWKSTLSCertTrustedCA) String() string { func (*JWKSTLSCertTrustedCA) ProtoMessage() {} func (x *JWKSTLSCertTrustedCA) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[85] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[75] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7136,7 +6484,7 @@ func (x *JWKSTLSCertTrustedCA) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSTLSCertTrustedCA.ProtoReflect.Descriptor instead. func (*JWKSTLSCertTrustedCA) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{85} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{75} } func (x *JWKSTLSCertTrustedCA) GetFilename() string { @@ -7185,7 +6533,7 @@ type JWKSRetryPolicy struct { func (x *JWKSRetryPolicy) Reset() { *x = JWKSRetryPolicy{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[86] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7198,7 +6546,7 @@ func (x *JWKSRetryPolicy) String() string { func (*JWKSRetryPolicy) ProtoMessage() {} func (x *JWKSRetryPolicy) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[86] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[76] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7211,7 +6559,7 @@ func (x *JWKSRetryPolicy) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSRetryPolicy.ProtoReflect.Descriptor instead. func (*JWKSRetryPolicy) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{86} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{76} } func (x *JWKSRetryPolicy) GetNumRetries() int32 { @@ -7247,7 +6595,7 @@ type RetryPolicyBackOff struct { func (x *RetryPolicyBackOff) Reset() { *x = RetryPolicyBackOff{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[87] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7260,7 +6608,7 @@ func (x *RetryPolicyBackOff) String() string { func (*RetryPolicyBackOff) ProtoMessage() {} func (x *RetryPolicyBackOff) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[87] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[77] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7273,7 +6621,7 @@ func (x *RetryPolicyBackOff) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryPolicyBackOff.ProtoReflect.Descriptor instead. func (*RetryPolicyBackOff) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{87} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{77} } func (x *RetryPolicyBackOff) GetBaseInterval() *durationpb.Duration { @@ -7308,7 +6656,7 @@ type JWTLocation struct { func (x *JWTLocation) Reset() { *x = JWTLocation{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[88] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7321,7 +6669,7 @@ func (x *JWTLocation) String() string { func (*JWTLocation) ProtoMessage() {} func (x *JWTLocation) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[88] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[78] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7334,7 +6682,7 @@ func (x *JWTLocation) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTLocation.ProtoReflect.Descriptor instead. func (*JWTLocation) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{88} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{78} } func (x *JWTLocation) GetHeader() *JWTLocationHeader { @@ -7376,7 +6724,7 @@ type JWTLocationHeader struct { func (x *JWTLocationHeader) Reset() { *x = JWTLocationHeader{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[89] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7389,7 +6737,7 @@ func (x *JWTLocationHeader) String() string { func (*JWTLocationHeader) ProtoMessage() {} func (x *JWTLocationHeader) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[89] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[79] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7402,7 +6750,7 @@ func (x *JWTLocationHeader) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTLocationHeader.ProtoReflect.Descriptor instead. func (*JWTLocationHeader) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{89} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{79} } func (x *JWTLocationHeader) GetName() string { @@ -7442,7 +6790,7 @@ type JWTLocationQueryParam struct { func (x *JWTLocationQueryParam) Reset() { *x = JWTLocationQueryParam{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[90] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7455,7 +6803,7 @@ func (x *JWTLocationQueryParam) String() string { func (*JWTLocationQueryParam) ProtoMessage() {} func (x *JWTLocationQueryParam) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[90] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[80] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7468,7 +6816,7 @@ func (x *JWTLocationQueryParam) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTLocationQueryParam.ProtoReflect.Descriptor instead. func (*JWTLocationQueryParam) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{90} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{80} } func (x *JWTLocationQueryParam) GetName() string { @@ -7494,7 +6842,7 @@ type JWTLocationCookie struct { func (x *JWTLocationCookie) Reset() { *x = JWTLocationCookie{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[91] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7507,7 +6855,7 @@ func (x *JWTLocationCookie) String() string { func (*JWTLocationCookie) ProtoMessage() {} func (x *JWTLocationCookie) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[91] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[81] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7520,7 +6868,7 @@ func (x *JWTLocationCookie) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTLocationCookie.ProtoReflect.Descriptor instead. func (*JWTLocationCookie) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{91} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{81} } func (x *JWTLocationCookie) GetName() string { @@ -7547,7 +6895,7 @@ type JWTForwardingConfig struct { func (x *JWTForwardingConfig) Reset() { *x = JWTForwardingConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[92] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7560,7 +6908,7 @@ func (x *JWTForwardingConfig) String() string { func (*JWTForwardingConfig) ProtoMessage() {} func (x *JWTForwardingConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[92] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[82] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7573,7 +6921,7 @@ func (x *JWTForwardingConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTForwardingConfig.ProtoReflect.Descriptor instead. func (*JWTForwardingConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{92} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{82} } func (x *JWTForwardingConfig) GetHeaderName() string { @@ -7607,7 +6955,7 @@ type JWTCacheConfig struct { func (x *JWTCacheConfig) Reset() { *x = JWTCacheConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[93] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7620,7 +6968,7 @@ func (x *JWTCacheConfig) String() string { func (*JWTCacheConfig) ProtoMessage() {} func (x *JWTCacheConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[93] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[83] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7633,7 +6981,7 @@ func (x *JWTCacheConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTCacheConfig.ProtoReflect.Descriptor instead. func (*JWTCacheConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{93} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{83} } func (x *JWTCacheConfig) GetSize() int32 { @@ -8297,7 +7645,7 @@ var file_private_pbconfigentry_config_entry_proto_rawDesc = []byte{ 0x06, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x49, - 0x6e, 0x76, 0x65, 0x72, 0x74, 0x22, 0xe5, 0x09, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x6e, 0x76, 0x65, 0x72, 0x74, 0x22, 0x92, 0x09, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x44, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, @@ -8350,881 +7698,761 @@ var file_private_pbconfigentry_config_entry_proto_rawDesc = []byte{ 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x51, 0x0a, 0x0a, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, - 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x0a, 0x52, 0x61, 0x74, 0x65, - 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0d, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x74, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x5a, 0x0a, 0x0f, - 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, - 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, - 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x0d, 0x4d, 0x75, 0x74, 0x75, - 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, - 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0d, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, - 0x4d, 0x6f, 0x64, 0x65, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x74, 0x0a, - 0x16, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, - 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, 0x0a, 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x44, - 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0e, 0x44, 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x6c, 0x79, 0x22, 0x5f, 0x0a, 0x11, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4a, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, - 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, - 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x6f, 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x12, 0x47, 0x0a, 0x05, - 0x50, 0x61, 0x74, 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, - 0x50, 0x61, 0x74, 0x68, 0x73, 0x22, 0xb0, 0x01, 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x50, 0x61, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, - 0x50, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x4c, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0d, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, - 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x28, - 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x46, - 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x22, 0xbf, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x73, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x53, 0x0a, 0x09, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, - 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x51, 0x0a, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x8a, 0x05, 0x0a, 0x0e, 0x55, - 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, - 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, - 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x11, 0x45, - 0x6e, 0x76, 0x6f, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4c, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x2a, 0x0a, 0x10, 0x45, 0x6e, 0x76, - 0x6f, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x10, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x12, 0x2a, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x4d, 0x0a, - 0x06, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x12, - 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x52, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x5a, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, - 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, + 0x6f, 0x6e, 0x73, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0d, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x5a, 0x0a, 0x0f, 0x45, 0x6e, 0x76, + 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0e, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x0d, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, + 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x12, 0x3e, 0x0a, 0x1a, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x4f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x22, 0x9e, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x4d, 0x61, - 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, - 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, 0x9e, 0x02, 0x0a, 0x12, 0x50, 0x61, 0x73, - 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, - 0x35, 0x0a, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x4d, 0x61, 0x78, 0x46, 0x61, 0x69, - 0x6c, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x4d, 0x61, 0x78, - 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x45, 0x6e, 0x66, 0x6f, - 0x72, 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, - 0x35, 0x78, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x17, 0x45, 0x6e, 0x66, 0x6f, 0x72, - 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, - 0x78, 0x78, 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, - 0x4d, 0x61, 0x78, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, - 0x6e, 0x74, 0x12, 0x45, 0x0a, 0x10, 0x42, 0x61, 0x73, 0x65, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x42, 0x61, 0x73, 0x65, 0x45, 0x6a, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x45, 0x0a, 0x11, 0x44, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, - 0x0a, 0x09, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x09, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, - 0x22, 0x72, 0x0a, 0x0a, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x64, - 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x61, 0x74, 0x65, 0x4c, - 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, - 0x65, 0x76, 0x65, 0x6c, 0x22, 0xd0, 0x01, 0x0a, 0x17, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, - 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, - 0x12, 0x2c, 0x0a, 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x2a, - 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, - 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, 0x12, 0x5b, 0x0a, 0x06, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, - 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x1c, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x61, - 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, - 0x45, 0x78, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, - 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x61, 0x74, 0x68, - 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, - 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, - 0x65, 0x67, 0x65, 0x78, 0x12, 0x2c, 0x0a, 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, - 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x12, 0x2a, 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, - 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, 0x22, 0xb6, - 0x02, 0x0a, 0x0a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x4f, 0x0a, - 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x4d, - 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x57, - 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x37, - 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x5a, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x50, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x22, 0x8b, 0x02, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, - 0x06, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x52, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x54, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x4c, 0x61, 0x73, 0x74, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x12, 0x4c, - 0x61, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, - 0x65, 0x22, 0xb4, 0x03, 0x0a, 0x12, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x5d, 0x0a, 0x08, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x41, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x53, 0x0a, 0x03, 0x54, - 0x4c, 0x53, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, + 0x64, 0x65, 0x52, 0x0d, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, + 0x65, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x74, 0x0a, 0x16, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, 0x0a, 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, + 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x44, 0x69, 0x61, 0x6c, + 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0e, 0x44, 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, + 0x22, 0x5f, 0x0a, 0x11, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4a, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x4d, 0x6f, 0x64, + 0x65, 0x22, 0x6f, 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x16, 0x0a, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x12, 0x47, 0x0a, 0x05, 0x50, 0x61, 0x74, + 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x54, 0x4c, 0x53, - 0x12, 0x53, 0x0a, 0x08, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, 0x50, 0x61, 0x74, + 0x68, 0x73, 0x22, 0xb0, 0x01, 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, + 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, + 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0d, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x12, + 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x28, 0x0a, 0x0f, 0x50, + 0x61, 0x72, 0x73, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x22, 0xbf, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x53, 0x0a, 0x09, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x51, 0x0a, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x73, 0x12, 0x51, 0x0a, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, - 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, - 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0xde, 0x01, 0x0a, 0x1a, 0x41, 0x50, 0x49, - 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, - 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4d, 0x69, 0x6e, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4d, 0x61, 0x78, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, - 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x69, 0x70, - 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x65, 0x0a, 0x10, 0x41, 0x50, 0x49, - 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x51, 0x0a, - 0x03, 0x4a, 0x57, 0x54, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, + 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x44, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x8a, 0x05, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, + 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, + 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, + 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x11, 0x45, 0x6e, 0x76, 0x6f, + 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x11, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, + 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x2a, 0x0a, 0x10, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x10, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4a, 0x53, + 0x4f, 0x4e, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x2a, + 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0x4d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x4d, 0x0a, 0x06, 0x4c, 0x69, + 0x6d, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, - 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x03, 0x4a, 0x57, 0x54, - 0x22, 0x76, 0x0a, 0x18, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, - 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x5a, 0x0a, 0x09, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x09, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x15, 0x41, 0x50, 0x49, - 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x69, 0x0a, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, - 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, - 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6c, 0x61, 0x69, 0x6d, - 0x73, 0x22, 0x4a, 0x0a, 0x1e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, - 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb7, 0x01, - 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x53, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, - 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x72, 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, + 0x73, 0x52, 0x06, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x12, 0x50, 0x61, 0x73, + 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0xfe, 0x01, 0x0a, 0x0f, 0x42, 0x6f, 0x75, 0x6e, - 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x54, 0x0a, 0x04, 0x4d, - 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x61, + 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x52, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x12, 0x5a, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, - 0x61, 0x12, 0x5c, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, - 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x1a, - 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdd, 0x01, 0x0a, 0x17, 0x42, 0x6f, 0x75, - 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5c, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, - 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x12, 0x3e, 0x0a, 0x1a, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x4f, 0x75, 0x74, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x50, 0x65, 0x65, 0x72, 0x22, 0x9e, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x4d, 0x61, 0x78, + 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, + 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, + 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, 0x9e, 0x02, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, + 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x35, 0x0a, 0x08, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x76, 0x61, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x4d, 0x61, 0x78, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x4d, 0x61, 0x78, 0x46, 0x61, 0x69, + 0x6c, 0x75, 0x72, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x45, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x69, + 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, 0x78, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x17, 0x45, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x69, 0x6e, + 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, 0x78, 0x12, + 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, + 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x4d, 0x61, 0x78, + 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x12, + 0x45, 0x0a, 0x10, 0x42, 0x61, 0x73, 0x65, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, + 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x42, 0x61, 0x73, 0x65, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x45, 0x0a, 0x11, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22, 0xb6, 0x02, + 0x0a, 0x0a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x4f, 0x0a, 0x04, + 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x4d, 0x65, + 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x57, 0x0a, + 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, - 0x52, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0xe6, 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x56, - 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x72, 0x69, 0x76, - 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x72, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x22, 0x99, 0x03, 0x0a, 0x09, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, - 0x4e, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x2e, - 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, - 0x52, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x37, 0x0a, + 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x5a, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x50, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6e, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x22, 0x8b, 0x02, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, + 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x54, + 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x50, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x05, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, - 0x1c, 0x0a, 0x09, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x09, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x45, 0x0a, - 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, + 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x4c, 0x61, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x12, 0x4c, 0x61, + 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, + 0x22, 0x8c, 0x02, 0x0a, 0x12, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x48, + 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x48, + 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x5d, 0x0a, 0x08, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf9, 0x01, - 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, - 0x4c, 0x0a, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x73, 0x52, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x4a, 0x0a, - 0x07, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x52, 0x07, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x4e, 0x0a, 0x08, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, - 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0xc4, 0x02, 0x0a, 0x09, 0x48, 0x54, - 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x50, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x53, 0x0a, 0x03, 0x54, 0x4c, + 0x53, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, + 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x22, + 0xde, 0x01, 0x0a, 0x1a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, + 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, + 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, + 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, + 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, + 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, + 0x22, 0xb7, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x52, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x4e, 0x0a, 0x06, 0x4d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x52, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x48, 0x0a, 0x04, 0x50, 0x61, 0x74, - 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, + 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, + 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0xfe, 0x01, 0x0a, 0x0f, 0x42, + 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x54, + 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, + 0x4d, 0x65, 0x74, 0x61, 0x12, 0x5c, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x04, 0x50, - 0x61, 0x74, 0x68, 0x12, 0x4b, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x22, 0x8d, 0x01, 0x0a, 0x0f, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x12, 0x50, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, - 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x75, 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x12, 0x4e, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, - 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x0e, 0x48, 0x54, 0x54, 0x50, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x4f, 0x0a, 0x05, 0x4d, 0x61, - 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, + 0x72, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdd, 0x01, 0x0a, 0x17, + 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5c, 0x0a, 0x0c, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x06, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xa9, 0x03, 0x0a, 0x0b, 0x48, 0x54, 0x54, 0x50, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, - 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, - 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x52, - 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, + 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x52, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0xe6, 0x01, 0x0a, 0x11, + 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x12, 0x56, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x50, + 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x1a, 0x37, 0x0a, 0x09, 0x4d, + 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0x99, 0x03, 0x0a, 0x09, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x12, 0x4e, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, + 0x74, 0x61, 0x12, 0x52, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x50, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x05, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, + 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x52, 0x75, 0x6c, + 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0xf9, 0x01, 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, + 0x6c, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, + 0x12, 0x4a, 0x0a, 0x07, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x52, 0x07, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x4e, 0x0a, 0x08, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0xc4, 0x02, 0x0a, + 0x09, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x50, 0x0a, 0x07, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x52, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x4e, 0x0a, 0x06, + 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x52, - 0x0a, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x52, - 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x12, 0x5a, 0x0a, 0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0d, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x42, 0x0a, - 0x03, 0x4a, 0x57, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x52, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x48, 0x0a, 0x04, + 0x50, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x03, 0x4a, 0x57, - 0x54, 0x22, 0x20, 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, - 0x61, 0x74, 0x68, 0x22, 0xad, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x12, 0x2e, 0x0a, - 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, - 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, - 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x34, 0x0a, - 0x15, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x46, - 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x52, 0x65, - 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x46, 0x61, 0x69, 0x6c, - 0x75, 0x72, 0x65, 0x22, 0x8f, 0x01, 0x0a, 0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x3b, 0x0a, 0x0b, 0x49, 0x64, 0x6c, 0x65, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x49, 0x64, 0x6c, 0x65, 0x54, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x67, 0x0a, 0x09, 0x4a, 0x57, 0x54, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x4b, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, - 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0xc2, - 0x02, 0x0a, 0x10, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x03, 0x41, 0x64, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, - 0x52, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, + 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x05, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x22, 0x8d, 0x01, 0x0a, 0x0f, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x50, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, + 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x22, 0x75, 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x12, 0x4e, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, + 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x0e, 0x48, + 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x4f, 0x0a, + 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, - 0x53, 0x65, 0x74, 0x1a, 0x36, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x36, 0x0a, 0x08, 0x53, - 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0xe1, 0x01, 0x0a, 0x0b, 0x48, 0x54, 0x54, 0x50, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x57, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, - 0x4c, 0x0a, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x73, 0x52, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x58, 0x0a, - 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0xfc, 0x02, 0x0a, 0x08, 0x54, 0x43, 0x50, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4d, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x12, + 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb3, 0x01, 0x0a, 0x0b, 0x48, 0x54, 0x54, + 0x50, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x52, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x0a, 0x55, + 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, + 0x74, 0x65, 0x52, 0x0a, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22, 0x20, + 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, + 0x22, 0xc2, 0x02, 0x0a, 0x10, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x41, 0x64, 0x64, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x41, 0x64, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x12, 0x52, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x03, 0x53, 0x65, 0x74, 0x1a, 0x36, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x36, 0x0a, + 0x08, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe1, 0x01, 0x0a, 0x0b, 0x48, 0x54, 0x54, 0x50, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x57, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x57, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x12, 0x4c, 0x0a, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x43, 0x50, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, - 0x65, 0x74, 0x61, 0x12, 0x52, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, + 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0xfc, 0x02, 0x0a, 0x08, 0x54, 0x43, + 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4d, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x07, - 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4d, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x54, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x43, 0x50, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x52, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x37, 0x0a, - 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x7a, 0x0a, 0x0a, 0x54, 0x43, 0x50, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x52, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4d, 0x0a, 0x08, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x54, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, + 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x7a, 0x0a, 0x0a, 0x54, 0x43, 0x50, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x22, 0xb4, 0x03, 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, + 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x44, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x6f, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, + 0x6f, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0c, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x54, + 0x0a, 0x07, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x12, 0x52, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x61, 0x6d, 0x65, 0x6e, + 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, + 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, - 0x74, 0x61, 0x22, 0xb4, 0x03, 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x44, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x46, 0x6f, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x6f, 0x72, - 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x63, 0x6c, - 0x75, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, - 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x54, 0x0a, 0x07, - 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x73, 0x12, 0x52, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, - 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, - 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x47, 0x0a, 0x13, 0x53, 0x61, 0x6d, - 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, - 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, - 0x65, 0x72, 0x22, 0xdd, 0x04, 0x0a, 0x0b, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x0d, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, - 0x53, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x52, - 0x0d, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x75, 0x64, 0x69, 0x65, 0x6e, - 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x41, 0x75, 0x64, 0x69, 0x65, - 0x6e, 0x63, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x4c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x0a, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, - 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, - 0x6e, 0x67, 0x12, 0x57, 0x0a, 0x0b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x4a, 0x57, 0x54, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x50, 0x0a, 0x04, 0x4d, - 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x47, 0x0a, 0x13, 0x53, + 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x50, 0x65, 0x65, 0x72, 0x22, 0xdd, 0x04, 0x0a, 0x0b, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x0d, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, + 0x65, 0x79, 0x53, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, + 0x74, 0x52, 0x0d, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, + 0x12, 0x16, 0x0a, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x75, 0x64, 0x69, + 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x41, 0x75, 0x64, + 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x4d, 0x65, - 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2a, 0x0a, - 0x10, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6b, 0x65, 0x77, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, - 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6b, - 0x65, 0x77, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0xa2, 0x01, 0x0a, 0x0d, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, - 0x79, 0x53, 0x65, 0x74, 0x12, 0x46, 0x0a, 0x05, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x05, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x49, 0x0a, 0x06, - 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, + 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x4c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x0a, 0x46, 0x6f, 0x72, 0x77, + 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4a, 0x57, 0x4b, 0x53, 0x52, - 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x22, 0x3b, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4a, 0x57, 0x4b, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x4a, 0x57, 0x4b, 0x53, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x4a, 0x57, 0x4b, 0x53, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x46, 0x69, 0x6c, 0x65, - 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xed, 0x02, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4a, - 0x57, 0x4b, 0x53, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x52, 0x49, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x55, 0x52, 0x49, 0x12, 0x2a, 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, - 0x73, 0x12, 0x3f, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x13, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x79, 0x6e, 0x63, - 0x68, 0x72, 0x6f, 0x6e, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x13, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x6f, - 0x75, 0x73, 0x6c, 0x79, 0x12, 0x58, 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, + 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, + 0x64, 0x69, 0x6e, 0x67, 0x12, 0x57, 0x0a, 0x0b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x52, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x54, - 0x0a, 0x0b, 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x22, 0xdb, 0x01, 0x0a, 0x0b, 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x79, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x44, 0x69, 0x73, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x63, 0x0a, 0x0f, 0x54, 0x4c, - 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x0b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x50, 0x0a, + 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2e, + 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, + 0x2a, 0x0a, 0x10, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6b, 0x65, 0x77, 0x53, 0x65, 0x63, 0x6f, + 0x6e, 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x43, 0x6c, 0x6f, 0x63, 0x6b, + 0x53, 0x6b, 0x65, 0x77, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4d, + 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa2, 0x01, 0x0a, 0x0d, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, + 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x12, 0x46, 0x0a, 0x05, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x05, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x49, + 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4a, 0x57, 0x4b, + 0x53, 0x52, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x22, 0x3b, 0x0a, 0x09, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4a, 0x57, 0x4b, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x4a, 0x57, 0x4b, 0x53, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4a, 0x57, 0x4b, 0x53, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x69, + 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x46, 0x69, + 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xed, 0x02, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x74, + 0x65, 0x4a, 0x57, 0x4b, 0x53, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x52, 0x49, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x55, 0x52, 0x49, 0x12, 0x2a, 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, + 0x74, 0x4d, 0x73, 0x12, 0x3f, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x44, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x44, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x13, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x79, + 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x13, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, + 0x6e, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x12, 0x58, 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x52, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x12, 0x54, 0x0a, 0x0b, 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, + 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x4a, 0x57, 0x4b, 0x53, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0xdb, 0x01, 0x0a, 0x0b, 0x4a, 0x57, 0x4b, 0x53, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x63, 0x0a, 0x0f, + 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, + 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x52, 0x0f, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, + 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x22, 0xfa, 0x01, 0x0a, 0x12, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x88, 0x01, 0x0a, 0x1d, + 0x43, 0x61, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, - 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0f, - 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, - 0x41, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x22, 0xfa, 0x01, 0x0a, 0x12, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, - 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x88, 0x01, 0x0a, 0x1d, 0x43, 0x61, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, - 0x53, 0x43, 0x65, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, - 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x1d, 0x43, 0x61, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x12, 0x59, 0x0a, 0x09, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, - 0x41, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, - 0x65, 0x64, 0x43, 0x41, 0x52, 0x09, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x22, - 0x6b, 0x0a, 0x1b, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x22, - 0x0a, 0x0c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x43, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xaa, 0x01, 0x0a, - 0x14, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, - 0x74, 0x65, 0x64, 0x43, 0x41, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x30, 0x0a, 0x13, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, - 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, - 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, - 0x62, 0x6c, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x49, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x49, 0x6e, 0x6c, 0x69, 0x6e, - 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x49, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x9c, 0x01, 0x0a, 0x0f, 0x4a, 0x57, - 0x4b, 0x53, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1e, 0x0a, - 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x69, 0x0a, - 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, - 0x4f, 0x66, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x1d, 0x43, 0x61, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x59, 0x0a, 0x09, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x43, 0x41, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, - 0x6b, 0x4f, 0x66, 0x66, 0x52, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x22, 0x90, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x74, - 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x12, - 0x3d, 0x0a, 0x0c, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x0c, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x3b, - 0x0a, 0x0b, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, - 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0x8f, 0x02, 0x0a, 0x0b, - 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x06, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x5c, 0x0a, - 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, - 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x50, 0x0a, 0x06, 0x43, - 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, + 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x52, 0x09, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, + 0x41, 0x22, 0x6b, 0x0a, 0x1b, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xaa, + 0x01, 0x0a, 0x14, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x13, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, + 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x49, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x49, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, + 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x9c, 0x01, 0x0a, 0x0f, + 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, + 0x1e, 0x0a, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, + 0x69, 0x0a, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, + 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, - 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x52, 0x06, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x22, 0x63, 0x0a, - 0x11, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50, - 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x18, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x77, - 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x46, 0x6f, 0x72, 0x77, 0x61, - 0x72, 0x64, 0x22, 0x2b, 0x0a, 0x15, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, - 0x27, 0x0a, 0x11, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, - 0x6f, 0x6b, 0x69, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x6f, 0x0a, 0x13, 0x4a, 0x57, 0x54, 0x46, - 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x1e, 0x0a, 0x0a, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x38, 0x0a, 0x17, 0x50, 0x61, 0x64, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x17, 0x50, 0x61, 0x64, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x50, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0x24, 0x0a, 0x0e, 0x4a, 0x57, 0x54, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x53, - 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x2a, - 0xa9, 0x02, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0f, 0x0a, 0x0b, 0x4b, 0x69, 0x6e, 0x64, - 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4b, 0x69, 0x6e, - 0x64, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x01, 0x12, 0x17, 0x0a, - 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, - 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x03, 0x12, 0x19, - 0x0a, 0x15, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, - 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, - 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x10, 0x06, 0x12, 0x12, 0x0a, - 0x0e, 0x4b, 0x69, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, - 0x07, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, - 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, 0x4b, 0x69, - 0x6e, 0x64, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, 0x09, 0x12, 0x10, 0x0a, - 0x0c, 0x4b, 0x69, 0x6e, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, 0x0a, 0x12, - 0x15, 0x0a, 0x11, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x10, 0x0b, 0x12, 0x13, 0x0a, 0x0f, 0x4b, 0x69, 0x6e, 0x64, 0x4a, 0x57, - 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x10, 0x0c, 0x2a, 0x26, 0x0a, 0x0f, 0x49, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, - 0x0a, 0x04, 0x44, 0x65, 0x6e, 0x79, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x6c, 0x6c, 0x6f, - 0x77, 0x10, 0x01, 0x2a, 0x21, 0x0a, 0x13, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x10, 0x00, 0x2a, 0x50, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, - 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, - 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, - 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x5f, 0x0a, 0x0d, 0x4d, 0x75, 0x74, 0x75, - 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x75, 0x74, - 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, - 0x4d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x69, 0x63, 0x74, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, - 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x50, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x76, 0x65, 0x10, 0x02, 0x2a, 0x7b, 0x0a, 0x0f, 0x4d, 0x65, 0x73, - 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x16, - 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x68, - 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x4e, 0x6f, 0x6e, 0x65, 0x10, - 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x4d, 0x6f, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x4d, - 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, - 0x6d, 0x6f, 0x74, 0x65, 0x10, 0x03, 0x2a, 0x4f, 0x0a, 0x1a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x17, - 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x54, 0x43, 0x50, 0x10, 0x01, 0x2a, 0x92, 0x02, 0x0a, 0x0f, 0x48, 0x54, 0x54, 0x50, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x16, 0x0a, 0x12, 0x48, - 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x6c, - 0x6c, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x10, 0x01, 0x12, - 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, - 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x47, 0x65, 0x74, - 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x48, 0x65, 0x61, 0x64, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x48, - 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x05, 0x12, 0x18, 0x0a, 0x14, 0x48, 0x54, 0x54, 0x50, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x61, 0x74, 0x63, 0x68, 0x10, - 0x06, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x50, 0x6f, 0x73, 0x74, 0x10, 0x07, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, - 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x75, 0x74, - 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x54, 0x72, 0x61, 0x63, 0x65, 0x10, 0x09, 0x2a, 0xa7, 0x01, 0x0a, - 0x13, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, 0x19, - 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x54, 0x54, - 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x73, - 0x65, 0x6e, 0x74, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, - 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x48, - 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, - 0x66, 0x66, 0x69, 0x78, 0x10, 0x04, 0x2a, 0x68, 0x0a, 0x11, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, - 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x48, - 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x61, 0x63, - 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x10, 0x01, 0x12, 0x22, 0x0a, 0x1e, - 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x67, - 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x03, - 0x2a, 0x6d, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, - 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, - 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x48, 0x54, - 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x67, 0x75, - 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x42, - 0xae, 0x02, 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x10, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x37, 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, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, - 0x43, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 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, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, + 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x52, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x22, 0x90, 0x01, 0x0a, 0x12, 0x52, + 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, + 0x66, 0x12, 0x3d, 0x0a, 0x0c, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, + 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0c, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, + 0x12, 0x3b, 0x0a, 0x0b, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x0b, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0x8f, 0x02, + 0x0a, 0x0b, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, + 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, + 0x5c, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x52, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x50, 0x0a, + 0x06, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x52, 0x06, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x22, + 0x63, 0x0a, 0x11, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x18, 0x0a, 0x07, 0x46, 0x6f, + 0x72, 0x77, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x46, 0x6f, 0x72, + 0x77, 0x61, 0x72, 0x64, 0x22, 0x2b, 0x0a, 0x15, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x12, 0x0a, + 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, + 0x65, 0x22, 0x27, 0x0a, 0x11, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x6f, 0x0a, 0x13, 0x4a, 0x57, + 0x54, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x38, 0x0a, 0x17, 0x50, 0x61, 0x64, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x50, + 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x17, 0x50, 0x61, 0x64, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x50, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0x24, 0x0a, 0x0e, 0x4a, + 0x57, 0x54, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, + 0x04, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x53, 0x69, 0x7a, + 0x65, 0x2a, 0xa9, 0x02, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0f, 0x0a, 0x0b, 0x4b, 0x69, + 0x6e, 0x64, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4b, + 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x01, 0x12, + 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4b, 0x69, 0x6e, 0x64, + 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x03, + 0x12, 0x19, 0x0a, 0x15, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x4b, + 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x73, 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x10, 0x06, 0x12, + 0x12, 0x0a, 0x0e, 0x4b, 0x69, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x10, 0x07, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x42, 0x6f, 0x75, 0x6e, 0x64, + 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, + 0x4b, 0x69, 0x6e, 0x64, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, 0x09, 0x12, + 0x10, 0x0a, 0x0c, 0x4b, 0x69, 0x6e, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, + 0x0a, 0x12, 0x15, 0x0a, 0x11, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, + 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x10, 0x0b, 0x12, 0x13, 0x0a, 0x0f, 0x4b, 0x69, 0x6e, 0x64, + 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x10, 0x0c, 0x2a, 0x26, 0x0a, + 0x0f, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x08, 0x0a, 0x04, 0x44, 0x65, 0x6e, 0x79, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x6c, + 0x6c, 0x6f, 0x77, 0x10, 0x01, 0x2a, 0x21, 0x0a, 0x13, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x10, 0x00, 0x2a, 0x50, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, + 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, + 0x64, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x5f, 0x0a, 0x0d, 0x4d, 0x75, + 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x4d, + 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, + 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x69, 0x63, 0x74, 0x10, 0x01, 0x12, 0x1b, + 0x0a, 0x17, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x50, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x76, 0x65, 0x10, 0x02, 0x2a, 0x7b, 0x0a, 0x0f, 0x4d, + 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, + 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, + 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x65, + 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x4e, 0x6f, 0x6e, + 0x65, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x10, 0x02, 0x12, 0x19, 0x0a, + 0x15, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x10, 0x03, 0x2a, 0x4f, 0x0a, 0x1a, 0x41, 0x50, 0x49, 0x47, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, + 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, + 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x54, 0x43, 0x50, 0x10, 0x01, 0x2a, 0x92, 0x02, 0x0a, 0x0f, 0x48, 0x54, + 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x16, 0x0a, + 0x12, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 0x41, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, + 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x10, + 0x01, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, + 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x47, + 0x65, 0x74, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, + 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x48, 0x65, 0x61, 0x64, 0x10, 0x04, 0x12, 0x1a, 0x0a, + 0x16, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x05, 0x12, 0x18, 0x0a, 0x14, 0x48, 0x54, 0x54, + 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x61, 0x74, 0x63, + 0x68, 0x10, 0x06, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x6f, 0x73, 0x74, 0x10, 0x07, 0x12, 0x16, 0x0a, 0x12, + 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, + 0x75, 0x74, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, + 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x54, 0x72, 0x61, 0x63, 0x65, 0x10, 0x09, 0x2a, 0xa7, + 0x01, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, + 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, 0x00, + 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x48, + 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, + 0x65, 0x73, 0x65, 0x6e, 0x74, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x48, 0x54, 0x54, 0x50, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, + 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x12, 0x19, 0x0a, + 0x15, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x10, 0x04, 0x2a, 0x68, 0x0a, 0x11, 0x48, 0x54, 0x54, 0x50, + 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, + 0x12, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, + 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, + 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x10, 0x01, 0x12, 0x22, + 0x0a, 0x1e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, + 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x10, 0x03, 0x2a, 0x6d, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, + 0x00, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, + 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, + 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, + 0x03, 0x42, 0xae, 0x02, 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x42, + 0x10, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x37, 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, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, + 0x62, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xa2, 0x02, 0x04, 0x48, + 0x43, 0x49, 0x43, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xca, 0x02, 0x25, 0x48, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 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, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -9240,7 +8468,7 @@ func file_private_pbconfigentry_config_entry_proto_rawDescGZIP() []byte { } var file_private_pbconfigentry_config_entry_proto_enumTypes = make([]protoimpl.EnumInfo, 11) -var file_private_pbconfigentry_config_entry_proto_msgTypes = make([]protoimpl.MessageInfo, 114) +var file_private_pbconfigentry_config_entry_proto_msgTypes = make([]protoimpl.MessageInfo, 104) var file_private_pbconfigentry_config_entry_proto_goTypes = []interface{}{ (Kind)(0), // 0: hashicorp.consul.internal.configentry.Kind (IntentionAction)(0), // 1: hashicorp.consul.internal.configentry.IntentionAction @@ -9298,111 +8526,101 @@ var file_private_pbconfigentry_config_entry_proto_goTypes = []interface{}{ (*UpstreamLimits)(nil), // 53: hashicorp.consul.internal.configentry.UpstreamLimits (*PassiveHealthCheck)(nil), // 54: hashicorp.consul.internal.configentry.PassiveHealthCheck (*DestinationConfig)(nil), // 55: hashicorp.consul.internal.configentry.DestinationConfig - (*RateLimits)(nil), // 56: hashicorp.consul.internal.configentry.RateLimits - (*InstanceLevelRateLimits)(nil), // 57: hashicorp.consul.internal.configentry.InstanceLevelRateLimits - (*InstanceLevelRouteRateLimits)(nil), // 58: hashicorp.consul.internal.configentry.InstanceLevelRouteRateLimits - (*APIGateway)(nil), // 59: hashicorp.consul.internal.configentry.APIGateway - (*Status)(nil), // 60: hashicorp.consul.internal.configentry.Status - (*Condition)(nil), // 61: hashicorp.consul.internal.configentry.Condition - (*APIGatewayListener)(nil), // 62: hashicorp.consul.internal.configentry.APIGatewayListener - (*APIGatewayTLSConfiguration)(nil), // 63: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration - (*APIGatewayPolicy)(nil), // 64: hashicorp.consul.internal.configentry.APIGatewayPolicy - (*APIGatewayJWTRequirement)(nil), // 65: hashicorp.consul.internal.configentry.APIGatewayJWTRequirement - (*APIGatewayJWTProvider)(nil), // 66: hashicorp.consul.internal.configentry.APIGatewayJWTProvider - (*APIGatewayJWTClaimVerification)(nil), // 67: hashicorp.consul.internal.configentry.APIGatewayJWTClaimVerification - (*ResourceReference)(nil), // 68: hashicorp.consul.internal.configentry.ResourceReference - (*BoundAPIGateway)(nil), // 69: hashicorp.consul.internal.configentry.BoundAPIGateway - (*BoundAPIGatewayListener)(nil), // 70: hashicorp.consul.internal.configentry.BoundAPIGatewayListener - (*InlineCertificate)(nil), // 71: hashicorp.consul.internal.configentry.InlineCertificate - (*HTTPRoute)(nil), // 72: hashicorp.consul.internal.configentry.HTTPRoute - (*HTTPRouteRule)(nil), // 73: hashicorp.consul.internal.configentry.HTTPRouteRule - (*HTTPMatch)(nil), // 74: hashicorp.consul.internal.configentry.HTTPMatch - (*HTTPHeaderMatch)(nil), // 75: hashicorp.consul.internal.configentry.HTTPHeaderMatch - (*HTTPPathMatch)(nil), // 76: hashicorp.consul.internal.configentry.HTTPPathMatch - (*HTTPQueryMatch)(nil), // 77: hashicorp.consul.internal.configentry.HTTPQueryMatch - (*HTTPFilters)(nil), // 78: hashicorp.consul.internal.configentry.HTTPFilters - (*URLRewrite)(nil), // 79: hashicorp.consul.internal.configentry.URLRewrite - (*RetryFilter)(nil), // 80: hashicorp.consul.internal.configentry.RetryFilter - (*TimeoutFilter)(nil), // 81: hashicorp.consul.internal.configentry.TimeoutFilter - (*JWTFilter)(nil), // 82: hashicorp.consul.internal.configentry.JWTFilter - (*HTTPHeaderFilter)(nil), // 83: hashicorp.consul.internal.configentry.HTTPHeaderFilter - (*HTTPService)(nil), // 84: hashicorp.consul.internal.configentry.HTTPService - (*TCPRoute)(nil), // 85: hashicorp.consul.internal.configentry.TCPRoute - (*TCPService)(nil), // 86: hashicorp.consul.internal.configentry.TCPService - (*SamenessGroup)(nil), // 87: hashicorp.consul.internal.configentry.SamenessGroup - (*SamenessGroupMember)(nil), // 88: hashicorp.consul.internal.configentry.SamenessGroupMember - (*JWTProvider)(nil), // 89: hashicorp.consul.internal.configentry.JWTProvider - (*JSONWebKeySet)(nil), // 90: hashicorp.consul.internal.configentry.JSONWebKeySet - (*LocalJWKS)(nil), // 91: hashicorp.consul.internal.configentry.LocalJWKS - (*RemoteJWKS)(nil), // 92: hashicorp.consul.internal.configentry.RemoteJWKS - (*JWKSCluster)(nil), // 93: hashicorp.consul.internal.configentry.JWKSCluster - (*JWKSTLSCertificate)(nil), // 94: hashicorp.consul.internal.configentry.JWKSTLSCertificate - (*JWKSTLSCertProviderInstance)(nil), // 95: hashicorp.consul.internal.configentry.JWKSTLSCertProviderInstance - (*JWKSTLSCertTrustedCA)(nil), // 96: hashicorp.consul.internal.configentry.JWKSTLSCertTrustedCA - (*JWKSRetryPolicy)(nil), // 97: hashicorp.consul.internal.configentry.JWKSRetryPolicy - (*RetryPolicyBackOff)(nil), // 98: hashicorp.consul.internal.configentry.RetryPolicyBackOff - (*JWTLocation)(nil), // 99: hashicorp.consul.internal.configentry.JWTLocation - (*JWTLocationHeader)(nil), // 100: hashicorp.consul.internal.configentry.JWTLocationHeader - (*JWTLocationQueryParam)(nil), // 101: hashicorp.consul.internal.configentry.JWTLocationQueryParam - (*JWTLocationCookie)(nil), // 102: hashicorp.consul.internal.configentry.JWTLocationCookie - (*JWTForwardingConfig)(nil), // 103: hashicorp.consul.internal.configentry.JWTForwardingConfig - (*JWTCacheConfig)(nil), // 104: hashicorp.consul.internal.configentry.JWTCacheConfig - nil, // 105: hashicorp.consul.internal.configentry.MeshConfig.MetaEntry - nil, // 106: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry - nil, // 107: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry - nil, // 108: hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry - nil, // 109: hashicorp.consul.internal.configentry.IngressGateway.MetaEntry - nil, // 110: hashicorp.consul.internal.configentry.IngressService.MetaEntry - nil, // 111: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry - nil, // 112: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry - nil, // 113: hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry - nil, // 114: hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry - nil, // 115: hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry - nil, // 116: hashicorp.consul.internal.configentry.APIGateway.MetaEntry - nil, // 117: hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry - nil, // 118: hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry - nil, // 119: hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry - nil, // 120: hashicorp.consul.internal.configentry.HTTPHeaderFilter.AddEntry - nil, // 121: hashicorp.consul.internal.configentry.HTTPHeaderFilter.SetEntry - nil, // 122: hashicorp.consul.internal.configentry.TCPRoute.MetaEntry - nil, // 123: hashicorp.consul.internal.configentry.SamenessGroup.MetaEntry - nil, // 124: hashicorp.consul.internal.configentry.JWTProvider.MetaEntry - (*pbcommon.EnterpriseMeta)(nil), // 125: hashicorp.consul.internal.common.EnterpriseMeta - (*pbcommon.RaftIndex)(nil), // 126: hashicorp.consul.internal.common.RaftIndex - (*durationpb.Duration)(nil), // 127: google.protobuf.Duration - (*timestamppb.Timestamp)(nil), // 128: google.protobuf.Timestamp - (*pbcommon.EnvoyExtension)(nil), // 129: hashicorp.consul.internal.common.EnvoyExtension + (*APIGateway)(nil), // 56: hashicorp.consul.internal.configentry.APIGateway + (*Status)(nil), // 57: hashicorp.consul.internal.configentry.Status + (*Condition)(nil), // 58: hashicorp.consul.internal.configentry.Condition + (*APIGatewayListener)(nil), // 59: hashicorp.consul.internal.configentry.APIGatewayListener + (*APIGatewayTLSConfiguration)(nil), // 60: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration + (*ResourceReference)(nil), // 61: hashicorp.consul.internal.configentry.ResourceReference + (*BoundAPIGateway)(nil), // 62: hashicorp.consul.internal.configentry.BoundAPIGateway + (*BoundAPIGatewayListener)(nil), // 63: hashicorp.consul.internal.configentry.BoundAPIGatewayListener + (*InlineCertificate)(nil), // 64: hashicorp.consul.internal.configentry.InlineCertificate + (*HTTPRoute)(nil), // 65: hashicorp.consul.internal.configentry.HTTPRoute + (*HTTPRouteRule)(nil), // 66: hashicorp.consul.internal.configentry.HTTPRouteRule + (*HTTPMatch)(nil), // 67: hashicorp.consul.internal.configentry.HTTPMatch + (*HTTPHeaderMatch)(nil), // 68: hashicorp.consul.internal.configentry.HTTPHeaderMatch + (*HTTPPathMatch)(nil), // 69: hashicorp.consul.internal.configentry.HTTPPathMatch + (*HTTPQueryMatch)(nil), // 70: hashicorp.consul.internal.configentry.HTTPQueryMatch + (*HTTPFilters)(nil), // 71: hashicorp.consul.internal.configentry.HTTPFilters + (*URLRewrite)(nil), // 72: hashicorp.consul.internal.configentry.URLRewrite + (*HTTPHeaderFilter)(nil), // 73: hashicorp.consul.internal.configentry.HTTPHeaderFilter + (*HTTPService)(nil), // 74: hashicorp.consul.internal.configentry.HTTPService + (*TCPRoute)(nil), // 75: hashicorp.consul.internal.configentry.TCPRoute + (*TCPService)(nil), // 76: hashicorp.consul.internal.configentry.TCPService + (*SamenessGroup)(nil), // 77: hashicorp.consul.internal.configentry.SamenessGroup + (*SamenessGroupMember)(nil), // 78: hashicorp.consul.internal.configentry.SamenessGroupMember + (*JWTProvider)(nil), // 79: hashicorp.consul.internal.configentry.JWTProvider + (*JSONWebKeySet)(nil), // 80: hashicorp.consul.internal.configentry.JSONWebKeySet + (*LocalJWKS)(nil), // 81: hashicorp.consul.internal.configentry.LocalJWKS + (*RemoteJWKS)(nil), // 82: hashicorp.consul.internal.configentry.RemoteJWKS + (*JWKSCluster)(nil), // 83: hashicorp.consul.internal.configentry.JWKSCluster + (*JWKSTLSCertificate)(nil), // 84: hashicorp.consul.internal.configentry.JWKSTLSCertificate + (*JWKSTLSCertProviderInstance)(nil), // 85: hashicorp.consul.internal.configentry.JWKSTLSCertProviderInstance + (*JWKSTLSCertTrustedCA)(nil), // 86: hashicorp.consul.internal.configentry.JWKSTLSCertTrustedCA + (*JWKSRetryPolicy)(nil), // 87: hashicorp.consul.internal.configentry.JWKSRetryPolicy + (*RetryPolicyBackOff)(nil), // 88: hashicorp.consul.internal.configentry.RetryPolicyBackOff + (*JWTLocation)(nil), // 89: hashicorp.consul.internal.configentry.JWTLocation + (*JWTLocationHeader)(nil), // 90: hashicorp.consul.internal.configentry.JWTLocationHeader + (*JWTLocationQueryParam)(nil), // 91: hashicorp.consul.internal.configentry.JWTLocationQueryParam + (*JWTLocationCookie)(nil), // 92: hashicorp.consul.internal.configentry.JWTLocationCookie + (*JWTForwardingConfig)(nil), // 93: hashicorp.consul.internal.configentry.JWTForwardingConfig + (*JWTCacheConfig)(nil), // 94: hashicorp.consul.internal.configentry.JWTCacheConfig + nil, // 95: hashicorp.consul.internal.configentry.MeshConfig.MetaEntry + nil, // 96: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry + nil, // 97: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry + nil, // 98: hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry + nil, // 99: hashicorp.consul.internal.configentry.IngressGateway.MetaEntry + nil, // 100: hashicorp.consul.internal.configentry.IngressService.MetaEntry + nil, // 101: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry + nil, // 102: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry + nil, // 103: hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry + nil, // 104: hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry + nil, // 105: hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry + nil, // 106: hashicorp.consul.internal.configentry.APIGateway.MetaEntry + nil, // 107: hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry + nil, // 108: hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry + nil, // 109: hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry + nil, // 110: hashicorp.consul.internal.configentry.HTTPHeaderFilter.AddEntry + nil, // 111: hashicorp.consul.internal.configentry.HTTPHeaderFilter.SetEntry + nil, // 112: hashicorp.consul.internal.configentry.TCPRoute.MetaEntry + nil, // 113: hashicorp.consul.internal.configentry.SamenessGroup.MetaEntry + nil, // 114: hashicorp.consul.internal.configentry.JWTProvider.MetaEntry + (*pbcommon.EnterpriseMeta)(nil), // 115: hashicorp.consul.internal.common.EnterpriseMeta + (*pbcommon.RaftIndex)(nil), // 116: hashicorp.consul.internal.common.RaftIndex + (*durationpb.Duration)(nil), // 117: google.protobuf.Duration + (*timestamppb.Timestamp)(nil), // 118: google.protobuf.Timestamp + (*pbcommon.EnvoyExtension)(nil), // 119: hashicorp.consul.internal.common.EnvoyExtension } var file_private_pbconfigentry_config_entry_proto_depIdxs = []int32{ 0, // 0: hashicorp.consul.internal.configentry.ConfigEntry.Kind:type_name -> hashicorp.consul.internal.configentry.Kind - 125, // 1: hashicorp.consul.internal.configentry.ConfigEntry.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 126, // 2: hashicorp.consul.internal.configentry.ConfigEntry.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex + 115, // 1: hashicorp.consul.internal.configentry.ConfigEntry.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 116, // 2: hashicorp.consul.internal.configentry.ConfigEntry.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex 12, // 3: hashicorp.consul.internal.configentry.ConfigEntry.MeshConfig:type_name -> hashicorp.consul.internal.configentry.MeshConfig 18, // 4: hashicorp.consul.internal.configentry.ConfigEntry.ServiceResolver:type_name -> hashicorp.consul.internal.configentry.ServiceResolver 30, // 5: hashicorp.consul.internal.configentry.ConfigEntry.IngressGateway:type_name -> hashicorp.consul.internal.configentry.IngressGateway 38, // 6: hashicorp.consul.internal.configentry.ConfigEntry.ServiceIntentions:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions 46, // 7: hashicorp.consul.internal.configentry.ConfigEntry.ServiceDefaults:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults - 59, // 8: hashicorp.consul.internal.configentry.ConfigEntry.APIGateway:type_name -> hashicorp.consul.internal.configentry.APIGateway - 69, // 9: hashicorp.consul.internal.configentry.ConfigEntry.BoundAPIGateway:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway - 85, // 10: hashicorp.consul.internal.configentry.ConfigEntry.TCPRoute:type_name -> hashicorp.consul.internal.configentry.TCPRoute - 72, // 11: hashicorp.consul.internal.configentry.ConfigEntry.HTTPRoute:type_name -> hashicorp.consul.internal.configentry.HTTPRoute - 71, // 12: hashicorp.consul.internal.configentry.ConfigEntry.InlineCertificate:type_name -> hashicorp.consul.internal.configentry.InlineCertificate - 87, // 13: hashicorp.consul.internal.configentry.ConfigEntry.SamenessGroup:type_name -> hashicorp.consul.internal.configentry.SamenessGroup - 89, // 14: hashicorp.consul.internal.configentry.ConfigEntry.JWTProvider:type_name -> hashicorp.consul.internal.configentry.JWTProvider + 56, // 8: hashicorp.consul.internal.configentry.ConfigEntry.APIGateway:type_name -> hashicorp.consul.internal.configentry.APIGateway + 62, // 9: hashicorp.consul.internal.configentry.ConfigEntry.BoundAPIGateway:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway + 75, // 10: hashicorp.consul.internal.configentry.ConfigEntry.TCPRoute:type_name -> hashicorp.consul.internal.configentry.TCPRoute + 65, // 11: hashicorp.consul.internal.configentry.ConfigEntry.HTTPRoute:type_name -> hashicorp.consul.internal.configentry.HTTPRoute + 64, // 12: hashicorp.consul.internal.configentry.ConfigEntry.InlineCertificate:type_name -> hashicorp.consul.internal.configentry.InlineCertificate + 77, // 13: hashicorp.consul.internal.configentry.ConfigEntry.SamenessGroup:type_name -> hashicorp.consul.internal.configentry.SamenessGroup + 79, // 14: hashicorp.consul.internal.configentry.ConfigEntry.JWTProvider:type_name -> hashicorp.consul.internal.configentry.JWTProvider 13, // 15: hashicorp.consul.internal.configentry.MeshConfig.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyMeshConfig 14, // 16: hashicorp.consul.internal.configentry.MeshConfig.TLS:type_name -> hashicorp.consul.internal.configentry.MeshTLSConfig 16, // 17: hashicorp.consul.internal.configentry.MeshConfig.HTTP:type_name -> hashicorp.consul.internal.configentry.MeshHTTPConfig - 105, // 18: hashicorp.consul.internal.configentry.MeshConfig.Meta:type_name -> hashicorp.consul.internal.configentry.MeshConfig.MetaEntry + 95, // 18: hashicorp.consul.internal.configentry.MeshConfig.Meta:type_name -> hashicorp.consul.internal.configentry.MeshConfig.MetaEntry 17, // 19: hashicorp.consul.internal.configentry.MeshConfig.Peering:type_name -> hashicorp.consul.internal.configentry.PeeringMeshConfig 15, // 20: hashicorp.consul.internal.configentry.MeshTLSConfig.Incoming:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig 15, // 21: hashicorp.consul.internal.configentry.MeshTLSConfig.Outgoing:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig - 106, // 22: hashicorp.consul.internal.configentry.ServiceResolver.Subsets:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry + 96, // 22: hashicorp.consul.internal.configentry.ServiceResolver.Subsets:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry 20, // 23: hashicorp.consul.internal.configentry.ServiceResolver.Redirect:type_name -> hashicorp.consul.internal.configentry.ServiceResolverRedirect - 107, // 24: hashicorp.consul.internal.configentry.ServiceResolver.Failover:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry - 127, // 25: hashicorp.consul.internal.configentry.ServiceResolver.ConnectTimeout:type_name -> google.protobuf.Duration + 97, // 24: hashicorp.consul.internal.configentry.ServiceResolver.Failover:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry + 117, // 25: hashicorp.consul.internal.configentry.ServiceResolver.ConnectTimeout:type_name -> google.protobuf.Duration 25, // 26: hashicorp.consul.internal.configentry.ServiceResolver.LoadBalancer:type_name -> hashicorp.consul.internal.configentry.LoadBalancer - 108, // 27: hashicorp.consul.internal.configentry.ServiceResolver.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry - 127, // 28: hashicorp.consul.internal.configentry.ServiceResolver.RequestTimeout:type_name -> google.protobuf.Duration + 98, // 27: hashicorp.consul.internal.configentry.ServiceResolver.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry + 117, // 28: hashicorp.consul.internal.configentry.ServiceResolver.RequestTimeout:type_name -> google.protobuf.Duration 23, // 29: hashicorp.consul.internal.configentry.ServiceResolver.PrioritizeByLocality:type_name -> hashicorp.consul.internal.configentry.ServiceResolverPrioritizeByLocality 24, // 30: hashicorp.consul.internal.configentry.ServiceResolverFailover.Targets:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailoverTarget 22, // 31: hashicorp.consul.internal.configentry.ServiceResolverFailover.Policy:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailoverPolicy @@ -9410,10 +8628,10 @@ var file_private_pbconfigentry_config_entry_proto_depIdxs = []int32{ 27, // 33: hashicorp.consul.internal.configentry.LoadBalancer.LeastRequestConfig:type_name -> hashicorp.consul.internal.configentry.LeastRequestConfig 28, // 34: hashicorp.consul.internal.configentry.LoadBalancer.HashPolicies:type_name -> hashicorp.consul.internal.configentry.HashPolicy 29, // 35: hashicorp.consul.internal.configentry.HashPolicy.CookieConfig:type_name -> hashicorp.consul.internal.configentry.CookieConfig - 127, // 36: hashicorp.consul.internal.configentry.CookieConfig.TTL:type_name -> google.protobuf.Duration + 117, // 36: hashicorp.consul.internal.configentry.CookieConfig.TTL:type_name -> google.protobuf.Duration 32, // 37: hashicorp.consul.internal.configentry.IngressGateway.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig 34, // 38: hashicorp.consul.internal.configentry.IngressGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.IngressListener - 109, // 39: hashicorp.consul.internal.configentry.IngressGateway.Meta:type_name -> hashicorp.consul.internal.configentry.IngressGateway.MetaEntry + 99, // 39: hashicorp.consul.internal.configentry.IngressGateway.Meta:type_name -> hashicorp.consul.internal.configentry.IngressGateway.MetaEntry 31, // 40: hashicorp.consul.internal.configentry.IngressGateway.Defaults:type_name -> hashicorp.consul.internal.configentry.IngressServiceConfig 54, // 41: hashicorp.consul.internal.configentry.IngressServiceConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck 33, // 42: hashicorp.consul.internal.configentry.GatewayTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig @@ -9422,24 +8640,24 @@ var file_private_pbconfigentry_config_entry_proto_depIdxs = []int32{ 36, // 45: hashicorp.consul.internal.configentry.IngressService.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayServiceTLSConfig 37, // 46: hashicorp.consul.internal.configentry.IngressService.RequestHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers 37, // 47: hashicorp.consul.internal.configentry.IngressService.ResponseHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers - 110, // 48: hashicorp.consul.internal.configentry.IngressService.Meta:type_name -> hashicorp.consul.internal.configentry.IngressService.MetaEntry - 125, // 49: hashicorp.consul.internal.configentry.IngressService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 100, // 48: hashicorp.consul.internal.configentry.IngressService.Meta:type_name -> hashicorp.consul.internal.configentry.IngressService.MetaEntry + 115, // 49: hashicorp.consul.internal.configentry.IngressService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta 54, // 50: hashicorp.consul.internal.configentry.IngressService.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck 33, // 51: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig - 111, // 52: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry - 112, // 53: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry + 101, // 52: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry + 102, // 53: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry 42, // 54: hashicorp.consul.internal.configentry.ServiceIntentions.Sources:type_name -> hashicorp.consul.internal.configentry.SourceIntention - 113, // 55: hashicorp.consul.internal.configentry.ServiceIntentions.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry + 103, // 55: hashicorp.consul.internal.configentry.ServiceIntentions.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry 39, // 56: hashicorp.consul.internal.configentry.ServiceIntentions.JWT:type_name -> hashicorp.consul.internal.configentry.IntentionJWTRequirement 40, // 57: hashicorp.consul.internal.configentry.IntentionJWTRequirement.Providers:type_name -> hashicorp.consul.internal.configentry.IntentionJWTProvider 41, // 58: hashicorp.consul.internal.configentry.IntentionJWTProvider.VerifyClaims:type_name -> hashicorp.consul.internal.configentry.IntentionJWTClaimVerification 1, // 59: hashicorp.consul.internal.configentry.SourceIntention.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction 43, // 60: hashicorp.consul.internal.configentry.SourceIntention.Permissions:type_name -> hashicorp.consul.internal.configentry.IntentionPermission 2, // 61: hashicorp.consul.internal.configentry.SourceIntention.Type:type_name -> hashicorp.consul.internal.configentry.IntentionSourceType - 114, // 62: hashicorp.consul.internal.configentry.SourceIntention.LegacyMeta:type_name -> hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry - 128, // 63: hashicorp.consul.internal.configentry.SourceIntention.LegacyCreateTime:type_name -> google.protobuf.Timestamp - 128, // 64: hashicorp.consul.internal.configentry.SourceIntention.LegacyUpdateTime:type_name -> google.protobuf.Timestamp - 125, // 65: hashicorp.consul.internal.configentry.SourceIntention.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 104, // 62: hashicorp.consul.internal.configentry.SourceIntention.LegacyMeta:type_name -> hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry + 118, // 63: hashicorp.consul.internal.configentry.SourceIntention.LegacyCreateTime:type_name -> google.protobuf.Timestamp + 118, // 64: hashicorp.consul.internal.configentry.SourceIntention.LegacyUpdateTime:type_name -> google.protobuf.Timestamp + 115, // 65: hashicorp.consul.internal.configentry.SourceIntention.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta 1, // 66: hashicorp.consul.internal.configentry.IntentionPermission.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction 44, // 67: hashicorp.consul.internal.configentry.IntentionPermission.HTTP:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPPermission 39, // 68: hashicorp.consul.internal.configentry.IntentionPermission.JWT:type_name -> hashicorp.consul.internal.configentry.IntentionJWTRequirement @@ -9450,103 +8668,89 @@ var file_private_pbconfigentry_config_entry_proto_depIdxs = []int32{ 49, // 73: hashicorp.consul.internal.configentry.ServiceDefaults.Expose:type_name -> hashicorp.consul.internal.configentry.ExposeConfig 51, // 74: hashicorp.consul.internal.configentry.ServiceDefaults.UpstreamConfig:type_name -> hashicorp.consul.internal.configentry.UpstreamConfiguration 55, // 75: hashicorp.consul.internal.configentry.ServiceDefaults.Destination:type_name -> hashicorp.consul.internal.configentry.DestinationConfig - 56, // 76: hashicorp.consul.internal.configentry.ServiceDefaults.RateLimits:type_name -> hashicorp.consul.internal.configentry.RateLimits - 115, // 77: hashicorp.consul.internal.configentry.ServiceDefaults.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry - 129, // 78: hashicorp.consul.internal.configentry.ServiceDefaults.EnvoyExtensions:type_name -> hashicorp.consul.internal.common.EnvoyExtension - 4, // 79: hashicorp.consul.internal.configentry.ServiceDefaults.MutualTLSMode:type_name -> hashicorp.consul.internal.configentry.MutualTLSMode - 5, // 80: hashicorp.consul.internal.configentry.MeshGatewayConfig.Mode:type_name -> hashicorp.consul.internal.configentry.MeshGatewayMode - 50, // 81: hashicorp.consul.internal.configentry.ExposeConfig.Paths:type_name -> hashicorp.consul.internal.configentry.ExposePath - 52, // 82: hashicorp.consul.internal.configentry.UpstreamConfiguration.Overrides:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig - 52, // 83: hashicorp.consul.internal.configentry.UpstreamConfiguration.Defaults:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig - 125, // 84: hashicorp.consul.internal.configentry.UpstreamConfig.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 53, // 85: hashicorp.consul.internal.configentry.UpstreamConfig.Limits:type_name -> hashicorp.consul.internal.configentry.UpstreamLimits - 54, // 86: hashicorp.consul.internal.configentry.UpstreamConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck - 48, // 87: hashicorp.consul.internal.configentry.UpstreamConfig.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig - 127, // 88: hashicorp.consul.internal.configentry.PassiveHealthCheck.Interval:type_name -> google.protobuf.Duration - 127, // 89: hashicorp.consul.internal.configentry.PassiveHealthCheck.BaseEjectionTime:type_name -> google.protobuf.Duration - 57, // 90: hashicorp.consul.internal.configentry.RateLimits.InstanceLevel:type_name -> hashicorp.consul.internal.configentry.InstanceLevelRateLimits - 58, // 91: hashicorp.consul.internal.configentry.InstanceLevelRateLimits.Routes:type_name -> hashicorp.consul.internal.configentry.InstanceLevelRouteRateLimits - 116, // 92: hashicorp.consul.internal.configentry.APIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.APIGateway.MetaEntry - 62, // 93: hashicorp.consul.internal.configentry.APIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.APIGatewayListener - 60, // 94: hashicorp.consul.internal.configentry.APIGateway.Status:type_name -> hashicorp.consul.internal.configentry.Status - 61, // 95: hashicorp.consul.internal.configentry.Status.Conditions:type_name -> hashicorp.consul.internal.configentry.Condition - 68, // 96: hashicorp.consul.internal.configentry.Condition.Resource:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 128, // 97: hashicorp.consul.internal.configentry.Condition.LastTransitionTime:type_name -> google.protobuf.Timestamp - 6, // 98: hashicorp.consul.internal.configentry.APIGatewayListener.Protocol:type_name -> hashicorp.consul.internal.configentry.APIGatewayListenerProtocol - 63, // 99: hashicorp.consul.internal.configentry.APIGatewayListener.TLS:type_name -> hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration - 64, // 100: hashicorp.consul.internal.configentry.APIGatewayListener.Override:type_name -> hashicorp.consul.internal.configentry.APIGatewayPolicy - 64, // 101: hashicorp.consul.internal.configentry.APIGatewayListener.Default:type_name -> hashicorp.consul.internal.configentry.APIGatewayPolicy - 68, // 102: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 65, // 103: hashicorp.consul.internal.configentry.APIGatewayPolicy.JWT:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTRequirement - 66, // 104: hashicorp.consul.internal.configentry.APIGatewayJWTRequirement.Providers:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTProvider - 67, // 105: hashicorp.consul.internal.configentry.APIGatewayJWTProvider.VerifyClaims:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTClaimVerification - 125, // 106: hashicorp.consul.internal.configentry.ResourceReference.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 117, // 107: hashicorp.consul.internal.configentry.BoundAPIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry - 70, // 108: hashicorp.consul.internal.configentry.BoundAPIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.BoundAPIGatewayListener - 68, // 109: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 68, // 110: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Routes:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 118, // 111: hashicorp.consul.internal.configentry.InlineCertificate.Meta:type_name -> hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry - 119, // 112: hashicorp.consul.internal.configentry.HTTPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry - 68, // 113: hashicorp.consul.internal.configentry.HTTPRoute.Parents:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 73, // 114: hashicorp.consul.internal.configentry.HTTPRoute.Rules:type_name -> hashicorp.consul.internal.configentry.HTTPRouteRule - 60, // 115: hashicorp.consul.internal.configentry.HTTPRoute.Status:type_name -> hashicorp.consul.internal.configentry.Status - 78, // 116: hashicorp.consul.internal.configentry.HTTPRouteRule.Filters:type_name -> hashicorp.consul.internal.configentry.HTTPFilters - 74, // 117: hashicorp.consul.internal.configentry.HTTPRouteRule.Matches:type_name -> hashicorp.consul.internal.configentry.HTTPMatch - 84, // 118: hashicorp.consul.internal.configentry.HTTPRouteRule.Services:type_name -> hashicorp.consul.internal.configentry.HTTPService - 75, // 119: hashicorp.consul.internal.configentry.HTTPMatch.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderMatch - 7, // 120: hashicorp.consul.internal.configentry.HTTPMatch.Method:type_name -> hashicorp.consul.internal.configentry.HTTPMatchMethod - 76, // 121: hashicorp.consul.internal.configentry.HTTPMatch.Path:type_name -> hashicorp.consul.internal.configentry.HTTPPathMatch - 77, // 122: hashicorp.consul.internal.configentry.HTTPMatch.Query:type_name -> hashicorp.consul.internal.configentry.HTTPQueryMatch - 8, // 123: hashicorp.consul.internal.configentry.HTTPHeaderMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderMatchType - 9, // 124: hashicorp.consul.internal.configentry.HTTPPathMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPPathMatchType - 10, // 125: hashicorp.consul.internal.configentry.HTTPQueryMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPQueryMatchType - 83, // 126: hashicorp.consul.internal.configentry.HTTPFilters.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter - 79, // 127: hashicorp.consul.internal.configentry.HTTPFilters.URLRewrite:type_name -> hashicorp.consul.internal.configentry.URLRewrite - 80, // 128: hashicorp.consul.internal.configentry.HTTPFilters.RetryFilter:type_name -> hashicorp.consul.internal.configentry.RetryFilter - 81, // 129: hashicorp.consul.internal.configentry.HTTPFilters.TimeoutFilter:type_name -> hashicorp.consul.internal.configentry.TimeoutFilter - 82, // 130: hashicorp.consul.internal.configentry.HTTPFilters.JWT:type_name -> hashicorp.consul.internal.configentry.JWTFilter - 127, // 131: hashicorp.consul.internal.configentry.TimeoutFilter.RequestTimeout:type_name -> google.protobuf.Duration - 127, // 132: hashicorp.consul.internal.configentry.TimeoutFilter.IdleTimeout:type_name -> google.protobuf.Duration - 66, // 133: hashicorp.consul.internal.configentry.JWTFilter.Providers:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTProvider - 120, // 134: hashicorp.consul.internal.configentry.HTTPHeaderFilter.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter.AddEntry - 121, // 135: hashicorp.consul.internal.configentry.HTTPHeaderFilter.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter.SetEntry - 78, // 136: hashicorp.consul.internal.configentry.HTTPService.Filters:type_name -> hashicorp.consul.internal.configentry.HTTPFilters - 125, // 137: hashicorp.consul.internal.configentry.HTTPService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 122, // 138: hashicorp.consul.internal.configentry.TCPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.TCPRoute.MetaEntry - 68, // 139: hashicorp.consul.internal.configentry.TCPRoute.Parents:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 86, // 140: hashicorp.consul.internal.configentry.TCPRoute.Services:type_name -> hashicorp.consul.internal.configentry.TCPService - 60, // 141: hashicorp.consul.internal.configentry.TCPRoute.Status:type_name -> hashicorp.consul.internal.configentry.Status - 125, // 142: hashicorp.consul.internal.configentry.TCPService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 88, // 143: hashicorp.consul.internal.configentry.SamenessGroup.Members:type_name -> hashicorp.consul.internal.configentry.SamenessGroupMember - 123, // 144: hashicorp.consul.internal.configentry.SamenessGroup.Meta:type_name -> hashicorp.consul.internal.configentry.SamenessGroup.MetaEntry - 125, // 145: hashicorp.consul.internal.configentry.SamenessGroup.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 90, // 146: hashicorp.consul.internal.configentry.JWTProvider.JSONWebKeySet:type_name -> hashicorp.consul.internal.configentry.JSONWebKeySet - 99, // 147: hashicorp.consul.internal.configentry.JWTProvider.Locations:type_name -> hashicorp.consul.internal.configentry.JWTLocation - 103, // 148: hashicorp.consul.internal.configentry.JWTProvider.Forwarding:type_name -> hashicorp.consul.internal.configentry.JWTForwardingConfig - 104, // 149: hashicorp.consul.internal.configentry.JWTProvider.CacheConfig:type_name -> hashicorp.consul.internal.configentry.JWTCacheConfig - 124, // 150: hashicorp.consul.internal.configentry.JWTProvider.Meta:type_name -> hashicorp.consul.internal.configentry.JWTProvider.MetaEntry - 91, // 151: hashicorp.consul.internal.configentry.JSONWebKeySet.Local:type_name -> hashicorp.consul.internal.configentry.LocalJWKS - 92, // 152: hashicorp.consul.internal.configentry.JSONWebKeySet.Remote:type_name -> hashicorp.consul.internal.configentry.RemoteJWKS - 127, // 153: hashicorp.consul.internal.configentry.RemoteJWKS.CacheDuration:type_name -> google.protobuf.Duration - 97, // 154: hashicorp.consul.internal.configentry.RemoteJWKS.RetryPolicy:type_name -> hashicorp.consul.internal.configentry.JWKSRetryPolicy - 93, // 155: hashicorp.consul.internal.configentry.RemoteJWKS.JWKSCluster:type_name -> hashicorp.consul.internal.configentry.JWKSCluster - 94, // 156: hashicorp.consul.internal.configentry.JWKSCluster.TLSCertificates:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertificate - 127, // 157: hashicorp.consul.internal.configentry.JWKSCluster.ConnectTimeout:type_name -> google.protobuf.Duration - 95, // 158: hashicorp.consul.internal.configentry.JWKSTLSCertificate.CaCertificateProviderInstance:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertProviderInstance - 96, // 159: hashicorp.consul.internal.configentry.JWKSTLSCertificate.TrustedCA:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertTrustedCA - 98, // 160: hashicorp.consul.internal.configentry.JWKSRetryPolicy.RetryPolicyBackOff:type_name -> hashicorp.consul.internal.configentry.RetryPolicyBackOff - 127, // 161: hashicorp.consul.internal.configentry.RetryPolicyBackOff.BaseInterval:type_name -> google.protobuf.Duration - 127, // 162: hashicorp.consul.internal.configentry.RetryPolicyBackOff.MaxInterval:type_name -> google.protobuf.Duration - 100, // 163: hashicorp.consul.internal.configentry.JWTLocation.Header:type_name -> hashicorp.consul.internal.configentry.JWTLocationHeader - 101, // 164: hashicorp.consul.internal.configentry.JWTLocation.QueryParam:type_name -> hashicorp.consul.internal.configentry.JWTLocationQueryParam - 102, // 165: hashicorp.consul.internal.configentry.JWTLocation.Cookie:type_name -> hashicorp.consul.internal.configentry.JWTLocationCookie - 19, // 166: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverSubset - 21, // 167: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailover - 168, // [168:168] is the sub-list for method output_type - 168, // [168:168] is the sub-list for method input_type - 168, // [168:168] is the sub-list for extension type_name - 168, // [168:168] is the sub-list for extension extendee - 0, // [0:168] is the sub-list for field type_name + 105, // 76: hashicorp.consul.internal.configentry.ServiceDefaults.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry + 119, // 77: hashicorp.consul.internal.configentry.ServiceDefaults.EnvoyExtensions:type_name -> hashicorp.consul.internal.common.EnvoyExtension + 4, // 78: hashicorp.consul.internal.configentry.ServiceDefaults.MutualTLSMode:type_name -> hashicorp.consul.internal.configentry.MutualTLSMode + 5, // 79: hashicorp.consul.internal.configentry.MeshGatewayConfig.Mode:type_name -> hashicorp.consul.internal.configentry.MeshGatewayMode + 50, // 80: hashicorp.consul.internal.configentry.ExposeConfig.Paths:type_name -> hashicorp.consul.internal.configentry.ExposePath + 52, // 81: hashicorp.consul.internal.configentry.UpstreamConfiguration.Overrides:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig + 52, // 82: hashicorp.consul.internal.configentry.UpstreamConfiguration.Defaults:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig + 115, // 83: hashicorp.consul.internal.configentry.UpstreamConfig.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 53, // 84: hashicorp.consul.internal.configentry.UpstreamConfig.Limits:type_name -> hashicorp.consul.internal.configentry.UpstreamLimits + 54, // 85: hashicorp.consul.internal.configentry.UpstreamConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck + 48, // 86: hashicorp.consul.internal.configentry.UpstreamConfig.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig + 117, // 87: hashicorp.consul.internal.configentry.PassiveHealthCheck.Interval:type_name -> google.protobuf.Duration + 117, // 88: hashicorp.consul.internal.configentry.PassiveHealthCheck.BaseEjectionTime:type_name -> google.protobuf.Duration + 106, // 89: hashicorp.consul.internal.configentry.APIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.APIGateway.MetaEntry + 59, // 90: hashicorp.consul.internal.configentry.APIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.APIGatewayListener + 57, // 91: hashicorp.consul.internal.configentry.APIGateway.Status:type_name -> hashicorp.consul.internal.configentry.Status + 58, // 92: hashicorp.consul.internal.configentry.Status.Conditions:type_name -> hashicorp.consul.internal.configentry.Condition + 61, // 93: hashicorp.consul.internal.configentry.Condition.Resource:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 118, // 94: hashicorp.consul.internal.configentry.Condition.LastTransitionTime:type_name -> google.protobuf.Timestamp + 6, // 95: hashicorp.consul.internal.configentry.APIGatewayListener.Protocol:type_name -> hashicorp.consul.internal.configentry.APIGatewayListenerProtocol + 60, // 96: hashicorp.consul.internal.configentry.APIGatewayListener.TLS:type_name -> hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration + 61, // 97: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 115, // 98: hashicorp.consul.internal.configentry.ResourceReference.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 107, // 99: hashicorp.consul.internal.configentry.BoundAPIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry + 63, // 100: hashicorp.consul.internal.configentry.BoundAPIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.BoundAPIGatewayListener + 61, // 101: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 61, // 102: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Routes:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 108, // 103: hashicorp.consul.internal.configentry.InlineCertificate.Meta:type_name -> hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry + 109, // 104: hashicorp.consul.internal.configentry.HTTPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry + 61, // 105: hashicorp.consul.internal.configentry.HTTPRoute.Parents:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 66, // 106: hashicorp.consul.internal.configentry.HTTPRoute.Rules:type_name -> hashicorp.consul.internal.configentry.HTTPRouteRule + 57, // 107: hashicorp.consul.internal.configentry.HTTPRoute.Status:type_name -> hashicorp.consul.internal.configentry.Status + 71, // 108: hashicorp.consul.internal.configentry.HTTPRouteRule.Filters:type_name -> hashicorp.consul.internal.configentry.HTTPFilters + 67, // 109: hashicorp.consul.internal.configentry.HTTPRouteRule.Matches:type_name -> hashicorp.consul.internal.configentry.HTTPMatch + 74, // 110: hashicorp.consul.internal.configentry.HTTPRouteRule.Services:type_name -> hashicorp.consul.internal.configentry.HTTPService + 68, // 111: hashicorp.consul.internal.configentry.HTTPMatch.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderMatch + 7, // 112: hashicorp.consul.internal.configentry.HTTPMatch.Method:type_name -> hashicorp.consul.internal.configentry.HTTPMatchMethod + 69, // 113: hashicorp.consul.internal.configentry.HTTPMatch.Path:type_name -> hashicorp.consul.internal.configentry.HTTPPathMatch + 70, // 114: hashicorp.consul.internal.configentry.HTTPMatch.Query:type_name -> hashicorp.consul.internal.configentry.HTTPQueryMatch + 8, // 115: hashicorp.consul.internal.configentry.HTTPHeaderMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderMatchType + 9, // 116: hashicorp.consul.internal.configentry.HTTPPathMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPPathMatchType + 10, // 117: hashicorp.consul.internal.configentry.HTTPQueryMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPQueryMatchType + 73, // 118: hashicorp.consul.internal.configentry.HTTPFilters.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter + 72, // 119: hashicorp.consul.internal.configentry.HTTPFilters.URLRewrite:type_name -> hashicorp.consul.internal.configentry.URLRewrite + 110, // 120: hashicorp.consul.internal.configentry.HTTPHeaderFilter.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter.AddEntry + 111, // 121: hashicorp.consul.internal.configentry.HTTPHeaderFilter.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter.SetEntry + 71, // 122: hashicorp.consul.internal.configentry.HTTPService.Filters:type_name -> hashicorp.consul.internal.configentry.HTTPFilters + 115, // 123: hashicorp.consul.internal.configentry.HTTPService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 112, // 124: hashicorp.consul.internal.configentry.TCPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.TCPRoute.MetaEntry + 61, // 125: hashicorp.consul.internal.configentry.TCPRoute.Parents:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 76, // 126: hashicorp.consul.internal.configentry.TCPRoute.Services:type_name -> hashicorp.consul.internal.configentry.TCPService + 57, // 127: hashicorp.consul.internal.configentry.TCPRoute.Status:type_name -> hashicorp.consul.internal.configentry.Status + 115, // 128: hashicorp.consul.internal.configentry.TCPService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 78, // 129: hashicorp.consul.internal.configentry.SamenessGroup.Members:type_name -> hashicorp.consul.internal.configentry.SamenessGroupMember + 113, // 130: hashicorp.consul.internal.configentry.SamenessGroup.Meta:type_name -> hashicorp.consul.internal.configentry.SamenessGroup.MetaEntry + 115, // 131: hashicorp.consul.internal.configentry.SamenessGroup.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 80, // 132: hashicorp.consul.internal.configentry.JWTProvider.JSONWebKeySet:type_name -> hashicorp.consul.internal.configentry.JSONWebKeySet + 89, // 133: hashicorp.consul.internal.configentry.JWTProvider.Locations:type_name -> hashicorp.consul.internal.configentry.JWTLocation + 93, // 134: hashicorp.consul.internal.configentry.JWTProvider.Forwarding:type_name -> hashicorp.consul.internal.configentry.JWTForwardingConfig + 94, // 135: hashicorp.consul.internal.configentry.JWTProvider.CacheConfig:type_name -> hashicorp.consul.internal.configentry.JWTCacheConfig + 114, // 136: hashicorp.consul.internal.configentry.JWTProvider.Meta:type_name -> hashicorp.consul.internal.configentry.JWTProvider.MetaEntry + 81, // 137: hashicorp.consul.internal.configentry.JSONWebKeySet.Local:type_name -> hashicorp.consul.internal.configentry.LocalJWKS + 82, // 138: hashicorp.consul.internal.configentry.JSONWebKeySet.Remote:type_name -> hashicorp.consul.internal.configentry.RemoteJWKS + 117, // 139: hashicorp.consul.internal.configentry.RemoteJWKS.CacheDuration:type_name -> google.protobuf.Duration + 87, // 140: hashicorp.consul.internal.configentry.RemoteJWKS.RetryPolicy:type_name -> hashicorp.consul.internal.configentry.JWKSRetryPolicy + 83, // 141: hashicorp.consul.internal.configentry.RemoteJWKS.JWKSCluster:type_name -> hashicorp.consul.internal.configentry.JWKSCluster + 84, // 142: hashicorp.consul.internal.configentry.JWKSCluster.TLSCertificates:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertificate + 117, // 143: hashicorp.consul.internal.configentry.JWKSCluster.ConnectTimeout:type_name -> google.protobuf.Duration + 85, // 144: hashicorp.consul.internal.configentry.JWKSTLSCertificate.CaCertificateProviderInstance:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertProviderInstance + 86, // 145: hashicorp.consul.internal.configentry.JWKSTLSCertificate.TrustedCA:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertTrustedCA + 88, // 146: hashicorp.consul.internal.configentry.JWKSRetryPolicy.RetryPolicyBackOff:type_name -> hashicorp.consul.internal.configentry.RetryPolicyBackOff + 117, // 147: hashicorp.consul.internal.configentry.RetryPolicyBackOff.BaseInterval:type_name -> google.protobuf.Duration + 117, // 148: hashicorp.consul.internal.configentry.RetryPolicyBackOff.MaxInterval:type_name -> google.protobuf.Duration + 90, // 149: hashicorp.consul.internal.configentry.JWTLocation.Header:type_name -> hashicorp.consul.internal.configentry.JWTLocationHeader + 91, // 150: hashicorp.consul.internal.configentry.JWTLocation.QueryParam:type_name -> hashicorp.consul.internal.configentry.JWTLocationQueryParam + 92, // 151: hashicorp.consul.internal.configentry.JWTLocation.Cookie:type_name -> hashicorp.consul.internal.configentry.JWTLocationCookie + 19, // 152: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverSubset + 21, // 153: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailover + 154, // [154:154] is the sub-list for method output_type + 154, // [154:154] is the sub-list for method input_type + 154, // [154:154] is the sub-list for extension type_name + 154, // [154:154] is the sub-list for extension extendee + 0, // [0:154] is the sub-list for field type_name } func init() { file_private_pbconfigentry_config_entry_proto_init() } @@ -10096,42 +9300,6 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RateLimits); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_private_pbconfigentry_config_entry_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InstanceLevelRateLimits); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_private_pbconfigentry_config_entry_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InstanceLevelRouteRateLimits); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_private_pbconfigentry_config_entry_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*APIGateway); i { case 0: return &v.state @@ -10143,7 +9311,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Status); i { case 0: return &v.state @@ -10155,7 +9323,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Condition); i { case 0: return &v.state @@ -10167,7 +9335,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*APIGatewayListener); i { case 0: return &v.state @@ -10179,7 +9347,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*APIGatewayTLSConfiguration); i { case 0: return &v.state @@ -10191,55 +9359,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*APIGatewayPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_private_pbconfigentry_config_entry_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*APIGatewayJWTRequirement); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_private_pbconfigentry_config_entry_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*APIGatewayJWTProvider); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_private_pbconfigentry_config_entry_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*APIGatewayJWTClaimVerification); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_private_pbconfigentry_config_entry_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ResourceReference); i { case 0: return &v.state @@ -10251,7 +9371,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BoundAPIGateway); i { case 0: return &v.state @@ -10263,7 +9383,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BoundAPIGatewayListener); i { case 0: return &v.state @@ -10275,7 +9395,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*InlineCertificate); i { case 0: return &v.state @@ -10287,7 +9407,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPRoute); i { case 0: return &v.state @@ -10299,7 +9419,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPRouteRule); i { case 0: return &v.state @@ -10311,7 +9431,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPMatch); i { case 0: return &v.state @@ -10323,7 +9443,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPHeaderMatch); i { case 0: return &v.state @@ -10335,7 +9455,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPPathMatch); i { case 0: return &v.state @@ -10347,7 +9467,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPQueryMatch); i { case 0: return &v.state @@ -10359,7 +9479,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPFilters); i { case 0: return &v.state @@ -10371,7 +9491,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*URLRewrite); i { case 0: return &v.state @@ -10383,43 +9503,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RetryFilter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_private_pbconfigentry_config_entry_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TimeoutFilter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_private_pbconfigentry_config_entry_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWTFilter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_private_pbconfigentry_config_entry_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPHeaderFilter); i { case 0: return &v.state @@ -10431,7 +9515,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPService); i { case 0: return &v.state @@ -10443,7 +9527,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TCPRoute); i { case 0: return &v.state @@ -10455,7 +9539,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TCPService); i { case 0: return &v.state @@ -10467,7 +9551,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SamenessGroup); i { case 0: return &v.state @@ -10479,7 +9563,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SamenessGroupMember); i { case 0: return &v.state @@ -10491,7 +9575,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTProvider); i { case 0: return &v.state @@ -10503,7 +9587,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JSONWebKeySet); i { case 0: return &v.state @@ -10515,7 +9599,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LocalJWKS); i { case 0: return &v.state @@ -10527,7 +9611,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RemoteJWKS); i { case 0: return &v.state @@ -10539,7 +9623,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWKSCluster); i { case 0: return &v.state @@ -10551,7 +9635,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWKSTLSCertificate); i { case 0: return &v.state @@ -10563,7 +9647,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWKSTLSCertProviderInstance); i { case 0: return &v.state @@ -10575,7 +9659,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWKSTLSCertTrustedCA); i { case 0: return &v.state @@ -10587,7 +9671,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWKSRetryPolicy); i { case 0: return &v.state @@ -10599,7 +9683,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[87].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RetryPolicyBackOff); i { case 0: return &v.state @@ -10611,7 +9695,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[88].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTLocation); i { case 0: return &v.state @@ -10623,7 +9707,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[89].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTLocationHeader); i { case 0: return &v.state @@ -10635,7 +9719,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[90].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTLocationQueryParam); i { case 0: return &v.state @@ -10647,7 +9731,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[91].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTLocationCookie); i { case 0: return &v.state @@ -10659,7 +9743,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[92].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTForwardingConfig); i { case 0: return &v.state @@ -10671,7 +9755,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[93].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTCacheConfig); i { case 0: return &v.state @@ -10704,7 +9788,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_private_pbconfigentry_config_entry_proto_rawDesc, NumEnums: 11, - NumMessages: 114, + NumMessages: 104, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/private/pbconfigentry/config_entry.proto b/proto/private/pbconfigentry/config_entry.proto index c5bb243a5cafd..5c675ec16c0cc 100644 --- a/proto/private/pbconfigentry/config_entry.proto +++ b/proto/private/pbconfigentry/config_entry.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; @@ -507,7 +507,6 @@ message ServiceDefaults { // mog: func-to=int func-from=int32 int32 LocalRequestTimeoutMs = 11; string BalanceInboundConnections = 12; - RateLimits RateLimits = 16; map Meta = 13; // mog: func-to=EnvoyExtensionsToStructs func-from=EnvoyExtensionsFromStructs repeated hashicorp.consul.internal.common.EnvoyExtension EnvoyExtensions = 14; @@ -653,43 +652,6 @@ message DestinationConfig { int32 Port = 2; } -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.RateLimits -// output=config_entry.gen.go -// name=Structs -message RateLimits { - InstanceLevelRateLimits InstanceLevel = 1; -} - -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.InstanceLevelRateLimits -// output=config_entry.gen.go -// name=Structs -message InstanceLevelRateLimits { - // mog: func-to=int func-from=uint32 - uint32 RequestsPerSecond = 1; - // mog: func-to=int func-from=uint32 - uint32 RequestsMaxBurst = 2; - repeated InstanceLevelRouteRateLimits Routes = 3; -} - -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.InstanceLevelRouteRateLimits -// output=config_entry.gen.go -// name=Structs -message InstanceLevelRouteRateLimits { - string PathExact = 1; - string PathPrefix = 2; - string PathRegex = 3; - // mog: func-to=int func-from=uint32 - uint32 RequestsPerSecond = 4; - // mog: func-to=int func-from=uint32 - uint32 RequestsMaxBurst = 5; -} - // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.APIGatewayConfigEntry @@ -744,8 +706,6 @@ message APIGatewayListener { // mog: func-to=apiGatewayProtocolToStructs func-from=apiGatewayProtocolFromStructs APIGatewayListenerProtocol Protocol = 4; APIGatewayTLSConfiguration TLS = 5; - APIGatewayPolicy Override = 6; - APIGatewayPolicy Default = 7; } // mog annotation: @@ -763,30 +723,6 @@ message APIGatewayTLSConfiguration { repeated string CipherSuites = 4; } -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.APIGatewayPolicy -// output=config_entry.gen.go -// name=Structs -message APIGatewayPolicy { - // mog: func-to=gwJWTRequirementToStructs func-from=gwJWTRequirementFromStructs - APIGatewayJWTRequirement JWT = 1; -} - -message APIGatewayJWTRequirement { - repeated APIGatewayJWTProvider Providers = 1; -} - -message APIGatewayJWTProvider { - string Name = 1; - repeated APIGatewayJWTClaimVerification VerifyClaims = 2; -} - -message APIGatewayJWTClaimVerification { - repeated string Path = 1; - string Value = 2; -} - // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.ResourceReference @@ -948,10 +884,6 @@ message HTTPQueryMatch { message HTTPFilters { repeated HTTPHeaderFilter Headers = 1; URLRewrite URLRewrite = 2; - RetryFilter RetryFilter = 3; - TimeoutFilter TimeoutFilter = 4; - // mog: func-to=routeJWTFilterToStructs func-from=routeJWTFilterFromStructs - JWTFilter JWT = 5; } // mog annotation: @@ -963,34 +895,6 @@ message URLRewrite { string Path = 1; } -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.RetryFilter -// output=config_entry.gen.go -// name=Structs -message RetryFilter { - uint32 NumRetries = 1; - repeated string RetryOn = 2; - repeated uint32 RetryOnStatusCodes = 3; - bool RetryOnConnectFailure = 4; -} - -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.TimeoutFilter -// output=config_entry.gen.go -// name=Structs -message TimeoutFilter { - // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto - google.protobuf.Duration RequestTimeout = 1; - // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto - google.protobuf.Duration IdleTimeout = 2; -} - -message JWTFilter { - repeated APIGatewayJWTProvider Providers = 1; -} - // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.HTTPHeaderFilter diff --git a/proto/private/pbconfigentry/config_entry_ce.go b/proto/private/pbconfigentry/config_entry_ce.go deleted file mode 100644 index b81e07686136d..0000000000000 --- a/proto/private/pbconfigentry/config_entry_ce.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent -// +build !consulent - -package pbconfigentry - -import "github.com/hashicorp/consul/agent/structs" - -func gwJWTRequirementToStructs(m *APIGatewayJWTRequirement) *structs.APIGatewayJWTRequirement { - return &structs.APIGatewayJWTRequirement{} -} - -func gwJWTRequirementFromStructs(*structs.APIGatewayJWTRequirement) *APIGatewayJWTRequirement { - return &APIGatewayJWTRequirement{} -} - -func routeJWTFilterToStructs(m *JWTFilter) *structs.JWTFilter { - return &structs.JWTFilter{} -} - -func routeJWTFilterFromStructs(*structs.JWTFilter) *JWTFilter { - return &JWTFilter{} -} diff --git a/proto/private/pbconnect/connect.go b/proto/private/pbconnect/connect.go index 9c3ed9d7355e0..85f8a35b7d37b 100644 --- a/proto/private/pbconnect/connect.go +++ b/proto/private/pbconnect/connect.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbconnect diff --git a/proto/private/pbconnect/connect.pb.go b/proto/private/pbconnect/connect.pb.go index 18942ff7dea54..278114b3b4aa9 100644 --- a/proto/private/pbconnect/connect.pb.go +++ b/proto/private/pbconnect/connect.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: diff --git a/proto/private/pbconnect/connect.proto b/proto/private/pbconnect/connect.proto index f829dd22629a8..afd1a4e1a4dd6 100644 --- a/proto/private/pbconnect/connect.proto +++ b/proto/private/pbconnect/connect.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; diff --git a/proto/private/pbdemo/v1/demo.pb.binary.go b/proto/private/pbdemo/v1/demo.pb.binary.go index b52d5f33496eb..45a3c34e5536e 100644 --- a/proto/private/pbdemo/v1/demo.pb.binary.go +++ b/proto/private/pbdemo/v1/demo.pb.binary.go @@ -7,16 +7,6 @@ import ( "google.golang.org/protobuf/proto" ) -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RecordLabel) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RecordLabel) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - // MarshalBinary implements encoding.BinaryMarshaler func (msg *Artist) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) diff --git a/proto/private/pbdemo/v1/demo.pb.go b/proto/private/pbdemo/v1/demo.pb.go index ebc5bc3700ae8..9ee119d76f54d 100644 --- a/proto/private/pbdemo/v1/demo.pb.go +++ b/proto/private/pbdemo/v1/demo.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: @@ -105,61 +105,6 @@ func (Genre) EnumDescriptor() ([]byte, []int) { return file_private_pbdemo_v1_demo_proto_rawDescGZIP(), []int{0} } -type RecordLabel struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` -} - -func (x *RecordLabel) Reset() { - *x = RecordLabel{} - if protoimpl.UnsafeEnabled { - mi := &file_private_pbdemo_v1_demo_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RecordLabel) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RecordLabel) ProtoMessage() {} - -func (x *RecordLabel) ProtoReflect() protoreflect.Message { - mi := &file_private_pbdemo_v1_demo_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 RecordLabel.ProtoReflect.Descriptor instead. -func (*RecordLabel) Descriptor() ([]byte, []int) { - return file_private_pbdemo_v1_demo_proto_rawDescGZIP(), []int{0} -} - -func (x *RecordLabel) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *RecordLabel) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - type Artist struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -174,7 +119,7 @@ type Artist struct { func (x *Artist) Reset() { *x = Artist{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbdemo_v1_demo_proto_msgTypes[1] + mi := &file_private_pbdemo_v1_demo_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -187,7 +132,7 @@ func (x *Artist) String() string { func (*Artist) ProtoMessage() {} func (x *Artist) ProtoReflect() protoreflect.Message { - mi := &file_private_pbdemo_v1_demo_proto_msgTypes[1] + mi := &file_private_pbdemo_v1_demo_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -200,7 +145,7 @@ func (x *Artist) ProtoReflect() protoreflect.Message { // Deprecated: Use Artist.ProtoReflect.Descriptor instead. func (*Artist) Descriptor() ([]byte, []int) { - return file_private_pbdemo_v1_demo_proto_rawDescGZIP(), []int{1} + return file_private_pbdemo_v1_demo_proto_rawDescGZIP(), []int{0} } func (x *Artist) GetName() string { @@ -245,7 +190,7 @@ type Album struct { func (x *Album) Reset() { *x = Album{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbdemo_v1_demo_proto_msgTypes[2] + mi := &file_private_pbdemo_v1_demo_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -258,7 +203,7 @@ func (x *Album) String() string { func (*Album) ProtoMessage() {} func (x *Album) ProtoReflect() protoreflect.Message { - mi := &file_private_pbdemo_v1_demo_proto_msgTypes[2] + mi := &file_private_pbdemo_v1_demo_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -271,7 +216,7 @@ func (x *Album) ProtoReflect() protoreflect.Message { // Deprecated: Use Album.ProtoReflect.Descriptor instead. func (*Album) Descriptor() ([]byte, []int) { - return file_private_pbdemo_v1_demo_proto_rawDescGZIP(), []int{2} + return file_private_pbdemo_v1_demo_proto_rawDescGZIP(), []int{1} } func (x *Album) GetName() string { @@ -309,63 +254,59 @@ var file_private_pbdemo_v1_demo_proto_rawDesc = []byte{ 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x6d, 0x6f, 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, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76, - 0x31, 0x22, 0x43, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4c, 0x61, 0x62, 0x65, 0x6c, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa3, 0x01, 0x0a, 0x06, 0x41, 0x72, 0x74, 0x69, 0x73, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x05, 0x67, 0x65, 0x6e, 0x72, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x72, 0x65, - 0x52, 0x05, 0x67, 0x65, 0x6e, 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, - 0x67, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0x8c, 0x01, 0x0a, - 0x05, 0x41, 0x6c, 0x62, 0x75, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x79, 0x65, - 0x61, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x0d, 0x79, 0x65, 0x61, 0x72, 0x4f, 0x66, 0x52, 0x65, 0x6c, 0x65, 0x61, - 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x13, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, - 0x5f, 0x61, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x12, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x41, 0x63, 0x6c, 0x61, 0x69, - 0x6d, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x2a, 0xe9, 0x01, 0x0a, 0x05, - 0x47, 0x65, 0x6e, 0x72, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, - 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x4a, 0x41, 0x5a, 0x5a, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, - 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x46, 0x4f, 0x4c, 0x4b, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, - 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x50, 0x4f, 0x50, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x47, - 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x4c, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, - 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x50, 0x55, 0x4e, 0x4b, 0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b, - 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x42, 0x4c, 0x55, 0x45, 0x53, 0x10, 0x06, 0x12, 0x11, 0x0a, - 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x52, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x42, 0x10, 0x07, - 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x52, - 0x59, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x44, 0x49, 0x53, - 0x43, 0x4f, 0x10, 0x09, 0x12, 0x0d, 0x0a, 0x09, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x53, 0x4b, - 0x41, 0x10, 0x0a, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x48, 0x49, 0x50, - 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x0b, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, - 0x49, 0x4e, 0x44, 0x49, 0x45, 0x10, 0x0c, 0x42, 0x97, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76, - 0x31, 0x42, 0x09, 0x44, 0x65, 0x6d, 0x6f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, - 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, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x64, 0x65, 0x6d, 0x6f, - 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x65, 0x6d, 0x6f, 0x76, 0x31, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, - 0x44, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x44, 0x65, - 0x6d, 0x6f, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x5c, 0x44, 0x65, 0x6d, 0x6f, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x44, 0x65, 0x6d, 0x6f, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, - 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x44, 0x65, 0x6d, 0x6f, 0x3a, 0x3a, 0x56, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x31, 0x22, 0xa3, 0x01, 0x0a, 0x06, 0x41, 0x72, 0x74, 0x69, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x05, 0x67, 0x65, 0x6e, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x28, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, + 0x6d, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x72, 0x65, 0x52, 0x05, 0x67, 0x65, 0x6e, + 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0x8c, 0x01, 0x0a, 0x05, 0x41, 0x6c, 0x62, 0x75, + 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x79, 0x65, 0x61, 0x72, 0x5f, 0x6f, 0x66, + 0x5f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, + 0x79, 0x65, 0x61, 0x72, 0x4f, 0x66, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x2f, 0x0a, + 0x13, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x5f, 0x61, 0x63, 0x6c, 0x61, + 0x69, 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x63, 0x72, 0x69, 0x74, + 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x41, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x12, 0x16, + 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, + 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x2a, 0xe9, 0x01, 0x0a, 0x05, 0x47, 0x65, 0x6e, 0x72, 0x65, + 0x12, 0x15, 0x0a, 0x11, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, + 0x5f, 0x4a, 0x41, 0x5a, 0x5a, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, + 0x5f, 0x46, 0x4f, 0x4c, 0x4b, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x47, 0x45, 0x4e, 0x52, 0x45, + 0x5f, 0x50, 0x4f, 0x50, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, + 0x4d, 0x45, 0x54, 0x41, 0x4c, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, + 0x5f, 0x50, 0x55, 0x4e, 0x4b, 0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, + 0x5f, 0x42, 0x4c, 0x55, 0x45, 0x53, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, + 0x45, 0x5f, 0x52, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x42, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x47, + 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x52, 0x59, 0x10, 0x08, 0x12, 0x0f, + 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x10, 0x09, 0x12, + 0x0d, 0x0a, 0x09, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x53, 0x4b, 0x41, 0x10, 0x0a, 0x12, 0x11, + 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x48, 0x49, 0x50, 0x5f, 0x48, 0x4f, 0x50, 0x10, + 0x0b, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x44, 0x49, 0x45, + 0x10, 0x0c, 0x42, 0x97, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x44, 0x65, + 0x6d, 0x6f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 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, 0x2f, 0x70, 0x72, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x64, 0x65, 0x6d, 0x6f, 0x2f, 0x76, 0x31, 0x3b, 0x64, + 0x65, 0x6d, 0x6f, 0x76, 0x31, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x44, 0xaa, 0x02, 0x21, 0x48, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x44, 0x65, 0x6d, 0x6f, 0x2e, 0x56, 0x31, + 0xca, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x44, 0x65, 0x6d, + 0x6f, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x5c, 0x44, 0x65, 0x6d, 0x6f, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x3a, 0x3a, 0x44, 0x65, 0x6d, 0x6f, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -381,12 +322,11 @@ func file_private_pbdemo_v1_demo_proto_rawDescGZIP() []byte { } var file_private_pbdemo_v1_demo_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_private_pbdemo_v1_demo_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_private_pbdemo_v1_demo_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_private_pbdemo_v1_demo_proto_goTypes = []interface{}{ - (Genre)(0), // 0: hashicorp.consul.internal.demo.v1.Genre - (*RecordLabel)(nil), // 1: hashicorp.consul.internal.demo.v1.RecordLabel - (*Artist)(nil), // 2: hashicorp.consul.internal.demo.v1.Artist - (*Album)(nil), // 3: hashicorp.consul.internal.demo.v1.Album + (Genre)(0), // 0: hashicorp.consul.internal.demo.v1.Genre + (*Artist)(nil), // 1: hashicorp.consul.internal.demo.v1.Artist + (*Album)(nil), // 2: hashicorp.consul.internal.demo.v1.Album } var file_private_pbdemo_v1_demo_proto_depIdxs = []int32{ 0, // 0: hashicorp.consul.internal.demo.v1.Artist.genre:type_name -> hashicorp.consul.internal.demo.v1.Genre @@ -404,18 +344,6 @@ func file_private_pbdemo_v1_demo_proto_init() { } if !protoimpl.UnsafeEnabled { file_private_pbdemo_v1_demo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RecordLabel); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_private_pbdemo_v1_demo_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Artist); i { case 0: return &v.state @@ -427,7 +355,7 @@ func file_private_pbdemo_v1_demo_proto_init() { return nil } } - file_private_pbdemo_v1_demo_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_private_pbdemo_v1_demo_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Album); i { case 0: return &v.state @@ -446,7 +374,7 @@ func file_private_pbdemo_v1_demo_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_private_pbdemo_v1_demo_proto_rawDesc, NumEnums: 1, - NumMessages: 3, + NumMessages: 2, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/private/pbdemo/v1/demo.proto b/proto/private/pbdemo/v1/demo.proto index a0498cbd4fe30..60ce1d0a4f507 100644 --- a/proto/private/pbdemo/v1/demo.proto +++ b/proto/private/pbdemo/v1/demo.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; @@ -7,11 +7,6 @@ syntax = "proto3"; // Consul's generic storage APIs. package hashicorp.consul.internal.demo.v1; -message RecordLabel { - string name = 1; - string description = 2; -} - message Artist { string name = 1; string description = 2; diff --git a/proto/private/pbdemo/v2/demo.pb.go b/proto/private/pbdemo/v2/demo.pb.go index a4c52a99d6a6c..2ffed20dcc6f5 100644 --- a/proto/private/pbdemo/v2/demo.pb.go +++ b/proto/private/pbdemo/v2/demo.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: diff --git a/proto/private/pbdemo/v2/demo.proto b/proto/private/pbdemo/v2/demo.proto index 546cfe6972611..b208324801c12 100644 --- a/proto/private/pbdemo/v2/demo.proto +++ b/proto/private/pbdemo/v2/demo.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; diff --git a/proto/private/pboperator/operator.pb.go b/proto/private/pboperator/operator.pb.go index e7e457bc7389e..5f264c53937af 100644 --- a/proto/private/pboperator/operator.pb.go +++ b/proto/private/pboperator/operator.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: diff --git a/proto/private/pboperator/operator.proto b/proto/private/pboperator/operator.proto index 8669f03041fd9..4f8b99358d4e9 100644 --- a/proto/private/pboperator/operator.proto +++ b/proto/private/pboperator/operator.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; diff --git a/proto/private/pbpeering/peering.go b/proto/private/pbpeering/peering.go index 5759061afce24..0fec964c46b1a 100644 --- a/proto/private/pbpeering/peering.go +++ b/proto/private/pbpeering/peering.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbpeering diff --git a/proto/private/pbpeering/peering.pb.go b/proto/private/pbpeering/peering.pb.go index a0c7bd21676d2..65a75ada268f5 100644 --- a/proto/private/pbpeering/peering.pb.go +++ b/proto/private/pbpeering/peering.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: @@ -324,7 +324,7 @@ type Peering struct { PeerCAPems []string `protobuf:"bytes,8,rep,name=PeerCAPems,proto3" json:"PeerCAPems,omitempty"` // PeerServerName is the name of the remote server as it relates to TLS. PeerServerName string `protobuf:"bytes,9,opt,name=PeerServerName,proto3" json:"PeerServerName,omitempty"` - // PeerServerAddresses contains all the connection addresses for the remote peer. + // PeerServerAddresses contains all the the connection addresses for the remote peer. PeerServerAddresses []string `protobuf:"bytes,10,rep,name=PeerServerAddresses,proto3" json:"PeerServerAddresses,omitempty"` // StreamStatus contains information computed on read based on the state of the stream. // diff --git a/proto/private/pbpeering/peering.proto b/proto/private/pbpeering/peering.proto index 02fddbf17fea4..098c8f6387d56 100644 --- a/proto/private/pbpeering/peering.proto +++ b/proto/private/pbpeering/peering.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; @@ -229,7 +229,7 @@ message Peering { // PeerServerName is the name of the remote server as it relates to TLS. string PeerServerName = 9; - // PeerServerAddresses contains all the connection addresses for the remote peer. + // PeerServerAddresses contains all the the connection addresses for the remote peer. repeated string PeerServerAddresses = 10; // StreamStatus contains information computed on read based on the state of the stream. diff --git a/proto/private/pbpeering/peering_ce.go b/proto/private/pbpeering/peering_ce.go index 4c4dd959e8a73..04d1107d02c83 100644 --- a/proto/private/pbpeering/peering_ce.go +++ b/proto/private/pbpeering/peering_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/proto/private/pbpeerstream/convert.go b/proto/private/pbpeerstream/convert.go index d71dc5d3b15ff..27848e0e399e4 100644 --- a/proto/private/pbpeerstream/convert.go +++ b/proto/private/pbpeerstream/convert.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbpeerstream diff --git a/proto/private/pbpeerstream/peerstream.go b/proto/private/pbpeerstream/peerstream.go index 3dc6aa6093d83..85d44785d04e8 100644 --- a/proto/private/pbpeerstream/peerstream.go +++ b/proto/private/pbpeerstream/peerstream.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbpeerstream diff --git a/proto/private/pbpeerstream/peerstream.pb.go b/proto/private/pbpeerstream/peerstream.pb.go index aeb1bdb22082f..f20496642d30f 100644 --- a/proto/private/pbpeerstream/peerstream.pb.go +++ b/proto/private/pbpeerstream/peerstream.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: diff --git a/proto/private/pbpeerstream/peerstream.proto b/proto/private/pbpeerstream/peerstream.proto index b46fcf2270dba..a66e823e049e1 100644 --- a/proto/private/pbpeerstream/peerstream.proto +++ b/proto/private/pbpeerstream/peerstream.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; diff --git a/proto/private/pbpeerstream/types.go b/proto/private/pbpeerstream/types.go index bf2250c64dd9c..6b55bfb425665 100644 --- a/proto/private/pbpeerstream/types.go +++ b/proto/private/pbpeerstream/types.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbpeerstream diff --git a/proto/private/pbservice/convert.go b/proto/private/pbservice/convert.go index 8396ff7c649f2..973369f03dcde 100644 --- a/proto/private/pbservice/convert.go +++ b/proto/private/pbservice/convert.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbservice diff --git a/proto/private/pbservice/convert_ce.go b/proto/private/pbservice/convert_ce.go index 482a2640c74a2..938495b96b772 100644 --- a/proto/private/pbservice/convert_ce.go +++ b/proto/private/pbservice/convert_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/proto/private/pbservice/convert_ce_test.go b/proto/private/pbservice/convert_ce_test.go index 59a29c6ca7620..2367f3e73aeba 100644 --- a/proto/private/pbservice/convert_ce_test.go +++ b/proto/private/pbservice/convert_ce_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/proto/private/pbservice/convert_test.go b/proto/private/pbservice/convert_test.go index 5b3c97680ef6d..0093a76dd9fb9 100644 --- a/proto/private/pbservice/convert_test.go +++ b/proto/private/pbservice/convert_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbservice diff --git a/proto/private/pbservice/healthcheck.gen.go b/proto/private/pbservice/healthcheck.gen.go index 092a4ded9e82f..1c608d88c7a72 100644 --- a/proto/private/pbservice/healthcheck.gen.go +++ b/proto/private/pbservice/healthcheck.gen.go @@ -21,6 +21,7 @@ func CheckTypeToStructs(s *CheckType, t *structs.CheckType) { t.Body = s.Body t.DisableRedirects = s.DisableRedirects t.TCP = s.TCP + t.TCPUseTLS = s.TCPUseTLS t.UDP = s.UDP t.Interval = structs.DurationFromProto(s.Interval) t.AliasNode = s.AliasNode @@ -59,6 +60,7 @@ func CheckTypeFromStructs(t *structs.CheckType, s *CheckType) { s.Body = t.Body s.DisableRedirects = t.DisableRedirects s.TCP = t.TCP + s.TCPUseTLS = t.TCPUseTLS s.UDP = t.UDP s.Interval = structs.DurationToProto(t.Interval) s.AliasNode = t.AliasNode @@ -142,6 +144,7 @@ func HealthCheckDefinitionToStructs(s *HealthCheckDefinition, t *structs.HealthC t.Body = s.Body t.DisableRedirects = s.DisableRedirects t.TCP = s.TCP + t.TCPUseTLS = s.TCPUseTLS t.UDP = s.UDP t.H2PING = s.H2PING t.OSService = s.OSService @@ -171,6 +174,7 @@ func HealthCheckDefinitionFromStructs(t *structs.HealthCheckDefinition, s *Healt s.Body = t.Body s.DisableRedirects = t.DisableRedirects s.TCP = t.TCP + s.TCPUseTLS = t.TCPUseTLS s.UDP = t.UDP s.H2PING = t.H2PING s.OSService = t.OSService diff --git a/proto/private/pbservice/healthcheck.pb.go b/proto/private/pbservice/healthcheck.pb.go index ba0edbde9d648..524d95d6663d1 100644 --- a/proto/private/pbservice/healthcheck.pb.go +++ b/proto/private/pbservice/healthcheck.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: @@ -279,6 +279,7 @@ type HealthCheckDefinition struct { Body string `protobuf:"bytes,18,opt,name=Body,proto3" json:"Body,omitempty"` DisableRedirects bool `protobuf:"varint,22,opt,name=DisableRedirects,proto3" json:"DisableRedirects,omitempty"` TCP string `protobuf:"bytes,5,opt,name=TCP,proto3" json:"TCP,omitempty"` + TCPUseTLS bool `protobuf:"varint,25,opt,name=TCPUseTLS,proto3" json:"TCPUseTLS,omitempty"` UDP string `protobuf:"bytes,23,opt,name=UDP,proto3" json:"UDP,omitempty"` OSService string `protobuf:"bytes,24,opt,name=OSService,proto3" json:"OSService,omitempty"` // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto @@ -390,6 +391,13 @@ func (x *HealthCheckDefinition) GetTCP() string { return "" } +func (x *HealthCheckDefinition) GetTCPUseTLS() bool { + if x != nil { + return x.TCPUseTLS + } + return false +} + func (x *HealthCheckDefinition) GetUDP() string { if x != nil { return x.UDP @@ -532,6 +540,7 @@ type CheckType struct { Body string `protobuf:"bytes,26,opt,name=Body,proto3" json:"Body,omitempty"` DisableRedirects bool `protobuf:"varint,31,opt,name=DisableRedirects,proto3" json:"DisableRedirects,omitempty"` TCP string `protobuf:"bytes,8,opt,name=TCP,proto3" json:"TCP,omitempty"` + TCPUseTLS bool `protobuf:"varint,34,opt,name=TCPUseTLS,proto3" json:"TCPUseTLS,omitempty"` UDP string `protobuf:"bytes,32,opt,name=UDP,proto3" json:"UDP,omitempty"` OSService string `protobuf:"bytes,33,opt,name=OSService,proto3" json:"OSService,omitempty"` // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto @@ -677,6 +686,13 @@ func (x *CheckType) GetTCP() string { return "" } +func (x *CheckType) GetTCPUseTLS() bool { + if x != nil { + return x.TCPUseTLS + } + return false +} + func (x *CheckType) GetUDP() string { if x != nil { return x.UDP @@ -884,7 +900,7 @@ var file_private_pbservice_healthcheck_proto_rawDesc = []byte{ 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x92, 0x08, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb0, 0x08, 0x0a, 0x15, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x24, 0x0a, 0x0d, 0x54, @@ -905,153 +921,157 @@ var file_private_pbservice_healthcheck_proto_rawDesc = []byte{ 0x72, 0x65, 0x63, 0x74, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x54, 0x43, 0x50, 0x12, - 0x10, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x44, - 0x50, 0x12, 0x1c, 0x0a, 0x09, 0x4f, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x18, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4f, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x35, 0x0a, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x4f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x33, 0x0a, 0x07, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x12, 0x61, 0x0a, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, + 0x1c, 0x0a, 0x09, 0x54, 0x43, 0x50, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x19, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x09, 0x54, 0x43, 0x50, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x10, 0x0a, + 0x03, 0x55, 0x44, 0x50, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x44, 0x50, 0x12, + 0x1c, 0x0a, 0x09, 0x4f, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x18, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x4f, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, 0x0a, + 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x61, + 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x4f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x54, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, + 0x61, 0x0a, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, + 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, + 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, + 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x66, 0x74, + 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, + 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, + 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x44, + 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, + 0x12, 0x14, 0x0a, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, + 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, 0x12, 0x22, + 0x0a, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x15, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, + 0x4c, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x47, 0x52, 0x50, 0x43, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x52, 0x50, 0x43, 0x55, 0x73, + 0x65, 0x54, 0x4c, 0x53, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x47, 0x52, 0x50, 0x43, + 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, + 0x6f, 0x64, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, + 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, 0x4c, 0x18, + 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x03, 0x54, 0x54, 0x4c, 0x1a, 0x69, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0xd2, 0x0a, 0x0a, 0x09, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x54, + 0x54, 0x50, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x50, + 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2a, 0x0a, 0x10, + 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, + 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, + 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x54, 0x43, 0x50, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x43, + 0x50, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x22, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x54, + 0x43, 0x50, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x18, + 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x44, 0x50, 0x12, 0x1c, 0x0a, 0x09, 0x4f, 0x53, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x21, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4f, + 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, + 0x1c, 0x0a, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x0a, + 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x44, 0x6f, + 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, + 0x14, 0x0a, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, 0x18, + 0x1c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, 0x12, 0x22, 0x0a, + 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x1e, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, + 0x53, 0x12, 0x12, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x47, 0x52, 0x50, 0x43, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x52, 0x50, 0x43, 0x55, 0x73, 0x65, + 0x54, 0x4c, 0x53, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x47, 0x52, 0x50, 0x43, 0x55, + 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, + 0x53, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x54, + 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, 0x10, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x12, 0x33, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x11, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x54, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, 0x4c, 0x18, 0x12, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, + 0x54, 0x54, 0x4c, 0x12, 0x32, 0x0a, 0x14, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x65, + 0x66, 0x6f, 0x72, 0x65, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x15, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x14, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, + 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x15, 0x46, 0x61, 0x69, 0x6c, 0x75, + 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, + 0x18, 0x1d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, + 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x36, 0x0a, + 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x43, + 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x16, 0x20, 0x01, 0x28, 0x05, 0x52, 0x16, 0x46, + 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x43, 0x72, 0x69, + 0x74, 0x69, 0x63, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x48, 0x54, + 0x54, 0x50, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x48, + 0x54, 0x54, 0x50, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x47, 0x52, 0x50, 0x43, + 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x47, 0x52, 0x50, + 0x43, 0x12, 0x61, 0x0a, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x66, - 0x74, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x74, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, - 0x66, 0x74, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, - 0x67, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x41, 0x72, 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x32, 0x50, 0x49, - 0x4e, 0x47, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, - 0x12, 0x22, 0x0a, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, - 0x18, 0x15, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, - 0x65, 0x54, 0x4c, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x47, 0x52, 0x50, 0x43, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x52, 0x50, 0x43, - 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x47, 0x52, - 0x50, 0x43, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x6c, 0x69, 0x61, - 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, 0x6c, 0x69, - 0x61, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x6c, - 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, - 0x4c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x03, 0x54, 0x54, 0x4c, 0x1a, 0x69, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0xb4, 0x0a, 0x0a, 0x09, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, - 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x48, 0x54, 0x54, 0x50, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, - 0x12, 0x50, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2a, - 0x0a, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, - 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x43, - 0x50, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x54, 0x43, 0x50, 0x12, 0x10, 0x0a, 0x03, - 0x55, 0x44, 0x50, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x44, 0x50, 0x12, 0x1c, - 0x0a, 0x09, 0x4f, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x21, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x4f, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, 0x0a, 0x08, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x76, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, 0x64, 0x65, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, 0x64, - 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x32, 0x50, - 0x49, 0x4e, 0x47, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, - 0x47, 0x12, 0x22, 0x0a, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, - 0x53, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, - 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x18, 0x0e, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x47, 0x52, 0x50, 0x43, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x52, 0x50, - 0x43, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x47, - 0x52, 0x50, 0x43, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, - 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, - 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x33, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, - 0x4c, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x03, 0x54, 0x54, 0x4c, 0x12, 0x32, 0x0a, 0x14, 0x53, 0x75, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, - 0x15, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x65, - 0x66, 0x6f, 0x72, 0x65, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x15, 0x46, - 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x72, - 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x46, 0x61, 0x69, 0x6c, - 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, - 0x67, 0x12, 0x36, 0x0a, 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, - 0x6f, 0x72, 0x65, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x16, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, - 0x65, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x48, 0x54, 0x54, 0x50, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, - 0x6f, 0x78, 0x79, 0x48, 0x54, 0x54, 0x50, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x47, 0x52, 0x50, 0x43, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x78, - 0x79, 0x47, 0x52, 0x50, 0x43, 0x12, 0x61, 0x0a, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x4f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x69, - 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x44, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x96, 0x02, 0x0a, 0x25, 0x63, 0x6f, - 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x42, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 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, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xa2, 0x02, 0x04, 0x48, - 0x43, 0x49, 0x53, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xca, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x66, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x61, + 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x4f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x69, 0x0a, 0x0b, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x96, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, + 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x33, 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, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, + 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x53, 0xaa, + 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0xca, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xe2, 0x02, 0x2d, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 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, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x61, 0x6c, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 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, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/private/pbservice/healthcheck.proto b/proto/private/pbservice/healthcheck.proto index b3cbf050448b0..681cfae9754ee 100644 --- a/proto/private/pbservice/healthcheck.proto +++ b/proto/private/pbservice/healthcheck.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; @@ -66,6 +66,7 @@ message HealthCheckDefinition { string Body = 18; bool DisableRedirects = 22; string TCP = 5; + bool TCPUseTLS = 25; string UDP = 23; string OSService = 24; // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto @@ -117,6 +118,7 @@ message CheckType { string Body = 26; bool DisableRedirects = 31; string TCP = 8; + bool TCPUseTLS = 34; string UDP = 32; string OSService = 33; // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto diff --git a/proto/private/pbservice/ids.go b/proto/private/pbservice/ids.go index bac74d6f7e805..8ab248c3e8d5b 100644 --- a/proto/private/pbservice/ids.go +++ b/proto/private/pbservice/ids.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbservice diff --git a/proto/private/pbservice/ids_test.go b/proto/private/pbservice/ids_test.go index 9477bb8d9bb72..9a56604ee8c1e 100644 --- a/proto/private/pbservice/ids_test.go +++ b/proto/private/pbservice/ids_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbservice diff --git a/proto/private/pbservice/node.pb.go b/proto/private/pbservice/node.pb.go index 3d562fe31f716..7b8fa6a3345b7 100644 --- a/proto/private/pbservice/node.pb.go +++ b/proto/private/pbservice/node.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: diff --git a/proto/private/pbservice/node.proto b/proto/private/pbservice/node.proto index 6b81f0b6c06d3..85e82de7082ec 100644 --- a/proto/private/pbservice/node.proto +++ b/proto/private/pbservice/node.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; diff --git a/proto/private/pbservice/service.pb.go b/proto/private/pbservice/service.pb.go index 871b6a04118cd..13826aa752eaa 100644 --- a/proto/private/pbservice/service.pb.go +++ b/proto/private/pbservice/service.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: diff --git a/proto/private/pbservice/service.proto b/proto/private/pbservice/service.proto index b89f1717b17c1..4573a920a6eb8 100644 --- a/proto/private/pbservice/service.proto +++ b/proto/private/pbservice/service.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; diff --git a/proto/private/pbstorage/raft.pb.go b/proto/private/pbstorage/raft.pb.go index 6efa5c8f8fb10..8ae22a6aba912 100644 --- a/proto/private/pbstorage/raft.pb.go +++ b/proto/private/pbstorage/raft.pb.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // Code generated by protoc-gen-go. DO NOT EDIT. // versions: diff --git a/proto/private/pbstorage/raft.proto b/proto/private/pbstorage/raft.proto index ed7954a8690e5..1dbae409e28a3 100644 --- a/proto/private/pbstorage/raft.proto +++ b/proto/private/pbstorage/raft.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 syntax = "proto3"; diff --git a/proto/private/pbsubscribe/subscribe.go b/proto/private/pbsubscribe/subscribe.go index 918c3d298078b..53b7081245364 100644 --- a/proto/private/pbsubscribe/subscribe.go +++ b/proto/private/pbsubscribe/subscribe.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package pbsubscribe diff --git a/proto/private/pbsubscribe/subscribe.pb.go b/proto/private/pbsubscribe/subscribe.pb.go index 93dcf9c21c230..f71a855107c59 100644 --- a/proto/private/pbsubscribe/subscribe.pb.go +++ b/proto/private/pbsubscribe/subscribe.pb.go @@ -1,8 +1,8 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // -//Package event provides a service for subscribing to state change events. +// Package event provides a service for subscribing to state change events. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: diff --git a/proto/private/pbsubscribe/subscribe.proto b/proto/private/pbsubscribe/subscribe.proto index c327c92c7f024..37124b5d02770 100644 --- a/proto/private/pbsubscribe/subscribe.proto +++ b/proto/private/pbsubscribe/subscribe.proto @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 /* Package event provides a service for subscribing to state change events. diff --git a/proto/private/prototest/testing.go b/proto/private/prototest/testing.go index 32839a78aa809..28341012afa6d 100644 --- a/proto/private/prototest/testing.go +++ b/proto/private/prototest/testing.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package prototest @@ -13,12 +13,12 @@ type TestingT interface { Fatalf(string, ...any) } -func AssertDeepEqual(t TestingT, exp, got interface{}, opts ...cmp.Option) { +func AssertDeepEqual(t TestingT, x, y interface{}, opts ...cmp.Option) { t.Helper() opts = append(opts, protocmp.Transform()) - if diff := cmp.Diff(exp, got, opts...); diff != "" { + if diff := cmp.Diff(x, y, opts...); diff != "" { t.Fatalf("assertion failed: values are not equal\n--- expected\n+++ actual\n%v", diff) } } @@ -32,7 +32,6 @@ func AssertDeepEqual(t TestingT, exp, got interface{}, opts ...cmp.Option) { func AssertElementsMatch[V any]( t TestingT, listX, listY []V, opts ...cmp.Option, ) { - t.Helper() diff := diffElements(listX, listY, opts...) if diff != "" { t.Fatalf("assertion failed: slices do not have matching elements\n--- expected\n+++ actual\n%v", diff) @@ -101,5 +100,5 @@ func AssertContainsElement[V any](t TestingT, list []V, element V, opts ...cmp.O } } - t.Fatalf("assertion failed: list does not contain element\n--- list\n%+v\n--- element: %+v", list, element) + t.Fatalf("assertion failed: list does not contain element\n--- list\n%#v\n--- element: %#v", list, element) } diff --git a/proto/private/prototest/testing_test.go b/proto/private/prototest/testing_test.go index 2ee383baa1da3..22c1848821ddc 100644 --- a/proto/private/prototest/testing_test.go +++ b/proto/private/prototest/testing_test.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package prototest import ( diff --git a/sdk/LICENSE b/sdk/LICENSE deleted file mode 100644 index 7c5baa45e1c29..0000000000000 --- a/sdk/LICENSE +++ /dev/null @@ -1,365 +0,0 @@ -Copyright (c) 2020 HashiCorp, Inc. - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - diff --git a/sdk/iptables/iptables.go b/sdk/iptables/iptables.go index 32f089a6c9a82..5b965a6322ac1 100644 --- a/sdk/iptables/iptables.go +++ b/sdk/iptables/iptables.go @@ -149,7 +149,7 @@ func Setup(cfg Config) error { // Redirect remaining outbound traffic to Envoy. cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", ProxyOutputChain, "-j", ProxyOutputRedirectChain) - // We are using "insert" (-I) instead of "append" (-A) so the provided rules take precedence over default ones. + // We are using "insert" (-I) instead of "append" (-A) so the the provided rules take precedence over default ones. for _, outboundPort := range cfg.ExcludeOutboundPorts { cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-I", ProxyOutputChain, "-p", "tcp", "--dport", outboundPort, "-j", "RETURN") } diff --git a/sdk/testutil/context.go b/sdk/testutil/context.go index 47ff794c96c6d..257f205aa298e 100644 --- a/sdk/testutil/context.go +++ b/sdk/testutil/context.go @@ -5,14 +5,10 @@ package testutil import ( "context" + "testing" ) -type CleanerT interface { - Helper() - Cleanup(func()) -} - -func TestContext(t CleanerT) context.Context { +func TestContext(t *testing.T) context.Context { t.Helper() ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) diff --git a/sdk/testutil/retry/counter.go b/sdk/testutil/retry/counter.go deleted file mode 100644 index 96a37ab9d2fcf..0000000000000 --- a/sdk/testutil/retry/counter.go +++ /dev/null @@ -1,23 +0,0 @@ -package retry - -import "time" - -// Counter repeats an operation a given number of -// times and waits between subsequent operations. -type Counter struct { - Count int - Wait time.Duration - - count int -} - -func (r *Counter) Continue() bool { - if r.count == r.Count { - return false - } - if r.count > 0 { - time.Sleep(r.Wait) - } - r.count++ - return true -} diff --git a/sdk/testutil/retry/retry.go b/sdk/testutil/retry/retry.go index af468460d592a..ce0e4b6ecd2d6 100644 --- a/sdk/testutil/retry/retry.go +++ b/sdk/testutil/retry/retry.go @@ -53,8 +53,6 @@ type R struct { // and triggers t.FailNow() done bool output []string - - cleanups []func() } func (r *R) Logf(format string, args ...interface{}) { @@ -67,41 +65,6 @@ func (r *R) Log(args ...interface{}) { func (r *R) Helper() {} -// Cleanup register a function to be run to cleanup resources that -// were allocated during the retry attempt. These functions are executed -// after a retry attempt. If they panic, it will not stop further retry -// attempts but will be cause for the overall test failure. -func (r *R) Cleanup(fn func()) { - r.cleanups = append(r.cleanups, fn) -} - -func (r *R) runCleanup() { - - // Make sure that if a cleanup function panics, - // we still run the remaining cleanup functions. - defer func() { - err := recover() - if err != nil { - r.Stop(fmt.Errorf("error when performing test cleanup: %v", err)) - } - if len(r.cleanups) > 0 { - r.runCleanup() - } - }() - - for len(r.cleanups) > 0 { - var cleanup func() - if len(r.cleanups) > 0 { - last := len(r.cleanups) - 1 - cleanup = r.cleanups[last] - r.cleanups = r.cleanups[:last] - } - if cleanup != nil { - cleanup() - } - } -} - // runFailed is a sentinel value to indicate that the func itself // didn't panic, rather that `FailNow` was called. type runFailed struct{} @@ -227,7 +190,6 @@ func run(r Retryer, t Failer, f func(r *R)) { // run f(rr), but if recover yields a runFailed value, we know // FailNow was called. func() { - defer rr.runCleanup() defer func() { if p := recover(); p != nil && p != (runFailed{}) { panic(p) @@ -254,6 +216,22 @@ func DefaultFailer() *Timer { return &Timer{Timeout: 7 * time.Second, Wait: 25 * time.Millisecond} } +// ThirtySeconds repeats an operation for thirty seconds and waits 500ms in between. +// Best for known slower operations like waiting on eventually consistent state. +func ThirtySeconds() *Timer { + return &Timer{Timeout: 30 * time.Second, Wait: 500 * time.Millisecond} +} + +// TwoSeconds repeats an operation for two seconds and waits 25ms in between. +func TwoSeconds() *Timer { + return &Timer{Timeout: 2 * time.Second, Wait: 25 * time.Millisecond} +} + +// ThreeTimes repeats an operation three times and waits 25ms in between. +func ThreeTimes() *Counter { + return &Counter{Count: 3, Wait: 25 * time.Millisecond} +} + // Retryer provides an interface for repeating operations // until they succeed or an exit condition is met. type Retryer interface { @@ -261,3 +239,47 @@ type Retryer interface { // returns false to indicate retrying should stop. Continue() bool } + +// Counter repeats an operation a given number of +// times and waits between subsequent operations. +type Counter struct { + Count int + Wait time.Duration + + count int +} + +func (r *Counter) Continue() bool { + if r.count == r.Count { + return false + } + if r.count > 0 { + time.Sleep(r.Wait) + } + r.count++ + return true +} + +// Timer repeats an operation for a given amount +// of time and waits between subsequent operations. +type Timer struct { + Timeout time.Duration + Wait time.Duration + + // stop is the timeout deadline. + // TODO: Next()? + // Set on the first invocation of Next(). + stop time.Time +} + +func (r *Timer) Continue() bool { + if r.stop.IsZero() { + r.stop = time.Now().Add(r.Timeout) + return true + } + if time.Now().After(r.stop) { + return false + } + time.Sleep(r.Wait) + return true +} diff --git a/sdk/testutil/retry/retry_test.go b/sdk/testutil/retry/retry_test.go index 77bc2d4d9f96b..1f7eda7b31338 100644 --- a/sdk/testutil/retry/retry_test.go +++ b/sdk/testutil/retry/retry_test.go @@ -128,69 +128,6 @@ func TestRunWith(t *testing.T) { }) } -func TestCleanup(t *testing.T) { - t.Run("basic", func(t *testing.T) { - ft := &fakeT{} - cleanupsExecuted := 0 - RunWith(&Counter{Count: 2, Wait: time.Millisecond}, ft, func(r *R) { - r.Cleanup(func() { - cleanupsExecuted += 1 - }) - }) - - require.Equal(t, 0, ft.fails) - require.Equal(t, 1, cleanupsExecuted) - }) - t.Run("cleanup-panic-recovery", func(t *testing.T) { - ft := &fakeT{} - cleanupsExecuted := 0 - RunWith(&Counter{Count: 2, Wait: time.Millisecond}, ft, func(r *R) { - r.Cleanup(func() { - cleanupsExecuted += 1 - }) - - r.Cleanup(func() { - cleanupsExecuted += 1 - panic(fmt.Errorf("fake test error")) - }) - - r.Cleanup(func() { - cleanupsExecuted += 1 - }) - - // test is successful but should fail due to the cleanup panicing - }) - - require.Equal(t, 3, cleanupsExecuted) - require.Equal(t, 1, ft.fails) - require.Contains(t, ft.out[0], "fake test error") - }) - - t.Run("cleanup-per-retry", func(t *testing.T) { - ft := &fakeT{} - iter := 0 - cleanupsExecuted := 0 - RunWith(&Counter{Count: 3, Wait: time.Millisecond}, ft, func(r *R) { - if cleanupsExecuted != iter { - r.Stop(fmt.Errorf("cleanups not executed between retries")) - return - } - iter += 1 - - r.Cleanup(func() { - cleanupsExecuted += 1 - }) - - r.FailNow() - }) - - require.Equal(t, 3, cleanupsExecuted) - // ensure that r.Stop hadn't been called. If it was then we would - // have log output - require.Len(t, ft.out, 0) - }) -} - type fakeT struct { fails int out []string diff --git a/sdk/testutil/retry/timer.go b/sdk/testutil/retry/timer.go deleted file mode 100644 index 16433e9ec7b02..0000000000000 --- a/sdk/testutil/retry/timer.go +++ /dev/null @@ -1,43 +0,0 @@ -package retry - -import "time" - -// ThirtySeconds repeats an operation for thirty seconds and waits 500ms in between. -// Best for known slower operations like waiting on eventually consistent state. -func ThirtySeconds() *Timer { - return &Timer{Timeout: 30 * time.Second, Wait: 500 * time.Millisecond} -} - -// TwoSeconds repeats an operation for two seconds and waits 25ms in between. -func TwoSeconds() *Timer { - return &Timer{Timeout: 2 * time.Second, Wait: 25 * time.Millisecond} -} - -// ThreeTimes repeats an operation three times and waits 25ms in between. -func ThreeTimes() *Counter { - return &Counter{Count: 3, Wait: 25 * time.Millisecond} -} - -// Timer repeats an operation for a given amount -// of time and waits between subsequent operations. -type Timer struct { - Timeout time.Duration - Wait time.Duration - - // stop is the timeout deadline. - // TODO: Next()? - // Set on the first invocation of Next(). - stop time.Time -} - -func (r *Timer) Continue() bool { - if r.stop.IsZero() { - r.stop = time.Now().Add(r.Timeout) - return true - } - if time.Now().After(r.stop) { - return false - } - time.Sleep(r.Wait) - return true -} diff --git a/sdk/testutil/server.go b/sdk/testutil/server.go index 148fb03d6a956..a20f95123aaba 100644 --- a/sdk/testutil/server.go +++ b/sdk/testutil/server.go @@ -131,7 +131,6 @@ type TestServerConfig struct { ReturnPorts func() `json:"-"` Audit *TestAuditConfig `json:"audit,omitempty"` Version string `json:"version,omitempty"` - Experiments []string `json:"experiments,omitempty"` } type TestACLs struct { diff --git a/sentinel/evaluator.go b/sentinel/evaluator.go index fd609fff90097..d37a82704e616 100644 --- a/sentinel/evaluator.go +++ b/sentinel/evaluator.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package sentinel diff --git a/sentinel/scope.go b/sentinel/scope.go index 4a6a87e146ab3..7f2fb5d721ef5 100644 --- a/sentinel/scope.go +++ b/sentinel/scope.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package sentinel diff --git a/sentinel/sentinel_ce.go b/sentinel/sentinel_ce.go index 9b21607c431b4..fc688bcb933ec 100644 --- a/sentinel/sentinel_ce.go +++ b/sentinel/sentinel_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/service_os/service.go b/service_os/service.go index 8a23c093475ae..cba71b23acf92 100644 --- a/service_os/service.go +++ b/service_os/service.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package service_os diff --git a/service_os/service_windows.go b/service_os/service_windows.go index 6a9ca4386a683..0ff9f2e7c9688 100644 --- a/service_os/service_windows.go +++ b/service_os/service_windows.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build windows // +build windows diff --git a/snapshot/archive.go b/snapshot/archive.go index 38aad441bf0ab..3560e0ac2319e 100644 --- a/snapshot/archive.go +++ b/snapshot/archive.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // The archive utilities manage the internal format of a snapshot, which is a // tar file with the following contents: diff --git a/snapshot/archive_test.go b/snapshot/archive_test.go index 74148b84e8f60..d7568edb80ce8 100644 --- a/snapshot/archive_test.go +++ b/snapshot/archive_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package snapshot diff --git a/snapshot/snapshot.go b/snapshot/snapshot.go index f09f8870e3253..a1deee9153dc4 100644 --- a/snapshot/snapshot.go +++ b/snapshot/snapshot.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 // snapshot manages the interactions between Consul and Raft in order to take // and restore snapshots for disaster recovery. The internal format of a diff --git a/snapshot/snapshot_test.go b/snapshot/snapshot_test.go index 4e9701360dfa9..d59061e9eab61 100644 --- a/snapshot/snapshot_test.go +++ b/snapshot/snapshot_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package snapshot diff --git a/test-integ/README.md b/test-integ/README.md deleted file mode 100644 index ebc611efa2bc0..0000000000000 --- a/test-integ/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# test-integ - -Go integration tests for consul. `/test/integration` also holds integration tests; they need migrating. \ No newline at end of file diff --git a/test-integ/go.mod b/test-integ/go.mod deleted file mode 100644 index 76c91af83ca96..0000000000000 --- a/test-integ/go.mod +++ /dev/null @@ -1,246 +0,0 @@ -module github.com/hashicorp/consul/test-integ - -go 1.20 - -require ( - github.com/hashicorp/consul/api v1.24.0 - github.com/hashicorp/consul/sdk v0.14.1 - github.com/hashicorp/consul/test/integration/consul-container v0.0.0-20230628201853-bdf4fad7c5a5 - github.com/hashicorp/consul/testing/deployer v0.0.0-00010101000000-000000000000 - github.com/hashicorp/go-cleanhttp v0.5.2 - github.com/itchyny/gojq v0.12.13 - github.com/mitchellh/copystructure v1.2.0 - github.com/stretchr/testify v1.8.4 -) - -require ( - cloud.google.com/go/compute v1.20.1 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.1 // indirect - dario.cat/mergo v1.0.0 // indirect - fortio.org/dflag v1.5.2 // indirect - fortio.org/fortio v1.54.0 // indirect - fortio.org/log v1.3.0 // indirect - fortio.org/sets v1.0.2 // indirect - fortio.org/version v1.0.2 // indirect - github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/DataDog/datadog-go v4.8.2+incompatible // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/agext/levenshtein v1.2.1 // indirect - github.com/aliyun/alibaba-cloud-sdk-go v1.62.156 // indirect - github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect - github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e // indirect - github.com/armon/go-metrics v0.4.1 // indirect - github.com/armon/go-radix v1.0.0 // indirect - github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect - github.com/avast/retry-go v3.0.0+incompatible // indirect - github.com/aws/aws-sdk-go v1.44.289 // indirect - github.com/benbjohnson/immutable v0.4.0 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/boltdb/bolt v1.3.1 // indirect - github.com/cenkalti/backoff/v3 v3.0.0 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible // indirect - github.com/circonus-labs/circonusllhist v0.1.3 // indirect - github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect - github.com/containerd/containerd v1.7.3 // indirect - github.com/coreos/etcd v3.3.27+incompatible // indirect - github.com/coreos/go-oidc v2.1.0+incompatible // indirect - github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect - github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v24.0.5+incompatible // indirect - github.com/docker/go-connections v0.4.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/emicklei/go-restful/v3 v3.10.1 // indirect - github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f // indirect - github.com/envoyproxy/protoc-gen-validate v0.10.1 // indirect - github.com/evanphx/json-patch v4.12.0+incompatible // indirect - github.com/fatih/color v1.14.1 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-jose/go-jose/v3 v3.0.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/analysis v0.21.4 // indirect - github.com/go-openapi/errors v0.20.3 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.20.0 // indirect - github.com/go-openapi/loads v0.21.2 // indirect - github.com/go-openapi/runtime v0.25.0 // indirect - github.com/go-openapi/spec v0.20.8 // indirect - github.com/go-openapi/strfmt v0.21.3 // indirect - github.com/go-openapi/swag v0.22.3 // indirect - github.com/go-openapi/validate v0.22.1 // indirect - github.com/go-ozzo/ozzo-validation v3.6.0+incompatible // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/google/btree v1.0.1 // indirect - github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.9 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/s2a-go v0.1.4 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/googleapis/gax-go/v2 v2.11.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 // indirect - github.com/hashicorp/consul v0.0.0-00010101000000-000000000000 // indirect - github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706 // indirect - github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69 // indirect - github.com/hashicorp/consul/envoyextensions v0.4.1 // indirect - github.com/hashicorp/consul/proto-public v0.4.1 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-bexpr v0.1.2 // indirect - github.com/hashicorp/go-connlimit v0.3.0 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect - github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/go-memdb v1.3.4 // indirect - github.com/hashicorp/go-msgpack v1.1.5 // indirect - github.com/hashicorp/go-msgpack/v2 v2.0.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.5 // indirect - github.com/hashicorp/go-raftchunking v0.7.0 // indirect - github.com/hashicorp/go-retryablehttp v0.6.7 // indirect - github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 // indirect - github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 // indirect - github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect - github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect - github.com/hashicorp/go-sockaddr v1.0.2 // indirect - github.com/hashicorp/go-syslog v1.0.0 // indirect - github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/go-version v1.2.1 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hashicorp/hcl/v2 v2.16.2 // indirect - github.com/hashicorp/hcp-scada-provider v0.2.3 // indirect - github.com/hashicorp/hcp-sdk-go v0.61.0 // indirect - github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038 // indirect - github.com/hashicorp/memberlist v0.5.0 // indirect - github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0 // indirect - github.com/hashicorp/raft v1.5.0 // indirect - github.com/hashicorp/raft-autopilot v0.1.6 // indirect - github.com/hashicorp/raft-boltdb/v2 v2.2.2 // indirect - github.com/hashicorp/raft-wal v0.3.0 // indirect - github.com/hashicorp/serf v0.10.1 // indirect - github.com/hashicorp/vault-plugin-auth-alicloud v0.14.0 // indirect - github.com/hashicorp/vault/api v1.8.3 // indirect - github.com/hashicorp/vault/api/auth/gcp v0.3.0 // indirect - github.com/hashicorp/vault/sdk v0.7.0 // indirect - github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect - github.com/imdario/mergo v0.3.15 // indirect - github.com/itchyny/timefmt-go v0.1.5 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.16.7 // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/miekg/dns v1.1.50 // indirect - github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.0 // indirect - github.com/mitchellh/go-wordwrap v1.0.0 // indirect - github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452 // indirect - github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/mitchellh/pointerstructure v1.2.1 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/moby/patternmatcher v0.5.0 // indirect - github.com/moby/sys/sequential v0.5.0 // indirect - github.com/moby/term v0.5.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/morikuni/aec v1.0.0 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/oklog/run v1.0.0 // indirect - github.com/oklog/ulid v1.3.1 // indirect - github.com/oklog/ulid/v2 v2.1.0 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc4 // indirect - github.com/opencontainers/runc v1.1.8 // indirect - github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect - github.com/otiai10/copy v1.10.0 // indirect - github.com/patrickmn/go-cache v2.1.0+incompatible // indirect - github.com/pierrec/lz4 v2.5.2+incompatible // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect - github.com/prometheus/client_golang v1.14.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.39.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect - github.com/rboyer/safeio v0.2.3 // indirect - github.com/ryanuber/go-glob v1.0.0 // indirect - github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect - github.com/segmentio/fasthash v1.0.3 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect - github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 // indirect - github.com/testcontainers/testcontainers-go v0.22.0 // indirect - github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect - github.com/zclconf/go-cty v1.12.1 // indirect - go.etcd.io/bbolt v1.3.7 // indirect - go.mongodb.org/mongo-driver v1.11.0 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel v1.16.0 // indirect - go.opentelemetry.io/otel/metric v1.16.0 // indirect - go.opentelemetry.io/otel/sdk v1.16.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.39.0 // indirect - go.opentelemetry.io/otel/trace v1.16.0 // indirect - go.opentelemetry.io/proto/otlp v0.19.0 // indirect - go.uber.org/atomic v1.9.0 // indirect - golang.org/x/crypto v0.12.0 // indirect - golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.14.0 // indirect - golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.11.0 // indirect - golang.org/x/term v0.11.0 // indirect - golang.org/x/text v0.12.0 // indirect - golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.11.1 // indirect - google.golang.org/api v0.126.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 // indirect - google.golang.org/grpc v1.57.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/ini.v1 v1.66.2 // indirect - gopkg.in/square/go-jose.v2 v2.5.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.26.2 // indirect - k8s.io/apimachinery v0.26.2 // indirect - k8s.io/client-go v0.26.2 // indirect - k8s.io/klog/v2 v2.90.1 // indirect - k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect - k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect -) - -replace ( - github.com/hashicorp/consul => ../ - github.com/hashicorp/consul/api => ../api - github.com/hashicorp/consul/envoyextensions => ../envoyextensions - github.com/hashicorp/consul/proto-public => ../proto-public - github.com/hashicorp/consul/sdk => ../sdk - github.com/hashicorp/consul/test/integration/consul-container => ../test/integration/consul-container - github.com/hashicorp/consul/testing/deployer => ../testing/deployer -) diff --git a/test-integ/go.sum b/test-integ/go.sum deleted file mode 100644 index e662768b13d0b..0000000000000 --- a/test-integ/go.sum +++ /dev/null @@ -1,1336 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg= -cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y= -cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -fortio.org/assert v1.1.4 h1:Za1RaG+OjsTMpQS3J3UCvTF6wc4+IOHCz+jAOU37Y4o= -fortio.org/dflag v1.5.2 h1:F9XVRj4Qr2IbJP7BMj7XZc9wB0Q/RZ61Ool+4YPVad8= -fortio.org/dflag v1.5.2/go.mod h1:ppb/A8u+KKg+qUUYZNYuvRnXuVb8IsdHb/XGzsmjkN8= -fortio.org/fortio v1.54.0 h1:2jn8yTd6hcIEoKY4CjI0lI6XxTWVxsMYF2bMiWOmv+Y= -fortio.org/fortio v1.54.0/go.mod h1:SRaZbikL31UoAkw0On2hwpvHrQ0rRVnsAz3UGVNvMRw= -fortio.org/log v1.3.0 h1:bESPvuQGKejw7rrx41Sg3GoF+tsrB7oC08PxBs5/AM0= -fortio.org/log v1.3.0/go.mod h1:u/8/2lyczXq52aT5Nw6reD+3cR6m/EbS2jBiIYhgiTU= -fortio.org/sets v1.0.2 h1:gSWZFg9rgzl1zJfI/93lDJKBFw8WZ3Uxe3oQ5uDM4T4= -fortio.org/sets v1.0.2/go.mod h1:xVjulHr0FhlmReSymI+AhDtQ4FgjiazQ3JmuNpYFMs8= -fortio.org/version v1.0.2 h1:8NwxdX58aoeKx7T5xAPO0xlUu1Hpk42nRz5s6e6eKZ0= -fortio.org/version v1.0.2/go.mod h1:2JQp9Ax+tm6QKiGuzR5nJY63kFeANcgrZ0osoQFDVm0= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/datadog-go v4.8.2+incompatible h1:qbcKSx29aBLD+5QLvlQZlGmRMF/FfGqFLFev/1TDzRo= -github.com/DataDog/datadog-go v4.8.2+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8= -github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.156 h1:K4N91T1+RlSlx+t2dujeDviy4ehSGVjEltluDgmeHS4= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.156/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= -github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= -github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= -github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= -github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= -github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.44.289 h1:5CVEjiHFvdiVlKPBzv0rjG4zH/21W/onT18R5AH/qx0= -github.com/aws/aws-sdk-go v1.44.289/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/benbjohnson/immutable v0.4.0 h1:CTqXbEerYso8YzVPxmWxh2gnoRQbbB9X1quUC8+vGZA= -github.com/benbjohnson/immutable v0.4.0/go.mod h1:iAr8OjJGLnLmVUr9MZ/rz4PWUy6Ouc2JLYuMArmvAJM= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= -github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA= -github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/containerd/containerd v1.7.3 h1:cKwYKkP1eTj54bP3wCdXXBymmKRQMrWjkLSWZZJDa8o= -github.com/containerd/containerd v1.7.3/go.mod h1:32FOM4/O0RkNg7AjQj3hDzN9cUGtu+HMvaKUNiqCZB8= -github.com/coreos/etcd v3.3.27+incompatible h1:QIudLb9KeBsE5zyYxd1mjzRSkzLg9Wf9QlRwFgd6oTA= -github.com/coreos/etcd v3.3.27+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf h1:GOPo6vn/vTN+3IwZBvXX0y5doJfSC7My0cdzelyOCsQ= -github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= -github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= -github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= -github.com/frankban/quicktest v1.13.0 h1:yNZif1OkDfNoDfb9zZa9aXIpejNR4F23Wely0c+Qdqk= -github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= -github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= -github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc= -github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo= -github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.3 h1:rz6kiC84sqNQoqrtulzaL/VERgkoCyB6WdEkc2ujzUc= -github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= -github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= -github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= -github.com/go-openapi/runtime v0.25.0 h1:7yQTCdRbWhX8vnIjdzU8S00tBYf7Sg71EBeorlPHvhc= -github.com/go-openapi/runtime v0.25.0/go.mod h1:Ux6fikcHXyyob6LNWxtE96hWwjBPYF0DXgVFuMTneOs= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/spec v0.20.8 h1:ubHmXNY3FCIOinT8RNrrPfGc9t7I1qhPtdOGoG2AxRU= -github.com/go-openapi/spec v0.20.8/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= -github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/strfmt v0.21.3 h1:xwhj5X6CjXEZZHMWy1zKJxvW9AfHC9pkyUjLvHtKG7o= -github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= -github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= -github.com/go-ozzo/ozzo-validation v3.6.0+incompatible h1:msy24VGS42fKO9K1vLz82/GeYW1cILu7Nuuj1N3BBkE= -github.com/go-ozzo/ozzo-validation v3.6.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= -github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= -github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= -github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= -github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= -github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2 h1:AtvtonGEH/fZK0XPNNBdB6swgy7Iudfx88wzyIpwqJ8= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4= -github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjdKDqyr/2L+f6U12Fk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= -github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706 h1:1ZEjnveDe20yFa6lSkfdQZm5BR/b271n0MsB5R2L3us= -github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706/go.mod h1:1Cs8FlmD1BfSQXJGcFLSV5FuIx1AbJP+EJGdxosoS2g= -github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69 h1:wzWurXrxfSyG1PHskIZlfuXlTSCj1Tsyatp9DtaasuY= -github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69/go.mod h1:svUZZDvotY8zTODknUePc6mZ9pX8nN0ViGwWcUSOBEA= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-bexpr v0.1.2 h1:ijMXI4qERbzxbCnkxmfUtwMyjrrk3y+Vt0MxojNCbBs= -github.com/hashicorp/go-bexpr v0.1.2/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-connlimit v0.3.0 h1:oAojHGjFxUTTTA8c5XXnDqWJ2HLuWbDiBPTpWvNzvqM= -github.com/hashicorp/go-connlimit v0.3.0/go.mod h1:OUj9FGL1tPIhl/2RCfzYHrIiWj+VVPGNyVPnUX8AqS0= -github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= -github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.0/go.mod h1:xvb32K2keAc+R8DSFG2IwDcydK9DBQE+fGA5fsw6hSk= -github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c= -github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs= -github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4= -github.com/hashicorp/go-msgpack/v2 v2.0.0 h1:c1fiLq1LNghmLOry1ipGhvLDi+/zEoaEP2JrE1oFJ9s= -github.com/hashicorp/go-msgpack/v2 v2.0.0/go.mod h1:JIxYkkFJRDDRSoWQBSh7s9QAVThq+82iWmUpmE4jKak= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= -github.com/hashicorp/go-plugin v1.4.5 h1:oTE/oQR4eghggRg8VY7PAz3dr++VwDNBGCcOfIvHpBo= -github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= -github.com/hashicorp/go-raftchunking v0.7.0 h1:APNMnCXmTOhumkFv/GpJIbq7HteWF7EnGZ3875lRN0Y= -github.com/hashicorp/go-raftchunking v0.7.0/go.mod h1:Dg/eBOaJzE0jYKNwNLs5IA5j0OSmL5HoCUiMy3mDmrI= -github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-retryablehttp v0.6.7 h1:8/CAEZt/+F7kR7GevNHulKkUjLht3CPmn7egmhieNKo= -github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= -github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 h1:W9WN8p6moV1fjKLkeqEgkAMu5rauy9QeYDAmIaPuuiA= -github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6/go.mod h1:MpCPSPGLDILGb4JMm94/mMi3YysIqsXzGCzkEZjcjXg= -github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 h1:cCRo8gK7oq6A2L6LICkUZ+/a5rLiRXFMf1Qd4xSwxTc= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.1/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= -github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo= -github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= -github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= -github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= -github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= -github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= -github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= -github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/hcl/v2 v2.16.2 h1:mpkHZh/Tv+xet3sy3F9Ld4FyI2tUpWe9x3XtPx9f1a0= -github.com/hashicorp/hcl/v2 v2.16.2/go.mod h1:JRmR89jycNkrrqnMmvPDMd56n1rQJ2Q6KocSLCMCXng= -github.com/hashicorp/hcp-scada-provider v0.2.3 h1:AarYR+/Pcv+cMvPdAlb92uOBmZfEH6ny4+DT+4NY2VQ= -github.com/hashicorp/hcp-scada-provider v0.2.3/go.mod h1:ZFTgGwkzNv99PLQjTsulzaCplCzOTBh0IUQsPKzrQFo= -github.com/hashicorp/hcp-sdk-go v0.61.0 h1:x4hJ8SlLI5WCE8Uzcu4q5jfdOEz/hFxfUkhAdoFdzSg= -github.com/hashicorp/hcp-sdk-go v0.61.0/go.mod h1:xP7wmWAmdMxs/7+ovH3jZn+MCDhHRj50Rn+m7JIY3Ck= -github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038 h1:n9J0rwVWXDpNd5iZnwY7w4WZyq53/rROeI7OVvLW8Ok= -github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= -github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= -github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= -github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0 h1:kBpVVl1sl3MaSrs97e0+pDQhSrqJv9gVbSUrPpVfl1w= -github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0/go.mod h1:6pdNz0vo0mF0GvhwDG56O3N18qBrAz/XRIcfINfTbwo= -github.com/hashicorp/raft v1.1.0/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= -github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= -github.com/hashicorp/raft v1.3.11/go.mod h1:J8naEwc6XaaCfts7+28whSeRvCqTd6e20BlCU3LtEO4= -github.com/hashicorp/raft v1.5.0 h1:uNs9EfJ4FwiArZRxxfd/dQ5d33nV31/CdCHArH89hT8= -github.com/hashicorp/raft v1.5.0/go.mod h1:pKHB2mf/Y25u3AHNSXVRv+yT+WAnmeTX0BwVppVQV+M= -github.com/hashicorp/raft-autopilot v0.1.6 h1:C1q3RNF2FfXNZfHWbvVAu0QixaQK8K5pX4O5lh+9z4I= -github.com/hashicorp/raft-autopilot v0.1.6/go.mod h1:Af4jZBwaNOI+tXfIqIdbcAnh/UyyqIMj/pOISIfhArw= -github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= -github.com/hashicorp/raft-boltdb v0.0.0-20210409134258-03c10cc3d4ea/go.mod h1:qRd6nFJYYS6Iqnc/8HcUmko2/2Gw8qTFEmxDLii6W5I= -github.com/hashicorp/raft-boltdb v0.0.0-20220329195025-15018e9b97e0 h1:CO8dBMLH6dvE1jTn/30ZZw3iuPsNfajshWoJTnVc5cc= -github.com/hashicorp/raft-boltdb/v2 v2.2.2 h1:rlkPtOllgIcKLxVT4nutqlTH2NRFn+tO1wwZk/4Dxqw= -github.com/hashicorp/raft-boltdb/v2 v2.2.2/go.mod h1:N8YgaZgNJLpZC+h+by7vDu5rzsRgONThTEeUS3zWbfY= -github.com/hashicorp/raft-wal v0.3.0 h1:Mi6RPoRbsxIIYZryI+bSTXHD97Ua6rIYO51ibYV9bkY= -github.com/hashicorp/raft-wal v0.3.0/go.mod h1:A6vP5o8hGOs1LHfC1Okh9xPwWDcmb6Vvuz/QyqUXlOE= -github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= -github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/hashicorp/vault-plugin-auth-alicloud v0.14.0 h1:O6tNk0s/arubLUbLeCyaRs5xGo9VwmbQazISY/BfPK4= -github.com/hashicorp/vault-plugin-auth-alicloud v0.14.0/go.mod h1:We3fJplmALwK1VpjwrLuXr/4QCQHYMdnXLHmLUU6Ntg= -github.com/hashicorp/vault/api v1.8.0/go.mod h1:uJrw6D3y9Rv7hhmS17JQC50jbPDAZdjZoTtrCCxxs7E= -github.com/hashicorp/vault/api v1.8.3 h1:cHQOLcMhBR+aVI0HzhPxO62w2+gJhIrKguQNONPzu6o= -github.com/hashicorp/vault/api v1.8.3/go.mod h1:4g/9lj9lmuJQMtT6CmVMHC5FW1yENaVv+Nv4ZfG8fAg= -github.com/hashicorp/vault/api/auth/gcp v0.3.0 h1:taum+3pCmOXnNgEKHlQbmgXmKw5daWHk7YJrLPP/w8g= -github.com/hashicorp/vault/api/auth/gcp v0.3.0/go.mod h1:gnNBFOASYUaFunedTHOzdir7vKcHL3skWBUzEn263bo= -github.com/hashicorp/vault/sdk v0.6.0/go.mod h1:+DRpzoXIdMvKc88R4qxr+edwy/RvH5QK8itmxLiDHLc= -github.com/hashicorp/vault/sdk v0.7.0 h1:2pQRO40R1etpKkia5fb4kjrdYMx3BHklPxl1pxpxDHg= -github.com/hashicorp/vault/sdk v0.7.0/go.mod h1:KyfArJkhooyba7gYCKSq8v66QdqJmnbAxtV/OX1+JTs= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I= -github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/itchyny/gojq v0.12.13 h1:IxyYlHYIlspQHHTE0f3cJF0NKDMfajxViuhBLnHd/QU= -github.com/itchyny/gojq v0.12.13/go.mod h1:JzwzAqenfhrPUuwbmEz3nu3JQmFLlQTQMUcOdnu/Sf4= -github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE= -github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= -github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= -github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= -github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= -github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= -github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.14.0 h1:/x0XQ6h+3U3nAyk1yx+bHPURrKa9sVVvYbuqZ7pIAtI= -github.com/mitchellh/go-testing-interface v1.14.0/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= -github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452 h1:hOY53G+kBFhbYFpRVxHl5eS7laP6B1+Cq+Z9Dry1iMU= -github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= -github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= -github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= -github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= -github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= -github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= -github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= -github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs= -github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= -github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.1.8 h1:zICRlc+C1XzivLc3nzE+cbJV4LIi8tib6YG0MqC6OqA= -github.com/opencontainers/runc v1.1.8/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= -github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= -github.com/otiai10/copy v1.10.0 h1:znyI7l134wNg/wDktoVQPxPkgvhDfGCYUasey+h0rDQ= -github.com/otiai10/copy v1.10.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= -github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= -github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= -github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI= -github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= -github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/rboyer/safeio v0.2.3 h1:gUybicx1kp8nuM4vO0GA5xTBX58/OBd8MQuErBfDxP8= -github.com/rboyer/safeio v0.2.3/go.mod h1:d7RMmt7utQBJZ4B7f0H/cU/EdZibQAU1Y8NWepK2dS8= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= -github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= -github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= -github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= -github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 h1:xzABM9let0HLLqFypcxvLmlvEciCHL7+Lv+4vwZqecI= -github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569/go.mod h1:2Ly+NIftZN4de9zRmENdYbvPQeaVIYKWpLFStLFEBgI= -github.com/testcontainers/testcontainers-go v0.22.0 h1:hOK4NzNu82VZcKEB1aP9LO1xYssVFMvlfeuDW9JMmV0= -github.com/testcontainers/testcontainers-go v0.22.0/go.mod h1:k0YiPa26xJCRUbUkYqy5rY6NGvSbVCeUBXCvucscBR4= -github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= -github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= -github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zclconf/go-cty v1.12.1 h1:PcupnljUm9EIvbgSHQnHhUr3fO6oFmkOrvs2BAFNXXY= -github.com/zclconf/go-cty v1.12.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= -go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= -go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= -go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE= -go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= -go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= -go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= -go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= -go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= -go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= -go.opentelemetry.io/otel/sdk/metric v0.39.0 h1:Kun8i1eYf48kHH83RucG93ffz0zGV1sh46FAScOTuDI= -go.opentelemetry.io/otel/sdk/metric v0.39.0/go.mod h1:piDIRgjcK7u0HCL5pCA4e74qpK/jk3NiUoAHATVAmiI= -go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= -go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b h1:r+vk0EmXNmekl0S0BascoeeoHk/L7wmaW2QF90K+kYI= -golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.11.1 h1:ojD5zOW8+7dOGzdnNgersm8aPfcDjhMp12UfG93NIMc= -golang.org/x/tools v0.11.1/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.126.0 h1:q4GJq+cAdMAC7XP7njvQ4tvohGLiSlytuL4BQxbIZ+o= -google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e h1:xIXmWJ303kJCuogpj0bHq+dcjcZHU+XFyc1I0Yl9cRg= -google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:0ggbjUrZYpy1q+ANUS30SEoGZ53cdfwtbuG7Ptgy108= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 h1:eSaPbMR4T7WfH9FvABk36NBMacoTUKdWCvV0dx+KfOg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I= -google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= -gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= -gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.26.2 h1:dM3cinp3PGB6asOySalOZxEG4CZ0IAdJsrYZXE/ovGQ= -k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU= -k8s.io/apimachinery v0.26.2 h1:da1u3D5wfR5u2RpLhE/ZtZS2P7QvDgLZTi9wrNZl/tQ= -k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= -k8s.io/client-go v0.26.2 h1:s1WkVujHX3kTp4Zn4yGNFK+dlDXy1bAAkIl+cFAiuYI= -k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU= -k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= -k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk= -k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/test-integ/peering_commontopo/README.md b/test-integ/peering_commontopo/README.md deleted file mode 100644 index 96466bb29b86f..0000000000000 --- a/test-integ/peering_commontopo/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# CONSUL PEERING COMMON TOPOLOGY TESTS - -These peering tests all use a `commonTopo` (read: "common topology") to enable sharing a deployment of a Consul. Sharing a deployment of Consul cuts down on setup time. - -To run these tests, you will need to have docker installed. Next, make sure that you have all the required consul containers built: - -``` -make test-compat-integ-setup -``` - -## Non-Shared CommonTopo Tests - -The tests in question are designed in a manner that modifies the topology. As a result, it is not possible to share the testing environment across these tests. - -## Shared CommonTopo Tests - -The tests in question are designed in a manner that does not modify the topology in any way that would interfere with other tests. As a result, it is possible to share the testing environment across these tests. - -To run all consul peering tests with no shared topology, run the following command: - -``` -cd /path/to/peering_commontopo -go test -timeout=10m -v -no-share-topo . -``` - -To run all peering tests with shared topology only: - -``` -cd /path/to/peering_commontopo -go test -timeout=10m -run '^TestSuitesOnSharedTopo' -v . -``` - -To run individual peering topology tests: - -``` -cd /path/to/peering_commontopo -go test -timeout=10m -run '^TestSuiteExample' -v -no-share-topo . -``` - -## Local Development and Testing - -If writing tests for peering with no shared topology, this recommendation does not apply. The following methods below not necessarily need to be implmented. For shared topology tests, all the methods in the `sharedTopoSuite` interface must be implemented. - -- `testName()` prepends the test suite name to each test in the test suite. -- `setup()` phase must ensure that any resources added to the topology cannot interfere with other tests. Principally by prefixing. -- `test()` phase must be "passive" and not mutate the topology in any way that would interfere with other tests. - -Common topology peering tests are defined in the [test-integ/peering_commontopo/](/test-integ/peering_commontopo/) directory and new peering integration tests should always be added to this location. Adding integration tests that does not modify the topology should always start by invoking - -```go -runShareableSuites(t, testSuiteExample) -``` - -else - -```go -func TestSuiteExample(t *testing.T) { - ct := NewCommonTopo(t) - s := &testSuiteExample{} - s.setup(t, ct) - ct.Launch(t) - s.test(t, ct) -} -``` - -Some of these tests *do* mutate in their `test()` phase, and while they use `commonTopo` for the purpose of code sharing, they are not included in the "shared topo" tests in `sharedtopology_test.go`. diff --git a/test-integ/peering_commontopo/ac1_basic_test.go b/test-integ/peering_commontopo/ac1_basic_test.go deleted file mode 100644 index 85aaee4e6b55b..0000000000000 --- a/test-integ/peering_commontopo/ac1_basic_test.go +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package peering - -import ( - "fmt" - "testing" - - "github.com/hashicorp/consul/testing/deployer/topology" - - "github.com/hashicorp/consul/api" -) - -type ac1BasicSuite struct { - // inputs - DC string - Peer string - - // test points - sidServerHTTP topology.ServiceID - sidServerTCP topology.ServiceID - nodeServerHTTP topology.NodeID - nodeServerTCP topology.NodeID - - // 1.1 - sidClientTCP topology.ServiceID - nodeClientTCP topology.NodeID - - // 1.2 - sidClientHTTP topology.ServiceID - nodeClientHTTP topology.NodeID - - upstreamHTTP *topology.Upstream - upstreamTCP *topology.Upstream -} - -var ac1BasicSuites []sharedTopoSuite = []sharedTopoSuite{ - &ac1BasicSuite{DC: "dc1", Peer: "dc2"}, - &ac1BasicSuite{DC: "dc2", Peer: "dc1"}, -} - -func TestAC1Basic(t *testing.T) { - runShareableSuites(t, ac1BasicSuites) -} - -func (s *ac1BasicSuite) testName() string { - return fmt.Sprintf("ac1 basic %s->%s", s.DC, s.Peer) -} - -// creates clients in s.DC and servers in s.Peer -func (s *ac1BasicSuite) setup(t *testing.T, ct *commonTopo) { - clu := ct.ClusterByDatacenter(t, s.DC) - peerClu := ct.ClusterByDatacenter(t, s.Peer) - - partition := "default" - peer := LocalPeerName(peerClu, "default") - cluPeerName := LocalPeerName(clu, "default") - const prefix = "ac1-" - - tcpServerSID := topology.ServiceID{ - Name: prefix + "server-tcp", - Partition: partition, - } - httpServerSID := topology.ServiceID{ - Name: prefix + "server-http", - Partition: partition, - } - upstreamHTTP := &topology.Upstream{ - ID: topology.ServiceID{ - Name: httpServerSID.Name, - Partition: partition, - }, - LocalPort: 5001, - Peer: peer, - } - upstreamTCP := &topology.Upstream{ - ID: topology.ServiceID{ - Name: tcpServerSID.Name, - Partition: partition, - }, - LocalPort: 5000, - Peer: peer, - } - - // Make clients which have server upstreams - setupClientServiceAndConfigs := func(protocol string) (serviceExt, *topology.Node) { - sid := topology.ServiceID{ - Name: prefix + "client-" + protocol, - Partition: partition, - } - svc := serviceExt{ - Service: NewFortioServiceWithDefaults( - clu.Datacenter, - sid, - func(s *topology.Service) { - s.Upstreams = []*topology.Upstream{ - upstreamTCP, - upstreamHTTP, - } - }, - ), - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: sid.Name, - Partition: ConfigEntryPartition(sid.Partition), - Protocol: protocol, - UpstreamConfig: &api.UpstreamConfiguration{ - Defaults: &api.UpstreamConfig{ - MeshGateway: api.MeshGatewayConfig{ - Mode: api.MeshGatewayModeLocal, - }, - }, - }, - }, - } - - node := ct.AddServiceNode(clu, svc) - - return svc, node - } - tcpClient, tcpClientNode := setupClientServiceAndConfigs("tcp") - httpClient, httpClientNode := setupClientServiceAndConfigs("http") - - httpServer := serviceExt{ - Service: NewFortioServiceWithDefaults( - peerClu.Datacenter, - httpServerSID, - nil, - ), - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: httpServerSID.Name, - Partition: ConfigEntryPartition(httpServerSID.Partition), - Protocol: "http", - }, - Exports: []api.ServiceConsumer{{Peer: cluPeerName}}, - Intentions: &api.ServiceIntentionsConfigEntry{ - Kind: api.ServiceIntentions, - Name: httpServerSID.Name, - Partition: ConfigEntryPartition(httpServerSID.Partition), - Sources: []*api.SourceIntention{ - { - Name: tcpClient.ID.Name, - Peer: cluPeerName, - Action: api.IntentionActionAllow, - }, - { - Name: httpClient.ID.Name, - Peer: cluPeerName, - Action: api.IntentionActionAllow, - }, - }, - }, - } - tcpServer := serviceExt{ - Service: NewFortioServiceWithDefaults( - peerClu.Datacenter, - tcpServerSID, - nil, - ), - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: tcpServerSID.Name, - Partition: ConfigEntryPartition(tcpServerSID.Partition), - Protocol: "tcp", - }, - Exports: []api.ServiceConsumer{{Peer: cluPeerName}}, - Intentions: &api.ServiceIntentionsConfigEntry{ - Kind: api.ServiceIntentions, - Name: tcpServerSID.Name, - Partition: ConfigEntryPartition(tcpServerSID.Partition), - Sources: []*api.SourceIntention{ - { - Name: tcpClient.ID.Name, - Peer: cluPeerName, - Action: api.IntentionActionAllow, - }, - { - Name: httpClient.ID.Name, - Peer: cluPeerName, - Action: api.IntentionActionAllow, - }, - }, - }, - } - - httpServerNode := ct.AddServiceNode(peerClu, httpServer) - tcpServerNode := ct.AddServiceNode(peerClu, tcpServer) - - s.sidClientHTTP = httpClient.ID - s.nodeClientHTTP = httpClientNode.ID() - s.sidClientTCP = tcpClient.ID - s.nodeClientTCP = tcpClientNode.ID() - s.upstreamHTTP = upstreamHTTP - s.upstreamTCP = upstreamTCP - - // these are references in Peer - s.sidServerHTTP = httpServerSID - s.nodeServerHTTP = httpServerNode.ID() - s.sidServerTCP = tcpServerSID - s.nodeServerTCP = tcpServerNode.ID() -} - -// implements https://docs.google.com/document/d/1Fs3gNMhCqE4zVNMFcbzf02ZrB0kxxtJpI2h905oKhrs/edit#heading=h.wtzvyryyb56v -func (s *ac1BasicSuite) test(t *testing.T, ct *commonTopo) { - dc := ct.Sprawl.Topology().Clusters[s.DC] - peer := ct.Sprawl.Topology().Clusters[s.Peer] - ac := s - - // refresh this from Topology - svcClientTCP := dc.ServiceByID( - ac.nodeClientTCP, - ac.sidClientTCP, - ) - svcClientHTTP := dc.ServiceByID( - ac.nodeClientHTTP, - ac.sidClientHTTP, - ) - // our ac has the node/sid for server in the peer DC - svcServerHTTP := peer.ServiceByID( - ac.nodeServerHTTP, - ac.sidServerHTTP, - ) - svcServerTCP := peer.ServiceByID( - ac.nodeServerTCP, - ac.sidServerTCP, - ) - - // preconditions - // these could be done parallel with each other, but complexity - // probably not worth the speed boost - ct.Assert.HealthyWithPeer(t, dc.Name, svcServerHTTP.ID, LocalPeerName(peer, "default")) - ct.Assert.HealthyWithPeer(t, dc.Name, svcServerTCP.ID, LocalPeerName(peer, "default")) - ct.Assert.UpstreamEndpointHealthy(t, svcClientTCP, ac.upstreamTCP) - ct.Assert.UpstreamEndpointHealthy(t, svcClientTCP, ac.upstreamHTTP) - - tcs := []struct { - acSub int - proto string - svc *topology.Service - }{ - {1, "tcp", svcClientTCP}, - {2, "http", svcClientHTTP}, - } - for _, tc := range tcs { - tc := tc - t.Run(fmt.Sprintf("1.%d. %s in A can call HTTP upstream", tc.acSub, tc.proto), func(t *testing.T) { - t.Parallel() - ct.Assert.FortioFetch2HeaderEcho(t, tc.svc, ac.upstreamHTTP) - }) - t.Run(fmt.Sprintf("1.%d. %s in A can call TCP upstream", tc.acSub, tc.proto), func(t *testing.T) { - t.Parallel() - ct.Assert.FortioFetch2HeaderEcho(t, tc.svc, ac.upstreamTCP) - }) - t.Run(fmt.Sprintf("1.%d. via %s in A, FORTIO_NAME of HTTP upstream", tc.acSub, tc.proto), func(t *testing.T) { - t.Parallel() - ct.Assert.FortioFetch2FortioName(t, - tc.svc, - ac.upstreamHTTP, - peer.Name, - svcServerHTTP.ID, - ) - }) - t.Run(fmt.Sprintf("1.%d. via %s in A, FORTIO_NAME of TCP upstream", tc.acSub, tc.proto), func(t *testing.T) { - t.Parallel() - ct.Assert.FortioFetch2FortioName(t, - tc.svc, - ac.upstreamTCP, - peer.Name, - svcServerTCP.ID, - ) - }) - } -} diff --git a/test-integ/peering_commontopo/ac2_disco_chain_test.go b/test-integ/peering_commontopo/ac2_disco_chain_test.go deleted file mode 100644 index 448ab2840bfea..0000000000000 --- a/test-integ/peering_commontopo/ac2_disco_chain_test.go +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package peering - -import ( - "fmt" - "testing" - - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/api" -) - -type ac2DiscoChainSuite struct { - DC string - Peer string - - clientSID topology.ServiceID -} - -var ac2DiscoChainSuites []sharedTopoSuite = []sharedTopoSuite{ - &ac2DiscoChainSuite{DC: "dc1", Peer: "dc2"}, - &ac2DiscoChainSuite{DC: "dc2", Peer: "dc1"}, -} - -func TestAC2DiscoChain(t *testing.T) { - runShareableSuites(t, ac2DiscoChainSuites) -} - -func (s *ac2DiscoChainSuite) testName() string { - return fmt.Sprintf("ac2 disco chain %s->%s", s.DC, s.Peer) -} - -func (s *ac2DiscoChainSuite) setup(t *testing.T, ct *commonTopo) { - clu := ct.ClusterByDatacenter(t, s.DC) - peerClu := ct.ClusterByDatacenter(t, s.Peer) - partition := "default" - peer := LocalPeerName(peerClu, "default") - - // Make an HTTP server with discovery chain config entries - server := NewFortioServiceWithDefaults( - clu.Datacenter, - topology.ServiceID{ - Name: "ac2-disco-chain-svc", - Partition: partition, - }, - nil, - ) - ct.ExportService(clu, partition, - api.ExportedService{ - Name: server.ID.Name, - Consumers: []api.ServiceConsumer{ - { - Peer: peer, - }, - }, - }, - ) - - clu.InitialConfigEntries = append(clu.InitialConfigEntries, - &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: server.ID.Name, - Partition: ConfigEntryPartition(partition), - Protocol: "http", - }, - &api.ServiceSplitterConfigEntry{ - Kind: api.ServiceSplitter, - Name: server.ID.Name, - Partition: ConfigEntryPartition(partition), - Splits: []api.ServiceSplit{ - { - Weight: 100.0, - ResponseHeaders: &api.HTTPHeaderModifiers{ - Add: map[string]string{ - "X-Split": "test", - }, - }, - }, - }, - }, - ) - ct.AddServiceNode(clu, serviceExt{Service: server}) - - // Define server as upstream for client - upstream := &topology.Upstream{ - ID: topology.ServiceID{ - Name: server.ID.Name, - Partition: partition, // TODO: iterate over all possible partitions - }, - // TODO: we need to expose this on 0.0.0.0 so we can check it - // through our forward proxy. not realistic IMO - LocalAddress: "0.0.0.0", - LocalPort: 5000, - Peer: peer, - } - - // Make client which will dial server - clientSID := topology.ServiceID{ - Name: "ac2-client", - Partition: partition, - } - client := NewFortioServiceWithDefaults( - clu.Datacenter, - clientSID, - func(s *topology.Service) { - s.Upstreams = []*topology.Upstream{ - upstream, - } - }, - ) - ct.ExportService(clu, partition, - api.ExportedService{ - Name: client.ID.Name, - Consumers: []api.ServiceConsumer{ - { - Peer: peer, - }, - }, - }, - ) - ct.AddServiceNode(clu, serviceExt{Service: client}) - - clu.InitialConfigEntries = append(clu.InitialConfigEntries, - &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: client.ID.Name, - Partition: ConfigEntryPartition(partition), - Protocol: "http", - UpstreamConfig: &api.UpstreamConfiguration{ - Defaults: &api.UpstreamConfig{ - MeshGateway: api.MeshGatewayConfig{ - Mode: api.MeshGatewayModeLocal, - }, - }, - }, - }, - ) - - // Add intention allowing client to call server - clu.InitialConfigEntries = append(clu.InitialConfigEntries, - &api.ServiceIntentionsConfigEntry{ - Kind: api.ServiceIntentions, - Name: server.ID.Name, - Partition: ConfigEntryPartition(partition), - Sources: []*api.SourceIntention{ - { - Name: client.ID.Name, - Peer: peer, - Action: api.IntentionActionAllow, - }, - }, - }, - ) - - s.clientSID = clientSID -} - -func (s *ac2DiscoChainSuite) test(t *testing.T, ct *commonTopo) { - dc := ct.Sprawl.Topology().Clusters[s.DC] - - svcs := dc.ServicesByID(s.clientSID) - require.Len(t, svcs, 1, "expected exactly one client in datacenter") - - client := svcs[0] - require.Len(t, client.Upstreams, 1, "expected exactly one upstream for client") - u := client.Upstreams[0] - - t.Run("peered upstream exists in catalog", func(t *testing.T) { - t.Parallel() - ct.Assert.CatalogServiceExists(t, s.DC, u.ID.Name, &api.QueryOptions{ - Peer: u.Peer, - }) - }) - - t.Run("peered upstream endpoint status is healthy", func(t *testing.T) { - t.Parallel() - ct.Assert.UpstreamEndpointStatus(t, client, peerClusterPrefix(u), "HEALTHY", 1) - }) - - t.Run("response contains header injected by splitter", func(t *testing.T) { - t.Parallel() - // TODO: not sure we should call u.LocalPort? it's not realistic from a security - // standpoint. prefer the fortio fetch2 stuff myself - ct.Assert.HTTPServiceEchoesResHeader(t, client, u.LocalPort, "", - map[string]string{ - "X-Split": "test", - }, - ) - }) -} - -// For reference see consul/xds/clusters.go: -// -// func (s *ResourceGenerator) getTargetClusterName -// -// and connect/sni.go -func peerClusterPrefix(u *topology.Upstream) string { - if u.Peer == "" { - panic("upstream is not from a peer") - } - u.ID.Normalize() - return u.ID.Name + "." + u.ID.Namespace + "." + u.Peer + ".external" -} diff --git a/test-integ/peering_commontopo/ac3_service_defaults_upstream_test.go b/test-integ/peering_commontopo/ac3_service_defaults_upstream_test.go deleted file mode 100644 index 586103c111272..0000000000000 --- a/test-integ/peering_commontopo/ac3_service_defaults_upstream_test.go +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package peering - -import ( - "encoding/json" - "fmt" - "net/http" - "net/url" - "testing" - "time" - - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/go-cleanhttp" - "github.com/itchyny/gojq" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil/retry" - libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" -) - -var ac3SvcDefaultsSuites []sharedTopoSuite = []sharedTopoSuite{ - &ac3SvcDefaultsSuite{DC: "dc1", Peer: "dc2"}, - &ac3SvcDefaultsSuite{DC: "dc2", Peer: "dc1"}, -} - -func TestAC3SvcDefaults(t *testing.T) { - runShareableSuites(t, ac3SvcDefaultsSuites) -} - -type ac3SvcDefaultsSuite struct { - // inputs - DC string - Peer string - - // test points - sidServer topology.ServiceID - nodeServer topology.NodeID - sidClient topology.ServiceID - nodeClient topology.NodeID - - upstream *topology.Upstream -} - -func (s *ac3SvcDefaultsSuite) testName() string { - return fmt.Sprintf("ac3 service defaults upstreams %s->%s", s.DC, s.Peer) -} - -// creates clients in s.DC and servers in s.Peer -func (s *ac3SvcDefaultsSuite) setup(t *testing.T, ct *commonTopo) { - clu := ct.ClusterByDatacenter(t, s.DC) - peerClu := ct.ClusterByDatacenter(t, s.Peer) - - partition := "default" - peer := LocalPeerName(peerClu, "default") - cluPeerName := LocalPeerName(clu, "default") - - serverSID := topology.ServiceID{ - Name: "ac3-server", - Partition: partition, - } - upstream := &topology.Upstream{ - ID: topology.ServiceID{ - Name: serverSID.Name, - Partition: partition, - }, - LocalPort: 5001, - Peer: peer, - } - - sid := topology.ServiceID{ - Name: "ac3-client", - Partition: partition, - } - client := serviceExt{ - Service: NewFortioServiceWithDefaults( - clu.Datacenter, - sid, - func(s *topology.Service) { - s.Upstreams = []*topology.Upstream{ - upstream, - } - }, - ), - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: sid.Name, - Partition: ConfigEntryPartition(sid.Partition), - Protocol: "http", - UpstreamConfig: &api.UpstreamConfiguration{ - Overrides: []*api.UpstreamConfig{ - { - Name: upstream.ID.Name, - Namespace: upstream.ID.Namespace, - Peer: peer, - PassiveHealthCheck: &api.PassiveHealthCheck{ - MaxFailures: 1, - Interval: 10 * time.Minute, - }, - }, - }, - Defaults: &api.UpstreamConfig{ - MeshGateway: api.MeshGatewayConfig{ - Mode: api.MeshGatewayModeLocal, - }, - }, - }, - }, - } - - clientNode := ct.AddServiceNode(clu, client) - - server := serviceExt{ - Service: NewFortioServiceWithDefaults( - peerClu.Datacenter, - serverSID, - nil, - ), - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: serverSID.Name, - Partition: ConfigEntryPartition(serverSID.Partition), - Protocol: "http", - }, - Exports: []api.ServiceConsumer{{Peer: cluPeerName}}, - Intentions: &api.ServiceIntentionsConfigEntry{ - Kind: api.ServiceIntentions, - Name: serverSID.Name, - Partition: ConfigEntryPartition(serverSID.Partition), - Sources: []*api.SourceIntention{ - { - Name: client.ID.Name, - Peer: cluPeerName, - Action: api.IntentionActionAllow, - }, - }, - }, - } - - serverNode := ct.AddServiceNode(peerClu, server) - - s.sidClient = client.ID - s.nodeClient = clientNode.ID() - s.upstream = upstream - - // these are references in Peer - s.sidServer = serverSID - s.nodeServer = serverNode.ID() -} - -// make two requests to upstream via client's fetch2 with status= -// the first time, it should return nonceStatus -// the second time, we expect the upstream to have been removed from the envoy cluster, -// and thereby get some other 5xx -func (s *ac3SvcDefaultsSuite) test(t *testing.T, ct *commonTopo) { - dc := ct.Sprawl.Topology().Clusters[s.DC] - peer := ct.Sprawl.Topology().Clusters[s.Peer] - - // refresh this from Topology - svcClient := dc.ServiceByID( - s.nodeClient, - s.sidClient, - ) - // our ac has the node/sid for server in the peer DC - svcServer := peer.ServiceByID( - s.nodeServer, - s.sidServer, - ) - - // preconditions - // these could be done parallel with each other, but complexity - // probably not worth the speed boost - ct.Assert.HealthyWithPeer(t, dc.Name, svcServer.ID, LocalPeerName(peer, "default")) - ct.Assert.UpstreamEndpointHealthy(t, svcClient, s.upstream) - // TODO: we need to let the upstream start serving properly before we do this. if it - // isn't ready and returns a 5xx (which it will do if it's not up yet!), it will stick - // in a down state for PassiveHealthCheck.Interval - time.Sleep(30 * time.Second) - ct.Assert.FortioFetch2HeaderEcho(t, svcClient, s.upstream) - - // TODO: use proxied HTTP client - client := cleanhttp.DefaultClient() - // TODO: what is default? namespace? partition? - clusterName := fmt.Sprintf("%s.default.%s.external", s.upstream.ID.Name, s.upstream.Peer) - nonceStatus := http.StatusInsufficientStorage - url507 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", svcClient.ExposedPort, - url.QueryEscape(fmt.Sprintf("http://localhost:%d/?status=%d", s.upstream.LocalPort, nonceStatus)), - ) - - // we only make this call once - req, err := http.NewRequest(http.MethodGet, url507, nil) - require.NoError(t, err) - res, err := client.Do(req) - require.NoError(t, err) - defer res.Body.Close() - require.Equal(t, nonceStatus, res.StatusCode) - - // this is a modified version of assertEnvoyUpstreamHealthy - envoyAddr := fmt.Sprintf("localhost:%d", svcClient.ExposedEnvoyAdminPort) - retry.RunWith(&retry.Timer{Timeout: 30 * time.Second, Wait: 500 * time.Millisecond}, t, func(r *retry.R) { - // BOOKMARK: avoid libassert, but we need to resurrect this method in asserter first - clusters, statusCode, err := libassert.GetEnvoyOutputWithClient(client, envoyAddr, "clusters", map[string]string{"format": "json"}) - if err != nil { - r.Fatal("could not fetch envoy clusters") - } - require.Equal(r, 200, statusCode) - - filter := fmt.Sprintf( - `.cluster_statuses[] - | select(.name|contains("%s")) - | [.host_statuses[].health_status.failed_outlier_check] - |.[0]`, - clusterName) - result, err := jqOne(clusters, filter) - require.NoErrorf(r, err, "could not found cluster name %q: %v \n%s", clusterName, err, clusters) - - resultAsBool, ok := result.(bool) - require.True(r, ok) - require.True(r, resultAsBool) - }) - - url200 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", svcClient.ExposedPort, - url.QueryEscape(fmt.Sprintf("http://localhost:%d/", s.upstream.LocalPort)), - ) - retry.RunWith(&retry.Timer{Timeout: time.Minute * 1, Wait: time.Millisecond * 500}, t, func(r *retry.R) { - req, err := http.NewRequest(http.MethodGet, url200, nil) - require.NoError(r, err) - res, err := client.Do(req) - require.NoError(r, err) - defer res.Body.Close() - require.True(r, res.StatusCode >= 500 && res.StatusCode < 600 && res.StatusCode != nonceStatus) - }) -} - -// Executes the JQ filter against the given JSON string. -// Iff there is one result, return that. -func jqOne(config, filter string) (interface{}, error) { - query, err := gojq.Parse(filter) - if err != nil { - return nil, err - } - - var m interface{} - err = json.Unmarshal([]byte(config), &m) - if err != nil { - return nil, err - } - - iter := query.Run(m) - result := []interface{}{} - for { - v, ok := iter.Next() - if !ok { - break - } - if err, ok := v.(error); ok { - return nil, err - } - result = append(result, v) - } - if len(result) != 1 { - return nil, fmt.Errorf("required result of len 1, but is %d: %v", len(result), result) - } - return result[0], nil -} diff --git a/test-integ/peering_commontopo/ac4_proxy_defaults_test.go b/test-integ/peering_commontopo/ac4_proxy_defaults_test.go deleted file mode 100644 index c413820c6f2b7..0000000000000 --- a/test-integ/peering_commontopo/ac4_proxy_defaults_test.go +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package peering - -import ( - "fmt" - "net/http" - "net/url" - "testing" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/go-cleanhttp" - "github.com/stretchr/testify/require" -) - -type ac4ProxyDefaultsSuite struct { - DC string - Peer string - - nodeClient topology.NodeID - nodeServer topology.NodeID - - serverSID topology.ServiceID - clientSID topology.ServiceID - upstream *topology.Upstream -} - -var ac4ProxyDefaultsSuites []sharedTopoSuite = []sharedTopoSuite{ - &ac4ProxyDefaultsSuite{DC: "dc1", Peer: "dc2"}, - &ac4ProxyDefaultsSuite{DC: "dc2", Peer: "dc1"}, -} - -func TestAC4ProxyDefaults(t *testing.T) { - runShareableSuites(t, ac4ProxyDefaultsSuites) -} - -func (s *ac4ProxyDefaultsSuite) testName() string { - return fmt.Sprintf("ac4 proxy defaults %s->%s", s.DC, s.Peer) -} - -// creates clients in s.DC and servers in s.Peer -func (s *ac4ProxyDefaultsSuite) setup(t *testing.T, ct *commonTopo) { - clu := ct.ClusterByDatacenter(t, s.DC) - peerClu := ct.ClusterByDatacenter(t, s.Peer) - - partition := "default" - peer := LocalPeerName(peerClu, "default") - cluPeerName := LocalPeerName(clu, "default") - - serverSID := topology.ServiceID{ - Name: "ac4-server-http", - Partition: partition, - } - // Define server as upstream for client - upstream := &topology.Upstream{ - ID: serverSID, - LocalPort: 5000, - Peer: peer, - } - - // Make client which will dial server - clientSID := topology.ServiceID{ - Name: "ac4-http-client", - Partition: partition, - } - client := serviceExt{ - Service: NewFortioServiceWithDefaults( - clu.Datacenter, - clientSID, - func(s *topology.Service) { - s.Upstreams = []*topology.Upstream{ - upstream, - } - }, - ), - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: clientSID.Name, - Partition: ConfigEntryPartition(clientSID.Partition), - Protocol: "http", - UpstreamConfig: &api.UpstreamConfiguration{ - Defaults: &api.UpstreamConfig{ - MeshGateway: api.MeshGatewayConfig{ - Mode: api.MeshGatewayModeLocal, - }, - }, - }, - }, - } - clientNode := ct.AddServiceNode(clu, client) - - server := serviceExt{ - Service: NewFortioServiceWithDefaults( - peerClu.Datacenter, - serverSID, - nil, - ), - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: serverSID.Name, - Partition: ConfigEntryPartition(serverSID.Partition), - Protocol: "http", - }, - Exports: []api.ServiceConsumer{{Peer: cluPeerName}}, - Intentions: &api.ServiceIntentionsConfigEntry{ - Kind: api.ServiceIntentions, - Name: serverSID.Name, - Partition: ConfigEntryPartition(serverSID.Partition), - Sources: []*api.SourceIntention{ - { - Name: client.ID.Name, - Peer: cluPeerName, - Action: api.IntentionActionAllow, - }, - }, - }, - } - - peerClu.InitialConfigEntries = append(peerClu.InitialConfigEntries, - &api.ProxyConfigEntry{ - Kind: api.ProxyDefaults, - Name: api.ProxyConfigGlobal, - Partition: ConfigEntryPartition(server.ID.Partition), - Config: map[string]interface{}{ - "protocol": "http", - "local_request_timeout_ms": 500, - }, - MeshGateway: api.MeshGatewayConfig{ - Mode: api.MeshGatewayModeLocal, - }, - }, - ) - - serverNode := ct.AddServiceNode(peerClu, server) - - s.clientSID = clientSID - s.serverSID = serverSID - s.nodeServer = serverNode.ID() - s.nodeClient = clientNode.ID() - s.upstream = upstream -} - -func (s *ac4ProxyDefaultsSuite) test(t *testing.T, ct *commonTopo) { - var client *topology.Service - - dc := ct.Sprawl.Topology().Clusters[s.DC] - peer := ct.Sprawl.Topology().Clusters[s.Peer] - - clientSVC := dc.ServiceByID( - s.nodeClient, - s.clientSID, - ) - serverSVC := peer.ServiceByID( - s.nodeServer, - s.serverSID, - ) - - // preconditions check - ct.Assert.HealthyWithPeer(t, dc.Name, serverSVC.ID, LocalPeerName(peer, "default")) - ct.Assert.UpstreamEndpointHealthy(t, clientSVC, s.upstream) - ct.Assert.FortioFetch2HeaderEcho(t, clientSVC, s.upstream) - - t.Run("Validate services exist in catalog", func(t *testing.T) { - dcSvcs := dc.ServicesByID(s.clientSID) - require.Len(t, dcSvcs, 1, "expected exactly one client") - client = dcSvcs[0] - require.Len(t, client.Upstreams, 1, "expected exactly one upstream for client") - - server := dc.ServicesByID(s.serverSID) - require.Len(t, server, 1, "expected exactly one server") - require.Len(t, server[0].Upstreams, 0, "expected no upstream for server") - }) - - t.Run("peered upstream exists in catalog", func(t *testing.T) { - ct.Assert.CatalogServiceExists(t, s.DC, s.upstream.ID.Name, &api.QueryOptions{ - Peer: s.upstream.Peer, - }) - }) - - t.Run("HTTP service fails due to connection timeout", func(t *testing.T) { - url504 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", client.ExposedPort, - url.QueryEscape(fmt.Sprintf("http://localhost:%d/?delay=1000ms", s.upstream.LocalPort)), - ) - - url200 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", client.ExposedPort, - url.QueryEscape(fmt.Sprintf("http://localhost:%d/", s.upstream.LocalPort)), - ) - - // validate request timeout error where service has 1000ms response delay and - // proxy default is set to local_request_timeout_ms: 500ms - // return 504 - httpClient := cleanhttp.DefaultClient() - req, err := http.NewRequest(http.MethodGet, url504, nil) - require.NoError(t, err) - - res, err := httpClient.Do(req) - require.NoError(t, err) - - defer res.Body.Close() - require.Equal(t, http.StatusGatewayTimeout, res.StatusCode) - - // validate successful GET request where service has no response delay and - // proxy default is set to local_request_timeout_ms: 500ms - // return 200 - req, err = http.NewRequest(http.MethodGet, url200, nil) - require.NoError(t, err) - - res, err = httpClient.Do(req) - require.NoError(t, err) - - defer res.Body.Close() - require.Equal(t, http.StatusOK, res.StatusCode) - }) -} diff --git a/test-integ/peering_commontopo/ac5_1_no_svc_mesh_test.go b/test-integ/peering_commontopo/ac5_1_no_svc_mesh_test.go deleted file mode 100644 index 9706eba63ca99..0000000000000 --- a/test-integ/peering_commontopo/ac5_1_no_svc_mesh_test.go +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package peering - -import ( - "fmt" - - "testing" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil/retry" - libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/require" -) - -type ac5_1NoSvcMeshSuite struct { - DC string - Peer string - - serverSID topology.ServiceID - clientSID topology.ServiceID -} - -var ( - ac5_1NoSvcMeshSuites []sharedTopoSuite = []sharedTopoSuite{ - &ac5_1NoSvcMeshSuite{DC: "dc1", Peer: "dc2"}, - &ac5_1NoSvcMeshSuite{DC: "dc2", Peer: "dc1"}, - } -) - -func TestAC5ServiceMeshDisabledSuite(t *testing.T) { - runShareableSuites(t, ac5_1NoSvcMeshSuites) -} - -func (s *ac5_1NoSvcMeshSuite) testName() string { - return fmt.Sprintf("ac5.1 no service mesh %s->%s", s.DC, s.Peer) -} - -// creates clients in s.DC and servers in s.Peer -func (s *ac5_1NoSvcMeshSuite) setup(t *testing.T, ct *commonTopo) { - clu := ct.ClusterByDatacenter(t, s.DC) - peerClu := ct.ClusterByDatacenter(t, s.Peer) - - // TODO: handle all partitions - partition := "default" - peer := LocalPeerName(peerClu, partition) - - serverSID := topology.ServiceID{ - Name: "ac5-server-http", - Partition: partition, - } - - // Make client which will dial server - clientSID := topology.ServiceID{ - Name: "ac5-http-client", - Partition: partition, - } - - // disable service mesh for client in s.DC - client := serviceExt{ - Service: NewFortioServiceWithDefaults( - clu.Datacenter, - clientSID, - func(s *topology.Service) { - s.EnvoyAdminPort = 0 - s.DisableServiceMesh = true - }, - ), - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: clientSID.Name, - Partition: ConfigEntryPartition(clientSID.Partition), - Protocol: "http", - }, - Exports: []api.ServiceConsumer{{Peer: peer}}, - } - ct.AddServiceNode(clu, client) - - server := serviceExt{ - Service: NewFortioServiceWithDefaults( - clu.Datacenter, - serverSID, - nil, - ), - Exports: []api.ServiceConsumer{{Peer: peer}}, - } - - ct.AddServiceNode(clu, server) - - s.clientSID = clientSID - s.serverSID = serverSID -} - -func (s *ac5_1NoSvcMeshSuite) test(t *testing.T, ct *commonTopo) { - dc := ct.Sprawl.Topology().Clusters[s.DC] - peer := ct.Sprawl.Topology().Clusters[s.Peer] - cl := ct.APIClientForCluster(t, dc) - peerName := LocalPeerName(peer, "default") - - s.testServiceHealthInCatalog(t, ct, cl, peerName) - s.testProxyDisabledInDC2(t, cl, peerName) -} - -func (s *ac5_1NoSvcMeshSuite) testServiceHealthInCatalog(t *testing.T, ct *commonTopo, cl *api.Client, peer string) { - t.Run("validate service health in catalog", func(t *testing.T) { - libassert.CatalogServiceExists(t, cl, s.clientSID.Name, &api.QueryOptions{ - Peer: peer, - }) - require.NotEqual(t, s.serverSID.Name, s.Peer) - assertServiceHealth(t, cl, s.serverSID.Name, 1) - }) -} - -func (s *ac5_1NoSvcMeshSuite) testProxyDisabledInDC2(t *testing.T, cl *api.Client, peer string) { - t.Run("service mesh is disabled", func(t *testing.T) { - var ( - services map[string][]string - err error - expected = fmt.Sprintf("%s-sidecar-proxy", s.clientSID.Name) - ) - retry.Run(t, func(r *retry.R) { - services, _, err = cl.Catalog().Services(&api.QueryOptions{ - Peer: peer, - }) - require.NoError(r, err, "error reading service data") - require.Greater(r, len(services), 0, "did not find service(s) in catalog") - }) - require.NotContains(t, services, expected, fmt.Sprintf("error: should not create proxy for service: %s", services)) - }) -} diff --git a/test-integ/peering_commontopo/ac5_2_pq_failover_test.go b/test-integ/peering_commontopo/ac5_2_pq_failover_test.go deleted file mode 100644 index 94930647408ff..0000000000000 --- a/test-integ/peering_commontopo/ac5_2_pq_failover_test.go +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package peering - -import ( - "fmt" - "time" - - "testing" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil/retry" - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/require" -) - -// 1. Setup: put health service instances in each of the 3 clusters and create the PQ in one of them -// 2. Execute the PQ: Validate that failover count == 0 and that the pq results come from the local cluster -// 3. Register a failing TTL health check with the agent managing the service instance in the local cluster -// 4. Execute the PQ: Validate that failover count == 1 and that the pq results come from the first failover target peer -// 5. Register a failing TTL health check with the agent managing the service instance in the first failover peer -// 6. Execute the PQ: Validate that failover count == 2 and that the pq results come from the second failover target -// 7. Delete failing health check from step 5 -// 8. Repeat step 4 -// 9. Delete failing health check from step 3 -// 10. Repeat step 2 -type ac5_2PQFailoverSuite struct { - clientSID topology.ServiceID - serverSID topology.ServiceID - nodeServer topology.NodeID -} - -var ac5_2Context = make(map[nodeKey]ac5_2PQFailoverSuite) - -func TestAC5PreparedQueryFailover(t *testing.T) { - ct := NewCommonTopo(t) - s := &ac5_2PQFailoverSuite{} - s.setup(t, ct) - ct.Launch(t) - s.test(t, ct) -} - -func (s *ac5_2PQFailoverSuite) setup(t *testing.T, ct *commonTopo) { - s.setupDC(ct, ct.DC1, ct.DC2) - s.setupDC(ct, ct.DC2, ct.DC1) - s.setupDC3(ct, ct.DC3, ct.DC1, ct.DC2) -} - -func (s *ac5_2PQFailoverSuite) setupDC(ct *commonTopo, clu, peerClu *topology.Cluster) { - // TODO: handle all partitions - partition := "default" - peer := LocalPeerName(peerClu, partition) - - serverSID := topology.ServiceID{ - Name: "ac5-server-http", - Partition: partition, - } - - clientSID := topology.ServiceID{ - Name: "ac5-client-http", - Partition: partition, - } - - client := serviceExt{ - Service: NewFortioServiceWithDefaults( - clu.Datacenter, - clientSID, - func(s *topology.Service) { - s.EnvoyAdminPort = 0 - s.DisableServiceMesh = true - }, - ), - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: clientSID.Name, - Partition: ConfigEntryPartition(clientSID.Partition), - Protocol: "http", - }, - Exports: []api.ServiceConsumer{{Peer: peer}}, - } - - ct.AddServiceNode(clu, client) - - server := serviceExt{ - Service: NewFortioServiceWithDefaults( - clu.Datacenter, - serverSID, - nil, - ), - Exports: []api.ServiceConsumer{{Peer: peer}}, - } - serverNode := ct.AddServiceNode(clu, server) - - ac5_2Context[nodeKey{clu.Datacenter, partition}] = ac5_2PQFailoverSuite{ - clientSID: clientSID, - serverSID: serverSID, - nodeServer: serverNode.ID(), - } -} - -func (s *ac5_2PQFailoverSuite) setupDC3(ct *commonTopo, clu, peer1, peer2 *topology.Cluster) { - var ( - peers []string - partition = "default" - ) - peers = append(peers, LocalPeerName(peer1, partition), LocalPeerName(peer2, partition)) - - serverSID := topology.ServiceID{ - Name: "ac5-server-http", - Partition: partition, - } - - clientSID := topology.ServiceID{ - Name: "ac5-client-http", - Partition: partition, - } - - // disable service mesh for client in DC3 - client := serviceExt{ - Service: NewFortioServiceWithDefaults( - clu.Datacenter, - clientSID, - func(s *topology.Service) { - s.EnvoyAdminPort = 0 - s.DisableServiceMesh = true - }, - ), - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: clientSID.Name, - Partition: ConfigEntryPartition(clientSID.Partition), - Protocol: "http", - }, - Exports: func() []api.ServiceConsumer { - var consumers []api.ServiceConsumer - for _, peer := range peers { - consumers = append(consumers, api.ServiceConsumer{ - Peer: peer, - }) - } - return consumers - }(), - } - - ct.AddServiceNode(clu, client) - - server := serviceExt{ - Service: NewFortioServiceWithDefaults( - clu.Datacenter, - serverSID, - nil, - ), - Exports: func() []api.ServiceConsumer { - var consumers []api.ServiceConsumer - for _, peer := range peers { - consumers = append(consumers, api.ServiceConsumer{ - Peer: peer, - }) - } - return consumers - }(), - } - - serverNode := ct.AddServiceNode(clu, server) - - ac5_2Context[nodeKey{clu.Datacenter, partition}] = ac5_2PQFailoverSuite{ - clientSID: clientSID, - serverSID: serverSID, - nodeServer: serverNode.ID(), - } -} - -func (s *ac5_2PQFailoverSuite) createPreparedQuery(t *testing.T, ct *commonTopo, c *api.Client, serviceName, partition string) (*api.PreparedQueryDefinition, *api.PreparedQuery) { - var ( - peers []string - err error - ) - peers = append(peers, LocalPeerName(ct.DC2, partition), LocalPeerName(ct.DC3, partition)) - - def := &api.PreparedQueryDefinition{ - Name: "ac5-prepared-query", - Service: api.ServiceQuery{ - Service: serviceName, - Partition: ConfigEntryPartition(partition), - OnlyPassing: true, - Failover: api.QueryFailoverOptions{ - Targets: func() []api.QueryFailoverTarget { - var queryFailoverTargets []api.QueryFailoverTarget - for _, peer := range peers { - queryFailoverTargets = append(queryFailoverTargets, api.QueryFailoverTarget{ - Peer: peer, - }) - } - return queryFailoverTargets - }(), - }, - }, - } - - query := c.PreparedQuery() - def.ID, _, err = query.Create(def, nil) - require.NoError(t, err, "error creating prepared query in cluster") - - return def, query -} - -func (s *ac5_2PQFailoverSuite) test(t *testing.T, ct *commonTopo) { - partition := "default" - dc1 := ct.Sprawl.Topology().Clusters[ct.DC1.Name] - dc2 := ct.Sprawl.Topology().Clusters[ct.DC2.Name] - dc3 := ct.Sprawl.Topology().Clusters[ct.DC3.Name] - - type testcase struct { - cluster *topology.Cluster - peer *topology.Cluster - targetCluster *topology.Cluster - } - tcs := []testcase{ - { - cluster: dc1, - peer: dc2, - targetCluster: dc3, - }, - } - for _, tc := range tcs { - client := ct.APIClientForCluster(t, tc.cluster) - - t.Run(fmt.Sprintf("%#v", tc), func(t *testing.T) { - svc := ac5_2Context[nodeKey{tc.cluster.Name, partition}] - require.NotNil(t, svc.serverSID.Name, "expected service name to not be nil") - require.NotNil(t, svc.nodeServer, "expected node server to not be nil") - - assertServiceHealth(t, client, svc.serverSID.Name, 1) - def, _ := s.createPreparedQuery(t, ct, client, svc.serverSID.Name, partition) - s.testPreparedQueryZeroFailover(t, client, def, tc.cluster) - s.testPreparedQuerySingleFailover(t, ct, client, def, tc.cluster, tc.peer, partition) - s.testPreparedQueryTwoFailovers(t, ct, client, def, tc.cluster, tc.peer, tc.targetCluster, partition) - - // delete failing health check in peer cluster & validate single failover - s.testPQSingleFailover(t, ct, client, def, tc.cluster, tc.peer, partition) - // delete failing health check in cluster & validate zero failover - s.testPQZeroFailover(t, ct, client, def, tc.cluster, tc.peer, partition) - }) - } -} - -func (s *ac5_2PQFailoverSuite) testPreparedQueryZeroFailover(t *testing.T, cl *api.Client, def *api.PreparedQueryDefinition, cluster *topology.Cluster) { - t.Run(fmt.Sprintf("prepared query should not failover %s", cluster.Name), func(t *testing.T) { - - // Validate prepared query exists in cluster - queryDef, _, err := cl.PreparedQuery().Get(def.ID, nil) - require.NoError(t, err) - require.Len(t, queryDef, 1, "expected 1 prepared query") - require.Equal(t, 2, len(queryDef[0].Service.Failover.Targets), "expected 2 prepared query failover targets to dc2 and dc3") - - retry.RunWith(&retry.Timer{Timeout: 10 * time.Second, Wait: 500 * time.Millisecond}, t, func(r *retry.R) { - queryResult, _, err := cl.PreparedQuery().Execute(def.ID, nil) - require.NoError(r, err) - - // expected outcome should show 0 failover - require.Equal(r, 0, queryResult.Failovers, "expected 0 prepared query failover") - require.Equal(r, cluster.Name, queryResult.Nodes[0].Node.Datacenter, "pq results should come from the local cluster") - }) - }) -} - -func (s *ac5_2PQFailoverSuite) testPreparedQuerySingleFailover(t *testing.T, ct *commonTopo, cl *api.Client, def *api.PreparedQueryDefinition, cluster, peerClu *topology.Cluster, partition string) { - t.Run(fmt.Sprintf("prepared query with single failover %s", cluster.Name), func(t *testing.T) { - cfg := ct.Sprawl.Config() - svc := ac5_2Context[nodeKey{cluster.Name, partition}] - - nodeCfg := DisableNode(t, cfg, cluster.Name, svc.nodeServer) - require.NoError(t, ct.Sprawl.Relaunch(nodeCfg)) - - // assert server health status - assertServiceHealth(t, cl, svc.serverSID.Name, 0) - - // Validate prepared query exists in cluster - queryDef, _, err := cl.PreparedQuery().Get(def.ID, nil) - require.NoError(t, err) - require.Len(t, queryDef, 1, "expected 1 prepared query") - - pqFailoverTargets := queryDef[0].Service.Failover.Targets - require.Len(t, pqFailoverTargets, 2, "expected 2 prepared query failover targets to dc2 and dc3") - - retry.RunWith(&retry.Timer{Timeout: 10 * time.Second, Wait: 500 * time.Millisecond}, t, func(r *retry.R) { - queryResult, _, err := cl.PreparedQuery().Execute(def.ID, nil) - require.NoError(r, err) - - require.Equal(r, 1, queryResult.Failovers, "expected 1 prepared query failover") - require.Equal(r, peerClu.Name, queryResult.Nodes[0].Node.Datacenter, fmt.Sprintf("the pq results should originate from peer clu %s", peerClu.Name)) - require.Equal(r, pqFailoverTargets[0].Peer, queryResult.Nodes[0].Checks[0].PeerName, - fmt.Sprintf("pq results should come from the first failover target peer %s", pqFailoverTargets[0].Peer)) - }) - }) -} - -func (s *ac5_2PQFailoverSuite) testPreparedQueryTwoFailovers(t *testing.T, ct *commonTopo, cl *api.Client, def *api.PreparedQueryDefinition, cluster, peerClu, targetCluster *topology.Cluster, partition string) { - t.Run(fmt.Sprintf("prepared query with two failovers %s", cluster.Name), func(t *testing.T) { - cfg := ct.Sprawl.Config() - - svc := ac5_2Context[nodeKey{peerClu.Name, partition}] - - cfg = DisableNode(t, cfg, peerClu.Name, svc.nodeServer) - require.NoError(t, ct.Sprawl.Relaunch(cfg)) - - // assert server health status - assertServiceHealth(t, cl, ac5_2Context[nodeKey{cluster.Name, partition}].serverSID.Name, 0) // cluster: failing - assertServiceHealth(t, cl, svc.serverSID.Name, 0) // peer cluster: failing - - queryDef, _, err := cl.PreparedQuery().Get(def.ID, nil) - require.NoError(t, err) - require.Len(t, queryDef, 1, "expected 1 prepared query") - - pqFailoverTargets := queryDef[0].Service.Failover.Targets - require.Len(t, pqFailoverTargets, 2, "expected 2 prepared query failover targets to dc2 and dc3") - - retry.RunWith(&retry.Timer{Timeout: 10 * time.Second, Wait: 500 * time.Millisecond}, t, func(r *retry.R) { - queryResult, _, err := cl.PreparedQuery().Execute(def.ID, nil) - require.NoError(r, err) - require.Equal(r, 2, queryResult.Failovers, "expected 2 prepared query failover") - - require.Equal(r, targetCluster.Name, queryResult.Nodes[0].Node.Datacenter, fmt.Sprintf("the pq results should originate from cluster %s", targetCluster.Name)) - require.Equal(r, pqFailoverTargets[1].Peer, queryResult.Nodes[0].Checks[0].PeerName, - fmt.Sprintf("pq results should come from the second failover target peer %s", pqFailoverTargets[1].Peer)) - }) - }) -} - -func (s *ac5_2PQFailoverSuite) testPQSingleFailover(t *testing.T, ct *commonTopo, cl *api.Client, def *api.PreparedQueryDefinition, cluster, peerClu *topology.Cluster, partition string) { - t.Run(fmt.Sprintf("delete failing health check in %s and validate single failover %s", peerClu.Name, cluster.Name), func(t *testing.T) { - cfg := ct.Sprawl.Config() - - svc := ac5_2Context[nodeKey{peerClu.Name, partition}] - - cfg = EnableNode(t, cfg, peerClu.Name, svc.nodeServer) - require.NoError(t, ct.Sprawl.Relaunch(cfg)) - - queryDef, _, err := cl.PreparedQuery().Get(def.ID, nil) - require.NoError(t, err) - - pqFailoverTargets := queryDef[0].Service.Failover.Targets - require.Len(t, pqFailoverTargets, 2, "expected 2 prepared query failover targets to dc2 and dc3") - - retry.RunWith(&retry.Timer{Timeout: 10 * time.Second, Wait: 500 * time.Millisecond}, t, func(r *retry.R) { - queryResult, _, err := cl.PreparedQuery().Execute(def.ID, nil) - require.NoError(r, err) - require.Equal(r, 1, queryResult.Failovers, "expected 1 prepared query failover") - - require.Equal(r, peerClu.Name, queryResult.Nodes[0].Node.Datacenter, fmt.Sprintf("the pq results should originate from cluster %s", peerClu.Name)) - require.Equal(r, pqFailoverTargets[0].Peer, queryResult.Nodes[0].Checks[0].PeerName, - fmt.Sprintf("pq results should come from the second failover target peer %s", pqFailoverTargets[0].Peer)) - }) - }) -} - -func (s *ac5_2PQFailoverSuite) testPQZeroFailover(t *testing.T, ct *commonTopo, cl *api.Client, def *api.PreparedQueryDefinition, cluster, peerClu *topology.Cluster, partition string) { - t.Run(fmt.Sprintf("delete failing health check in %s and validate zero failover %s", cluster.Name, cluster.Name), func(t *testing.T) { - cfg := ct.Sprawl.Config() - - svc := ac5_2Context[nodeKey{cluster.Name, partition}] - - cfg = EnableNode(t, cfg, cluster.Name, svc.nodeServer) - require.NoError(t, ct.Sprawl.Relaunch(cfg)) - - // assert server health status - assertServiceHealth(t, cl, ac5_2Context[nodeKey{cluster.Name, partition}].serverSID.Name, 1) // cluster: passing - assertServiceHealth(t, cl, svc.serverSID.Name, 1) // peer cluster: passing - - queryDef, _, err := cl.PreparedQuery().Get(def.ID, nil) - require.NoError(t, err) - - pqFailoverTargets := queryDef[0].Service.Failover.Targets - require.Len(t, pqFailoverTargets, 2, "expected 2 prepared query failover targets to dc2 and dc3") - - retry.RunWith(&retry.Timer{Timeout: 10 * time.Second, Wait: 500 * time.Millisecond}, t, func(r *retry.R) { - queryResult, _, err := cl.PreparedQuery().Execute(def.ID, nil) - require.NoError(r, err) - // expected outcome should show 0 failover - require.Equal(r, 0, queryResult.Failovers, "expected 0 prepared query failover") - require.Equal(r, cluster.Name, queryResult.Nodes[0].Node.Datacenter, "pq results should come from the local cluster") - }) - }) -} - -// assertServiceHealth checks that a service health status before running tests -func assertServiceHealth(t *testing.T, cl *api.Client, serverSVC string, count int) { - t.Helper() - t.Log("validate service health in catalog") - retry.RunWith(&retry.Timer{Timeout: time.Second * 20, Wait: time.Millisecond * 500}, t, func(r *retry.R) { - svcs, _, err := cl.Health().Service( - serverSVC, - "", - true, - nil, - ) - require.NoError(r, err) - require.Equal(r, count, len(svcs)) - }) -} diff --git a/test-integ/peering_commontopo/ac6_failovers_test.go b/test-integ/peering_commontopo/ac6_failovers_test.go deleted file mode 100644 index fe3cd181b2032..0000000000000 --- a/test-integ/peering_commontopo/ac6_failovers_test.go +++ /dev/null @@ -1,432 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package peering - -import ( - "fmt" - "testing" - - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" -) - -// note: unlike other *Suite structs that are per-peering direction, -// this one is special and does all directions itself, because the -// setup is not exactly symmetrical -type ac6FailoversSuite struct { - ac6 map[nodeKey]ac6FailoversContext -} -type ac6FailoversContext struct { - clientSID topology.ServiceID - serverSID topology.ServiceID - - // used to remove the node and trigger failover - serverNode topology.NodeID -} -type nodeKey struct { - dc string - partition string -} - -// Note: this test cannot share topo -func TestAC6Failovers(t *testing.T) { - ct := NewCommonTopo(t) - s := &ac6FailoversSuite{} - s.setup(t, ct) - ct.Launch(t) - s.test(t, ct) -} - -func (s *ac6FailoversSuite) setup(t *testing.T, ct *commonTopo) { - // TODO: update setups to loop through a cluster's partitions+namespaces internally - s.setupAC6Failovers(ct, ct.DC1, ct.DC2) - s.setupAC6Failovers(ct, ct.DC2, ct.DC1) - s.setupAC6FailoversDC3(ct, ct.DC3, ct.DC1, ct.DC2) -} - -// dc1 is peered with dc2 and dc3. -// dc1 has an ac6-client in "default" and "part1" partitions (only default in CE). -// ac6-client has a single upstream ac6-failover-svc in its respective partition^. -// -// ac6-failover-svc has the following failovers: -// - peer-dc2-default -// - peer-dc2-part1 (not in CE) -// - peer-dc3-default -// -// This setup is mirrored from dc2->dc1 as well -// (both dcs have dc3 as the last failover target) -// -// ^NOTE: There are no cross-partition upstreams because MeshGatewayMode = local -// and failover information gets stripped out by the mesh gateways so we -// can't test failovers. -func (s *ac6FailoversSuite) setupAC6Failovers(ct *commonTopo, clu, peerClu *topology.Cluster) { - for _, part := range clu.Partitions { - partition := part.Name - - // There is a peering per partition in the peered cluster - var peers []string - for _, peerPart := range peerClu.Partitions { - peers = append(peers, LocalPeerName(peerClu, peerPart.Name)) - } - - // Make an HTTP server with various failover targets - serverSID := topology.ServiceID{ - Name: "ac6-failover-svc", - Partition: partition, - } - server := NewFortioServiceWithDefaults( - clu.Datacenter, - serverSID, - nil, - ) - // Export to all known peers - ct.ExportService(clu, partition, - api.ExportedService{ - Name: server.ID.Name, - Consumers: func() []api.ServiceConsumer { - var consumers []api.ServiceConsumer - for _, peer := range peers { - consumers = append(consumers, api.ServiceConsumer{ - Peer: peer, - }) - } - return consumers - }(), - }, - ) - serverNode := ct.AddServiceNode(clu, serviceExt{Service: server}) - - clu.InitialConfigEntries = append(clu.InitialConfigEntries, - &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: server.ID.Name, - Partition: ConfigEntryPartition(partition), - Protocol: "http", - }, - &api.ServiceResolverConfigEntry{ - Kind: api.ServiceResolver, - Name: server.ID.Name, - Partition: ConfigEntryPartition(partition), - Failover: map[string]api.ServiceResolverFailover{ - "*": { - Targets: func() []api.ServiceResolverFailoverTarget { - // Make a failover target for every partition in the peer cluster - var targets []api.ServiceResolverFailoverTarget - for _, peer := range peers { - targets = append(targets, api.ServiceResolverFailoverTarget{ - Peer: peer, - }) - } - // Just hard code default partition for dc3, since the exhaustive - // testing will be done against dc2. - targets = append(targets, api.ServiceResolverFailoverTarget{ - Peer: "peer-dc3-default", - }) - return targets - }(), - }, - }, - }, - ) - - // Make client which will dial server - clientSID := topology.ServiceID{ - Name: "ac6-client", - Partition: partition, - } - client := NewFortioServiceWithDefaults( - clu.Datacenter, - clientSID, - func(s *topology.Service) { - // Upstream per partition - s.Upstreams = []*topology.Upstream{ - { - ID: topology.ServiceID{ - Name: server.ID.Name, - Partition: part.Name, - }, - LocalPort: 5000, - // exposed so we can hit it directly - // TODO: we shouldn't do this; it's not realistic - LocalAddress: "0.0.0.0", - }, - } - }, - ) - ct.ExportService(clu, partition, - api.ExportedService{ - Name: client.ID.Name, - Consumers: func() []api.ServiceConsumer { - var consumers []api.ServiceConsumer - // Export to each peer - for _, peer := range peers { - consumers = append(consumers, api.ServiceConsumer{ - Peer: peer, - }) - } - return consumers - }(), - }, - ) - ct.AddServiceNode(clu, serviceExt{Service: client}) - - clu.InitialConfigEntries = append(clu.InitialConfigEntries, - &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: client.ID.Name, - Partition: ConfigEntryPartition(partition), - Protocol: "http", - }, - ) - - // Add intention allowing local and peered clients to call server - clu.InitialConfigEntries = append(clu.InitialConfigEntries, - &api.ServiceIntentionsConfigEntry{ - Kind: api.ServiceIntentions, - Name: server.ID.Name, - Partition: ConfigEntryPartition(partition), - // SourceIntention for local client and peered clients - Sources: func() []*api.SourceIntention { - ixns := []*api.SourceIntention{ - { - Name: client.ID.Name, - Partition: ConfigEntryPartition(part.Name), - Action: api.IntentionActionAllow, - }, - } - for _, peer := range peers { - ixns = append(ixns, &api.SourceIntention{ - Name: client.ID.Name, - Peer: peer, - Action: api.IntentionActionAllow, - }) - } - return ixns - }(), - }, - ) - if s.ac6 == nil { - s.ac6 = map[nodeKey]ac6FailoversContext{} - } - s.ac6[nodeKey{clu.Datacenter, partition}] = struct { - clientSID topology.ServiceID - serverSID topology.ServiceID - serverNode topology.NodeID - }{ - clientSID: clientSID, - serverSID: serverSID, - serverNode: serverNode.ID(), - } - } -} - -func (s *ac6FailoversSuite) setupAC6FailoversDC3(ct *commonTopo, clu, peer1, peer2 *topology.Cluster) { - var peers []string - for _, part := range peer1.Partitions { - peers = append(peers, LocalPeerName(peer1, part.Name)) - } - for _, part := range peer2.Partitions { - peers = append(peers, LocalPeerName(peer2, part.Name)) - } - - partition := "default" - - // Make an HTTP server - server := NewFortioServiceWithDefaults( - clu.Datacenter, - topology.ServiceID{ - Name: "ac6-failover-svc", - Partition: partition, - }, - nil, - ) - - ct.AddServiceNode(clu, serviceExt{ - Service: server, - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: server.ID.Name, - Partition: ConfigEntryPartition(partition), - Protocol: "http", - }, - Intentions: &api.ServiceIntentionsConfigEntry{ - Kind: api.ServiceIntentions, - Name: server.ID.Name, - Partition: ConfigEntryPartition(partition), - Sources: func() []*api.SourceIntention { - var ixns []*api.SourceIntention - for _, peer := range peers { - ixns = append(ixns, &api.SourceIntention{ - Name: "ac6-client", - Peer: peer, - Action: api.IntentionActionAllow, - }) - } - return ixns - }(), - }, - Exports: func() []api.ServiceConsumer { - var consumers []api.ServiceConsumer - for _, peer := range peers { - consumers = append(consumers, api.ServiceConsumer{ - Peer: peer, - }) - } - return consumers - }(), - }) -} - -func (s *ac6FailoversSuite) test(t *testing.T, ct *commonTopo) { - dc1 := ct.Sprawl.Topology().Clusters["dc1"] - dc2 := ct.Sprawl.Topology().Clusters["dc2"] - - type testcase struct { - name string - cluster *topology.Cluster - peer *topology.Cluster - partition string - } - tcs := []testcase{ - { - name: "dc1 default partition failovers", - cluster: dc1, - peer: dc2, // dc3 is hardcoded - partition: "default", - }, - { - name: "dc1 part1 partition failovers", - cluster: dc1, - peer: dc2, // dc3 is hardcoded - partition: "part1", - }, - { - name: "dc2 default partition failovers", - cluster: dc2, - peer: dc1, // dc3 is hardcoded - partition: "default", - }, - { - name: "dc2 part1 partition failovers", - cluster: dc2, - peer: dc1, // dc3 is hardcoded - partition: "part1", - }, - } - for _, tc := range tcs { - t.Run(tc.name, func(t *testing.T) { - // NOTE: *not parallel* because we mutate resources that are shared - // between test cases (disable/enable nodes) - if !utils.IsEnterprise() && tc.partition != "default" { - t.Skip("skipping enterprise test") - } - partition := tc.partition - clu := tc.cluster - peerClu := tc.peer - - svcs := clu.ServicesByID(s.ac6[nodeKey{clu.Datacenter, partition}].clientSID) - require.Len(t, svcs, 1, "expected exactly one client in datacenter") - - serverSID := s.ac6[nodeKey{clu.Datacenter, partition}].serverSID - serverSID.Normalize() - - client := svcs[0] - require.Len(t, client.Upstreams, 1, "expected one upstream for client") - - u := client.Upstreams[0] - ct.Assert.CatalogServiceExists(t, clu.Name, u.ID.Name, utils.CompatQueryOpts(&api.QueryOptions{ - Partition: u.ID.Partition, - })) - - t.Cleanup(func() { - cfg := ct.Sprawl.Config() - for _, part := range clu.Partitions { - EnableNode(t, cfg, clu.Name, s.ac6[nodeKey{clu.Datacenter, part.Name}].serverNode) - } - for _, part := range peerClu.Partitions { - EnableNode(t, cfg, peerClu.Name, s.ac6[nodeKey{peerClu.Datacenter, part.Name}].serverNode) - } - require.NoError(t, ct.Sprawl.Relaunch(cfg)) - }) - - fmt.Println("### preconditions") - // TODO: deduce this number, instead of hard-coding - nFailoverTargets := 4 - // in CE, we don't have failover targets for non-default partitions - if !utils.IsEnterprise() { - nFailoverTargets = 3 - } - for i := 0; i < nFailoverTargets; i++ { - ct.Assert.UpstreamEndpointStatus(t, client, fmt.Sprintf("failover-target~%d~%s", i, clusterPrefix(u, clu.Datacenter)), "HEALTHY", 1) - } - - ct.Assert.FortioFetch2FortioName(t, client, u, clu.Name, serverSID) - - if t.Failed() { - t.Fatalf("failed preconditions") - } - - fmt.Println("### Failover to peer target") - cfg := ct.Sprawl.Config() - DisableNode(t, cfg, clu.Name, s.ac6[nodeKey{clu.Datacenter, partition}].serverNode) - require.NoError(t, ct.Sprawl.Relaunch(cfg)) - // Clusters for imported services rely on outlier detection for - // failovers, NOT eds_health_status. This means that killing the - // node above does not actually make the envoy cluster UNHEALTHY - // so we do not assert for it. - expectUID := topology.ServiceID{ - Name: u.ID.Name, - Partition: "default", - } - expectUID.Normalize() - ct.Assert.FortioFetch2FortioName(t, client, u, peerClu.Name, expectUID) - - if utils.IsEnterprise() { - fmt.Println("### Failover to peer target in non-default partition") - cfg = ct.Sprawl.Config() - DisableNode(t, cfg, clu.Name, s.ac6[nodeKey{clu.Datacenter, partition}].serverNode) - DisableNode(t, cfg, peerClu.Name, s.ac6[nodeKey{peerClu.Datacenter, "default"}].serverNode) - require.NoError(t, ct.Sprawl.Relaunch(cfg)) - // Retry until outlier_detection deems the cluster - // unhealthy and fails over to peer part1. - expectUID = topology.ServiceID{ - Name: u.ID.Name, - Partition: "part1", - } - expectUID.Normalize() - ct.Assert.FortioFetch2FortioName(t, client, u, peerClu.Name, expectUID) - } - - fmt.Println("### Failover to dc3 peer target") - cfg = ct.Sprawl.Config() - DisableNode(t, cfg, clu.Name, s.ac6[nodeKey{clu.Datacenter, partition}].serverNode) - // Disable all partitions for peer - for _, part := range peerClu.Partitions { - DisableNode(t, cfg, peerClu.Name, s.ac6[nodeKey{peerClu.Datacenter, part.Name}].serverNode) - } - require.NoError(t, ct.Sprawl.Relaunch(cfg)) - // This will retry until outlier_detection deems the cluster - // unhealthy and fails over to dc3. - expectUID = topology.ServiceID{ - Name: u.ID.Name, - Partition: "default", - } - expectUID.Normalize() - ct.Assert.FortioFetch2FortioName(t, client, u, "dc3", expectUID) - }) - } -} - -func clusterPrefix(u *topology.Upstream, dc string) string { - u.ID.Normalize() - switch u.ID.Partition { - case "default": - return fmt.Sprintf("%s.%s.%s.internal", u.ID.Name, u.ID.Namespace, dc) - default: - return fmt.Sprintf("%s.%s.%s.%s.internal-v1", u.ID.Name, u.ID.Namespace, u.ID.Partition, dc) - } -} diff --git a/test-integ/peering_commontopo/ac7_1_rotate_gw_test.go b/test-integ/peering_commontopo/ac7_1_rotate_gw_test.go deleted file mode 100644 index b8da4e34bf99f..0000000000000 --- a/test-integ/peering_commontopo/ac7_1_rotate_gw_test.go +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package peering - -import ( - "fmt" - "strings" - "testing" - - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/api" -) - -// TestRotateGW ensures that peered services continue to be able to talk to their -// upstreams during a mesh gateway rotation -// NOTE: because suiteRotateGW needs to mutate the topo, we actually *DO NOT* share a topo - -type suiteRotateGW struct { - DC string - Peer string - - sidServer topology.ServiceID - nodeServer topology.NodeID - - sidClient topology.ServiceID - nodeClient topology.NodeID - - upstream *topology.Upstream - - newMGWNodeName string -} - -func TestRotateGW(t *testing.T) { - suites := []*suiteRotateGW{ - {DC: "dc1", Peer: "dc2"}, - {DC: "dc2", Peer: "dc1"}, - } - ct := NewCommonTopo(t) - for _, s := range suites { - s.setup(t, ct) - } - ct.Launch(t) - for _, s := range suites { - s := s - t.Run(fmt.Sprintf("%s->%s", s.DC, s.Peer), func(t *testing.T) { - // no t.Parallel() due to Relaunch - s.test(t, ct) - }) - } -} - -func (s *suiteRotateGW) setup(t *testing.T, ct *commonTopo) { - const prefix = "ac7-1-" - - clu := ct.ClusterByDatacenter(t, s.DC) - peerClu := ct.ClusterByDatacenter(t, s.Peer) - partition := "default" - peer := LocalPeerName(peerClu, "default") - cluPeerName := LocalPeerName(clu, "default") - - server := NewFortioServiceWithDefaults( - peerClu.Datacenter, - topology.ServiceID{ - Name: prefix + "server-http", - Partition: partition, - }, - nil, - ) - - // Make clients which have server upstreams - upstream := &topology.Upstream{ - ID: topology.ServiceID{ - Name: server.ID.Name, - Partition: partition, - }, - // TODO: we shouldn't need this, need to investigate - LocalAddress: "0.0.0.0", - LocalPort: 5001, - Peer: peer, - } - // create client in us - client := NewFortioServiceWithDefaults( - clu.Datacenter, - topology.ServiceID{ - Name: prefix + "client", - Partition: partition, - }, - func(s *topology.Service) { - s.Upstreams = []*topology.Upstream{ - upstream, - } - }, - ) - clientNode := ct.AddServiceNode(clu, serviceExt{Service: client, - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: client.ID.Name, - Partition: ConfigEntryPartition(client.ID.Partition), - Protocol: "http", - UpstreamConfig: &api.UpstreamConfiguration{ - Defaults: &api.UpstreamConfig{ - MeshGateway: api.MeshGatewayConfig{ - Mode: api.MeshGatewayModeLocal, - }, - }, - }, - }, - }) - // actually to be used by the other pairing - serverNode := ct.AddServiceNode(peerClu, serviceExt{ - Service: server, - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: server.ID.Name, - Partition: ConfigEntryPartition(partition), - Protocol: "http", - }, - Exports: []api.ServiceConsumer{{Peer: cluPeerName}}, - Intentions: &api.ServiceIntentionsConfigEntry{ - Kind: api.ServiceIntentions, - Name: server.ID.Name, - Partition: ConfigEntryPartition(partition), - Sources: []*api.SourceIntention{ - { - Name: client.ID.Name, - Peer: cluPeerName, - Action: api.IntentionActionAllow, - }, - }, - }, - }) - - s.sidClient = client.ID - s.nodeClient = clientNode.ID() - s.upstream = upstream - s.sidServer = server.ID - s.nodeServer = serverNode.ID() - - // add a second mesh gateway "new" - s.newMGWNodeName = fmt.Sprintf("new-%s-default-mgw", clu.Name) - clu.Nodes = append(clu.Nodes, newTopologyMeshGatewaySet( - topology.NodeKindClient, - "default", - s.newMGWNodeName, - 1, - []string{clu.Datacenter, "wan"}, - func(i int, node *topology.Node) { - node.Disabled = true - }, - )...) -} - -func (s *suiteRotateGW) test(t *testing.T, ct *commonTopo) { - dc := ct.Sprawl.Topology().Clusters[s.DC] - peer := ct.Sprawl.Topology().Clusters[s.Peer] - - svcHTTPServer := peer.ServiceByID( - s.nodeServer, - s.sidServer, - ) - svcHTTPClient := dc.ServiceByID( - s.nodeClient, - s.sidClient, - ) - ct.Assert.HealthyWithPeer(t, dc.Name, svcHTTPServer.ID, LocalPeerName(peer, "default")) - - ct.Assert.FortioFetch2HeaderEcho(t, svcHTTPClient, s.upstream) - - t.Log("relaunching with new gateways") - cfg := ct.Sprawl.Config() - for _, n := range dc.Nodes { - if strings.HasPrefix(n.Name, s.newMGWNodeName) { - n.Disabled = false - } - } - require.NoError(t, ct.Sprawl.Relaunch(cfg)) - ct.Assert.FortioFetch2HeaderEcho(t, svcHTTPClient, s.upstream) - - t.Log("relaunching without old gateways") - cfg = ct.Sprawl.Config() - for _, n := range dc.Nodes { - if strings.HasPrefix(n.Name, fmt.Sprintf("%s-default-mgw", dc.Name)) { - n.Disabled = true - } - } - require.NoError(t, ct.Sprawl.Relaunch(cfg)) - ct.Assert.FortioFetch2HeaderEcho(t, svcHTTPClient, s.upstream) -} diff --git a/test-integ/peering_commontopo/ac7_2_rotate_leader_test.go b/test-integ/peering_commontopo/ac7_2_rotate_leader_test.go deleted file mode 100644 index 986e015a02445..0000000000000 --- a/test-integ/peering_commontopo/ac7_2_rotate_leader_test.go +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package peering - -import ( - "fmt" - "testing" - "time" - - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/mitchellh/copystructure" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil/retry" -) - -// TestAC7_2RotateLeader ensures that after a leader rotation, information continues to replicate to peers -// NOTE: because suiteRotateLeader needs to mutate the topo, we actually *DO NOT* share a topo -type ac7_2RotateLeaderSuite struct { - DC string - Peer string - - sidServer topology.ServiceID - nodeServer topology.NodeID - - sidClient topology.ServiceID - nodeClient topology.NodeID - - upstream *topology.Upstream -} - -func TestAC7_2RotateLeader(t *testing.T) { - suites := []*ac7_2RotateLeaderSuite{ - {DC: "dc1", Peer: "dc2"}, - {DC: "dc2", Peer: "dc1"}, - } - ct := NewCommonTopo(t) - for _, s := range suites { - s.setup(t, ct) - } - ct.Launch(t) - for _, s := range suites { - s := s - t.Run(fmt.Sprintf("%s->%s", s.DC, s.Peer), func(t *testing.T) { - // no t.Parallel() due to Relaunch - s.test(t, ct) - }) - } -} - -// makes client in clu, server in peerClu -func (s *ac7_2RotateLeaderSuite) setup(t *testing.T, ct *commonTopo) { - const prefix = "ac7-2-" - - clu := ct.ClusterByDatacenter(t, s.DC) - peerClu := ct.ClusterByDatacenter(t, s.Peer) - partition := "default" - peer := LocalPeerName(peerClu, "default") - cluPeerName := LocalPeerName(clu, "default") - - server := NewFortioServiceWithDefaults( - peerClu.Datacenter, - topology.ServiceID{ - Name: prefix + "server-http", - Partition: partition, - }, - nil, - ) - - // Make clients which have server upstreams - upstream := &topology.Upstream{ - ID: topology.ServiceID{ - Name: server.ID.Name, - Partition: partition, - }, - LocalPort: 5001, - Peer: peer, - } - // create client in us - client := NewFortioServiceWithDefaults( - clu.Datacenter, - topology.ServiceID{ - Name: prefix + "client", - Partition: partition, - }, - func(s *topology.Service) { - s.Upstreams = []*topology.Upstream{ - upstream, - } - }, - ) - clientNode := ct.AddServiceNode(clu, serviceExt{Service: client, - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: client.ID.Name, - Partition: ConfigEntryPartition(client.ID.Partition), - Protocol: "http", - UpstreamConfig: &api.UpstreamConfiguration{ - Defaults: &api.UpstreamConfig{ - MeshGateway: api.MeshGatewayConfig{ - Mode: api.MeshGatewayModeLocal, - }, - }, - }, - }, - }) - // actually to be used by the other pairing - serverNode := ct.AddServiceNode(peerClu, serviceExt{ - Service: server, - Config: &api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: server.ID.Name, - Partition: ConfigEntryPartition(partition), - Protocol: "http", - }, - Exports: []api.ServiceConsumer{{Peer: cluPeerName}}, - Intentions: &api.ServiceIntentionsConfigEntry{ - Kind: api.ServiceIntentions, - Name: server.ID.Name, - Partition: ConfigEntryPartition(partition), - Sources: []*api.SourceIntention{ - { - Name: client.ID.Name, - Peer: cluPeerName, - Action: api.IntentionActionAllow, - }, - }, - }, - }) - - s.sidClient = client.ID - s.nodeClient = clientNode.ID() - s.upstream = upstream - s.sidServer = server.ID - s.nodeServer = serverNode.ID() -} - -func (s *ac7_2RotateLeaderSuite) test(t *testing.T, ct *commonTopo) { - dc := ct.Sprawl.Topology().Clusters[s.DC] - peer := ct.Sprawl.Topology().Clusters[s.Peer] - clDC := ct.APIClientForCluster(t, dc) - clPeer := ct.APIClientForCluster(t, peer) - - svcServer := peer.ServiceByID(s.nodeServer, s.sidServer) - svcClient := dc.ServiceByID(s.nodeClient, s.sidClient) - ct.Assert.HealthyWithPeer(t, dc.Name, svcServer.ID, LocalPeerName(peer, "default")) - - ct.Assert.FortioFetch2HeaderEcho(t, svcClient, s.upstream) - - // force leader election - rotateLeader(t, clDC) - rotateLeader(t, clPeer) - - // unexport httpServer - ce, _, err := clPeer.ConfigEntries().Get(api.ExportedServices, s.sidServer.Partition, nil) - require.NoError(t, err) - // ceAsES = config entry as ExportedServicesConfigEntry - ceAsES := ce.(*api.ExportedServicesConfigEntry) - origCE, err := copystructure.Copy(ceAsES) - require.NoError(t, err) - found := 0 - foundI := 0 - for i, svc := range ceAsES.Services { - if svc.Name == s.sidServer.Name && svc.Namespace == utils.DefaultToEmpty(s.sidServer.Namespace) { - found += 1 - foundI = i - } - } - require.Equal(t, found, 1) - // remove found entry - ceAsES.Services = append(ceAsES.Services[:foundI], ceAsES.Services[foundI+1:]...) - _, _, err = clPeer.ConfigEntries().Set(ceAsES, nil) - require.NoError(t, err) - t.Cleanup(func() { - //restore for next pairing - _, _, err = clPeer.ConfigEntries().Set(origCE.(*api.ExportedServicesConfigEntry), nil) - require.NoError(t, err) - }) - - // expect health entry in for peer to disappear - retry.RunWith(&retry.Timer{Timeout: time.Minute, Wait: time.Millisecond * 500}, t, func(r *retry.R) { - svcs, _, err := clDC.Health().Service(s.sidServer.Name, "", true, utils.CompatQueryOpts(&api.QueryOptions{ - Partition: s.sidServer.Partition, - Namespace: s.sidServer.Namespace, - Peer: LocalPeerName(peer, "default"), - })) - require.NoError(r, err) - assert.Equal(r, len(svcs), 0, "health entry for imported service gone") - }) -} - -func rotateLeader(t *testing.T, cl *api.Client) { - t.Helper() - oldLeader := findLeader(t, cl) - cl.Operator().RaftLeaderTransfer(nil) - retry.RunWith(&retry.Timer{Timeout: 30 * time.Second, Wait: time.Second}, t, func(r *retry.R) { - newLeader := findLeader(r, cl) - require.NotEqual(r, oldLeader.ID, newLeader.ID) - }) -} - -func findLeader(t require.TestingT, cl *api.Client) *api.RaftServer { - raftConfig, err := cl.Operator().RaftGetConfiguration(nil) - require.NoError(t, err) - var leader *api.RaftServer - for _, svr := range raftConfig.Servers { - if svr.Leader { - leader = svr - } - } - require.NotNil(t, leader) - return leader -} diff --git a/test-integ/peering_commontopo/asserter.go b/test-integ/peering_commontopo/asserter.go deleted file mode 100644 index 1fa1b81ef1f43..0000000000000 --- a/test-integ/peering_commontopo/asserter.go +++ /dev/null @@ -1,301 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package peering - -import ( - "fmt" - "io" - "net/http" - "net/url" - "regexp" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/testing/deployer/topology" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil/retry" - libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" -) - -// asserter is a utility to help in reducing boilerplate in invoking test -// assertions against consul-topology Sprawl components. -// -// The methods should largely take in *topology.Service instances in lieu of -// ip/ports if there is only one port that makes sense for the assertion (such -// as use of the envoy admin port 19000). -// -// If it's up to the test (like picking an upstream) leave port as an argument -// but still take the service and use that to grab the local ip from the -// topology.Node. -type asserter struct { - sp sprawlLite -} - -// *sprawl.Sprawl satisfies this. We don't need anything else. -type sprawlLite interface { - HTTPClientForCluster(clusterName string) (*http.Client, error) - APIClientForNode(clusterName string, nid topology.NodeID, token string) (*api.Client, error) - Topology() *topology.Topology -} - -// newAsserter creates a new assertion helper for the provided sprawl. -func newAsserter(sp sprawlLite) *asserter { - return &asserter{ - sp: sp, - } -} - -func (a *asserter) mustGetHTTPClient(t *testing.T, cluster string) *http.Client { - client, err := a.httpClientFor(cluster) - require.NoError(t, err) - return client -} - -func (a *asserter) mustGetAPIClient(t *testing.T, cluster string) *api.Client { - cl, err := a.apiClientFor(cluster) - require.NoError(t, err) - return cl -} - -func (a *asserter) apiClientFor(cluster string) (*api.Client, error) { - clu := a.sp.Topology().Clusters[cluster] - // TODO: this always goes to the first client, but we might want to balance this - cl, err := a.sp.APIClientForNode(cluster, clu.FirstClient().ID(), "") - return cl, err -} - -// httpClientFor returns a pre-configured http.Client that proxies requests -// through the embedded squid instance in each LAN. -// -// Use this in methods below to magically pick the right proxied http client -// given the home of each node being checked. -func (a *asserter) httpClientFor(cluster string) (*http.Client, error) { - client, err := a.sp.HTTPClientForCluster(cluster) - if err != nil { - return nil, err - } - return client, nil -} - -// UpstreamEndpointStatus validates that proxy was configured with provided clusterName in the healthStatus -// -// Exposes libassert.UpstreamEndpointStatus for use against a Sprawl. -// -// NOTE: this doesn't take a port b/c you always want to use the envoy admin port. -func (a *asserter) UpstreamEndpointStatus( - t *testing.T, - service *topology.Service, - clusterName string, - healthStatus string, - count int, -) { - t.Helper() - node := service.Node - ip := node.LocalAddress() - port := service.EnvoyAdminPort - addr := fmt.Sprintf("%s:%d", ip, port) - - client := a.mustGetHTTPClient(t, node.Cluster) - libassert.AssertUpstreamEndpointStatusWithClient(t, client, addr, clusterName, healthStatus, count) -} - -// HTTPServiceEchoes verifies that a post to the given ip/port combination -// returns the data in the response body. Optional path can be provided to -// differentiate requests. -// -// Exposes libassert.HTTPServiceEchoes for use against a Sprawl. -// -// NOTE: this takes a port b/c you may want to reach this via your choice of upstream. -func (a *asserter) HTTPServiceEchoes( - t *testing.T, - service *topology.Service, - port int, - path string, -) { - t.Helper() - require.True(t, port > 0) - - node := service.Node - ip := node.LocalAddress() - addr := fmt.Sprintf("%s:%d", ip, port) - - client := a.mustGetHTTPClient(t, node.Cluster) - libassert.HTTPServiceEchoesWithClient(t, client, addr, path) -} - -// HTTPServiceEchoesResHeader verifies that a post to the given ip/port combination -// returns the data in the response body with expected response headers. -// Optional path can be provided to differentiate requests. -// -// Exposes libassert.HTTPServiceEchoes for use against a Sprawl. -// -// NOTE: this takes a port b/c you may want to reach this via your choice of upstream. -func (a *asserter) HTTPServiceEchoesResHeader( - t *testing.T, - service *topology.Service, - port int, - path string, - expectedResHeader map[string]string, -) { - t.Helper() - require.True(t, port > 0) - - node := service.Node - ip := node.LocalAddress() - addr := fmt.Sprintf("%s:%d", ip, port) - - client := a.mustGetHTTPClient(t, node.Cluster) - libassert.HTTPServiceEchoesResHeaderWithClient(t, client, addr, path, expectedResHeader) -} - -func (a *asserter) HTTPStatus( - t *testing.T, - service *topology.Service, - port int, - status int, -) { - t.Helper() - require.True(t, port > 0) - - node := service.Node - ip := node.LocalAddress() - addr := fmt.Sprintf("%s:%d", ip, port) - - client := a.mustGetHTTPClient(t, node.Cluster) - - url := "http://" + addr - - retry.RunWith(&retry.Timer{Timeout: 30 * time.Second, Wait: 500 * time.Millisecond}, t, func(r *retry.R) { - resp, err := client.Get(url) - if err != nil { - r.Fatalf("could not make request to %q: %v", url, err) - } - defer resp.Body.Close() - if resp.StatusCode != status { - r.Fatalf("expected status %d, got %d", status, resp.StatusCode) - } - }) -} - -// asserts that the service sid in cluster and exported by peer localPeerName is passing health checks, -func (a *asserter) HealthyWithPeer(t *testing.T, cluster string, sid topology.ServiceID, peerName string) { - t.Helper() - cl := a.mustGetAPIClient(t, cluster) - retry.RunWith(&retry.Timer{Timeout: time.Minute * 1, Wait: time.Millisecond * 500}, t, func(r *retry.R) { - svcs, _, err := cl.Health().Service( - sid.Name, - "", - true, - utils.CompatQueryOpts(&api.QueryOptions{ - Partition: sid.Partition, - Namespace: sid.Namespace, - Peer: peerName, - }), - ) - require.NoError(r, err) - assert.GreaterOrEqual(r, len(svcs), 1) - }) -} - -func (a *asserter) UpstreamEndpointHealthy(t *testing.T, svc *topology.Service, upstream *topology.Upstream) { - t.Helper() - node := svc.Node - ip := node.LocalAddress() - port := svc.EnvoyAdminPort - addr := fmt.Sprintf("%s:%d", ip, port) - - client := a.mustGetHTTPClient(t, node.Cluster) - libassert.AssertUpstreamEndpointStatusWithClient(t, - client, - addr, - // TODO: what is default? namespace? partition? - fmt.Sprintf("%s.default.%s.external", upstream.ID.Name, upstream.Peer), - "HEALTHY", - 1, - ) -} - -// does a fortio /fetch2 to the given fortio service, targetting the given upstream. Returns -// the body, and response with response.Body already Closed. -// -// We treat 400, 503, and 504s as retryable errors -func (a *asserter) fortioFetch2Upstream(t *testing.T, fortioSvc *topology.Service, upstream *topology.Upstream, path string) (body []byte, res *http.Response) { - t.Helper() - - // TODO: fortioSvc.ID.Normalize()? or should that be up to the caller? - - node := fortioSvc.Node - client := a.mustGetHTTPClient(t, node.Cluster) - urlbase := fmt.Sprintf("%s:%d", node.LocalAddress(), fortioSvc.Port) - - url := fmt.Sprintf("http://%s/fortio/fetch2?url=%s", urlbase, - url.QueryEscape(fmt.Sprintf("http://localhost:%d/%s", upstream.LocalPort, path)), - ) - - req, err := http.NewRequest(http.MethodPost, url, nil) - require.NoError(t, err) - retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Millisecond * 500}, t, func(r *retry.R) { - res, err = client.Do(req) - require.NoError(r, err) - defer res.Body.Close() - // not sure when these happen, suspect it's when the mesh gateway in the peer is not yet ready - require.NotEqual(r, http.StatusServiceUnavailable, res.StatusCode) - require.NotEqual(r, http.StatusGatewayTimeout, res.StatusCode) - // not sure when this happens, suspect it's when envoy hasn't configured the local upstream yet - require.NotEqual(r, http.StatusBadRequest, res.StatusCode) - body, err = io.ReadAll(res.Body) - require.NoError(r, err) - }) - - return body, res -} - -// uses the /fortio/fetch2 endpoint to do a header echo check against an -// upstream fortio -func (a *asserter) FortioFetch2HeaderEcho(t *testing.T, fortioSvc *topology.Service, upstream *topology.Upstream) { - const kPassphrase = "x-passphrase" - const passphrase = "hello" - path := (fmt.Sprintf("/?header=%s:%s", kPassphrase, passphrase)) - - retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Millisecond * 500}, t, func(r *retry.R) { - _, res := a.fortioFetch2Upstream(t, fortioSvc, upstream, path) - require.Equal(t, http.StatusOK, res.StatusCode) - v := res.Header.Get(kPassphrase) - require.Equal(t, passphrase, v) - }) -} - -// similar to libassert.AssertFortioName, -// uses the /fortio/fetch2 endpoint to hit the debug endpoint on the upstream, -// and assert that the FORTIO_NAME == name -func (a *asserter) FortioFetch2FortioName(t *testing.T, fortioSvc *topology.Service, upstream *topology.Upstream, clusterName string, sid topology.ServiceID) { - t.Helper() - - var fortioNameRE = regexp.MustCompile(("\nFORTIO_NAME=(.+)\n")) - path := "/debug?env=dump" - - retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Millisecond * 500}, t, func(r *retry.R) { - body, res := a.fortioFetch2Upstream(t, fortioSvc, upstream, path) - require.Equal(t, http.StatusOK, res.StatusCode) - - // TODO: not sure we should retry these? - m := fortioNameRE.FindStringSubmatch(string(body)) - require.GreaterOrEqual(r, len(m), 2) - // TODO: dedupe from NewFortioService - require.Equal(r, fmt.Sprintf("%s::%s", clusterName, sid.String()), m[1]) - }) -} - -// CatalogServiceExists is the same as libassert.CatalogServiceExists, except that it uses -// a proxied API client -func (a *asserter) CatalogServiceExists(t *testing.T, cluster string, svc string, opts *api.QueryOptions) { - t.Helper() - cl := a.mustGetAPIClient(t, cluster) - libassert.CatalogServiceExists(t, cl, svc, opts) -} diff --git a/test-integ/peering_commontopo/commontopo.go b/test-integ/peering_commontopo/commontopo.go deleted file mode 100644 index d0e2c8e55dcbf..0000000000000 --- a/test-integ/peering_commontopo/commontopo.go +++ /dev/null @@ -1,613 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package peering - -import ( - "bytes" - "context" - "fmt" - "strconv" - "testing" - "text/tabwriter" - "time" - - "github.com/hashicorp/consul/testing/deployer/sprawl" - "github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest" - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil/retry" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" -) - -// commonTopo helps create a shareable topology configured to represent -// the common denominator between tests. -// -// Use NewCommonTopo to create. -// -// Compatible suites should implement sharedTopoSuite. -// -// Style: -// - avoid referencing components using strings, prefer IDs like Service ID, etc. -// - avoid passing addresses and ports, etc. Instead, look up components in sprawl.Topology -// by ID to find a concrete type, then pass that to helper functions that know which port to use -// - minimize the surface area of information passed between setup and test code (via members) -// to those that are strictly necessary -type commonTopo struct { - // - Cfg *topology.Config - // shortcuts to corresponding entry in Cfg - DC1 *topology.Cluster - DC2 *topology.Cluster - DC3 *topology.Cluster - - // set after Launch. Should be considered read-only - Sprawl *sprawl.Sprawl - Assert *asserter - - // track per-DC services to prevent duplicates - services map[string]map[topology.ServiceID]struct{} -} - -func NewCommonTopo(t *testing.T) *commonTopo { - t.Helper() - - ct := commonTopo{} - - // Make 3-server clusters in dc1 and dc2 - // For simplicity, the Name and Datacenter of the clusters are the same. - // dc1 and dc2 should be symmetric. - dc1 := clusterWithJustServers("dc1", 3) - ct.DC1 = dc1 - dc2 := clusterWithJustServers("dc2", 3) - ct.DC2 = dc2 - // dc3 is a failover cluster for both dc1 and dc2 - dc3 := clusterWithJustServers("dc3", 1) - // dc3 is only used for certain failover scenarios and does not need tenancies - dc3.Partitions = []*topology.Partition{{Name: "default"}} - ct.DC3 = dc3 - - injectTenancies(dc1) - injectTenancies(dc2) - // dc3 is only used for certain failover scenarios and does not need tenancies - dc3.Partitions = []*topology.Partition{{Name: "default"}} - - ct.services = map[string]map[topology.ServiceID]struct{}{} - for _, dc := range []*topology.Cluster{dc1, dc2, dc3} { - ct.services[dc.Datacenter] = map[topology.ServiceID]struct{}{} - } - - peerings := addPeerings(dc1, dc2) - peerings = append(peerings, addPeerings(dc1, dc3)...) - peerings = append(peerings, addPeerings(dc2, dc3)...) - - addMeshGateways(dc1, topology.NodeKindClient) - addMeshGateways(dc2, topology.NodeKindClient) - addMeshGateways(dc3, topology.NodeKindClient) - // TODO: consul-topology doesn't support this yet - // addMeshGateways(dc2, topology.NodeKindDataplane) - - setupGlobals(dc1) - setupGlobals(dc2) - setupGlobals(dc3) - - // Build final configuration - ct.Cfg = &topology.Config{ - Images: utils.TargetImages(), - Networks: []*topology.Network{ - {Name: dc1.Datacenter}, // "dc1" LAN - {Name: dc2.Datacenter}, // "dc2" LAN - {Name: dc3.Datacenter}, // "dc3" LAN - {Name: "wan", Type: "wan"}, - }, - Clusters: []*topology.Cluster{ - dc1, - dc2, - dc3, - }, - Peerings: peerings, - } - return &ct -} - -// calls sprawltest.Launch followed by s.postLaunchChecks -func (ct *commonTopo) Launch(t *testing.T) { - if ct.Sprawl != nil { - t.Fatalf("Launch must only be called once") - } - ct.Sprawl = sprawltest.Launch(t, ct.Cfg) - - ct.Assert = newAsserter(ct.Sprawl) - ct.postLaunchChecks(t) -} - -// tests that use Relaunch might want to call this again afterwards -func (ct *commonTopo) postLaunchChecks(t *testing.T) { - t.Logf("TESTING RELATIONSHIPS: \n%s", - renderRelationships(computeRelationships(ct.Sprawl.Topology())), - ) - - // check that exports line up as expected - for _, clu := range ct.Sprawl.Config().Clusters { - // expected exports per peer - type key struct { - peer string - partition string - namespace string - } - eepp := map[key]int{} - for _, e := range clu.InitialConfigEntries { - if e.GetKind() == api.ExportedServices { - asExport := e.(*api.ExportedServicesConfigEntry) - // do we care about the partition? - for _, svc := range asExport.Services { - for _, con := range svc.Consumers { - // do we care about con.Partition? - // TODO: surely there is code to normalize this - partition := asExport.Partition - if partition == "" { - partition = "default" - } - namespace := svc.Namespace - if namespace == "" { - namespace = "default" - } - eepp[key{peer: con.Peer, partition: partition, namespace: namespace}] += 1 - } - } - } - } - cl := ct.APIClientForCluster(t, clu) - // TODO: these could probably be done in parallel - for k, v := range eepp { - retry.RunWith(&retry.Timer{Timeout: 30 * time.Second, Wait: 500 * time.Millisecond}, t, func(r *retry.R) { - peering, _, err := cl.Peerings().Read(context.Background(), k.peer, utils.CompatQueryOpts(&api.QueryOptions{ - Partition: k.partition, - Namespace: k.namespace, - })) - require.Nil(r, err, "reading peering data") - require.NotNilf(r, peering, "peering not found %q", k.peer) - assert.Len(r, peering.StreamStatus.ExportedServices, v, "peering exported services") - }) - } - } - - if t.Failed() { - t.Fatal("failing fast: post-Launch assertions failed") - } -} - -// PeerName is how you'd address a remote dc+partition locally -// as your peer name. -func LocalPeerName(clu *topology.Cluster, partition string) string { - return fmt.Sprintf("peer-%s-%s", clu.Datacenter, partition) -} - -// TODO: move these to topology -// TODO: alternatively, delete it: we only use it in one place, to bundle up args -type serviceExt struct { - *topology.Service - - // default NodeKindClient - NodeKind topology.NodeKind - - Exports []api.ServiceConsumer - Config *api.ServiceConfigEntry - Intentions *api.ServiceIntentionsConfigEntry -} - -func (ct *commonTopo) AddServiceNode(clu *topology.Cluster, svc serviceExt) *topology.Node { - clusterName := clu.Name - if _, ok := ct.services[clusterName][svc.ID]; ok { - panic(fmt.Sprintf("duplicate service %q in cluster %q", svc.ID, clusterName)) - } - ct.services[clusterName][svc.ID] = struct{}{} - - // TODO: inline - serviceHostnameString := func(dc string, id topology.ServiceID) string { - n := id.Name - // prepend - and - if they are not default/empty - // avoids hostname limit of 63 chars in most cases - // TODO: this obviously isn't scalable - if id.Namespace != "default" && id.Namespace != "" { - n = id.Namespace + "-" + n - } - if id.Partition != "default" && id.Partition != "" { - n = id.Partition + "-" + n - } - n = dc + "-" + n - // TODO: experimentally, when this is larger than 63, docker can't start - // the host. confirmed by internet rumor https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27763 - if len(n) > 63 { - panic(fmt.Sprintf("docker hostname must not be longer than 63 chars: %q", n)) - } - return n - } - - node := &topology.Node{ - Kind: topology.NodeKindClient, - Name: serviceHostnameString(clu.Datacenter, svc.ID), - Partition: svc.ID.Partition, - Addresses: []*topology.Address{ - {Network: clu.Datacenter}, - }, - Services: []*topology.Service{ - svc.Service, - }, - Cluster: clusterName, - } - if svc.NodeKind != "" { - node.Kind = svc.NodeKind - } - clu.Nodes = append(clu.Nodes, node) - - // Export if necessary - if len(svc.Exports) > 0 { - ct.ExportService(clu, svc.ID.Partition, api.ExportedService{ - Name: svc.ID.Name, - Namespace: svc.ID.Namespace, - Consumers: svc.Exports, - }) - } - - // Add any config entries - if svc.Config != nil { - clu.InitialConfigEntries = append(clu.InitialConfigEntries, svc.Config) - } - if svc.Intentions != nil { - clu.InitialConfigEntries = append(clu.InitialConfigEntries, svc.Intentions) - } - - return node -} - -func (ct *commonTopo) APIClientForCluster(t *testing.T, clu *topology.Cluster) *api.Client { - cl, err := ct.Sprawl.APIClientForNode(clu.Name, clu.FirstClient().ID(), "") - require.NoError(t, err) - return cl -} - -// ExportService looks for an existing ExportedServicesConfigEntry for the given partition -// and inserts svcs. If none is found, it inserts a new ExportedServicesConfigEntry. -func (ct *commonTopo) ExportService(clu *topology.Cluster, partition string, svcs ...api.ExportedService) { - var found bool - for _, ce := range clu.InitialConfigEntries { - // We check Name because it must be "default" in CE whereas Partition will be "". - if ce.GetKind() == api.ExportedServices && ce.GetName() == partition { - found = true - e := ce.(*api.ExportedServicesConfigEntry) - e.Services = append(e.Services, svcs...) - } - } - if !found { - clu.InitialConfigEntries = append(clu.InitialConfigEntries, - &api.ExportedServicesConfigEntry{ - Name: partition, // this NEEDs to be "default" in CE - Partition: ConfigEntryPartition(partition), - Services: svcs, - }, - ) - } -} - -func (ct *commonTopo) ClusterByDatacenter(t *testing.T, name string) *topology.Cluster { - t.Helper() - - for _, clu := range ct.Cfg.Clusters { - if clu.Datacenter == name { - return clu - } - } - t.Fatalf("cluster %q not found", name) - return nil -} - -// Since CE config entries do not contain the partition field, -// this func converts default partition to empty string. -func ConfigEntryPartition(p string) string { - if p == "default" { - return "" // make this CE friendly - } - return p -} - -// disableNode is a no-op if the node is already disabled. -func DisableNode(t *testing.T, cfg *topology.Config, clusterName string, nid topology.NodeID) *topology.Config { - nodes := cfg.Cluster(clusterName).Nodes - var found bool - for _, n := range nodes { - if n.ID() == nid { - found = true - if n.Disabled { - return cfg - } - t.Logf("disabling node %s in cluster %s", nid.String(), clusterName) - n.Disabled = true - break - } - } - require.True(t, found, "expected to find nodeID %q in cluster %q", nid.String(), clusterName) - return cfg -} - -// enableNode is a no-op if the node is already enabled. -func EnableNode(t *testing.T, cfg *topology.Config, clusterName string, nid topology.NodeID) *topology.Config { - nodes := cfg.Cluster(clusterName).Nodes - var found bool - for _, n := range nodes { - if n.ID() == nid { - found = true - if !n.Disabled { - return cfg - } - t.Logf("enabling node %s in cluster %s", nid.String(), clusterName) - n.Disabled = false - break - } - } - require.True(t, found, "expected to find nodeID %q in cluster %q", nid.String(), clusterName) - return cfg -} - -func setupGlobals(clu *topology.Cluster) { - for _, part := range clu.Partitions { - clu.InitialConfigEntries = append(clu.InitialConfigEntries, - &api.ProxyConfigEntry{ - Name: api.ProxyConfigGlobal, - Kind: api.ProxyDefaults, - Partition: ConfigEntryPartition(part.Name), - MeshGateway: api.MeshGatewayConfig{ - // Although we define service-defaults for most upstreams in - // this test suite, failover tests require a global mode - // because the default for peered targets is MeshGatewayModeRemote. - Mode: api.MeshGatewayModeLocal, - }, - }, - ) - } -} - -// addMeshGateways adds a mesh gateway for every partition in the cluster. -// Assumes that the LAN network name is equal to datacenter name. -func addMeshGateways(c *topology.Cluster, kind topology.NodeKind) { - for _, p := range c.Partitions { - c.Nodes = topology.MergeSlices(c.Nodes, newTopologyMeshGatewaySet( - kind, - p.Name, - fmt.Sprintf("%s-%s-mgw", c.Name, p.Name), - 1, - []string{c.Datacenter, "wan"}, - nil, - )) - } -} - -func clusterWithJustServers(name string, numServers int) *topology.Cluster { - return &topology.Cluster{ - Enterprise: utils.IsEnterprise(), - Name: name, - Datacenter: name, - Nodes: newTopologyServerSet( - name+"-server", - numServers, - []string{name, "wan"}, - nil, - ), - } -} - -func addPeerings(acc *topology.Cluster, dial *topology.Cluster) []*topology.Peering { - peerings := []*topology.Peering{} - for _, accPart := range acc.Partitions { - for _, dialPart := range dial.Partitions { - peerings = append(peerings, &topology.Peering{ - Accepting: topology.PeerCluster{ - Name: acc.Datacenter, - Partition: accPart.Name, - PeerName: LocalPeerName(dial, dialPart.Name), - }, - Dialing: topology.PeerCluster{ - Name: dial.Datacenter, - Partition: dialPart.Name, - PeerName: LocalPeerName(acc, accPart.Name), - }, - }) - } - } - return peerings -} - -func injectTenancies(clu *topology.Cluster) { - if !utils.IsEnterprise() { - clu.Partitions = []*topology.Partition{ - { - Name: "default", - Namespaces: []string{ - "default", - }, - }, - } - return - } - - for _, part := range []string{"default", "part1"} { - clu.Partitions = append(clu.Partitions, - &topology.Partition{ - Name: part, - Namespaces: []string{ - "default", - "ns1", - }, - }, - ) - } -} - -func newTopologyServerSet( - namePrefix string, - num int, - networks []string, - mutateFn func(i int, node *topology.Node), -) []*topology.Node { - var out []*topology.Node - for i := 1; i <= num; i++ { - name := namePrefix + strconv.Itoa(i) - - node := &topology.Node{ - Kind: topology.NodeKindServer, - Name: name, - } - for _, net := range networks { - node.Addresses = append(node.Addresses, &topology.Address{Network: net}) - } - - if mutateFn != nil { - mutateFn(i, node) - } - - out = append(out, node) - } - return out -} - -func newTopologyMeshGatewaySet( - nodeKind topology.NodeKind, - partition string, - namePrefix string, - num int, - networks []string, - mutateFn func(i int, node *topology.Node), -) []*topology.Node { - var out []*topology.Node - for i := 1; i <= num; i++ { - name := namePrefix + strconv.Itoa(i) - - node := &topology.Node{ - Kind: nodeKind, - Partition: partition, - Name: name, - Services: []*topology.Service{{ - ID: topology.ServiceID{Name: "mesh-gateway"}, - Port: 8443, - EnvoyAdminPort: 19000, - IsMeshGateway: true, - }}, - } - for _, net := range networks { - node.Addresses = append(node.Addresses, &topology.Address{Network: net}) - } - - if mutateFn != nil { - mutateFn(i, node) - } - - out = append(out, node) - } - return out -} - -const HashicorpDockerProxy = "docker.mirror.hashicorp.services" - -func NewFortioServiceWithDefaults( - cluster string, - sid topology.ServiceID, - mut func(s *topology.Service), -) *topology.Service { - const ( - httpPort = 8080 - grpcPort = 8079 - adminPort = 19000 - ) - sid.Normalize() - - svc := &topology.Service{ - ID: sid, - Image: HashicorpDockerProxy + "/fortio/fortio", - Port: httpPort, - EnvoyAdminPort: adminPort, - CheckTCP: "127.0.0.1:" + strconv.Itoa(httpPort), - Env: []string{ - "FORTIO_NAME=" + cluster + "::" + sid.String(), - }, - Command: []string{ - "server", - "-http-port", strconv.Itoa(httpPort), - "-grpc-port", strconv.Itoa(grpcPort), - "-redirect-port", "-disabled", - }, - } - if mut != nil { - mut(svc) - } - return svc -} - -// computeRelationships will analyze a full topology and generate all of the -// downstream/upstream information for all of them. -func computeRelationships(topo *topology.Topology) []Relationship { - var out []Relationship - for _, cluster := range topo.Clusters { - for _, n := range cluster.Nodes { - for _, s := range n.Services { - for _, u := range s.Upstreams { - out = append(out, Relationship{ - Caller: s, - Upstream: u, - }) - } - } - } - } - return out -} - -// renderRelationships will take the output of ComputeRelationships and display -// it in tabular form. -func renderRelationships(ships []Relationship) string { - var buf bytes.Buffer - w := tabwriter.NewWriter(&buf, 0, 0, 3, ' ', tabwriter.Debug) - fmt.Fprintf(w, "DOWN\tnode\tservice\tport\tUP\tservice\t\n") - for _, r := range ships { - fmt.Fprintf(w, - "%s\t%s\t%s\t%d\t%s\t%s\t\n", - r.downCluster(), - r.Caller.Node.ID().String(), - r.Caller.ID.String(), - r.Upstream.LocalPort, - r.upCluster(), - r.Upstream.ID.String(), - ) - } - fmt.Fprintf(w, "\t\t\t\t\t\t\n") - - w.Flush() - return buf.String() -} - -type Relationship struct { - Caller *topology.Service - Upstream *topology.Upstream -} - -func (r Relationship) String() string { - return fmt.Sprintf( - "%s on %s in %s via :%d => %s in %s", - r.Caller.ID.String(), - r.Caller.Node.ID().String(), - r.downCluster(), - r.Upstream.LocalPort, - r.Upstream.ID.String(), - r.upCluster(), - ) -} - -func (r Relationship) downCluster() string { - return r.Caller.Node.Cluster -} - -func (r Relationship) upCluster() string { - return r.Upstream.Cluster -} diff --git a/test-integ/peering_commontopo/sharedtopology_test.go b/test-integ/peering_commontopo/sharedtopology_test.go deleted file mode 100644 index f51b05e41ef78..0000000000000 --- a/test-integ/peering_commontopo/sharedtopology_test.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package peering - -import ( - "flag" - "testing" -) - -// Tests that use commonTopo should implement sharedTopoSuite. -// -// Tests that use commonTopo are either cooperative or non-cooperative. Non-cooperative -// uses of commonTopo include is anything that may interfere with other tests, namely -// mutations, such as: -// - any calls to commonTopo.Relaunch; this is generally disruptive to other tests -// - stopping or disabling nodes -// - ... -// -// Cooperative tests should just call testFuncMayReuseCommonTopo() to ensure they -// are run in the correct `sharetopo` mode. They should also ensure they are included -// in the commonTopoSuites slice in TestSuitesOnSharedTopo. -type sharedTopoSuite interface { - testName() string - setup(*testing.T, *commonTopo) - test(*testing.T, *commonTopo) -} - -var flagNoShareTopo = flag.Bool("no-share-topo", false, "do not share topology; run each test in its own isolated topology") - -func runShareableSuites(t *testing.T, suites []sharedTopoSuite) { - t.Helper() - if !*flagNoShareTopo { - names := []string{} - for _, s := range suites { - names = append(names, s.testName()) - } - t.Skipf(`Will run as part of "TestSuitesOnSharedTopo": %v`, names) - } - ct := NewCommonTopo(t) - for _, s := range suites { - s.setup(t, ct) - } - ct.Launch(t) - for _, s := range suites { - s := s - t.Run(s.testName(), func(t *testing.T) { - t.Parallel() - s.test(t, ct) - }) - } -} - -// Tests that can share topo must implement sharedTopoSuite and be appended to the sharedTopoSuites -// slice inside -func TestSuitesOnSharedTopo(t *testing.T) { - if *flagNoShareTopo { - t.Skip(`shared topo suites disabled by -no-share-topo`) - } - ct := NewCommonTopo(t) - - sharedTopoSuites := []sharedTopoSuite{} - sharedTopoSuites = append(sharedTopoSuites, ac1BasicSuites...) - sharedTopoSuites = append(sharedTopoSuites, ac2DiscoChainSuites...) - sharedTopoSuites = append(sharedTopoSuites, ac3SvcDefaultsSuites...) - sharedTopoSuites = append(sharedTopoSuites, ac4ProxyDefaultsSuites...) - sharedTopoSuites = append(sharedTopoSuites, ac5_1NoSvcMeshSuites...) - - for _, s := range sharedTopoSuites { - s.setup(t, ct) - } - ct.Launch(t) - for _, s := range sharedTopoSuites { - s := s - t.Run(s.testName(), func(t *testing.T) { - t.Parallel() - s.test(t, ct) - }) - } -} - -func TestCommonTopologySetup(t *testing.T) { - ct := NewCommonTopo(t) - ct.Launch(t) -} diff --git a/test/bin/cluster.bash b/test/bin/cluster.bash index a6bc7d336f11f..8b856c4a2c9a9 100755 --- a/test/bin/cluster.bash +++ b/test/bin/cluster.bash @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # # Script for bringing up an N node consul cluster diff --git a/test/ca/generate.sh b/test/ca/generate.sh index 7159431f4c490..897071dda8a0b 100755 --- a/test/ca/generate.sh +++ b/test/ca/generate.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -e diff --git a/test/client_certs/generate.sh b/test/client_certs/generate.sh index f5c645d7bbb76..e93f568dcb126 100755 --- a/test/client_certs/generate.sh +++ b/test/client_certs/generate.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/hostname/generate.sh b/test/hostname/generate.sh index 8e43dbee4e8a5..61febd2a36751 100755 --- a/test/hostname/generate.sh +++ b/test/hostname/generate.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/Dockerfile-consul-envoy-windows b/test/integration/connect/envoy/Dockerfile-consul-envoy-windows deleted file mode 100644 index b760fd5754f7d..0000000000000 --- a/test/integration/connect/envoy/Dockerfile-consul-envoy-windows +++ /dev/null @@ -1,12 +0,0 @@ -# From Consul Version 1.13.3 / 1.12.6 / 1.11.11 -ARG VERSION=1.16.0-dev -# From Envoy version 1.23.1 / 1.21.5 / 1.20.7 -ARG ENVOY_VERSION - -FROM docker.mirror.hashicorp.services/windows/envoy-windows:v${ENVOY_VERSION} as envoy -FROM windows/consul:${VERSION} - -# Copy envoy.exe from FROM windows/envoy-windows:${ENVOY_VERSION} -COPY --from=envoy ["C:/Program Files/envoy/", "C:/envoy/"] - -RUN SETX /M path "%PATH%;C:\envoy;" \ No newline at end of file diff --git a/test/integration/connect/envoy/Dockerfile-tcpdump-windows b/test/integration/connect/envoy/Dockerfile-tcpdump-windows deleted file mode 100644 index cbf5041630b99..0000000000000 --- a/test/integration/connect/envoy/Dockerfile-tcpdump-windows +++ /dev/null @@ -1,7 +0,0 @@ -FROM mcr.microsoft.com/windows/servercore:ltsc2019 - -COPY ["tcpdump.exe", "C:/Program Files/"] - -ENTRYPOINT ["C:/Program Files/tcpdump.exe"] - -# docker.exe build -t envoy-tcpdump -f Dockerfile-tcpdump-windows . diff --git a/test/integration/connect/envoy/Dockerfile-test-sds-server-windows b/test/integration/connect/envoy/Dockerfile-test-sds-server-windows deleted file mode 100644 index fc5e45b88d355..0000000000000 --- a/test/integration/connect/envoy/Dockerfile-test-sds-server-windows +++ /dev/null @@ -1,8 +0,0 @@ -FROM docker.mirror.hashicorp.services/windows/golang:1809 - -WORKDIR /go/src -COPY ./ . - -RUN go build -v -o test-sds-server.exe sds.go - -CMD ["test-sds-server.exe"] diff --git a/test/integration/connect/envoy/README.md b/test/integration/connect/envoy/README.md index ef358e7a2b44a..a97acc710a953 100644 --- a/test/integration/connect/envoy/README.md +++ b/test/integration/connect/envoy/README.md @@ -52,7 +52,6 @@ Where `case-basic` can be replaced by any directory name from this directory. * When tests fail in CI, logs and additional debugging data are available in the artifacts of the test run. * You can re-run the tests locally by running `make test-envoy-integ GO_TEST_FLAGS="-run TestEnvoy/"` where `` is replaced with the name of the directory, e.g. `case-basic`. -* You can override the envoy version by specifying `ENVOY_VERSION=` eg. `ENVOY_VERSION=1.27.0 make test-envoy-integ`. * Locally, all the logs of the failed test will be available in `workdir` in this directory. * You can run with `DEBUG=1` to print out all the commands being run, e.g. `DEBUG=1 make test-envoy-integ GO_TEST_FLAGS="-run TestEnvoy/case-basic"`. * If you want to prevent the Docker containers from being spun down after test failure, add a `sleep 9999` to the `verify.bats` test case that's failing. diff --git a/test/integration/connect/envoy/WINDOWS-TEST.md b/test/integration/connect/envoy/WINDOWS-TEST.md deleted file mode 100644 index d9217f7a385a9..0000000000000 --- a/test/integration/connect/envoy/WINDOWS-TEST.md +++ /dev/null @@ -1,40 +0,0 @@ -# Envoy Integration Tests on Windows - -## Index - -- [About](#about) -- [Pre-built core images](#pre-built-core-images) -- [Test images](#integration-test-images) -- [Run Tests](#run-tests) - -## About - -This file is the entrypoint to understand how to execute Envoy integration tests on Windows as well as to understand the differences between Linux tests and Windows tests. Below you can find a list of relevant documentation that has been written while working on supporting the Envoy integration tests on Windows. - -- [Windows Testing Architecture](test/integration/connect/envoy/docs/windows-testing-architecture.md): On this file you will find why the testing architecture on Windows differs from Linux's. -- [Build Images](build-support-windows/BUILD-IMAGES.md): Here you will find how to build the images required for executing the tests. -- [Windows Troubleshooting](test/integration/connect/envoy/WindowsTroubleshooting.md): This file lists, among other things everything we needed to change/adapt for the existing tests to run in Windows containers. - -## Pre-built core images - -Before running the integration tests, you must pre-build the core images that the tests require to be ran on the Windows environment. Make sure to check out the `BUILD-IMAGES` file [here](build-support-windows/BUILD-IMAGES.md) for this purpose. - -## Integration test images - -During the execution of the integration tests, several images are built based-on the pre-built core images. To get more information about these and how to run them independently, please check out the `docker.windows` file [here](test/integration/connect/envoy/docker.windows.md). - -## Run tests - -To run all the integration tests, you need to execute next command - -```shell -go test -v -timeout=30s -tags integration ./test/integration/connect/envoy -run="TestEnvoy" -win=true -``` - -To run a single test case, the name should be specified. For instance, to run the `case-badauthz` test, you need to execute next command - -```shell -go test -v -timeout=30m -tags integration ./test/integration/connect/envoy -run="TestEnvoy/case-badauthz" -win=true -``` - -> :warning: Note that the flag `-win=true` must be specified as shown in the above commands. This flag is very important because the same allows to indicate that the tests will be executed on the Windows environment. When executing the Envoy integration tests the **End of Line Sequence** of every related file and or script will be automatically changed from **LF to CRLF**. diff --git a/test/integration/connect/envoy/case-api-gateway-http-hostnames/capture.sh b/test/integration/connect/envoy/case-api-gateway-http-hostnames/capture.sh index 92123f3f4c077..13eb01ba5f824 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-hostnames/capture.sh +++ b/test/integration/connect/envoy/case-api-gateway-http-hostnames/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 api-gateway primary || true \ No newline at end of file diff --git a/test/integration/connect/envoy/case-api-gateway-http-hostnames/service_gateway.hcl b/test/integration/connect/envoy/case-api-gateway-http-hostnames/service_gateway.hcl index 1d0d5fffe26bf..c0af862f92e32 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-hostnames/service_gateway.hcl +++ b/test/integration/connect/envoy/case-api-gateway-http-hostnames/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "api-gateway" diff --git a/test/integration/connect/envoy/case-api-gateway-http-hostnames/setup.sh b/test/integration/connect/envoy/case-api-gateway-http-hostnames/setup.sh index 3b3db83268911..754e461f847ed 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-hostnames/setup.sh +++ b/test/integration/connect/envoy/case-api-gateway-http-hostnames/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-api-gateway-http-hostnames/vars.sh b/test/integration/connect/envoy/case-api-gateway-http-hostnames/vars.sh index 1456b6a5ad024..87f668072e221 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-hostnames/vars.sh +++ b/test/integration/connect/envoy/case-api-gateway-http-hostnames/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES api-gateway-primary" diff --git a/test/integration/connect/envoy/case-api-gateway-http-simple/capture.sh b/test/integration/connect/envoy/case-api-gateway-http-simple/capture.sh index 92123f3f4c077..13eb01ba5f824 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-simple/capture.sh +++ b/test/integration/connect/envoy/case-api-gateway-http-simple/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 api-gateway primary || true \ No newline at end of file diff --git a/test/integration/connect/envoy/case-api-gateway-http-simple/service_gateway.hcl b/test/integration/connect/envoy/case-api-gateway-http-simple/service_gateway.hcl index 1d0d5fffe26bf..c0af862f92e32 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-simple/service_gateway.hcl +++ b/test/integration/connect/envoy/case-api-gateway-http-simple/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "api-gateway" diff --git a/test/integration/connect/envoy/case-api-gateway-http-simple/setup.sh b/test/integration/connect/envoy/case-api-gateway-http-simple/setup.sh index e25e92ba0011c..350eea0c5fde1 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-simple/setup.sh +++ b/test/integration/connect/envoy/case-api-gateway-http-simple/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-api-gateway-http-simple/vars.sh b/test/integration/connect/envoy/case-api-gateway-http-simple/vars.sh index 1456b6a5ad024..87f668072e221 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-simple/vars.sh +++ b/test/integration/connect/envoy/case-api-gateway-http-simple/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES api-gateway-primary" diff --git a/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/capture.sh b/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/capture.sh index 92123f3f4c077..13eb01ba5f824 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/capture.sh +++ b/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 api-gateway primary || true \ No newline at end of file diff --git a/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/service_gateway.hcl b/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/service_gateway.hcl index 1d0d5fffe26bf..c0af862f92e32 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/service_gateway.hcl +++ b/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "api-gateway" diff --git a/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/service_s3.hcl b/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/service_s3.hcl index b41ec0349862a..3b11b245d4fde 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/service_s3.hcl +++ b/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/service_s3.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s3" diff --git a/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/setup.sh b/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/setup.sh index 622df90c297a7..da74ff07c1237 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/setup.sh +++ b/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/vars.sh b/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/vars.sh index 1456b6a5ad024..87f668072e221 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/vars.sh +++ b/test/integration/connect/envoy/case-api-gateway-http-splitter-targets/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES api-gateway-primary" diff --git a/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/capture.sh b/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/capture.sh index 92123f3f4c077..13eb01ba5f824 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/capture.sh +++ b/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 api-gateway primary || true \ No newline at end of file diff --git a/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/service_gateway.hcl b/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/service_gateway.hcl index 1d0d5fffe26bf..c0af862f92e32 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/service_gateway.hcl +++ b/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "api-gateway" diff --git a/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/setup.sh b/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/setup.sh index 23076cd00e281..bb058d96fd75a 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/setup.sh +++ b/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/vars.sh b/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/vars.sh index 1456b6a5ad024..87f668072e221 100644 --- a/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/vars.sh +++ b/test/integration/connect/envoy/case-api-gateway-http-tls-overlapping-hosts/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES api-gateway-primary" diff --git a/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/capture.sh b/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/capture.sh index 92123f3f4c077..13eb01ba5f824 100644 --- a/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/capture.sh +++ b/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 api-gateway primary || true \ No newline at end of file diff --git a/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/service_gateway.hcl b/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/service_gateway.hcl index 1d0d5fffe26bf..c0af862f92e32 100644 --- a/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/service_gateway.hcl +++ b/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "api-gateway" diff --git a/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/setup.sh b/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/setup.sh index a4529b6772edc..35d01c8bb9318 100644 --- a/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/setup.sh +++ b/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/vars.sh b/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/vars.sh index 1456b6a5ad024..87f668072e221 100644 --- a/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/vars.sh +++ b/test/integration/connect/envoy/case-api-gateway-tcp-conflicted/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES api-gateway-primary" diff --git a/test/integration/connect/envoy/case-api-gateway-tcp-simple/capture.sh b/test/integration/connect/envoy/case-api-gateway-tcp-simple/capture.sh index 92123f3f4c077..13eb01ba5f824 100644 --- a/test/integration/connect/envoy/case-api-gateway-tcp-simple/capture.sh +++ b/test/integration/connect/envoy/case-api-gateway-tcp-simple/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 api-gateway primary || true \ No newline at end of file diff --git a/test/integration/connect/envoy/case-api-gateway-tcp-simple/service_gateway.hcl b/test/integration/connect/envoy/case-api-gateway-tcp-simple/service_gateway.hcl index 1d0d5fffe26bf..c0af862f92e32 100644 --- a/test/integration/connect/envoy/case-api-gateway-tcp-simple/service_gateway.hcl +++ b/test/integration/connect/envoy/case-api-gateway-tcp-simple/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "api-gateway" diff --git a/test/integration/connect/envoy/case-api-gateway-tcp-simple/setup.sh b/test/integration/connect/envoy/case-api-gateway-tcp-simple/setup.sh index 152e0772104e5..82504d09f5093 100644 --- a/test/integration/connect/envoy/case-api-gateway-tcp-simple/setup.sh +++ b/test/integration/connect/envoy/case-api-gateway-tcp-simple/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-api-gateway-tcp-simple/vars.sh b/test/integration/connect/envoy/case-api-gateway-tcp-simple/vars.sh index 1456b6a5ad024..87f668072e221 100644 --- a/test/integration/connect/envoy/case-api-gateway-tcp-simple/vars.sh +++ b/test/integration/connect/envoy/case-api-gateway-tcp-simple/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES api-gateway-primary" diff --git a/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/capture.sh b/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/capture.sh index 92123f3f4c077..13eb01ba5f824 100644 --- a/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/capture.sh +++ b/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 api-gateway primary || true \ No newline at end of file diff --git a/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/service_gateway.hcl b/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/service_gateway.hcl index 1d0d5fffe26bf..c0af862f92e32 100644 --- a/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/service_gateway.hcl +++ b/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "api-gateway" diff --git a/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/setup.sh b/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/setup.sh index ca9568e348846..a4be961ebb5bb 100644 --- a/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/setup.sh +++ b/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/vars.sh b/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/vars.sh index 1456b6a5ad024..87f668072e221 100644 --- a/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/vars.sh +++ b/test/integration/connect/envoy/case-api-gateway-tcp-tls-overlapping-hosts/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES api-gateway-primary" diff --git a/test/integration/connect/envoy/case-badauthz/capture.sh b/test/integration/connect/envoy/case-badauthz/capture.sh index c6b9e36ed1df1..94c0278ce256c 100644 --- a/test/integration/connect/envoy/case-badauthz/capture.sh +++ b/test/integration/connect/envoy/case-badauthz/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 || true diff --git a/test/integration/connect/envoy/case-badauthz/setup.sh b/test/integration/connect/envoy/case-badauthz/setup.sh index 1aa0962cf6fb1..6bd91b1f4e66f 100644 --- a/test/integration/connect/envoy/case-badauthz/setup.sh +++ b/test/integration/connect/envoy/case-badauthz/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-basic/capture.sh b/test/integration/connect/envoy/case-basic/capture.sh index 14dc00afc65b8..5268305f8ff6c 100644 --- a/test/integration/connect/envoy/case-basic/capture.sh +++ b/test/integration/connect/envoy/case-basic/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-basic/setup.sh b/test/integration/connect/envoy/case-basic/setup.sh index 3fb3ade6c5fbb..b88cc90129682 100644 --- a/test/integration/connect/envoy/case-basic/setup.sh +++ b/test/integration/connect/envoy/case-basic/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-centralconf/capture.sh b/test/integration/connect/envoy/case-centralconf/capture.sh index 8bc4413d09f9e..21ebba78787be 100644 --- a/test/integration/connect/envoy/case-centralconf/capture.sh +++ b/test/integration/connect/envoy/case-centralconf/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-centralconf/service_s1.hcl b/test/integration/connect/envoy/case-centralconf/service_s1.hcl index 54c6ac6501b40..6eaca129855b9 100644 --- a/test/integration/connect/envoy/case-centralconf/service_s1.hcl +++ b/test/integration/connect/envoy/case-centralconf/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-centralconf/service_s2.hcl b/test/integration/connect/envoy/case-centralconf/service_s2.hcl index 1a89f855944da..dfb92edce6368 100644 --- a/test/integration/connect/envoy/case-centralconf/service_s2.hcl +++ b/test/integration/connect/envoy/case-centralconf/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-centralconf/setup.sh b/test/integration/connect/envoy/case-centralconf/setup.sh index 934ea006fddbb..10038488c8c23 100644 --- a/test/integration/connect/envoy/case-centralconf/setup.sh +++ b/test/integration/connect/envoy/case-centralconf/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/base.hcl b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/base.hcl index 8cd6db14878a7..899e81705a4cf 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/base.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 primary_datacenter = "alpha" log_level = "trace" diff --git a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/service_gateway.hcl b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/service_gateway.hcl index 640b9b6ce753f..82ddd559eb3a5 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/service_s1.hcl b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/service_s1.hcl index b065abc9055e2..11acde14f4270 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/service_s1.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s1 service in this peer diff --git a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/service_s2.hcl b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/service_s2.hcl index 90d2315f4d2c9..42252eb82f686 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/service_s2.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/setup.sh b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/setup.sh index af71eccb8e188..917d0ba6c125f 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/setup.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/alpha/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/bind.hcl b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/bind.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/capture.sh b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/capture.sh index 0921d3c32a0e9..e1b411ab95176 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/capture.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/base.hcl b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/base.hcl index 55c268b37e784..189b8e0ccf722 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/base.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 peering { enabled = true diff --git a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/service_s1.hcl b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/service_s1.hcl index 63dfc2994f3de..c9da404077ffe 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/service_s1.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/service_s2.hcl b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/service_s2.hcl index 90d2315f4d2c9..42252eb82f686 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/service_s2.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/setup.sh b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/setup.sh index d84fe0a869918..830ecb23b73cd 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/setup.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/vars.sh b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/vars.sh index 41b95915331d4..9d1f5c977a9bc 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/vars.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-cluster-peering-failover/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy s2 s2-sidecar-proxy s2-alpha s2-sidecar-proxy-alpha gateway-alpha tcpdump-primary tcpdump-alpha" diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/bind.hcl b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/bind.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/capture.sh b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/capture.sh index 0ee4884a15215..93352a5228b92 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/capture.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/primary/setup.sh b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/primary/setup.sh index 8b24664564cb7..e9a9055ab6a55 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/primary/setup.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/join.hcl b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/join.hcl index f0bd3fbd4ac7e..0f63220d549fe 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/join.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/join.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 retry_join_wan = ["consul-primary-server"] diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/service_gateway.hcl b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/service_gateway.hcl index 4f91a740182af..8c2315b9ae360 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/service_s1.hcl b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/service_s1.hcl index 8b4d4a83a42d4..06af757cd68e7 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/service_s1.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # we don't want an s1 service in the secondary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/setup.sh b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/setup.sh index ed13954a1f5e6..1af35392b9c26 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/setup.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/secondary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/vars.sh b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/vars.sh index 11e14176e3892..e33bd22ca6184 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/vars.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-none/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES=" diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/bind.hcl b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/bind.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/capture.sh b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/capture.sh index 0ee4884a15215..93352a5228b92 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/capture.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/primary/setup.sh b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/primary/setup.sh index 25a7c173f08bb..33a1a035c53ac 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/primary/setup.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/join.hcl b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/join.hcl index f0bd3fbd4ac7e..0f63220d549fe 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/join.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/join.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 retry_join_wan = ["consul-primary-server"] diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/service_gateway.hcl b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/service_gateway.hcl index 4f91a740182af..8c2315b9ae360 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/service_s1.hcl b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/service_s1.hcl index 8b4d4a83a42d4..06af757cd68e7 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/service_s1.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # we don't want an s1 service in the secondary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/setup.sh b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/setup.sh index ed13954a1f5e6..1af35392b9c26 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/setup.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/secondary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/vars.sh b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/vars.sh index 11e14176e3892..e33bd22ca6184 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/vars.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-dc-failover-gateways-remote/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES=" diff --git a/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/service_s2-v1.hcl b/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/service_s2-v1.hcl index b96b473cf4fbf..9dd3cb782fd3f 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/service_s2-v1.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/service_s2-v1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s2-v1" diff --git a/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/service_s2-v2.hcl b/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/service_s2-v2.hcl index d642e71fa31b1..451f835e86881 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/service_s2-v2.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/service_s2-v2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s2-v2" diff --git a/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/setup.sh b/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/setup.sh index 043dd7f7fc66b..20dd92172327f 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/setup.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/vars.sh b/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/vars.sh index 358c95541fda3..50c5f8f67f9b0 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/vars.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-defaultsubset/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES=" diff --git a/test/integration/connect/envoy/case-cfg-resolver-features/capture.sh b/test/integration/connect/envoy/case-cfg-resolver-features/capture.sh index b1782df01e27c..39878041c3672 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-features/capture.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-features/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-cfg-resolver-features/service_s2-v1.hcl b/test/integration/connect/envoy/case-cfg-resolver-features/service_s2-v1.hcl index b96b473cf4fbf..9dd3cb782fd3f 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-features/service_s2-v1.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-features/service_s2-v1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s2-v1" diff --git a/test/integration/connect/envoy/case-cfg-resolver-features/service_s2-v2.hcl b/test/integration/connect/envoy/case-cfg-resolver-features/service_s2-v2.hcl index d642e71fa31b1..451f835e86881 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-features/service_s2-v2.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-features/service_s2-v2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s2-v2" diff --git a/test/integration/connect/envoy/case-cfg-resolver-features/setup.sh b/test/integration/connect/envoy/case-cfg-resolver-features/setup.sh index 2e3078edc872c..c3f2fa3a1d4f5 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-features/setup.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-features/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-features/vars.sh b/test/integration/connect/envoy/case-cfg-resolver-features/vars.sh index 358c95541fda3..50c5f8f67f9b0 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-features/vars.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-features/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES=" diff --git a/test/integration/connect/envoy/case-cfg-resolver-subset-onlypassing/service_s2-v1.hcl b/test/integration/connect/envoy/case-cfg-resolver-subset-onlypassing/service_s2-v1.hcl index d45b1462723f4..551db8a322a9a 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-subset-onlypassing/service_s2-v1.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-subset-onlypassing/service_s2-v1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s2-v1" diff --git a/test/integration/connect/envoy/case-cfg-resolver-subset-onlypassing/setup.sh b/test/integration/connect/envoy/case-cfg-resolver-subset-onlypassing/setup.sh index 606cadd8f1fb3..229247da4f512 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-subset-onlypassing/setup.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-subset-onlypassing/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-subset-onlypassing/vars.sh b/test/integration/connect/envoy/case-cfg-resolver-subset-onlypassing/vars.sh index aab3c8c39ea5b..9f9b54a8e9ebd 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-subset-onlypassing/vars.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-subset-onlypassing/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES=" diff --git a/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/service_s3-v1.hcl b/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/service_s3-v1.hcl index d9a050a16f653..af20754d254de 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/service_s3-v1.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/service_s3-v1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s3-v1" diff --git a/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/service_s3-v2.hcl b/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/service_s3-v2.hcl index 19e2c7cac1506..22a40609e19e8 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/service_s3-v2.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/service_s3-v2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s3-v2" diff --git a/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/service_s3.hcl b/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/service_s3.hcl index 973e69b01c89a..82db490a879b9 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/service_s3.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/service_s3.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s3" diff --git a/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/setup.sh b/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/setup.sh index 7d02158a6325c..e1fb33c3dca3e 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/setup.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/vars.sh b/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/vars.sh index a9a2bcd57188d..f76eb49ceb2db 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/vars.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-subset-redirect/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES=" diff --git a/test/integration/connect/envoy/case-cfg-resolver-svc-failover/service_s3-v1.hcl b/test/integration/connect/envoy/case-cfg-resolver-svc-failover/service_s3-v1.hcl index d9a050a16f653..af20754d254de 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-svc-failover/service_s3-v1.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-svc-failover/service_s3-v1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s3-v1" diff --git a/test/integration/connect/envoy/case-cfg-resolver-svc-failover/service_s3-v2.hcl b/test/integration/connect/envoy/case-cfg-resolver-svc-failover/service_s3-v2.hcl index 19e2c7cac1506..22a40609e19e8 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-svc-failover/service_s3-v2.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-svc-failover/service_s3-v2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s3-v2" diff --git a/test/integration/connect/envoy/case-cfg-resolver-svc-failover/service_s3.hcl b/test/integration/connect/envoy/case-cfg-resolver-svc-failover/service_s3.hcl index 973e69b01c89a..82db490a879b9 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-svc-failover/service_s3.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-svc-failover/service_s3.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s3" diff --git a/test/integration/connect/envoy/case-cfg-resolver-svc-failover/setup.sh b/test/integration/connect/envoy/case-cfg-resolver-svc-failover/setup.sh index eae9bd4feaf13..b4472fd8a207c 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-svc-failover/setup.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-svc-failover/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-svc-failover/vars.sh b/test/integration/connect/envoy/case-cfg-resolver-svc-failover/vars.sh index a9a2bcd57188d..f76eb49ceb2db 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-svc-failover/vars.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-svc-failover/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES=" diff --git a/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-http/service_s3.hcl b/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-http/service_s3.hcl index 94e31c3df895d..59209aab121c1 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-http/service_s3.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-http/service_s3.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s3" diff --git a/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-http/setup.sh b/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-http/setup.sh index 097f1fa756663..640e1519ea473 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-http/setup.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-http/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-http/vars.sh b/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-http/vars.sh index 63c854f959c9e..bbc811fa66db5 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-http/vars.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-http/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES s3 s3-sidecar-proxy" diff --git a/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-tcp/service_s3.hcl b/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-tcp/service_s3.hcl index 94e31c3df895d..59209aab121c1 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-tcp/service_s3.hcl +++ b/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-tcp/service_s3.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s3" diff --git a/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-tcp/setup.sh b/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-tcp/setup.sh index fd106032bf2e9..9ce5a82f75468 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-tcp/setup.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-tcp/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-tcp/vars.sh b/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-tcp/vars.sh index 63c854f959c9e..bbc811fa66db5 100644 --- a/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-tcp/vars.sh +++ b/test/integration/connect/envoy/case-cfg-resolver-svc-redirect-tcp/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES s3 s3-sidecar-proxy" diff --git a/test/integration/connect/envoy/case-cfg-router-features/capture.sh b/test/integration/connect/envoy/case-cfg-router-features/capture.sh index b1782df01e27c..39878041c3672 100644 --- a/test/integration/connect/envoy/case-cfg-router-features/capture.sh +++ b/test/integration/connect/envoy/case-cfg-router-features/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-cfg-router-features/service_s2-v1.hcl b/test/integration/connect/envoy/case-cfg-router-features/service_s2-v1.hcl index b96b473cf4fbf..9dd3cb782fd3f 100644 --- a/test/integration/connect/envoy/case-cfg-router-features/service_s2-v1.hcl +++ b/test/integration/connect/envoy/case-cfg-router-features/service_s2-v1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s2-v1" diff --git a/test/integration/connect/envoy/case-cfg-router-features/service_s2-v2.hcl b/test/integration/connect/envoy/case-cfg-router-features/service_s2-v2.hcl index d642e71fa31b1..451f835e86881 100644 --- a/test/integration/connect/envoy/case-cfg-router-features/service_s2-v2.hcl +++ b/test/integration/connect/envoy/case-cfg-router-features/service_s2-v2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s2-v2" diff --git a/test/integration/connect/envoy/case-cfg-router-features/setup.sh b/test/integration/connect/envoy/case-cfg-router-features/setup.sh index 577b3512b4fe3..247bc00c33beb 100644 --- a/test/integration/connect/envoy/case-cfg-router-features/setup.sh +++ b/test/integration/connect/envoy/case-cfg-router-features/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cfg-router-features/vars.sh b/test/integration/connect/envoy/case-cfg-router-features/vars.sh index 358c95541fda3..50c5f8f67f9b0 100644 --- a/test/integration/connect/envoy/case-cfg-router-features/vars.sh +++ b/test/integration/connect/envoy/case-cfg-router-features/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES=" diff --git a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/base.hcl b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/base.hcl index 8cd6db14878a7..899e81705a4cf 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/base.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 primary_datacenter = "alpha" log_level = "trace" diff --git a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/service_gateway.hcl b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/service_gateway.hcl index 640b9b6ce753f..82ddd559eb3a5 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/service_s1.hcl b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/service_s1.hcl index b065abc9055e2..11acde14f4270 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/service_s1.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s1 service in this peer diff --git a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/service_s2.hcl b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/service_s2.hcl index 26b5f481f377a..6666a63ba257e 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/service_s2.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/setup.sh b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/setup.sh index 99c4eb46f2186..5aabbbbee0e5d 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/setup.sh +++ b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/alpha/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/bind.hcl b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/bind.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/capture.sh b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/capture.sh index 0921d3c32a0e9..e1b411ab95176 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/capture.sh +++ b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/base.hcl b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/base.hcl index 55c268b37e784..189b8e0ccf722 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/base.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 peering { enabled = true diff --git a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/service_s1.hcl b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/service_s1.hcl index d50d8cb04979c..70caaaebc900b 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/service_s1.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/service_s2.hcl b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/service_s2.hcl index 26b5f481f377a..6666a63ba257e 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/service_s2.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/setup.sh b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/setup.sh index 9b274b375f874..8bc36b6d02299 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/setup.sh +++ b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/vars.sh b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/vars.sh index 7c231bcfad68f..17f98153dd14d 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/vars.sh +++ b/test/integration/connect/envoy/case-cfg-splitter-cluster-peering/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy s2 s2-sidecar-proxy s2-alpha s2-sidecar-proxy-alpha gateway-alpha" diff --git a/test/integration/connect/envoy/case-cfg-splitter-features/capture.sh b/test/integration/connect/envoy/case-cfg-splitter-features/capture.sh index b1782df01e27c..39878041c3672 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-features/capture.sh +++ b/test/integration/connect/envoy/case-cfg-splitter-features/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-cfg-splitter-features/service_s2-v1.hcl b/test/integration/connect/envoy/case-cfg-splitter-features/service_s2-v1.hcl index b96b473cf4fbf..9dd3cb782fd3f 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-features/service_s2-v1.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-features/service_s2-v1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s2-v1" diff --git a/test/integration/connect/envoy/case-cfg-splitter-features/service_s2-v2.hcl b/test/integration/connect/envoy/case-cfg-splitter-features/service_s2-v2.hcl index d642e71fa31b1..451f835e86881 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-features/service_s2-v2.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-features/service_s2-v2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s2-v2" diff --git a/test/integration/connect/envoy/case-cfg-splitter-features/setup.sh b/test/integration/connect/envoy/case-cfg-splitter-features/setup.sh index 311799fccfbc1..68c8ac0a6cb4f 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-features/setup.sh +++ b/test/integration/connect/envoy/case-cfg-splitter-features/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cfg-splitter-features/vars.sh b/test/integration/connect/envoy/case-cfg-splitter-features/vars.sh index 358c95541fda3..50c5f8f67f9b0 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-features/vars.sh +++ b/test/integration/connect/envoy/case-cfg-splitter-features/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES=" diff --git a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/base.hcl b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/base.hcl index 8cd6db14878a7..899e81705a4cf 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/base.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 primary_datacenter = "alpha" log_level = "trace" diff --git a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/service_gateway.hcl b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/service_gateway.hcl index 640b9b6ce753f..82ddd559eb3a5 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/service_s1.hcl b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/service_s1.hcl index ca196db64f0f4..976e0e993d4d5 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/service_s1.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/service_s2.hcl b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/service_s2.hcl index 26b5f481f377a..6666a63ba257e 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/service_s2.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/setup.sh b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/setup.sh index 47127ab03d482..8c24708aebe2b 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/setup.sh +++ b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/alpha/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/bind.hcl b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/bind.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/capture.sh b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/capture.sh index 965f136de6822..a3dd69ed05b86 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/capture.sh +++ b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 ingress-gateway primary || true diff --git a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/primary/base.hcl b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/primary/base.hcl index 55c268b37e784..189b8e0ccf722 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/primary/base.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/primary/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 peering { enabled = true diff --git a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/primary/service_ingress.hcl b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/primary/service_ingress.hcl index a1324f7f83799..fbb1d402f9869 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/primary/service_ingress.hcl +++ b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/primary/service_ingress.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "ingress-gateway" diff --git a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/primary/setup.sh b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/primary/setup.sh index ed0da099d6527..d69a26f1d89c6 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/primary/setup.sh +++ b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/vars.sh b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/vars.sh index e5b080741aa26..2a2aa6fb1e9c6 100644 --- a/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/vars.sh +++ b/test/integration/connect/envoy/case-cfg-splitter-peering-ingress-gateways/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy s1-alpha s1-sidecar-proxy-alpha s2-alpha s2-sidecar-proxy-alpha gateway-alpha ingress-gateway-primary" diff --git a/test/integration/connect/envoy/case-consul-exec/setup.sh b/test/integration/connect/envoy/case-consul-exec/setup.sh index 7e869b53f17ad..fe3505623b54e 100644 --- a/test/integration/connect/envoy/case-consul-exec/setup.sh +++ b/test/integration/connect/envoy/case-consul-exec/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-consul-exec/vars.sh b/test/integration/connect/envoy/case-consul-exec/vars.sh index 81ee777414571..4af0cb775d386 100644 --- a/test/integration/connect/envoy/case-consul-exec/vars.sh +++ b/test/integration/connect/envoy/case-consul-exec/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # Bring up s1 and it's proxy as well because the check that it has a cert causes diff --git a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/base.hcl b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/base.hcl index 8cd6db14878a7..899e81705a4cf 100644 --- a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/base.hcl +++ b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 primary_datacenter = "alpha" log_level = "trace" diff --git a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/service_gateway.hcl b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/service_gateway.hcl index 640b9b6ce753f..82ddd559eb3a5 100644 --- a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/service_s1.hcl b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/service_s1.hcl index b065abc9055e2..11acde14f4270 100644 --- a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/service_s1.hcl +++ b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s1 service in this peer diff --git a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/service_s2.hcl b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/service_s2.hcl index 90d2315f4d2c9..42252eb82f686 100644 --- a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/service_s2.hcl +++ b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/setup.sh b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/setup.sh index ca05659843d7c..a7fb502a28159 100644 --- a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/setup.sh +++ b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/alpha/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/bind.hcl b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/bind.hcl +++ b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/capture.sh b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/capture.sh index b4316246f3ab6..8168b3de6416e 100644 --- a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/capture.sh +++ b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19001 mesh-gateway primary || true diff --git a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/base.hcl b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/base.hcl index 55c268b37e784..189b8e0ccf722 100644 --- a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/base.hcl +++ b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 peering { enabled = true diff --git a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/service_gateway.hcl b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/service_gateway.hcl index a6b33968ad020..9ea00427e9e7d 100644 --- a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/service_s1.hcl b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/service_s1.hcl index b3230f6dcfa1f..b8bd0f20be465 100644 --- a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/service_s1.hcl +++ b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/service_s2.hcl b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/service_s2.hcl index d0f6294f72802..acd65faf3d612 100644 --- a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/service_s2.hcl +++ b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/service_s2.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s2 service in the primary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/setup.sh b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/setup.sh index d107c44ea6f39..cf57a59db8739 100644 --- a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/setup.sh +++ b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/vars.sh b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/vars.sh index 93ac3281f1286..475b7f2312782 100644 --- a/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/vars.sh +++ b/test/integration/connect/envoy/case-cross-peer-control-plane-mgw/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy gateway-primary s2-alpha s2-sidecar-proxy-alpha gateway-alpha" diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/alpha/base.hcl b/test/integration/connect/envoy/case-cross-peers-http-router/alpha/base.hcl index 8cd6db14878a7..899e81705a4cf 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/alpha/base.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http-router/alpha/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 primary_datacenter = "alpha" log_level = "trace" diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_gateway.hcl b/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_gateway.hcl index 640b9b6ce753f..82ddd559eb3a5 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_s1.hcl b/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_s1.hcl index b065abc9055e2..11acde14f4270 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_s1.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s1 service in this peer diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_s2.hcl b/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_s2.hcl index 90d2315f4d2c9..42252eb82f686 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_s2.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_s3.hcl b/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_s3.hcl index 94e31c3df895d..59209aab121c1 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_s3.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http-router/alpha/service_s3.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s3" diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/alpha/setup.sh b/test/integration/connect/envoy/case-cross-peers-http-router/alpha/setup.sh index 00ab68e36144c..e852ef7d3d26c 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/alpha/setup.sh +++ b/test/integration/connect/envoy/case-cross-peers-http-router/alpha/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/bind.hcl b/test/integration/connect/envoy/case-cross-peers-http-router/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/bind.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http-router/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/capture.sh b/test/integration/connect/envoy/case-cross-peers-http-router/capture.sh index be4068fd193b2..bcea1e921c6d1 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/capture.sh +++ b/test/integration/connect/envoy/case-cross-peers-http-router/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/primary/base.hcl b/test/integration/connect/envoy/case-cross-peers-http-router/primary/base.hcl index 55c268b37e784..189b8e0ccf722 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/primary/base.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http-router/primary/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 peering { enabled = true diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/primary/service_gateway.hcl b/test/integration/connect/envoy/case-cross-peers-http-router/primary/service_gateway.hcl index a6b33968ad020..9ea00427e9e7d 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/primary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http-router/primary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/primary/service_s1.hcl b/test/integration/connect/envoy/case-cross-peers-http-router/primary/service_s1.hcl index ec6c29b8e158c..026636c814f75 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/primary/service_s1.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http-router/primary/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/primary/service_s2.hcl b/test/integration/connect/envoy/case-cross-peers-http-router/primary/service_s2.hcl index d0f6294f72802..acd65faf3d612 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/primary/service_s2.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http-router/primary/service_s2.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s2 service in the primary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/primary/setup.sh b/test/integration/connect/envoy/case-cross-peers-http-router/primary/setup.sh index 47c9eff11432a..2a06124a7d60c 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/primary/setup.sh +++ b/test/integration/connect/envoy/case-cross-peers-http-router/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cross-peers-http-router/vars.sh b/test/integration/connect/envoy/case-cross-peers-http-router/vars.sh index b11c21c524075..44ed49bb79619 100644 --- a/test/integration/connect/envoy/case-cross-peers-http-router/vars.sh +++ b/test/integration/connect/envoy/case-cross-peers-http-router/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy gateway-primary s2-alpha s2-sidecar-proxy-alpha s3-alpha s3-sidecar-proxy-alpha gateway-alpha tcpdump-primary tcpdump-alpha" diff --git a/test/integration/connect/envoy/case-cross-peers-http/alpha/base.hcl b/test/integration/connect/envoy/case-cross-peers-http/alpha/base.hcl index 8cd6db14878a7..899e81705a4cf 100644 --- a/test/integration/connect/envoy/case-cross-peers-http/alpha/base.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http/alpha/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 primary_datacenter = "alpha" log_level = "trace" diff --git a/test/integration/connect/envoy/case-cross-peers-http/alpha/service_gateway.hcl b/test/integration/connect/envoy/case-cross-peers-http/alpha/service_gateway.hcl index 640b9b6ce753f..82ddd559eb3a5 100644 --- a/test/integration/connect/envoy/case-cross-peers-http/alpha/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http/alpha/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cross-peers-http/alpha/service_s1.hcl b/test/integration/connect/envoy/case-cross-peers-http/alpha/service_s1.hcl index b065abc9055e2..11acde14f4270 100644 --- a/test/integration/connect/envoy/case-cross-peers-http/alpha/service_s1.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http/alpha/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s1 service in this peer diff --git a/test/integration/connect/envoy/case-cross-peers-http/alpha/service_s2.hcl b/test/integration/connect/envoy/case-cross-peers-http/alpha/service_s2.hcl index 90d2315f4d2c9..42252eb82f686 100644 --- a/test/integration/connect/envoy/case-cross-peers-http/alpha/service_s2.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http/alpha/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-cross-peers-http/alpha/setup.sh b/test/integration/connect/envoy/case-cross-peers-http/alpha/setup.sh index 267d9403dba71..f7ac96c41a7ad 100644 --- a/test/integration/connect/envoy/case-cross-peers-http/alpha/setup.sh +++ b/test/integration/connect/envoy/case-cross-peers-http/alpha/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cross-peers-http/bind.hcl b/test/integration/connect/envoy/case-cross-peers-http/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-cross-peers-http/bind.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cross-peers-http/capture.sh b/test/integration/connect/envoy/case-cross-peers-http/capture.sh index 3e81bd44657f4..62c8c60d702c1 100644 --- a/test/integration/connect/envoy/case-cross-peers-http/capture.sh +++ b/test/integration/connect/envoy/case-cross-peers-http/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-cross-peers-http/primary/base.hcl b/test/integration/connect/envoy/case-cross-peers-http/primary/base.hcl index 55c268b37e784..189b8e0ccf722 100644 --- a/test/integration/connect/envoy/case-cross-peers-http/primary/base.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http/primary/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 peering { enabled = true diff --git a/test/integration/connect/envoy/case-cross-peers-http/primary/service_gateway.hcl b/test/integration/connect/envoy/case-cross-peers-http/primary/service_gateway.hcl index a6b33968ad020..9ea00427e9e7d 100644 --- a/test/integration/connect/envoy/case-cross-peers-http/primary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http/primary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cross-peers-http/primary/service_s1.hcl b/test/integration/connect/envoy/case-cross-peers-http/primary/service_s1.hcl index ec6c29b8e158c..026636c814f75 100644 --- a/test/integration/connect/envoy/case-cross-peers-http/primary/service_s1.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http/primary/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-cross-peers-http/primary/service_s2.hcl b/test/integration/connect/envoy/case-cross-peers-http/primary/service_s2.hcl index d0f6294f72802..acd65faf3d612 100644 --- a/test/integration/connect/envoy/case-cross-peers-http/primary/service_s2.hcl +++ b/test/integration/connect/envoy/case-cross-peers-http/primary/service_s2.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s2 service in the primary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cross-peers-http/primary/setup.sh b/test/integration/connect/envoy/case-cross-peers-http/primary/setup.sh index 7c5ac5fdb8ba9..997bb504f62d4 100644 --- a/test/integration/connect/envoy/case-cross-peers-http/primary/setup.sh +++ b/test/integration/connect/envoy/case-cross-peers-http/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cross-peers-http/vars.sh b/test/integration/connect/envoy/case-cross-peers-http/vars.sh index d999e45dd263e..0c1c07b28b9c3 100644 --- a/test/integration/connect/envoy/case-cross-peers-http/vars.sh +++ b/test/integration/connect/envoy/case-cross-peers-http/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy gateway-primary s2-alpha s2-sidecar-proxy-alpha gateway-alpha tcpdump-primary tcpdump-alpha" diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/base.hcl b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/base.hcl index 8cd6db14878a7..899e81705a4cf 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/base.hcl +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 primary_datacenter = "alpha" log_level = "trace" diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_gateway.hcl b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_gateway.hcl index 640b9b6ce753f..82ddd559eb3a5 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_s1.hcl b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_s1.hcl index b065abc9055e2..11acde14f4270 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_s1.hcl +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s1 service in this peer diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_s2.hcl b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_s2.hcl index 90d2315f4d2c9..42252eb82f686 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_s2.hcl +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_s3.hcl b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_s3.hcl index 94e31c3df895d..59209aab121c1 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_s3.hcl +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/service_s3.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s3" diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/setup.sh b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/setup.sh index 3cc1a2eb2de8d..6574ecf873a6f 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/setup.sh +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/alpha/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/bind.hcl b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/bind.hcl +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/capture.sh b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/capture.sh index be4068fd193b2..bcea1e921c6d1 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/capture.sh +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/base.hcl b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/base.hcl index 55c268b37e784..189b8e0ccf722 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/base.hcl +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 peering { enabled = true diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/service_gateway.hcl b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/service_gateway.hcl index a6b33968ad020..9ea00427e9e7d 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/service_s1.hcl b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/service_s1.hcl index ec6c29b8e158c..026636c814f75 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/service_s1.hcl +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/service_s2.hcl b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/service_s2.hcl index d0f6294f72802..acd65faf3d612 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/service_s2.hcl +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/service_s2.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s2 service in the primary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/setup.sh b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/setup.sh index d72b0798f5d8f..ad70bad80a866 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/setup.sh +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/vars.sh b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/vars.sh index b11c21c524075..44ed49bb79619 100644 --- a/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/vars.sh +++ b/test/integration/connect/envoy/case-cross-peers-resolver-redirect-tcp/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy gateway-primary s2-alpha s2-sidecar-proxy-alpha s3-alpha s3-sidecar-proxy-alpha gateway-alpha tcpdump-primary tcpdump-alpha" diff --git a/test/integration/connect/envoy/case-cross-peers/alpha/base.hcl b/test/integration/connect/envoy/case-cross-peers/alpha/base.hcl index 8cd6db14878a7..899e81705a4cf 100644 --- a/test/integration/connect/envoy/case-cross-peers/alpha/base.hcl +++ b/test/integration/connect/envoy/case-cross-peers/alpha/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 primary_datacenter = "alpha" log_level = "trace" diff --git a/test/integration/connect/envoy/case-cross-peers/alpha/service_gateway.hcl b/test/integration/connect/envoy/case-cross-peers/alpha/service_gateway.hcl index 640b9b6ce753f..82ddd559eb3a5 100644 --- a/test/integration/connect/envoy/case-cross-peers/alpha/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cross-peers/alpha/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cross-peers/alpha/service_s1.hcl b/test/integration/connect/envoy/case-cross-peers/alpha/service_s1.hcl index b065abc9055e2..11acde14f4270 100644 --- a/test/integration/connect/envoy/case-cross-peers/alpha/service_s1.hcl +++ b/test/integration/connect/envoy/case-cross-peers/alpha/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s1 service in this peer diff --git a/test/integration/connect/envoy/case-cross-peers/alpha/service_s2.hcl b/test/integration/connect/envoy/case-cross-peers/alpha/service_s2.hcl index 90d2315f4d2c9..42252eb82f686 100644 --- a/test/integration/connect/envoy/case-cross-peers/alpha/service_s2.hcl +++ b/test/integration/connect/envoy/case-cross-peers/alpha/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-cross-peers/alpha/setup.sh b/test/integration/connect/envoy/case-cross-peers/alpha/setup.sh index f5fd3d003aa68..afaa580684a7a 100644 --- a/test/integration/connect/envoy/case-cross-peers/alpha/setup.sh +++ b/test/integration/connect/envoy/case-cross-peers/alpha/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cross-peers/bind.hcl b/test/integration/connect/envoy/case-cross-peers/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-cross-peers/bind.hcl +++ b/test/integration/connect/envoy/case-cross-peers/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cross-peers/capture.sh b/test/integration/connect/envoy/case-cross-peers/capture.sh index 3e81bd44657f4..62c8c60d702c1 100644 --- a/test/integration/connect/envoy/case-cross-peers/capture.sh +++ b/test/integration/connect/envoy/case-cross-peers/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-cross-peers/primary/base.hcl b/test/integration/connect/envoy/case-cross-peers/primary/base.hcl index 55c268b37e784..189b8e0ccf722 100644 --- a/test/integration/connect/envoy/case-cross-peers/primary/base.hcl +++ b/test/integration/connect/envoy/case-cross-peers/primary/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 peering { enabled = true diff --git a/test/integration/connect/envoy/case-cross-peers/primary/service_gateway.hcl b/test/integration/connect/envoy/case-cross-peers/primary/service_gateway.hcl index a6b33968ad020..9ea00427e9e7d 100644 --- a/test/integration/connect/envoy/case-cross-peers/primary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-cross-peers/primary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-cross-peers/primary/service_s1.hcl b/test/integration/connect/envoy/case-cross-peers/primary/service_s1.hcl index b3230f6dcfa1f..b8bd0f20be465 100644 --- a/test/integration/connect/envoy/case-cross-peers/primary/service_s1.hcl +++ b/test/integration/connect/envoy/case-cross-peers/primary/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-cross-peers/primary/service_s2.hcl b/test/integration/connect/envoy/case-cross-peers/primary/service_s2.hcl index d0f6294f72802..acd65faf3d612 100644 --- a/test/integration/connect/envoy/case-cross-peers/primary/service_s2.hcl +++ b/test/integration/connect/envoy/case-cross-peers/primary/service_s2.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s2 service in the primary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-cross-peers/primary/setup.sh b/test/integration/connect/envoy/case-cross-peers/primary/setup.sh index d72b0798f5d8f..ad70bad80a866 100644 --- a/test/integration/connect/envoy/case-cross-peers/primary/setup.sh +++ b/test/integration/connect/envoy/case-cross-peers/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-cross-peers/vars.sh b/test/integration/connect/envoy/case-cross-peers/vars.sh index d999e45dd263e..0c1c07b28b9c3 100644 --- a/test/integration/connect/envoy/case-cross-peers/vars.sh +++ b/test/integration/connect/envoy/case-cross-peers/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy gateway-primary s2-alpha s2-sidecar-proxy-alpha gateway-alpha tcpdump-primary tcpdump-alpha" diff --git a/test/integration/connect/envoy/case-dogstatsd-udp/service_s1.hcl b/test/integration/connect/envoy/case-dogstatsd-udp/service_s1.hcl index a4e91f3aa41b4..a75675751d525 100644 --- a/test/integration/connect/envoy/case-dogstatsd-udp/service_s1.hcl +++ b/test/integration/connect/envoy/case-dogstatsd-udp/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-dogstatsd-udp/setup.sh b/test/integration/connect/envoy/case-dogstatsd-udp/setup.sh index 3fb3ade6c5fbb..b88cc90129682 100644 --- a/test/integration/connect/envoy/case-dogstatsd-udp/setup.sh +++ b/test/integration/connect/envoy/case-dogstatsd-udp/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-dogstatsd-udp/vars.sh b/test/integration/connect/envoy/case-dogstatsd-udp/vars.sh index 7fa5a238ce933..c599f12e8232d 100644 --- a/test/integration/connect/envoy/case-dogstatsd-udp/vars.sh +++ b/test/integration/connect/envoy/case-dogstatsd-udp/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES fake-statsd" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-dogstatsd-udp/verify.bats b/test/integration/connect/envoy/case-dogstatsd-udp/verify.bats index dfc238ad6d9de..55b0ad76849c3 100644 --- a/test/integration/connect/envoy/case-dogstatsd-udp/verify.bats +++ b/test/integration/connect/envoy/case-dogstatsd-udp/verify.bats @@ -24,11 +24,14 @@ load helpers } @test "s1 proxy should be sending metrics to statsd" { - run retry_default must_match_in_statsd_logs '^envoy\.' primary + run retry_default cat /workdir/primary/statsd/statsd.log - echo "METRICS: $output" + echo "METRICS:" + echo "$output" + echo "COUNT: $(echo "$output" | grep -Ec '^envoy\.')" - [ "$status" == 0 ] + [ "$status" == 0 ] + [ $(echo $output | grep -Ec '^envoy\.') -gt "0" ] } @test "s1 proxy should be sending dogstatsd tagged metrics" { diff --git a/test/integration/connect/envoy/case-expose-checks/capture.sh b/test/integration/connect/envoy/case-expose-checks/capture.sh index c6b9e36ed1df1..94c0278ce256c 100644 --- a/test/integration/connect/envoy/case-expose-checks/capture.sh +++ b/test/integration/connect/envoy/case-expose-checks/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 || true diff --git a/test/integration/connect/envoy/case-expose-checks/service_s1.hcl b/test/integration/connect/envoy/case-expose-checks/service_s1.hcl index b2b685c08abec..9a883739e4fa3 100644 --- a/test/integration/connect/envoy/case-expose-checks/service_s1.hcl +++ b/test/integration/connect/envoy/case-expose-checks/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-expose-checks/service_s2.hcl b/test/integration/connect/envoy/case-expose-checks/service_s2.hcl index f5cb3fb0374c4..b09d152fc5f0f 100644 --- a/test/integration/connect/envoy/case-expose-checks/service_s2.hcl +++ b/test/integration/connect/envoy/case-expose-checks/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-expose-checks/setup.sh b/test/integration/connect/envoy/case-expose-checks/setup.sh index 3fb3ade6c5fbb..b88cc90129682 100644 --- a/test/integration/connect/envoy/case-expose-checks/setup.sh +++ b/test/integration/connect/envoy/case-expose-checks/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-gateway-without-services/bind.hcl b/test/integration/connect/envoy/case-gateway-without-services/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-gateway-without-services/bind.hcl +++ b/test/integration/connect/envoy/case-gateway-without-services/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-gateway-without-services/capture.sh b/test/integration/connect/envoy/case-gateway-without-services/capture.sh index ad74026c7ace2..fc5238fb6d6b2 100644 --- a/test/integration/connect/envoy/case-gateway-without-services/capture.sh +++ b/test/integration/connect/envoy/case-gateway-without-services/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 mesh-gateway primary || true diff --git a/test/integration/connect/envoy/case-gateway-without-services/service_gateway.hcl b/test/integration/connect/envoy/case-gateway-without-services/service_gateway.hcl index 2026fb2a94b84..446a2698e595b 100644 --- a/test/integration/connect/envoy/case-gateway-without-services/service_gateway.hcl +++ b/test/integration/connect/envoy/case-gateway-without-services/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-gateway-without-services/service_s1.hcl b/test/integration/connect/envoy/case-gateway-without-services/service_s1.hcl index 0891eebceb9c9..f74a67a5aef0c 100644 --- a/test/integration/connect/envoy/case-gateway-without-services/service_s1.hcl +++ b/test/integration/connect/envoy/case-gateway-without-services/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s1 service diff --git a/test/integration/connect/envoy/case-gateway-without-services/service_s2.hcl b/test/integration/connect/envoy/case-gateway-without-services/service_s2.hcl index ca644bb3ffa22..1f3f2edd47893 100644 --- a/test/integration/connect/envoy/case-gateway-without-services/service_s2.hcl +++ b/test/integration/connect/envoy/case-gateway-without-services/service_s2.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s2 service diff --git a/test/integration/connect/envoy/case-gateway-without-services/setup.sh b/test/integration/connect/envoy/case-gateway-without-services/setup.sh index 6e4f5d8ee9bf9..002ef312bc34b 100644 --- a/test/integration/connect/envoy/case-gateway-without-services/setup.sh +++ b/test/integration/connect/envoy/case-gateway-without-services/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-gateway-without-services/vars.sh b/test/integration/connect/envoy/case-gateway-without-services/vars.sh index 21ab024ab5375..2d42d0baf5d3d 100644 --- a/test/integration/connect/envoy/case-gateway-without-services/vars.sh +++ b/test/integration/connect/envoy/case-gateway-without-services/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="gateway-primary" diff --git a/test/integration/connect/envoy/case-gateways-local/bind.hcl b/test/integration/connect/envoy/case-gateways-local/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-gateways-local/bind.hcl +++ b/test/integration/connect/envoy/case-gateways-local/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-gateways-local/capture.sh b/test/integration/connect/envoy/case-gateways-local/capture.sh index f4727b52c72ad..f7ca8e9586481 100644 --- a/test/integration/connect/envoy/case-gateways-local/capture.sh +++ b/test/integration/connect/envoy/case-gateways-local/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-gateways-local/primary/service_gateway.hcl b/test/integration/connect/envoy/case-gateways-local/primary/service_gateway.hcl index 2026fb2a94b84..446a2698e595b 100644 --- a/test/integration/connect/envoy/case-gateways-local/primary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-gateways-local/primary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-gateways-local/primary/service_s1.hcl b/test/integration/connect/envoy/case-gateways-local/primary/service_s1.hcl index 75fa1acc0e7e3..a759b590b07c2 100644 --- a/test/integration/connect/envoy/case-gateways-local/primary/service_s1.hcl +++ b/test/integration/connect/envoy/case-gateways-local/primary/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-gateways-local/primary/service_s2.hcl b/test/integration/connect/envoy/case-gateways-local/primary/service_s2.hcl index d0f6294f72802..acd65faf3d612 100644 --- a/test/integration/connect/envoy/case-gateways-local/primary/service_s2.hcl +++ b/test/integration/connect/envoy/case-gateways-local/primary/service_s2.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s2 service in the primary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-gateways-local/primary/setup.sh b/test/integration/connect/envoy/case-gateways-local/primary/setup.sh index 29720753ba515..a8bfb7c9ffe5d 100644 --- a/test/integration/connect/envoy/case-gateways-local/primary/setup.sh +++ b/test/integration/connect/envoy/case-gateways-local/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-gateways-local/secondary/join.hcl b/test/integration/connect/envoy/case-gateways-local/secondary/join.hcl index f0bd3fbd4ac7e..0f63220d549fe 100644 --- a/test/integration/connect/envoy/case-gateways-local/secondary/join.hcl +++ b/test/integration/connect/envoy/case-gateways-local/secondary/join.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 retry_join_wan = ["consul-primary-server"] diff --git a/test/integration/connect/envoy/case-gateways-local/secondary/service_gateway.hcl b/test/integration/connect/envoy/case-gateways-local/secondary/service_gateway.hcl index 4f91a740182af..8c2315b9ae360 100644 --- a/test/integration/connect/envoy/case-gateways-local/secondary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-gateways-local/secondary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-gateways-local/secondary/service_s1.hcl b/test/integration/connect/envoy/case-gateways-local/secondary/service_s1.hcl index 8b4d4a83a42d4..06af757cd68e7 100644 --- a/test/integration/connect/envoy/case-gateways-local/secondary/service_s1.hcl +++ b/test/integration/connect/envoy/case-gateways-local/secondary/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # we don't want an s1 service in the secondary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-gateways-local/secondary/setup.sh b/test/integration/connect/envoy/case-gateways-local/secondary/setup.sh index ede2b4c4b9f70..938135c9f4ff3 100644 --- a/test/integration/connect/envoy/case-gateways-local/secondary/setup.sh +++ b/test/integration/connect/envoy/case-gateways-local/secondary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail @@ -9,4 +9,4 @@ register_services secondary gen_envoy_bootstrap s2 19001 secondary gen_envoy_bootstrap mesh-gateway 19003 secondary true -retry_default docker_consul secondary curl -s "http://localhost:8500/v1/catalog/service/consul?dc=primary" > /dev/null +retry_default docker_consul secondary curl -s "http://localhost:8500/v1/catalog/service/consul?dc=primary" >/dev/null diff --git a/test/integration/connect/envoy/case-gateways-local/vars.sh b/test/integration/connect/envoy/case-gateways-local/vars.sh index d9a319933f8da..c5ab45789beba 100644 --- a/test/integration/connect/envoy/case-gateways-local/vars.sh +++ b/test/integration/connect/envoy/case-gateways-local/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy gateway-primary s2-secondary s2-sidecar-proxy-secondary gateway-secondary" diff --git a/test/integration/connect/envoy/case-gateways-remote/bind.hcl b/test/integration/connect/envoy/case-gateways-remote/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-gateways-remote/bind.hcl +++ b/test/integration/connect/envoy/case-gateways-remote/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-gateways-remote/capture.sh b/test/integration/connect/envoy/case-gateways-remote/capture.sh index f4727b52c72ad..f7ca8e9586481 100644 --- a/test/integration/connect/envoy/case-gateways-remote/capture.sh +++ b/test/integration/connect/envoy/case-gateways-remote/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-gateways-remote/primary/service_s1.hcl b/test/integration/connect/envoy/case-gateways-remote/primary/service_s1.hcl index 4cb4fbc41d1e3..789717ee52297 100644 --- a/test/integration/connect/envoy/case-gateways-remote/primary/service_s1.hcl +++ b/test/integration/connect/envoy/case-gateways-remote/primary/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-gateways-remote/primary/service_s2.hcl b/test/integration/connect/envoy/case-gateways-remote/primary/service_s2.hcl index d0f6294f72802..acd65faf3d612 100644 --- a/test/integration/connect/envoy/case-gateways-remote/primary/service_s2.hcl +++ b/test/integration/connect/envoy/case-gateways-remote/primary/service_s2.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s2 service in the primary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-gateways-remote/primary/setup.sh b/test/integration/connect/envoy/case-gateways-remote/primary/setup.sh index 6dd0f0622bd36..f79f346477e47 100644 --- a/test/integration/connect/envoy/case-gateways-remote/primary/setup.sh +++ b/test/integration/connect/envoy/case-gateways-remote/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-gateways-remote/secondary/join.hcl b/test/integration/connect/envoy/case-gateways-remote/secondary/join.hcl index f0bd3fbd4ac7e..0f63220d549fe 100644 --- a/test/integration/connect/envoy/case-gateways-remote/secondary/join.hcl +++ b/test/integration/connect/envoy/case-gateways-remote/secondary/join.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 retry_join_wan = ["consul-primary-server"] diff --git a/test/integration/connect/envoy/case-gateways-remote/secondary/service_gateway.hcl b/test/integration/connect/envoy/case-gateways-remote/secondary/service_gateway.hcl index 4f91a740182af..8c2315b9ae360 100644 --- a/test/integration/connect/envoy/case-gateways-remote/secondary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-gateways-remote/secondary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-gateways-remote/secondary/service_s1.hcl b/test/integration/connect/envoy/case-gateways-remote/secondary/service_s1.hcl index 8b4d4a83a42d4..06af757cd68e7 100644 --- a/test/integration/connect/envoy/case-gateways-remote/secondary/service_s1.hcl +++ b/test/integration/connect/envoy/case-gateways-remote/secondary/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # we don't want an s1 service in the secondary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-gateways-remote/secondary/setup.sh b/test/integration/connect/envoy/case-gateways-remote/secondary/setup.sh index 43a4c713cee91..938135c9f4ff3 100644 --- a/test/integration/connect/envoy/case-gateways-remote/secondary/setup.sh +++ b/test/integration/connect/envoy/case-gateways-remote/secondary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-gateways-remote/vars.sh b/test/integration/connect/envoy/case-gateways-remote/vars.sh index d9a319933f8da..c5ab45789beba 100644 --- a/test/integration/connect/envoy/case-gateways-remote/vars.sh +++ b/test/integration/connect/envoy/case-gateways-remote/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy gateway-primary s2-secondary s2-sidecar-proxy-secondary gateway-secondary" diff --git a/test/integration/connect/envoy/case-grpc/service_s1.hcl b/test/integration/connect/envoy/case-grpc/service_s1.hcl index 7d7814800c4d7..b22ba221fa1df 100644 --- a/test/integration/connect/envoy/case-grpc/service_s1.hcl +++ b/test/integration/connect/envoy/case-grpc/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" @@ -20,7 +20,7 @@ services { protocol = "grpc" envoy_dogstatsd_url = "udp://127.0.0.1:8125" envoy_stats_tags = ["foo=bar"] - envoy_stats_flush_interval = "5s" + envoy_stats_flush_interval = "1s" } } } diff --git a/test/integration/connect/envoy/case-grpc/service_s2.hcl b/test/integration/connect/envoy/case-grpc/service_s2.hcl index aaebecf627320..f7d7a267343d3 100644 --- a/test/integration/connect/envoy/case-grpc/service_s2.hcl +++ b/test/integration/connect/envoy/case-grpc/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-grpc/setup.sh b/test/integration/connect/envoy/case-grpc/setup.sh index 3fb3ade6c5fbb..b88cc90129682 100644 --- a/test/integration/connect/envoy/case-grpc/setup.sh +++ b/test/integration/connect/envoy/case-grpc/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-grpc/vars.sh b/test/integration/connect/envoy/case-grpc/vars.sh index 7fa5a238ce933..c599f12e8232d 100644 --- a/test/integration/connect/envoy/case-grpc/vars.sh +++ b/test/integration/connect/envoy/case-grpc/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES fake-statsd" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-grpc/verify.bats b/test/integration/connect/envoy/case-grpc/verify.bats index fc7ca15b5b94a..422258a0c0ef7 100644 --- a/test/integration/connect/envoy/case-grpc/verify.bats +++ b/test/integration/connect/envoy/case-grpc/verify.bats @@ -43,7 +43,7 @@ load helpers metrics_query='envoy.cluster.grpc.PingServer.total.*[#,]local_cluster:s1(,|$)' fi - run retry_long must_match_in_statsd_logs "${metrics_query}" + run retry_default must_match_in_statsd_logs "${metrics_query}" echo "OUTPUT: $output" [ "$status" == 0 ] diff --git a/test/integration/connect/envoy/case-http-badauthz/capture.sh b/test/integration/connect/envoy/case-http-badauthz/capture.sh index c6b9e36ed1df1..94c0278ce256c 100644 --- a/test/integration/connect/envoy/case-http-badauthz/capture.sh +++ b/test/integration/connect/envoy/case-http-badauthz/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 || true diff --git a/test/integration/connect/envoy/case-http-badauthz/service_s1.hcl b/test/integration/connect/envoy/case-http-badauthz/service_s1.hcl index 25d2c1e380f26..96f67dcf40999 100644 --- a/test/integration/connect/envoy/case-http-badauthz/service_s1.hcl +++ b/test/integration/connect/envoy/case-http-badauthz/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-http-badauthz/service_s2.hcl b/test/integration/connect/envoy/case-http-badauthz/service_s2.hcl index fb857d005ee91..4b6632beb8365 100644 --- a/test/integration/connect/envoy/case-http-badauthz/service_s2.hcl +++ b/test/integration/connect/envoy/case-http-badauthz/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-http-badauthz/setup.sh b/test/integration/connect/envoy/case-http-badauthz/setup.sh index d15f836e65847..6bd91b1f4e66f 100644 --- a/test/integration/connect/envoy/case-http-badauthz/setup.sh +++ b/test/integration/connect/envoy/case-http-badauthz/setup.sh @@ -1,14 +1,14 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail -register_services primary - # Setup deny intention setup_upsert_l4_intention s1 s2 deny +register_services primary + gen_envoy_bootstrap s1 19000 primary gen_envoy_bootstrap s2 19001 primary diff --git a/test/integration/connect/envoy/case-http/capture.sh b/test/integration/connect/envoy/case-http/capture.sh index 14dc00afc65b8..5268305f8ff6c 100644 --- a/test/integration/connect/envoy/case-http/capture.sh +++ b/test/integration/connect/envoy/case-http/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-http/service_s1.hcl b/test/integration/connect/envoy/case-http/service_s1.hcl index 42a62acfb9f68..0c3f594fbc7d1 100644 --- a/test/integration/connect/envoy/case-http/service_s1.hcl +++ b/test/integration/connect/envoy/case-http/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-http/service_s2.hcl b/test/integration/connect/envoy/case-http/service_s2.hcl index fb857d005ee91..4b6632beb8365 100644 --- a/test/integration/connect/envoy/case-http/service_s2.hcl +++ b/test/integration/connect/envoy/case-http/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-http/setup.sh b/test/integration/connect/envoy/case-http/setup.sh index 3fb3ade6c5fbb..b88cc90129682 100644 --- a/test/integration/connect/envoy/case-http/setup.sh +++ b/test/integration/connect/envoy/case-http/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-ingress-gateway-grpc/capture.sh b/test/integration/connect/envoy/case-ingress-gateway-grpc/capture.sh index 4214ba8274aaa..1c244823aba8b 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-grpc/capture.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-grpc/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 ingress-gateway primary || true diff --git a/test/integration/connect/envoy/case-ingress-gateway-grpc/service_gateway.hcl b/test/integration/connect/envoy/case-ingress-gateway-grpc/service_gateway.hcl index a1324f7f83799..fbb1d402f9869 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-grpc/service_gateway.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-grpc/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "ingress-gateway" diff --git a/test/integration/connect/envoy/case-ingress-gateway-grpc/service_s1.hcl b/test/integration/connect/envoy/case-ingress-gateway-grpc/service_s1.hcl index f525d48868ced..ff23e6fea3a0d 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-grpc/service_s1.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-grpc/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-ingress-gateway-grpc/setup.sh b/test/integration/connect/envoy/case-ingress-gateway-grpc/setup.sh index 387d079e3bd2a..40e2802f02ccf 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-grpc/setup.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-grpc/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-ingress-gateway-grpc/vars.sh b/test/integration/connect/envoy/case-ingress-gateway-grpc/vars.sh index 8b34fe36ef2a3..32dc504c49ce0 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-grpc/vars.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-grpc/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES ingress-gateway-primary" diff --git a/test/integration/connect/envoy/case-ingress-gateway-http/capture.sh b/test/integration/connect/envoy/case-ingress-gateway-http/capture.sh index c2b55d229a591..ab02875e61359 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-http/capture.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-http/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 ingress-gateway primary || true \ No newline at end of file diff --git a/test/integration/connect/envoy/case-ingress-gateway-http/service_gateway.hcl b/test/integration/connect/envoy/case-ingress-gateway-http/service_gateway.hcl index a1324f7f83799..fbb1d402f9869 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-http/service_gateway.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-http/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "ingress-gateway" diff --git a/test/integration/connect/envoy/case-ingress-gateway-http/setup.sh b/test/integration/connect/envoy/case-ingress-gateway-http/setup.sh index 33d06b516c725..03f2184e6d067 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-http/setup.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-http/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-ingress-gateway-http/vars.sh b/test/integration/connect/envoy/case-ingress-gateway-http/vars.sh index 8b34fe36ef2a3..32dc504c49ce0 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-http/vars.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-http/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES ingress-gateway-primary" diff --git a/test/integration/connect/envoy/case-ingress-gateway-multiple-services/capture.sh b/test/integration/connect/envoy/case-ingress-gateway-multiple-services/capture.sh index c2b55d229a591..ab02875e61359 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-multiple-services/capture.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-multiple-services/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 ingress-gateway primary || true \ No newline at end of file diff --git a/test/integration/connect/envoy/case-ingress-gateway-multiple-services/service_gateway.hcl b/test/integration/connect/envoy/case-ingress-gateway-multiple-services/service_gateway.hcl index a1324f7f83799..fbb1d402f9869 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-multiple-services/service_gateway.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-multiple-services/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "ingress-gateway" diff --git a/test/integration/connect/envoy/case-ingress-gateway-multiple-services/setup.sh b/test/integration/connect/envoy/case-ingress-gateway-multiple-services/setup.sh index 858d2f9ce53a2..f80e42cb73325 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-multiple-services/setup.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-multiple-services/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-ingress-gateway-multiple-services/vars.sh b/test/integration/connect/envoy/case-ingress-gateway-multiple-services/vars.sh index 8b34fe36ef2a3..32dc504c49ce0 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-multiple-services/vars.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-multiple-services/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES ingress-gateway-primary" diff --git a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/base.hcl b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/base.hcl index 8cd6db14878a7..899e81705a4cf 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/base.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 primary_datacenter = "alpha" log_level = "trace" diff --git a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/service_gateway.hcl b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/service_gateway.hcl index 640b9b6ce753f..82ddd559eb3a5 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/service_gateway.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/service_s1.hcl b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/service_s1.hcl index b065abc9055e2..11acde14f4270 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/service_s1.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s1 service in this peer diff --git a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/service_s2.hcl b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/service_s2.hcl index 26b5f481f377a..6666a63ba257e 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/service_s2.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/setup.sh b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/setup.sh index 99c4eb46f2186..5aabbbbee0e5d 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/setup.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/alpha/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/bind.hcl b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/bind.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/capture.sh b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/capture.sh index ca10f2773107a..20ad858ecdb60 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/capture.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 ingress-gateway primary || true diff --git a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/base.hcl b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/base.hcl index 55c268b37e784..189b8e0ccf722 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/base.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 peering { enabled = true diff --git a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/service_ingress.hcl b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/service_ingress.hcl index a1324f7f83799..fbb1d402f9869 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/service_ingress.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/service_ingress.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "ingress-gateway" diff --git a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/service_s1.hcl b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/service_s1.hcl index 18be60cdbf96a..85f8da9740029 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/service_s1.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't need an s1 because requests go through the gateway and not a sidecar. \ No newline at end of file diff --git a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/service_s2.hcl b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/service_s2.hcl index 26b5f481f377a..6666a63ba257e 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/service_s2.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/setup.sh b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/setup.sh index b4a8dd736feec..58f12866948f2 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/setup.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/vars.sh b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/vars.sh index 8f9ac12cb1e3d..08bfe96a9d3b3 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-peering-failover/vars.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-peering-failover/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s2 s2-sidecar-proxy s2-alpha s2-sidecar-proxy-alpha gateway-alpha ingress-gateway-primary" diff --git a/test/integration/connect/envoy/case-ingress-gateway-sds/capture.sh b/test/integration/connect/envoy/case-ingress-gateway-sds/capture.sh index c2b55d229a591..ab02875e61359 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-sds/capture.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-sds/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 ingress-gateway primary || true \ No newline at end of file diff --git a/test/integration/connect/envoy/case-ingress-gateway-sds/service_gateway.hcl b/test/integration/connect/envoy/case-ingress-gateway-sds/service_gateway.hcl index 1ffa476e6ff98..176a66f1afef1 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-sds/service_gateway.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-sds/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "ingress-gateway" diff --git a/test/integration/connect/envoy/case-ingress-gateway-sds/setup.sh b/test/integration/connect/envoy/case-ingress-gateway-sds/setup.sh index fbef09b014cf2..fb98b05aad30a 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-sds/setup.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-sds/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-ingress-gateway-sds/vars.sh b/test/integration/connect/envoy/case-ingress-gateway-sds/vars.sh index 6bbbcfd6fe52d..0c98c8fe04507 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-sds/vars.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-sds/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES ingress-gateway-primary test-sds-server" diff --git a/test/integration/connect/envoy/case-ingress-gateway-simple/capture.sh b/test/integration/connect/envoy/case-ingress-gateway-simple/capture.sh index c2b55d229a591..ab02875e61359 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-simple/capture.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-simple/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 ingress-gateway primary || true \ No newline at end of file diff --git a/test/integration/connect/envoy/case-ingress-gateway-simple/service_gateway.hcl b/test/integration/connect/envoy/case-ingress-gateway-simple/service_gateway.hcl index a1324f7f83799..fbb1d402f9869 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-simple/service_gateway.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-simple/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "ingress-gateway" diff --git a/test/integration/connect/envoy/case-ingress-gateway-simple/setup.sh b/test/integration/connect/envoy/case-ingress-gateway-simple/setup.sh index aaaa4d91cb4de..8bcd42aa5075f 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-simple/setup.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-simple/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-ingress-gateway-simple/vars.sh b/test/integration/connect/envoy/case-ingress-gateway-simple/vars.sh index 8b34fe36ef2a3..32dc504c49ce0 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-simple/vars.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-simple/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES ingress-gateway-primary" diff --git a/test/integration/connect/envoy/case-ingress-gateway-tls/capture.sh b/test/integration/connect/envoy/case-ingress-gateway-tls/capture.sh index c2b55d229a591..ab02875e61359 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-tls/capture.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-tls/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 ingress-gateway primary || true \ No newline at end of file diff --git a/test/integration/connect/envoy/case-ingress-gateway-tls/service_gateway.hcl b/test/integration/connect/envoy/case-ingress-gateway-tls/service_gateway.hcl index a1324f7f83799..fbb1d402f9869 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-tls/service_gateway.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-tls/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "ingress-gateway" diff --git a/test/integration/connect/envoy/case-ingress-gateway-tls/setup.sh b/test/integration/connect/envoy/case-ingress-gateway-tls/setup.sh index a485eeaa5b29f..accafeb7353ee 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-tls/setup.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-tls/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-ingress-gateway-tls/vars.sh b/test/integration/connect/envoy/case-ingress-gateway-tls/vars.sh index 8b34fe36ef2a3..32dc504c49ce0 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-tls/vars.sh +++ b/test/integration/connect/envoy/case-ingress-gateway-tls/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES ingress-gateway-primary" diff --git a/test/integration/connect/envoy/case-ingress-gateway-tls/verify.bats b/test/integration/connect/envoy/case-ingress-gateway-tls/verify.bats index 92a158e51b6a5..61eaaf97ccdf8 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-tls/verify.bats +++ b/test/integration/connect/envoy/case-ingress-gateway-tls/verify.bats @@ -19,7 +19,7 @@ load helpers } @test "ingress-gateway should have healthy endpoints for s1" { - assert_upstream_has_endpoints_in_status 127.0.0.1:20000 s1 HEALTHY 1 + assert_upstream_has_endpoints_in_status 127.0.0.1:20000 s1 HEALTHY 1 } @test "should be able to connect to s1 through the TLS-enabled ingress port" { @@ -29,8 +29,8 @@ load helpers run retry_default curl --cacert <(get_ca_root) -s -f -d hello \ --resolve s1.ingress.consul:9998:127.0.0.1 \ https://s1.ingress.consul:9998 - [ "$status" -eq 0 ] - [[ "$output" == *"hello"* ]] + [ "$status" -eq 0 ] + [[ "$output" == *"hello"* ]] } @test "should be able to connect to s1 through the TLS-enabled ingress port using the custom host" { @@ -38,6 +38,6 @@ load helpers run retry_default curl --cacert <(get_ca_root) -s -f -d hello \ --resolve test.example.com:9999:127.0.0.1 \ https://test.example.com:9999 - [ "$status" -eq 0 ] - [[ "$output" == *"hello"* ]] + [ "$status" -eq 0 ] + [[ "$output" == *"hello"* ]] } diff --git a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/bind.hcl b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/bind.hcl +++ b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/capture.sh b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/capture.sh index 3bbc13144aa27..556a296756f0a 100644 --- a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/capture.sh +++ b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 ingress-gateway primary || true diff --git a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_gateway.hcl b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_gateway.hcl index 2026fb2a94b84..446a2698e595b 100644 --- a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_ingress.hcl b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_ingress.hcl index a1324f7f83799..fbb1d402f9869 100644 --- a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_ingress.hcl +++ b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_ingress.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "ingress-gateway" diff --git a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_s1.hcl b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_s1.hcl index e6f778e5c811d..b9772c7da8627 100644 --- a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_s1.hcl +++ b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s1 service in the primary dc diff --git a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_s2.hcl b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_s2.hcl index d0f6294f72802..acd65faf3d612 100644 --- a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_s2.hcl +++ b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/service_s2.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s2 service in the primary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/setup.sh b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/setup.sh index f7e31ac0db5a4..72025d4f8efed 100644 --- a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/setup.sh +++ b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/secondary/join.hcl b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/secondary/join.hcl index f0bd3fbd4ac7e..0f63220d549fe 100644 --- a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/secondary/join.hcl +++ b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/secondary/join.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 retry_join_wan = ["consul-primary-server"] diff --git a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/secondary/service_gateway.hcl b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/secondary/service_gateway.hcl index 4f91a740182af..8c2315b9ae360 100644 --- a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/secondary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/secondary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/secondary/setup.sh b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/secondary/setup.sh index 59f303a5eafde..a012c03b9e969 100644 --- a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/secondary/setup.sh +++ b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/secondary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/vars.sh b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/vars.sh index 85c791704a871..8d492ea3af8dc 100644 --- a/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/vars.sh +++ b/test/integration/connect/envoy/case-ingress-mesh-gateways-resolver/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="gateway-primary s1-secondary s1-sidecar-proxy-secondary s2-secondary s2-sidecar-proxy-secondary gateway-secondary ingress-gateway-primary" diff --git a/test/integration/connect/envoy/case-l7-intentions/acl.hcl b/test/integration/connect/envoy/case-l7-intentions/acl.hcl index 3d80d4f69420b..41e2b1995359c 100644 --- a/test/integration/connect/envoy/case-l7-intentions/acl.hcl +++ b/test/integration/connect/envoy/case-l7-intentions/acl.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 acl { default_policy = "deny" diff --git a/test/integration/connect/envoy/case-l7-intentions/capture.sh b/test/integration/connect/envoy/case-l7-intentions/capture.sh index d588be9381ea0..c93e4c6cea95e 100644 --- a/test/integration/connect/envoy/case-l7-intentions/capture.sh +++ b/test/integration/connect/envoy/case-l7-intentions/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-l7-intentions/setup.sh b/test/integration/connect/envoy/case-l7-intentions/setup.sh index 6946ce3263a9a..705eac06255be 100644 --- a/test/integration/connect/envoy/case-l7-intentions/setup.sh +++ b/test/integration/connect/envoy/case-l7-intentions/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-lua/capture.sh b/test/integration/connect/envoy/case-lua/capture.sh index 14dc00afc65b8..5268305f8ff6c 100644 --- a/test/integration/connect/envoy/case-lua/capture.sh +++ b/test/integration/connect/envoy/case-lua/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-lua/service_s1.hcl b/test/integration/connect/envoy/case-lua/service_s1.hcl index 54c6ac6501b40..6eaca129855b9 100644 --- a/test/integration/connect/envoy/case-lua/service_s1.hcl +++ b/test/integration/connect/envoy/case-lua/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-lua/service_s2.hcl b/test/integration/connect/envoy/case-lua/service_s2.hcl index a167379776625..c01f4b2fefe59 100644 --- a/test/integration/connect/envoy/case-lua/service_s2.hcl +++ b/test/integration/connect/envoy/case-lua/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-lua/setup.sh b/test/integration/connect/envoy/case-lua/setup.sh index 56a668c0ac061..e6b7e3eca3dd2 100644 --- a/test/integration/connect/envoy/case-lua/setup.sh +++ b/test/integration/connect/envoy/case-lua/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-lua/vars.sh b/test/integration/connect/envoy/case-lua/vars.sh index ac0664606f93b..091a358e13dfd 100644 --- a/test/integration/connect/envoy/case-lua/vars.sh +++ b/test/integration/connect/envoy/case-lua/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy s2 s2-sidecar-proxy" diff --git a/test/integration/connect/envoy/case-mesh-to-lambda/capture.sh b/test/integration/connect/envoy/case-mesh-to-lambda/capture.sh index b64ad4d05a9c1..3c3c6a928a0ca 100644 --- a/test/integration/connect/envoy/case-mesh-to-lambda/capture.sh +++ b/test/integration/connect/envoy/case-mesh-to-lambda/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-mesh-to-lambda/service_gateway.hcl b/test/integration/connect/envoy/case-mesh-to-lambda/service_gateway.hcl index 63c212da3ace6..e1b3ea8a8fdeb 100644 --- a/test/integration/connect/envoy/case-mesh-to-lambda/service_gateway.hcl +++ b/test/integration/connect/envoy/case-mesh-to-lambda/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "terminating-gateway" diff --git a/test/integration/connect/envoy/case-mesh-to-lambda/service_s1.hcl b/test/integration/connect/envoy/case-mesh-to-lambda/service_s1.hcl index 11e8328a82fac..9bc567caa0a9c 100644 --- a/test/integration/connect/envoy/case-mesh-to-lambda/service_s1.hcl +++ b/test/integration/connect/envoy/case-mesh-to-lambda/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-mesh-to-lambda/setup.sh b/test/integration/connect/envoy/case-mesh-to-lambda/setup.sh index 406914e3cf5a9..359fbd863fc47 100644 --- a/test/integration/connect/envoy/case-mesh-to-lambda/setup.sh +++ b/test/integration/connect/envoy/case-mesh-to-lambda/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-mesh-to-lambda/vars.sh b/test/integration/connect/envoy/case-mesh-to-lambda/vars.sh index 8643eead0d266..fbe042a40b479 100644 --- a/test/integration/connect/envoy/case-mesh-to-lambda/vars.sh +++ b/test/integration/connect/envoy/case-mesh-to-lambda/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # Ensure that the environment variables required to configure and invoke the Lambda function are present, otherwise skip. diff --git a/test/integration/connect/envoy/case-multidc-rsa-ca/bind.hcl b/test/integration/connect/envoy/case-multidc-rsa-ca/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-multidc-rsa-ca/bind.hcl +++ b/test/integration/connect/envoy/case-multidc-rsa-ca/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-multidc-rsa-ca/ca_config.hcl b/test/integration/connect/envoy/case-multidc-rsa-ca/ca_config.hcl index 0f8d98ac6be52..e5db7ec1b8855 100644 --- a/test/integration/connect/envoy/case-multidc-rsa-ca/ca_config.hcl +++ b/test/integration/connect/envoy/case-multidc-rsa-ca/ca_config.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 connect { enabled = true diff --git a/test/integration/connect/envoy/case-multidc-rsa-ca/capture.sh b/test/integration/connect/envoy/case-multidc-rsa-ca/capture.sh index daf25ad574959..170c0e3cdfb66 100644 --- a/test/integration/connect/envoy/case-multidc-rsa-ca/capture.sh +++ b/test/integration/connect/envoy/case-multidc-rsa-ca/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-multidc-rsa-ca/primary/service_s1.hcl b/test/integration/connect/envoy/case-multidc-rsa-ca/primary/service_s1.hcl index b4eb4b1f04fd7..e4f73b127142f 100644 --- a/test/integration/connect/envoy/case-multidc-rsa-ca/primary/service_s1.hcl +++ b/test/integration/connect/envoy/case-multidc-rsa-ca/primary/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-multidc-rsa-ca/primary/service_s2.hcl b/test/integration/connect/envoy/case-multidc-rsa-ca/primary/service_s2.hcl index d0f6294f72802..acd65faf3d612 100644 --- a/test/integration/connect/envoy/case-multidc-rsa-ca/primary/service_s2.hcl +++ b/test/integration/connect/envoy/case-multidc-rsa-ca/primary/service_s2.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s2 service in the primary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-multidc-rsa-ca/primary/setup.sh b/test/integration/connect/envoy/case-multidc-rsa-ca/primary/setup.sh index de07522f12f73..efbac1091d621 100644 --- a/test/integration/connect/envoy/case-multidc-rsa-ca/primary/setup.sh +++ b/test/integration/connect/envoy/case-multidc-rsa-ca/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-multidc-rsa-ca/secondary/join.hcl b/test/integration/connect/envoy/case-multidc-rsa-ca/secondary/join.hcl index f0bd3fbd4ac7e..0f63220d549fe 100644 --- a/test/integration/connect/envoy/case-multidc-rsa-ca/secondary/join.hcl +++ b/test/integration/connect/envoy/case-multidc-rsa-ca/secondary/join.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 retry_join_wan = ["consul-primary-server"] diff --git a/test/integration/connect/envoy/case-multidc-rsa-ca/secondary/service_s1.hcl b/test/integration/connect/envoy/case-multidc-rsa-ca/secondary/service_s1.hcl index 8b4d4a83a42d4..06af757cd68e7 100644 --- a/test/integration/connect/envoy/case-multidc-rsa-ca/secondary/service_s1.hcl +++ b/test/integration/connect/envoy/case-multidc-rsa-ca/secondary/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # we don't want an s1 service in the secondary dc \ No newline at end of file diff --git a/test/integration/connect/envoy/case-multidc-rsa-ca/secondary/setup.sh b/test/integration/connect/envoy/case-multidc-rsa-ca/secondary/setup.sh index 712cdd5e79456..17d9cecd2a027 100644 --- a/test/integration/connect/envoy/case-multidc-rsa-ca/secondary/setup.sh +++ b/test/integration/connect/envoy/case-multidc-rsa-ca/secondary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-multidc-rsa-ca/vars.sh b/test/integration/connect/envoy/case-multidc-rsa-ca/vars.sh index 7bf4a264a204f..f49887ddcdfa5 100644 --- a/test/integration/connect/envoy/case-multidc-rsa-ca/vars.sh +++ b/test/integration/connect/envoy/case-multidc-rsa-ca/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy s2-secondary s2-sidecar-proxy-secondary" diff --git a/test/integration/connect/envoy/case-prometheus/capture.sh b/test/integration/connect/envoy/case-prometheus/capture.sh index 8bc4413d09f9e..21ebba78787be 100644 --- a/test/integration/connect/envoy/case-prometheus/capture.sh +++ b/test/integration/connect/envoy/case-prometheus/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-prometheus/service_s1.hcl b/test/integration/connect/envoy/case-prometheus/service_s1.hcl index 4ac588d9a2a09..d318f786c1079 100644 --- a/test/integration/connect/envoy/case-prometheus/service_s1.hcl +++ b/test/integration/connect/envoy/case-prometheus/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-prometheus/service_s2.hcl b/test/integration/connect/envoy/case-prometheus/service_s2.hcl index fb857d005ee91..4b6632beb8365 100644 --- a/test/integration/connect/envoy/case-prometheus/service_s2.hcl +++ b/test/integration/connect/envoy/case-prometheus/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-prometheus/setup.sh b/test/integration/connect/envoy/case-prometheus/setup.sh index 3fb3ade6c5fbb..b88cc90129682 100644 --- a/test/integration/connect/envoy/case-prometheus/setup.sh +++ b/test/integration/connect/envoy/case-prometheus/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-property-override/capture.sh b/test/integration/connect/envoy/case-property-override/capture.sh index bc1ac2dcf172e..88f1dd6465f25 100644 --- a/test/integration/connect/envoy/case-property-override/capture.sh +++ b/test/integration/connect/envoy/case-property-override/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-property-override/service_s1.hcl b/test/integration/connect/envoy/case-property-override/service_s1.hcl index a1f811b527429..6bacecf916171 100644 --- a/test/integration/connect/envoy/case-property-override/service_s1.hcl +++ b/test/integration/connect/envoy/case-property-override/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-property-override/service_s2.hcl b/test/integration/connect/envoy/case-property-override/service_s2.hcl index a167379776625..c01f4b2fefe59 100644 --- a/test/integration/connect/envoy/case-property-override/service_s2.hcl +++ b/test/integration/connect/envoy/case-property-override/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-property-override/service_s3.hcl b/test/integration/connect/envoy/case-property-override/service_s3.hcl index 4e5c7cb78e03a..d616906e4c678 100644 --- a/test/integration/connect/envoy/case-property-override/service_s3.hcl +++ b/test/integration/connect/envoy/case-property-override/service_s3.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s3" diff --git a/test/integration/connect/envoy/case-property-override/setup.sh b/test/integration/connect/envoy/case-property-override/setup.sh index dd82af3487d8e..744055f94966f 100644 --- a/test/integration/connect/envoy/case-property-override/setup.sh +++ b/test/integration/connect/envoy/case-property-override/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-property-override/vars.sh b/test/integration/connect/envoy/case-property-override/vars.sh index 172824ba73d10..358866872a137 100644 --- a/test/integration/connect/envoy/case-property-override/vars.sh +++ b/test/integration/connect/envoy/case-property-override/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy s2 s2-sidecar-proxy s3 s3-sidecar-proxy" diff --git a/test/integration/connect/envoy/case-stats-proxy/service_s1.hcl b/test/integration/connect/envoy/case-stats-proxy/service_s1.hcl index 3be3803cb4882..25d959520cfe5 100644 --- a/test/integration/connect/envoy/case-stats-proxy/service_s1.hcl +++ b/test/integration/connect/envoy/case-stats-proxy/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-stats-proxy/service_s2.hcl b/test/integration/connect/envoy/case-stats-proxy/service_s2.hcl index fb857d005ee91..4b6632beb8365 100644 --- a/test/integration/connect/envoy/case-stats-proxy/service_s2.hcl +++ b/test/integration/connect/envoy/case-stats-proxy/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-stats-proxy/setup.sh b/test/integration/connect/envoy/case-stats-proxy/setup.sh index 3fb3ade6c5fbb..b88cc90129682 100644 --- a/test/integration/connect/envoy/case-stats-proxy/setup.sh +++ b/test/integration/connect/envoy/case-stats-proxy/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-stats-proxy/verify.bats b/test/integration/connect/envoy/case-stats-proxy/verify.bats index a200a5a313671..2d02010dc1851 100644 --- a/test/integration/connect/envoy/case-stats-proxy/verify.bats +++ b/test/integration/connect/envoy/case-stats-proxy/verify.bats @@ -40,7 +40,7 @@ load helpers must_match_in_stats_proxy_response localhost:1239 \ 'stats' '^http.envoy_metrics.downstream_rq_active' - # Response should include the local cluster request. + # Response should include the the local cluster request. retry_default \ must_match_in_stats_proxy_response localhost:1239 \ 'stats' 'cluster.local_agent.upstream_rq_active' diff --git a/test/integration/connect/envoy/case-statsd-udp/service_s1.hcl b/test/integration/connect/envoy/case-statsd-udp/service_s1.hcl index a416ce25a0ce0..2748dc59b0843 100644 --- a/test/integration/connect/envoy/case-statsd-udp/service_s1.hcl +++ b/test/integration/connect/envoy/case-statsd-udp/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-statsd-udp/setup.sh b/test/integration/connect/envoy/case-statsd-udp/setup.sh index 883c78e1eb7f5..66e5af830037c 100644 --- a/test/integration/connect/envoy/case-statsd-udp/setup.sh +++ b/test/integration/connect/envoy/case-statsd-udp/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-statsd-udp/vars.sh b/test/integration/connect/envoy/case-statsd-udp/vars.sh index 7fa5a238ce933..c599f12e8232d 100644 --- a/test/integration/connect/envoy/case-statsd-udp/vars.sh +++ b/test/integration/connect/envoy/case-statsd-udp/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES fake-statsd" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-terminating-gateway-hostnames/capture.sh b/test/integration/connect/envoy/case-terminating-gateway-hostnames/capture.sh index f5515165d799d..fbfd74951abf1 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-hostnames/capture.sh +++ b/test/integration/connect/envoy/case-terminating-gateway-hostnames/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 terminating-gateway primary || true diff --git a/test/integration/connect/envoy/case-terminating-gateway-hostnames/service_gateway.hcl b/test/integration/connect/envoy/case-terminating-gateway-hostnames/service_gateway.hcl index 63c212da3ace6..e1b3ea8a8fdeb 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-hostnames/service_gateway.hcl +++ b/test/integration/connect/envoy/case-terminating-gateway-hostnames/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "terminating-gateway" diff --git a/test/integration/connect/envoy/case-terminating-gateway-hostnames/service_s1.hcl b/test/integration/connect/envoy/case-terminating-gateway-hostnames/service_s1.hcl index da98b2729cbf1..a0f80d75676c5 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-hostnames/service_s1.hcl +++ b/test/integration/connect/envoy/case-terminating-gateway-hostnames/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-terminating-gateway-hostnames/service_s4.hcl b/test/integration/connect/envoy/case-terminating-gateway-hostnames/service_s4.hcl index 3fba0f792ebd8..ce8a7bbcf67ae 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-hostnames/service_s4.hcl +++ b/test/integration/connect/envoy/case-terminating-gateway-hostnames/service_s4.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s4" diff --git a/test/integration/connect/envoy/case-terminating-gateway-hostnames/setup.sh b/test/integration/connect/envoy/case-terminating-gateway-hostnames/setup.sh index 919f9cfd1e9a2..bca191d6d11df 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-hostnames/setup.sh +++ b/test/integration/connect/envoy/case-terminating-gateway-hostnames/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-terminating-gateway-hostnames/vars.sh b/test/integration/connect/envoy/case-terminating-gateway-hostnames/vars.sh index a86dca2e7e31a..e4e3560ceea56 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-hostnames/vars.sh +++ b/test/integration/connect/envoy/case-terminating-gateway-hostnames/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # There is no sidecar proxy for s2, since the terminating gateway acts as the proxy diff --git a/test/integration/connect/envoy/case-terminating-gateway-simple/service_gateway.hcl b/test/integration/connect/envoy/case-terminating-gateway-simple/service_gateway.hcl index 63c212da3ace6..e1b3ea8a8fdeb 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-simple/service_gateway.hcl +++ b/test/integration/connect/envoy/case-terminating-gateway-simple/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "terminating-gateway" diff --git a/test/integration/connect/envoy/case-terminating-gateway-simple/setup.sh b/test/integration/connect/envoy/case-terminating-gateway-simple/setup.sh index f8638925a4a17..c4d33d8fe1df8 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-simple/setup.sh +++ b/test/integration/connect/envoy/case-terminating-gateway-simple/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-terminating-gateway-simple/vars.sh b/test/integration/connect/envoy/case-terminating-gateway-simple/vars.sh index 02ed45703c1e2..12cb3aa9ae1f9 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-simple/vars.sh +++ b/test/integration/connect/envoy/case-terminating-gateway-simple/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # There is no sidecar proxy for s2, since the terminating gateway acts as the proxy diff --git a/test/integration/connect/envoy/case-terminating-gateway-subsets/capture.sh b/test/integration/connect/envoy/case-terminating-gateway-subsets/capture.sh index 8a28a10f3a6df..30d597a96aa5c 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-subsets/capture.sh +++ b/test/integration/connect/envoy/case-terminating-gateway-subsets/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:20000 terminating-gateway primary || true diff --git a/test/integration/connect/envoy/case-terminating-gateway-subsets/service_gateway.hcl b/test/integration/connect/envoy/case-terminating-gateway-subsets/service_gateway.hcl index f294b64e6966a..b9af6a07093d4 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-subsets/service_gateway.hcl +++ b/test/integration/connect/envoy/case-terminating-gateway-subsets/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "terminating-gateway" diff --git a/test/integration/connect/envoy/case-terminating-gateway-subsets/service_s2-v1.hcl b/test/integration/connect/envoy/case-terminating-gateway-subsets/service_s2-v1.hcl index 2191385000f66..4812ba8db3907 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-subsets/service_s2-v1.hcl +++ b/test/integration/connect/envoy/case-terminating-gateway-subsets/service_s2-v1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s2-v1" diff --git a/test/integration/connect/envoy/case-terminating-gateway-subsets/service_s2-v2.hcl b/test/integration/connect/envoy/case-terminating-gateway-subsets/service_s2-v2.hcl index cc7df98777ebd..aa8f453a17e62 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-subsets/service_s2-v2.hcl +++ b/test/integration/connect/envoy/case-terminating-gateway-subsets/service_s2-v2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s2-v2" diff --git a/test/integration/connect/envoy/case-terminating-gateway-subsets/service_s3.hcl b/test/integration/connect/envoy/case-terminating-gateway-subsets/service_s3.hcl index 3269b33a8117f..30b3f9e6658b0 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-subsets/service_s3.hcl +++ b/test/integration/connect/envoy/case-terminating-gateway-subsets/service_s3.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { id = "s3" diff --git a/test/integration/connect/envoy/case-terminating-gateway-subsets/setup.sh b/test/integration/connect/envoy/case-terminating-gateway-subsets/setup.sh index ec38097fd2735..63e0708aca594 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-subsets/setup.sh +++ b/test/integration/connect/envoy/case-terminating-gateway-subsets/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -euo pipefail diff --git a/test/integration/connect/envoy/case-terminating-gateway-subsets/vars.sh b/test/integration/connect/envoy/case-terminating-gateway-subsets/vars.sh index e6d96721e4c50..0dd7176570f20 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-subsets/vars.sh +++ b/test/integration/connect/envoy/case-terminating-gateway-subsets/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # There is no sidecar proxy for s2-v1, since the terminating gateway acts as the proxy diff --git a/test/integration/connect/envoy/case-terminating-gateway-without-services/bind.hcl b/test/integration/connect/envoy/case-terminating-gateway-without-services/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-without-services/bind.hcl +++ b/test/integration/connect/envoy/case-terminating-gateway-without-services/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-terminating-gateway-without-services/service_gateway.hcl b/test/integration/connect/envoy/case-terminating-gateway-without-services/service_gateway.hcl index fee3bb25b00b0..4f784aab291b4 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-without-services/service_gateway.hcl +++ b/test/integration/connect/envoy/case-terminating-gateway-without-services/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "terminating-gateway" diff --git a/test/integration/connect/envoy/case-terminating-gateway-without-services/service_s1.hcl b/test/integration/connect/envoy/case-terminating-gateway-without-services/service_s1.hcl index 0891eebceb9c9..f74a67a5aef0c 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-without-services/service_s1.hcl +++ b/test/integration/connect/envoy/case-terminating-gateway-without-services/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s1 service diff --git a/test/integration/connect/envoy/case-terminating-gateway-without-services/service_s2.hcl b/test/integration/connect/envoy/case-terminating-gateway-without-services/service_s2.hcl index ca644bb3ffa22..1f3f2edd47893 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-without-services/service_s2.hcl +++ b/test/integration/connect/envoy/case-terminating-gateway-without-services/service_s2.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s2 service diff --git a/test/integration/connect/envoy/case-terminating-gateway-without-services/setup.sh b/test/integration/connect/envoy/case-terminating-gateway-without-services/setup.sh index 91f82633b3d51..4192820bd514c 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-without-services/setup.sh +++ b/test/integration/connect/envoy/case-terminating-gateway-without-services/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-terminating-gateway-without-services/vars.sh b/test/integration/connect/envoy/case-terminating-gateway-without-services/vars.sh index a8d23fead535d..d6e7573ffff2c 100644 --- a/test/integration/connect/envoy/case-terminating-gateway-without-services/vars.sh +++ b/test/integration/connect/envoy/case-terminating-gateway-without-services/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="terminating-gateway-primary" diff --git a/test/integration/connect/envoy/case-upstream-config/service_s1.hcl b/test/integration/connect/envoy/case-upstream-config/service_s1.hcl index 3bfcb906db70f..6d3da674ed968 100644 --- a/test/integration/connect/envoy/case-upstream-config/service_s1.hcl +++ b/test/integration/connect/envoy/case-upstream-config/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-upstream-config/service_s2.hcl b/test/integration/connect/envoy/case-upstream-config/service_s2.hcl index a167379776625..c01f4b2fefe59 100644 --- a/test/integration/connect/envoy/case-upstream-config/service_s2.hcl +++ b/test/integration/connect/envoy/case-upstream-config/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-upstream-config/setup.sh b/test/integration/connect/envoy/case-upstream-config/setup.sh index 3fb3ade6c5fbb..b88cc90129682 100644 --- a/test/integration/connect/envoy/case-upstream-config/setup.sh +++ b/test/integration/connect/envoy/case-upstream-config/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-wanfed-gw/bind.hcl b/test/integration/connect/envoy/case-wanfed-gw/bind.hcl index e54caa47a4922..057e0e727f66a 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/bind.hcl +++ b/test/integration/connect/envoy/case-wanfed-gw/bind.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 bind_addr = "0.0.0.0" advertise_addr = "{{ GetInterfaceIP \"eth0\" }}" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-wanfed-gw/capture.sh b/test/integration/connect/envoy/case-wanfed-gw/capture.sh index 5c24811d11722..17a53a4320405 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/capture.sh +++ b/test/integration/connect/envoy/case-wanfed-gw/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 mesh-gateway primary || true diff --git a/test/integration/connect/envoy/case-wanfed-gw/global-setup-windows.sh b/test/integration/connect/envoy/case-wanfed-gw/global-setup-windows.sh deleted file mode 100644 index 080d5abf94f1d..0000000000000 --- a/test/integration/connect/envoy/case-wanfed-gw/global-setup-windows.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - - -# initialize the outputs for each dc -for dc in primary secondary; do - rm -rf "workdir/${dc}/tls" - mkdir -p "workdir/${dc}/tls" -done - -container="consul-envoy-integ-tls-init--${CASE_NAME}" - -scriptlet=" -mkdir /out ; -cd /out ; -consul tls ca create ; -consul tls cert create -dc=primary -server -node=pri ; -consul tls cert create -dc=secondary -server -node=sec ; -" - -docker.exe rm -f "$container" &>/dev/null || true -docker.exe run -i --net=none --name="$container" windows/consul:local bash -c "${scriptlet}" - -# primary -for f in \ - consul-agent-ca.pem \ - primary-server-consul-0-key.pem \ - primary-server-consul-0.pem \ - ; do - docker.exe cp "${container}:C:\\Program Files\\Git\\out\\$f" workdir/primary/tls -done - -# secondary -for f in \ - consul-agent-ca.pem \ - secondary-server-consul-0-key.pem \ - secondary-server-consul-0.pem \ - ; do - docker.exe cp "${container}:C:\\Program Files\\Git\\out\\$f" workdir/secondary/tls -done - -# Private keys have 600 perms but tests are run as another user -chmod 666 workdir/primary/tls/primary-server-consul-0-key.pem -chmod 666 workdir/secondary/tls/secondary-server-consul-0-key.pem - -docker.exe rm -f "$container" >/dev/null || true \ No newline at end of file diff --git a/test/integration/connect/envoy/case-wanfed-gw/global-setup.sh b/test/integration/connect/envoy/case-wanfed-gw/global-setup.sh index 0e21aef6893ad..50625daf07878 100755 --- a/test/integration/connect/envoy/case-wanfed-gw/global-setup.sh +++ b/test/integration/connect/envoy/case-wanfed-gw/global-setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # initialize the outputs for each dc diff --git a/test/integration/connect/envoy/case-wanfed-gw/primary/common.hcl b/test/integration/connect/envoy/case-wanfed-gw/primary/common.hcl index 06ad70b29aaf7..d30c465429cca 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/primary/common.hcl +++ b/test/integration/connect/envoy/case-wanfed-gw/primary/common.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 tls { internal_rpc { diff --git a/test/integration/connect/envoy/case-wanfed-gw/primary/server.hcl b/test/integration/connect/envoy/case-wanfed-gw/primary/server.hcl index e694d94c441eb..ee2d77e48637d 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/primary/server.hcl +++ b/test/integration/connect/envoy/case-wanfed-gw/primary/server.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 node_name = "pri" connect { diff --git a/test/integration/connect/envoy/case-wanfed-gw/primary/service_gateway.hcl b/test/integration/connect/envoy/case-wanfed-gw/primary/service_gateway.hcl index 0a33536b9c8dd..31c8747b9308c 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/primary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-wanfed-gw/primary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-wanfed-gw/primary/service_s1.hcl b/test/integration/connect/envoy/case-wanfed-gw/primary/service_s1.hcl index 0891eebceb9c9..f74a67a5aef0c 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/primary/service_s1.hcl +++ b/test/integration/connect/envoy/case-wanfed-gw/primary/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s1 service diff --git a/test/integration/connect/envoy/case-wanfed-gw/primary/service_s2.hcl b/test/integration/connect/envoy/case-wanfed-gw/primary/service_s2.hcl index ca644bb3ffa22..1f3f2edd47893 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/primary/service_s2.hcl +++ b/test/integration/connect/envoy/case-wanfed-gw/primary/service_s2.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s2 service diff --git a/test/integration/connect/envoy/case-wanfed-gw/primary/setup.sh b/test/integration/connect/envoy/case-wanfed-gw/primary/setup.sh index 11d5abf14d595..f39cf66dd0097 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/primary/setup.sh +++ b/test/integration/connect/envoy/case-wanfed-gw/primary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-wanfed-gw/secondary/common.hcl b/test/integration/connect/envoy/case-wanfed-gw/secondary/common.hcl index 6b76d377d8210..570fa9d0594e0 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/secondary/common.hcl +++ b/test/integration/connect/envoy/case-wanfed-gw/secondary/common.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 tls { internal_rpc { diff --git a/test/integration/connect/envoy/case-wanfed-gw/secondary/server.hcl b/test/integration/connect/envoy/case-wanfed-gw/secondary/server.hcl index 027174bf632d7..6265b917445e7 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/secondary/server.hcl +++ b/test/integration/connect/envoy/case-wanfed-gw/secondary/server.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 node_name = "sec" connect { diff --git a/test/integration/connect/envoy/case-wanfed-gw/secondary/service_gateway.hcl b/test/integration/connect/envoy/case-wanfed-gw/secondary/service_gateway.hcl index bba04fd97146f..c010c4d4e4a25 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/secondary/service_gateway.hcl +++ b/test/integration/connect/envoy/case-wanfed-gw/secondary/service_gateway.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "mesh-gateway" diff --git a/test/integration/connect/envoy/case-wanfed-gw/secondary/service_s1.hcl b/test/integration/connect/envoy/case-wanfed-gw/secondary/service_s1.hcl index 0891eebceb9c9..f74a67a5aef0c 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/secondary/service_s1.hcl +++ b/test/integration/connect/envoy/case-wanfed-gw/secondary/service_s1.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s1 service diff --git a/test/integration/connect/envoy/case-wanfed-gw/secondary/service_s2.hcl b/test/integration/connect/envoy/case-wanfed-gw/secondary/service_s2.hcl index ca644bb3ffa22..1f3f2edd47893 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/secondary/service_s2.hcl +++ b/test/integration/connect/envoy/case-wanfed-gw/secondary/service_s2.hcl @@ -1,4 +1,4 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 # We don't want an s2 service diff --git a/test/integration/connect/envoy/case-wanfed-gw/secondary/setup.sh b/test/integration/connect/envoy/case-wanfed-gw/secondary/setup.sh index 0f4313108c8ce..ef5032115a59d 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/secondary/setup.sh +++ b/test/integration/connect/envoy/case-wanfed-gw/secondary/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-wanfed-gw/vars.sh b/test/integration/connect/envoy/case-wanfed-gw/vars.sh index 4de3b552dcf83..79007fcfe8d27 100644 --- a/test/integration/connect/envoy/case-wanfed-gw/vars.sh +++ b/test/integration/connect/envoy/case-wanfed-gw/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="gateway-primary gateway-secondary" diff --git a/test/integration/connect/envoy/case-wasm/capture.sh b/test/integration/connect/envoy/case-wasm/capture.sh index 14dc00afc65b8..5268305f8ff6c 100644 --- a/test/integration/connect/envoy/case-wasm/capture.sh +++ b/test/integration/connect/envoy/case-wasm/capture.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 snapshot_envoy_admin localhost:19000 s1 primary || true diff --git a/test/integration/connect/envoy/case-wasm/service_s1.hcl b/test/integration/connect/envoy/case-wasm/service_s1.hcl index 54c6ac6501b40..6eaca129855b9 100644 --- a/test/integration/connect/envoy/case-wasm/service_s1.hcl +++ b/test/integration/connect/envoy/case-wasm/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-wasm/service_s2.hcl b/test/integration/connect/envoy/case-wasm/service_s2.hcl index a167379776625..c01f4b2fefe59 100644 --- a/test/integration/connect/envoy/case-wasm/service_s2.hcl +++ b/test/integration/connect/envoy/case-wasm/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-wasm/setup.sh b/test/integration/connect/envoy/case-wasm/setup.sh index 54ab4d4c72ce4..d491aa92fc1db 100644 --- a/test/integration/connect/envoy/case-wasm/setup.sh +++ b/test/integration/connect/envoy/case-wasm/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-wasm/vars.sh b/test/integration/connect/envoy/case-wasm/vars.sh index ac0664606f93b..091a358e13dfd 100644 --- a/test/integration/connect/envoy/case-wasm/vars.sh +++ b/test/integration/connect/envoy/case-wasm/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="s1 s1-sidecar-proxy s2 s2-sidecar-proxy" diff --git a/test/integration/connect/envoy/case-zipkin/service_s1.hcl b/test/integration/connect/envoy/case-zipkin/service_s1.hcl index 5f6935fedfbfe..7adcedd7db9e0 100644 --- a/test/integration/connect/envoy/case-zipkin/service_s1.hcl +++ b/test/integration/connect/envoy/case-zipkin/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/case-zipkin/service_s2.hcl b/test/integration/connect/envoy/case-zipkin/service_s2.hcl index 21b8f859b8f23..a537840dff690 100644 --- a/test/integration/connect/envoy/case-zipkin/service_s2.hcl +++ b/test/integration/connect/envoy/case-zipkin/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/case-zipkin/setup.sh b/test/integration/connect/envoy/case-zipkin/setup.sh index 3fb3ade6c5fbb..b88cc90129682 100644 --- a/test/integration/connect/envoy/case-zipkin/setup.sh +++ b/test/integration/connect/envoy/case-zipkin/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/case-zipkin/vars.sh b/test/integration/connect/envoy/case-zipkin/vars.sh index 7f4fb54ac6d79..c4221f8b1aca8 100644 --- a/test/integration/connect/envoy/case-zipkin/vars.sh +++ b/test/integration/connect/envoy/case-zipkin/vars.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES jaeger" \ No newline at end of file diff --git a/test/integration/connect/envoy/case-zipkin/verify.bats b/test/integration/connect/envoy/case-zipkin/verify.bats index 509345689069c..d771d523639a4 100644 --- a/test/integration/connect/envoy/case-zipkin/verify.bats +++ b/test/integration/connect/envoy/case-zipkin/verify.bats @@ -35,17 +35,14 @@ load helpers # Send traced request through upstream. Debug echoes headers back which we can # use to get the traceID generated (no way to force one I can find with Envoy # currently?) - # Fixed from /Debug -> /debug. Reason: /Debug return null - run curl -s -f -H 'x-client-trace-id:test-sentinel' localhost:5000/debug -m 5 + run curl -s -f -H 'x-client-trace-id:test-sentinel' localhost:5000/Debug echo "OUTPUT $output" [ "$status" == "0" ] # Get the traceID from the output - # Replaced grep by jq to filter the TraceId. - # Reason: Grep did not filter and return the entire raw string and the test was failing - TRACEID=$(echo $output | jq -rR 'split("X-B3-Traceid: ") | last' | cut -c -16) + TRACEID=$(echo $output | grep 'X-B3-Traceid:' | cut -c 15-) # Get the trace from Jaeger. Won't bother parsing it just seeing it show up # there is enough to know that the tracing config worked. diff --git a/test/integration/connect/envoy/consul-base-cfg/base.hcl b/test/integration/connect/envoy/consul-base-cfg/base.hcl index 941f68aa26f6a..49116ea6e9b0e 100644 --- a/test/integration/connect/envoy/consul-base-cfg/base.hcl +++ b/test/integration/connect/envoy/consul-base-cfg/base.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 primary_datacenter = "primary" log_level = "trace" \ No newline at end of file diff --git a/test/integration/connect/envoy/consul-base-cfg/service_s1.hcl b/test/integration/connect/envoy/consul-base-cfg/service_s1.hcl index b2b685c08abec..9a883739e4fa3 100644 --- a/test/integration/connect/envoy/consul-base-cfg/service_s1.hcl +++ b/test/integration/connect/envoy/consul-base-cfg/service_s1.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s1" diff --git a/test/integration/connect/envoy/consul-base-cfg/service_s2.hcl b/test/integration/connect/envoy/consul-base-cfg/service_s2.hcl index 73d7798297812..0869e74f24068 100644 --- a/test/integration/connect/envoy/consul-base-cfg/service_s2.hcl +++ b/test/integration/connect/envoy/consul-base-cfg/service_s2.hcl @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 services { name = "s2" diff --git a/test/integration/connect/envoy/defaults.sh b/test/integration/connect/envoy/defaults.sh index f92c2cfb1fa9f..ad428e49eaf5f 100644 --- a/test/integration/connect/envoy/defaults.sh +++ b/test/integration/connect/envoy/defaults.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 export DEFAULT_REQUIRED_SERVICES="s1 s1-sidecar-proxy s2 s2-sidecar-proxy" diff --git a/test/integration/connect/envoy/docker-windows.md b/test/integration/connect/envoy/docker-windows.md deleted file mode 100644 index a9f2bbcaca1ca..0000000000000 --- a/test/integration/connect/envoy/docker-windows.md +++ /dev/null @@ -1,42 +0,0 @@ -# Docker Files for Windows Integration Tests - -## Index - -- [About](#about-this-file) -- [Pre-requisites](#pre-requisites) -- [Dockerfile-test-sds-server-windows](#dockerfile-test-sds-server-windows) - -## About this File - -In this file you will find which Dockerfiles are needed to run the Envoy integration tests on Windows, as well as information on how to run each of these files individually for testing purposes. - -## Pre-requisites - -After building and running the images and containers, you need to have pre-built the base images used by these Dockerfiles. See [pre-built images required in Windows](../../../../build-support-windows/BUILD-IMAGES.md) - -## Dockerfile-test-sds-server-windows - -This file sole purpose is to build the test-sds-server executable using Go. To do so, we use an official [golang image](https://hub.docker.com/_/golang/) provided in docker hub with Windows nano server. -To build this image you need to run the following command on your terminal: - -```shell -docker build -t test-sds-server -f Dockerfile-test-sds-server-windows test-sds-server -``` - -This is the same command used in run-tests.sh - -You can test the built file by running the following command: - -```shell -docker run --rm -p 1234:1234 --name test-sds-server test-sds-server -``` - -If everything works properly you should get the following output: - -```shell -20XX-XX-XXTXX:XX:XX.XXX-XXX [INFO] Loaded cert from file: name=ca-root -20XX-XX-XXTXX:XX:XX.XXX-XXX [INFO] Loaded cert from file: name=foo.example.com -20XX-XX-XXTXX:XX:XX.XXX-XXX [INFO] Loaded cert from file: name=wildcard.ingress.consul -20XX-XX-XXTXX:XX:XX.XXX-XXX [INFO] Loaded cert from file: name=www.example.com -20XX-XX-XXTXX:XX:XX.XXX-XXX [INFO] ==> SDS listening: addr=0.0.0.0:1234 -``` diff --git a/test/integration/connect/envoy/docs/img/linux-arch.png b/test/integration/connect/envoy/docs/img/linux-arch.png deleted file mode 100644 index 710b83b24570baad3e673b71d2c59c8e8018edd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63964 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 #@kZ!sf*w33Y#gk z83*)hmRaW^9SzLkjnk`q;-{}8{)>y3dh<@8Ti>z^%7ZZQFv)F4Uf!M(ZACwICg7+x7xXoZOMX8|v52r4vcTC<`Nh0yWbk}GX#k4tVAM*7Y`L5)R z7b)@FEcfv>@j8K$3pw3t%xVv5&v&VqwkKL;D8@aUSDghF5v%2bIc(?kNon`!;uw)C zql0v$IL~9p;V(l3ojlvWJ-c3F8I?gh=gH&-O+`)_?{WE^ybVVP{OYse?6{)UIdOx= z#_8)~4}Q(uk`rB-I#<$Cw1JcFvGc@+x@*^ukBYiF4;db|aa_}IyAT>iDxC3Q!ePzr zkc=jZw)*C|c5G?Yk%?oK=Mz2+a9vaEL4TgkZm_fDA{>q-3adPH*{4--zzK`wR`*S? z3hRqAwzSa(6N>|UT8k}VMm$nal%JHJJ;CUt7o*w6-}kiXVmygPx2rS{dEJW6ota45 zqYsU8dO&qD{xxVDZi@_O+?OhAatIAfA8>r=92-uvDdI={AxtYYHtwK^U71(84Y^AF zW})>lyP6*3ALh|3gAdCcvCPv@xl6@KQmE&h*-1sNVFr62v*)s~w>6ar{!c4+A*l9F zO;z`>-<140q3zfLc6QkGA?O9~_g&2Jm4tRh1xA(TW{m0hxH5) z_^>L8gD>?3ClnY;Y47sUUK8EcUO4fn7?qm?wq{k#Ka0)|YAQk>*<_Y{3f=0&YGNui z_a8SkEX7Tk%HgWr`gRE8P)*#@Eq-m%lIecPrvm^V(2ZD+%cOYCBPZ5i?La_Y0s(nW zt%Mv!ox0FM8$cJ3v%Z%npDAqKPN(=7VxoP!{B~md5k@Xm?;vdZG!FmBgMVY3D zbaOqv%M|7JXmDaZC+Oh^u8Dx_5k2{F@6p76Sc_jPTH6M;mr~^1{*|*ocItI{a3tcf z)0%ZG5XRmwkN8VS$cYHX2w2MX;Ymt)e4=mlnIa|AU#h2!k};DdxIOz%h3s&@D3;5& zASDfcDAa?y_F6c$IdqCA7nb zL(sNVH&@kdj^DC2uTa|nvk#l*`6bEcH>XjzGN(ty=gJn!V(npQ-S@JnC?)(|OjK1y zw|@Rx0W{COF{^akQ-g=#Ta|8V_q5-}*uwD?XX%NU)>9BFs&|(@8=C`x2C#g;be3+= ze#3MfAyWXUZ?9Xn`-nhm98{mCWSo<#JfNoGRM~!Dmr*j@cE}BXHx>%tVBEVZES# ziBaEU2cn2|&6_&Jd%(~}#wKeDM#(15$r{uBLcU~0XQD5^A5k!Y)g{JoB~+;v zGAUW6sgJu8=*`my8u)Dp{9Q*$%E3VC(bOP>7s2{@kdJvtVo)N6+MHEewL50Nnu|NL z{P>E3!hh=0uy*PU5O_#))#C|!B}JOoCkcLxy|L=PwR-FJU0-xkykLQS`Fl5W=ZF^x zhpv7qdfylrIr=R9ulnut%cKJUzZ^ifu3#N7rQSd$5c5+02^Y45A4e5UV zoHdzVb{2s+058EWa~erjG0FW+1=~mB>_(^~nhow{;dZ$Rx=qA7ho*@-3mr-3eBV5BrNV zJm^;z2Zk88aDmL~Eri}5y@x`}sTt7DdQw(>u&;tC)@|Z(q|xxym7>-0&u2~5hzJut z!KlQX{u6V{jbDkLPoF@;$3Yx9li97K=HNV#F;L+ewJ(SYmp~WvSG8)yS*efLL8hez z_s%_hBP)k_Et+&CW!F>>4C}_XkxPt;BZ~$oVZ>AGu<<&4hDY({B=RNLfR?p?Rzua@ zras@hsM&sB?q+*5<>`Wy*ohgdKu9qexBHW%kd`X0*tkQK!d=&qExO<9#XwDkY?f}J zSye^1t$9{g->+O|uuk2kXoGyi5nx?L;Dq?;V*jBaoFwGOwBnfqu&s{tVn=TiHlv`FqFf=+17RsDZ|0^B7e3SV@hpYOf4T6dp%?S~gqc%!#O{l4Kap7NSTSHNFbDr*%BSl~!v(xh7pi=Lxf!z%Zpc(phXAE9BU zGxudL$9$&pW5bUV4}ZR+oeBBtm}C|_34G8yXW^9-PUAx3HgtA}t~T4R;0!}i+`PH= zN8}VN(bsFFoNfXS3Zlg8)|VJ-d{n*j!I9I)f602G}`1CJmOnZ zxuAP7Ad0LsdhZfuVOVV@ifvKtK~K=^UW0sSyP3114GC-J@j25WPa!qYPj8Zma+^{_ zk+jw35_adANGUfPf3u{NIw&G!7SzvOdw$k$OwZ|YG7}$bLB#Y+M`DNz@9GY}fV7z3 z;@|D)!sZ9OjyYQ>BR85|xGoe}-9}VdU zs_YFgH-Vd*!8`lg@J{boe-BoXaZeXyEyRQUser=Q1i5jj z@ez1HX`ThG^x+`>$i1*2RlDngX7XaD6e8y=^XYxhO*PT(>UT!YLf!Ys)rY;aiOv6h$>H6$KVkhppm`fC z#ps1y`<>Sc6)Lzk0-#)IN^d(lztus1TT@*}-s>Lx)rwE&1AlNGVFTg% zh>Owdk#^m*D>)jFz$*@xfh_dCFr4T8V@IXs8#TI+eGe!1|{kUJ=Hu(oW z%yXZRs#Av_*>KF%9GdzYfIX`X0W?W1OU3xx4!Gu|IsEGHDWxx3btB`J+&l$%} z-S-?nc+h2D=%uF*JN)MJiq9a8 z+O_6ZBqPWnmkkl8&gC28e_JWBTcARbPH5~Qr?)|y(dorLe$F#?9cLOilt^fMEsTi$rY7*VJSq;#9}#O#tP>BrFW$^^c@Lu%u1xR_4QiN z8hU6-7@NIflLr7Pbxct0wRS06(7bZ>~;ASLK{xSmob*z6F)Hr8ur4E0T}Wg1xZG?EZ+k zru>a88;RL-+XP7u)X5?lLTqZ>q+GW?YKGo#*dtFxW>}sWhi&)^3pP;pMgie_0*?SQ)^#seQFa5LAzzgHG3AY=mu16t0`RnZb zg|qWd2OlU0_9>rDQ~V|S=>d8;3Zw$2>S)5v{1Uo&(Yi7vK?Mx`SuLIsg8rxl_moU; zY%D_~`U2^JEdgqt@q{LdZA~nx*s-9*mS^N6mWG8p1dVAAAG1Y)*NB{s5;Df?GP^z0 zc-#~hr0rK5kvIOyrE)_mp1?goERc zDgGAV5hC52$oEQKd>%PH5<+rh9zyfn`UA=@F%1z67ZVD3sPelT=M@p)Xef2YDYcuW z`yz~H>TNt*2C`95kaFy5hVz>t1sXjBVk!^p0@lkvRYE2MjlntuWHs4B2Q2tS8-d{@ z%*5hEKrK3c_cv~AIcjqhn28~f43E_-3k#tx9)@itfX)Po%oXZ>+DlsE-|avdE9cxv zaqkn3o3&trjQ(n&6T;E48Em+`W0eYynCvcHmC64(>~|i$vI@*)a$n3Ced!U<>x*gO zu9KxIPK7d>RiRVhdR!*~_x%~K>-yxi{(UVj z4gn4}Ha0HpySE;&u^rA}V>@{N$RXev58<~U;9;M~1Ff5E`1Z5Yz{x>74LuDuwxTG` zEo*k*{HW_)Qx7&ap|HJw`=TZmZQ0m%GqrDNzhf}DX95v$o<4+2kN=LF`zlAF?cX*Y`5O@Eh`(yVCbD5^nyTJghee)Pvvqa7l*LSL{3YyL?gC{?D;Hp2= zC^bxZZ@oAOT;Q)GM2;mJbnN#T8=Jc6AJKdF`0Icj+=ux6H}K-^6aUM8N1p!}%4H^Foz8CO1UYoflE^!8?I92Sc=30iV3+Mm0RYZnEQ# zKcesC30-$R*I(&VfVpSB`K`z%D0jKP%C8t=D`i&Fn%yzX^MmVvX`T^oNr!3`I8wFP zAP8pvoUyIiPeN5<_W$}M&s)5lcY`-Z!!nbDGu!p^90SpjVu)OS^r-4RBj8Ir%rSy65O$4vVZn z|FawR+_v0zB~RcUdW?`z?@f!Jh~^m=I6oNBR&f0GeZSU$!^b@}jGVd+ai+zWlma&j zG0lwCJ}VzvB`4}N^p)F&ujj3X@?Kgh`2F}x3+?1Hf?8+7oFS^Kuy(Qz92YpTXT|>< zjO_e<2=+KbmQsGE$*X7i+^Q?ln44F5zSnGwg{yd}wK-|8JDNa^K`eu+WwP2x_NU>1 zc~#84?Dz+dIIi(mWGgxkPC?Hg8jnYuzFM38`(xQUgq!)IOCEaaI9%+CcbMj>s$3rq z*ye#>I39^ND{ar#e;Y1S@pty85~qPlXxl{I(C$oL!6wXu!>Ey%PF7tv$J~3@nXYwt zd9rO8`WpFk6kj>F^gkAe^RAW8kQesL)Z%#KWg?N-^yT^C_v4LGl^Wf}cH}kWIU_5p z5fdW;;CLqv&DzK`&9yjAC@pSRZpr>MhHgz|43x599%dzui`dDoXO!`Vh-K{CfVuMQ zMGxQul7G~4%C6}A`-VsB@c7?@6`e8&Rvc3DH_lBY_7tKqrcR} zN-lV3>+z4j|I%AaMKIK?mcKk2Xxu)=Ux`xU6%3TLV`{_CIEaMv%eJ5K)J@;c34S7^ zA_L*7kHJ2BH_8-C${VpxvMR$bITBhY8+%@qN_VGh@zphJHx@a0-Dft7OLgDW1g$$I z^~Nt(&Xed+y@@2iGV)orb?^;kR#p74^MvlS7UhZGu?hnIdMzwQk$?eo;Bx!_3_ z+eKik+q$dc=)>G(gXg_%qLzw%ObNBoYMk}<=4ue)4zk9j+a5FOw(2KmG&x$tVIe=E zBn44998nh-)_AmEsbL}u<&ca|=xxdzq@8kTQ$5A8erisWX|&@$p+(DL5bjsuLVE`f z|60qC=hRaedaA|2-gmC3*Q(99H$4B#dYD%Ti1aMQ-Zz0jKX5HWI?^NTELoP z&F$%~NCPXY`FI78>-W!>=+lEX6H;neEVijqP1=kU=vT~KRI*pLygU+}r`x^uKCh~) zxtAxv3G`M(ZP+C?b=o)S=0pZE-W!vNOGMhYp^OlSzT38Ek@oiXpCadKT;ZBjZ;49Z zY64xj;FOih>%PuyjJIChc_+234-7BHnAZ{miorfoYlLR$BG%5_m+ZTSm_V;p{|Q)h zTQ66EMiB=4U{~SmdR#N^n;hg64cZO31X7M18XcK{tR|difaBaTQ3!^rjb~DLe-vr? zCSqhCGxPyz+#^=>*Se(G*n4qJ6VUg8Rk(ZT*y-=t_tN39Vca5X(3e=m_dI+>GsG5K zGQcPunaf^Mas3_wobnkL4afpP5oaZy+nFU`7qC9J>LE8*L6^ZaOBgd>N2)kc3017_ zPe6ELVh5L21wY=gMdyV+0!hH`S9s&9wft9SCZH6%m8ni}EYWZI38wiC>#32n9m?uO zSIIz;O&G*BQ>a+RXKB#LfIF}{CJ<<39Mo9r^Xu5R?K?u;zZS{9+~{z|h#yS|(|iwkuk_u@ zIW_0dl~6(F1#FjiSz6dcX2<4)L#Su#hpT#MB_RbzllLSq-XpnKtQ*QLUK7sLF4~uM zuY8`w3e4TwT%VtZzFeK{@6Lu_#(ivz64^VQ>a5Gog$BwX_LWGRm2AKolxQEjXIXzb zRhAC>w`9xR6ED5_hHETyC~C8nMqjUhNi*mEVE?P``*6PTX*fJFwwd$ zZR<|h6?d(oKHYsk0^97un`PQQKRtkw&=&TeO8rQmNFV3ltn8pJi}$Hs;J&e--svYE zb}y*$z^~iQ)yg~2r4=Q-ip}pm*uJ?+r|rk*g31G#OBo~*Sjl%Gg?iuXx$tma@QlgX zuWyj2kX9w!T-5n0zvaQA3ZMD8zUI4}cqup`=cu(uf5ZeS;Y3DMoMDVGU<;;TsFaP3KH_o%e%6dy1k0$MPnB)MBNyhlw|v8 zBo7ZhHLE54GlVE?1<1$D> z#6;H|&)_H^BuV+U`ue5rDC%kUG~z-hTH;xmdYMT9*se8$*^VxEnXIj@rC9G93}kbR zcv~-ydoxZtZc|2@Afm?)Z_G&2MEfQ!`faZ9N=KDySJreb!CO%u;^xsgHNAnJH4Ou$ zkM(Q%GR0QDpP1{VZZ{#530;yf#=EMz*`-uGFk~z}>8yD0VHu8HFLL##%po{@c3>XzCQCfB> z4t-7Nn!Wy~NA+*2^vW7ggZJ=gZ2FyuC2ao9wz|0Y=$>9?Ozwvz9eU$B6_XhoJW`TWhSh#*mL>;;HdQRvX1Rk>N7X!bgo;Dz)(HB)Hw-4yl+k?o}e^GAU#9% zZf38FI5lX2YU^0@#6HVq>@gwDMhSi)6Ouxoh&YWEJAUZtk+WfxV zTS}UMwq;V@a;^Vmw0vVWT!kcT9pOMR=Sqx^Lh904pc~}4pplZEiFm7IczZ?UqUwj< zE=^rxss~E8VdN!sw>3e28wRC@%{?_qg@2Y--CLKsFz$8iG0Gd`-QJl>Wt>^q1Fs+R zzQ6oYy~WT;9j^B^7yDQ>8gs?^=6i4~i09MerjwZF2O&)sN4wDH<_Ah$ zipP=qR^%d}6x@KdP_*=tgm3s>vGXY80O#aC!b#VBc;;QcUm;W9^`3^r1Y)m1Sc)-9 zws?*2ujjX#&6e{l0Iz)m%HPfUZH=&BixeqDhn}(SU;uew4SQ^;n=H)hLmFoOS%J`Xk&W=0y%1x!vRx;T52rzQ@9Ou>%duB<0nZBeX&W!~Dspj$O4COY(H5}{hfCpc{&7#yT?p6Fs6rHCJ+2eagTus6a zc%;4&5brU~Vp>eYXAb@1yBrV1A#NCg#gL(~#RT5YoMXdx!XMxvVzD? znuMDApRkyD?wG=T)u50?ctZV zXXLkFM&I7LDzy}R|sbvF0unP8ErttG&L$1bHCK38;} zG-b(TJ#h`trgxW`xD`)4BDQo_0i6XnmbcX8s`KD=z*&UH1L4tXB$=5S6~{@lF*=V# z<`Ab3)53BVV@|072eF zz<8|qrUpRwzDmgAoz)HiE5l9B7j-l3E=Z~kLW zNQ6d1qe$?L)#Xf9b%%}+;^~)w`RcxGbmelp3Q9r}uZkz5&gxTWe>xtrki~tYsp1WA zWTU|z|Dx^3{L83;2g+dt_g)`Z)h;1ky_a?1&*ytQ0(LIg4y0cZ8O z`LEA0x?S(c-xp7_NJUy-$z&}}lpy(uGg5vNeRY1!*zzcKWlUa9_+ zM)+(um|a%F`Fz|uME>~w8F}GDw^mJGKYxp3lAOeoo^LjB*F>$9N0|vkU;o=OcO!_8 zmH3e6FoKh4xgPRyt=1?%lLnm&xP#I}stTzLTGH0rRpvLalg-Tkgo~*ck@4D2PB`jQ z=guoZTfQ~%4C$W((;pSiSZSdspnfYiwJsD(i@?e zK7Fck{V{~!JSER~rlS5>#i6Vo`X9$fgWlqeslYkHb2k%*)btI$N8K#{N`J|sR{FRU zPcTC_z&InINYQPp*=v~=kP60A$=#&o*L_h1Nj$}o8AGLuw8zY)iMC#G@4G5!=db(&M+r`^8sU-MPDeo_f(pPPMpb77h^3>Cdz)0wsXiDP9o%aF&AR|y>9LOBr zAjiCV^R4A@1?1!>CT*pXDLm;IXWdaQor&?ejqPL6&;@AM+LAj zrc!zAN!TqnxIoWa)?ddXgj9O7bHhlI$-ZN+pRGrMT@aW)6YPlUnot(`7PuU2-0XAq zduyMTC;U_=ZkyzE6t%+{>sKBrI>T-DW#Z9p2|^WDzDG`fd?R_Ilv1s)Al_Y(E5- zhk8LrbldQh2=S7Bst>1qg-62Scum_^xu$jh;|cWwEF%`{2N+Leb!s|6+d)|~_xDub9q zE#b}Qq(qX^o25pIJlm~>iF!p7V#-;~YBG=s&Bk`atgJoIf}xr|E+$*?1VPJ2ewC69t7R`rNAp6^svQ&kdFb z<=RX;(th`E>gR2pJ_-JEn!N{2b%Fn$>Hl#s<99s;Jj<)`|9sIf&#ES<31}I&VPjo; zr8iUvVy7bV`!hJEy|)fx{skAOIOd$^`u!>!Th5XFUH?4`d2{aE|2Hqba&CkyOy|nY zehNeFLG(Y56b2~2x-+{u&#crL%+5y1Gq-;1aQF980RKfIZ3cPQc!qJ|*BjVEuEjvUty9W7#^#F1>FHo*1X0pQ{$_M&OEKN0fVa6%k1t|z=8uXieWmW2@Zmw0PV zrU@GE%h|)D_aNvm8tifgN&w*Dyae=SEbK9hY(#g~1XoFD%NV2EkxCF>4WHU!0XR#3 zx>nRCtfgvuZ2%lQ^2xR(Py#tx`_k|E;!hYxS4lkNKYLA$l*lrjxM~PKpnt|9t;w1F z@MYZ(>iQK)KRa^x{7Zhz1#A{i#xM~Xk7=IjOb>$)TXPK319NSK0~a(f4kFfi?&wl= zV;gDy9QJ1p>GKlE=?gfo->s#Y)#Oc;}RSTu<1;@jipBjt5OR(V4hV#91S*{yj7s`xeM_QSdIO zhYfGfXct&kZ^8VUw_jgQUcl;p_W_JbZ~y09_WT`T>U(s<@%eHtK?MR*`oAuaqUyB? z&Y%Q)-X(gCqf74WgRauBS=G3C3;J`|7qVfV5filB?GGQ>JVHrPw-skynL%Eg@4qg*2k0o;?7Di3qXj+RYM+Hlas%$@!mwMT5SX$F?@~TYaaE*Yf=PmnvS+JS zx^%#lAbib^Kc?AUPkQ=60d9`p>@uHoL4ZMRfX+ISTAk)MTJ1Q{;92lZS)gmPfkKLL znNTw~W_GB4ko6UDw!x(Du{@J{E!|5P9p7E#tL4Nsru}PzN6CClAT4jp-ohfFvpQv& zs~}-5VJ+zq-QMqfoUF=yslIhnJUw%nxav8~e6b$ajw9CE&}~oHEIYnpCB~a$KzjU} z!zIX5mg5AuE<#+y8TkgX_PYU>nrb&eE(Asv05%Ra$1mmC{EjyIlt^Q2YP^h_rXyeq zjj>LG4FI|q|3l%?*H@PYS`!t?vP}ResI-T#T%u=k0iJSWxTE8Hsl&|oFVAJv5CbnY zQK;&XG2h}L+y4vVW_*P=$p1*0I;B?1yr8z5-~4(AOP`5`cd#4>7cWOGS` z6FfRgUgC=qo~JVG&0LX$X>rI$GAu*jG8B$cc(U)6*DkXyvp+l-WE z$hLOB=6f*{@pSsK!>yl(eqPDAe&$`lMpa3|9ro5AZbzg}uET21Ng~nrC z&nSD^7w_Z_RQ5YF*Gg*`0M$i&xr~@5GKQ-w1^K&*?I4PKu!mrx7rmDW>y48(3zX1V z*O4NX0Nq;_#MU9S0mu6zjT}9<9oTbl3y6JNFa*pfH&#G-QA_@esy_i>y8c0NrUj_$ zZ@`rRUb;EyUH4jTEP}}L5@tG_%*!`SH)1I*+B7g|U%5kne2x0h@MMt~Rd{LcHowIW zDASC~_h*>uu77HPGeeP0^A0NGo9{MKuDA?WU22S6F1WX zf{AvTzBq>Y>JUC~>IP)%x@VvEGORuA)7?s0FWG6T{lJ32K#9@)G;&B}@Yvxv%=?R% zgF-+}16`Rq+wWRcAFr49c7vUEmE-W7|Lk$dTBhB2cCvqNfYIs3S1aZQ%fu@Ez+2?b zRVm*+^rrq$ zt{gL$*5Y$$GN2_RMT(!axwGyf`%fnQy(nSWF3`m+QF0qsG|kd*d1X(U!tquobxQgR z-ga?&vBGz^%v^KBC~Wvo1291(ApKTMysIGYf}7KW>Z>PfG)|Fjr)^7cmqbpe3~Pyj zy{QkG;sEUJ$AvHe*M5?W3A-jy;F?r63rceFlQK>yg_RX748Mu8S&y0eFe(>ol|$?^ zs+|z%`f8h4Vi`D(d^J+_W<9+WtxL7jq`A=2-L>;nag3XbON1}YS4kqESCPCJ$c7RK zF~YeBlK6^GZSclljZJ5$Szab-buFEVa|+a(-B2Deue}jkONPP2Po^P-<7_vo`QofL z5{|s2^K7=3+}dEaT)xq_aQ5aXO&Z_iwCoWJMKA2Mu5X_jK2Sb){+~U79Rg)khAx~j z$J-?^zmjWKs|?5|R*&hAFEGntT-bw-?FUa%{W5sE#SHq$*+vuJfwfenI0?tJGpitb659C8`fx(ujVEoI_z%PjeIhP1mD{ATMmW#(K>TT1!^px{IkDU zt6i0)Z`2PKxJa$5A~N;L?xNkDTAMJI@fqrtFQ#arF)osyL(L8`a$%G?!Evzkj_;Ov ztw)=W>|Ok-V^H7@^Mx&Do^@F&J#ge#>J(Gk-({h>aSY!>`|Ll5Alr41UB46n8m`^SS(#?z05;>)<>)l{ z(d+!ElD(Q+Hwk@wU6zSH>MZHNxA9fvidrm!dL4&dHxb1$1R$Leqy(GWY(78!dAi56mquoSxcdtpkiZW_OE*%2h%NsO}u+XklWrlL6EpfK+?4 z(UXfm5&A4Wm+YgZ;gvVbCeg@132gxU9*3GnsqK^rVm9{m&a!a07c>C{kK_h$%c7kL zlONQG%R+L1^q_BcwplD#7H8Ok{I7a11*N+1`9Opoas)uelrSFmlaz^z%(Ue31~Ri& zMs9UbSz6{4c%EpNcV4xW;4Ht|>i*>!yNpn`{EDbf+y?fd-%`_Mltd{SjsDq$N$8L} z7|fg(WV47zAfr2R1sh7FWxb<(3u1&EwVMUP`&4k6}yaN)cTOm z(6=8f#}{AvAN}C$$|@rHw&6;LXP^`OhwOlUA#wBOQ?A%F5$UzV=6%lbz~B__E(RD)q+q75MjF4yPO+AY462o;w((P(wky7f}vutTkh9w`tJgypU4 zDDr$A;%UyQZ1tUZ7WC{em%tBbX7~u3!3mr>ag68MGyvpc9L(ILrymVh`~|@G?b&iX zCOVva^z%o1l0v*D^0{e10^g>#IG3_4*lRvOCP7N z08L@<7`%h&upOK3?SR}L8E+NjR~#}7kUHkBnAO$Qh&E1|z;PjESX@Ye&Q$otd{LZw zHfe?9^?|m`oX{tgqQDbs`jW=@6=*#o94S~cn(>LVAZmXv2Oa|OtK_Dw^PQ+O3J_`L zP7VO@G-gwWPeE>sLeEqj9{4jQ-n+UhG|(l12-`5S+_;1WaTd_2)R02ZA8s@LZlTv?wqUaU&5xGUH>^fIClcXz zBJ2A~GW+34^@nW^FGfcHg3>J~bx z0PUr>l=->NtIvX#Em!-bQPg=XRRA0HbRk@BwoXCMB)nMkpH9-MVnpiIMZ~ts3+gyE z83=U%{9cN!y;P3t=b{Tz#ax9-)E_=Yo(fi2X}sKLcOgjQy!7XOf!wAF`_4brVpG*x zC+y)$3V|E0nC2?+KFgIqUsZokJ6C8~X23Lq%5iu$xFqo|k2l&|t)0=!6UWJwDl%q2 zRJ5;M$RHAn&5#SjZ0+yigO+A zedZoO>-ZuzbPfR3d+et6q+F1RIVwSP?1QPOq0YobLezbsXrmM7@YX6e4aYFeuhhz- zZY;fmfOrq{tehtXxq~8~+aY`N7qL>P*Cx9drkMK5N;d@P?AhPfX8mPIm&rJ1hgY`( zmH&iUPu*=Yw&`_n6JYo4a*(2?JaN+WznTKy53&xf=eRV%dCz!;Iw=`m7MDL)dZokB zud7;^1WU>4t5d{|!AS^AggNM|2x`Ru)0}fF!n&I055*xN1*8yKEjY;L{epvkIge)O zF+iLp`-wm-2wKep$ND{0f6o3_LDkYd#p5q!g}xG-ZLB2^S~Hl@u?3OX`6~f`++M#O zpxC$llc#+57)Xr(>&T%yP;E3fe}3Dw65s%~VDHXecm16G%i;(iFRui?;=e&($)wdP zvIJ2)$hFthuKYuc#QIc1Zm(6DYpNNZmTO&gUattJ;b7llq=z->CVEu>kciJ_h(rjF z!qamc$HmU^zClij`(|9yXFN~co_;PePcIp81|(%0oIlJ)HjUozJd3@IdM)P5@2!ss zcc`t`^Vy>{X7OY8aJ{B$Zr{Q9Btacc=a>76 z*LZd`{tBd7;E{rH#U|%W*1gSAPf9)$Ol{z%J-@Uz;8Hu-{Bui&lE-g{a1sdV4GJLUk-KIx5B%<2PkF>sg(fn~quA z(Oug~bdMk^BAW?&w^yxzDIYB#HXH7^)NGgh29@j~I9yByEqt_CTh$n*druDu`FOo( zvA;aIF4wF3CMY5gd)p#FK^m4nO;rw5hl_aT)#s$TjF9FI2n6pFJ8fZXOw0bn!}I!p zTW)#Y!w81#@jH?se;jUExpQyh%LAv+00LFcAc{;hJv#-I8$RPVmq0@}*^gyRYxXG5 zkA*i@US_gAB(d3>aU!*8Y2WiGV>}kzd4DDA!1amxT;vki6iyThEO6hBafsmnR*GmL zg->uA`vl=s7OeLC!>sV((*do!7;%=Pz3Je)r|mTztIpz#QvL2B+;&|~z#<@z^g;|Z z)`fC;d@&p9<8VZFa35>y=46LkYOl$?n7hDQJXy;32M0^FkNBX&kV&k{TPvI6XT8lm zGj0CGwykuW{;fn0&X{%QKw|UaN@7tPwST=>e?}@E_n>$yTd{|EC0zr^^FOz7og@4> zn*oy)YCFjJnU?J%%+c7_mahsKwec4`tKDO3P@zOjiNk|m0Yd%GmaYu0>s}GS7SWPL zC4^ySX7uFjP;$@emI3)Hpjb^>E@uLgSfC9X4&Fs!9D=Qlqh40%IqIEBJ8<1HGt{!; zD_7Aek&5wV@1nZb+=T;^0H6`X-G=Co5r;k~jXI2rM_O@lan1Q62KrMNngFoo^2ywf zD`{g1@yY!8WWs}H8-O|r%6ogWQRX(lU}>|I7ul(gQG%_nWd|=ULjupUM48iP>loK& zhbsGI+r(&oI%Tp96_F&ZG7^_WjR_Kuo2v2{ib61ZHWBn0_zTb7Y#jf{z z^Pgm{&iwJlASPUOT!Y1dspIn}iExhJV4@V9i~zzKp6 zx2>C-kUhrj*6gh&NXLcnp(_AxiS7}&?=hxHA3kS*sr9$H)#gddt-cJ;qS^u3+`00U zVzt$~R76{!``+sM%inHPS=@(oJY*Cza?0vX#6Vc>6IX zknV<*N3Y&yb>EQgE*ggqy^OSYGdEPJST6I@;c4Ea`$lNg$Bj=**o#V@Q_&FHCGUD( z;|=UqZPvTCBAdoQi3@?yyKits$vVEmFVW3qfIBBzT-M8`xH`5Gc_(hS`AiLSwcJ|w zFt>pcNORrMCE>_h^d0VkSo`Y2g0T-^K|sRliP09iKw9&bQ64EXMV$(gA);!6wzps& zaK2;@^PrO>&y`Ck?~F{v)GqabBraBkB1R-7I8jzp0T+7HwYU{~{eGzQC94KhxcQQ< z#s-@lQg%)aFvMx)ggWD^kfgXqy-(Sl>n0|>Ob5I8@HyxzpjX=!pbyqvD!$FsVa@SP zm@Rvf>F`jObGgTeNpUZ2A2)W|L5YpsQ}TIa&9bDfQM+Xzue-52NVW95RZm?Zl|I40 zeq{!UpNb=_qs}Yl6w?FFk1`7P1uEILM|bPrVD{xv{x-Kb^QPi#Ptg(%dfb{n)1Txp zq#oKMk>TYR-kz73)&;gO47FG*6jTJbi->(}Lh(WNCf&1}qXuH!b9kVkJ4DA;>ZYS|PLjp5KaSBZHUYkCQP^Lx5nfRK ztj^fN%dnl4W2jLtaWA)a=tt9gD5fB{35i2C{-I|T#GD9{=>AwL5oNky%xg7v?~!#v zhBP;Cv2$5u&dF#)xc_pSqF`kL%(8x|!7d$WL{;8|Tw_Z~TX}vD6&fA{n>zeU8mZrQ z<^r@9IbLq7bbCOtpCKCoSjyuoi*@cR-e{}DCo~IrDY!CQsls72$(%8+nE}|EsgCoQ{kbB*w1s+o)#gl|bABnSRzwGJ zTm(G(8{Y3Ao>lel$?n1yOlt}IeT9fNiN>3cLDg5&o1A~G4_gSEo_D(R>_BOOc5u_o zh~MnDq9!1KY<;}QoJx;+2Q=>GSrrt~v>aLcRbDRGz4Ds$BmX7I4j#Fijst}05(xl5 z)G2*e!hRcoLNB5=R~9`&mL%7Gc=Wt~W87?PjE4Y+&;$gG_kcq2@}4;Pfelsch$?_5 zW&n$g&C9!RI^uYkz<)WweE=ah)%-s=!l@Jg`hI|ckn)FS0U?mi6a1kIBRAdB5; zs&?&X)eh&}_!pNiR*7P*i2`)6_r4C_4?t`OCQJfL?+1JXhNc8XRJ>aw2D$--qD6vk zk}`$d)V9C5K0oov?#{OJpyfm){`J2ur+E&L7c`C5g<1G-Z7fFA0cY<4BJv_2&ey&3 z_Vnnpe2awUTSf(zNrAvHl}u6#r)<^thM!=|0ik{WnofhkEG#U>3+>3l#+rVBE?VZH zDxe6J5sDF3_RQhzY5_Q(!RryvC>-z>0BjsQJ$2;&z71|l-@yCW)cscpH| zZ~x4=6fbK0sv&ZBi#w~*EuefW5mM%+(_&5U#Wj7nYGbb4SDsrw1F(Ur(}0rd6Tqou zKrrASZQFiOPC)_WPLwdCi=o{XpVv_KY^D6!GP>Y9isZ#nv}A;HtUk+@A-*DHDDkfi zO|fVNq>Ys0MtajAWba0~DZQ`2XIoTKJxc@i015vxXHJkBeA1Dk(FBbAyqQrnMVTQ5 zaUu`EjtLCtm!Y!PPC}Y3UV+lZPBHTqmEKGux^nD|5SB{f0)vTx<5!=s}l8$5y6#ZkPl(zz1 zXPgWGI?dbF9BHgEYTFW5PS`{nF%ZZ(vpsDOyEcxm=$pbGU$$@Fb=RA#R-nuKhEw)x zen|;{@dN@~wDT}9CWfin*`&Ai5W#P6mD6$iyAX72*6i2Urz`+@-VeM<(Vqz* zWSoxVg7U-9Z1F~n$L#W=$G=K!ln3ty8DB6P3-QE1^gR6*HJMTS3M4h;B5aWU@lGV(L%DxV;N` z@x|VNYI*F)^Uk!T!oX?(@^Y5KiQB={_Uta?oq?tRTS%8F7s3IkL6s$UdQ;_7Lp|>V z^hTG+aUeTG^ZA@jkbMqJK>u)w-_kcV5nx|O(24Doiv(P@IzoV=z}MnaMEe-N2{$@L zvF4fwxKYipPa{Rr;_3H#qVEq}8rkV`xDgL;&ylJWo{(_)x491mu5@ZS=ZECwnA*MP zvyUYQ?<|93GlS3*8Sn4Ak3TZ${+8P*csN~?<5d>dBc@E)bho_hd6NkHen7`97)B(S z!S7JM$3XAz&FD3oJdY{<*je(gx*=s~PgCL?2y9%%BG9)CmcjPMny_P7B?P-NMYqI( zhn9v;D-SK~bw}zY-{_C1dr~QV9W@baTv0?Iyv?nqOjqZdxP*#k40U_;Z~OjX-vo_M1X zvT`tcw&8OXsra}!gY%g&7NP`0rF5r%&EBe4>f;`-KFxyJ^gzzHq$|cT2%8KCm zs^vkG{OOrJJ#a*L=1vw3=+(R8Exb+NvlVQ{@v(;uH1E}g4Uij)x5k-f(aJsVg2L%-L-mK>iB)!Hl!{ zA~Wu16rDc`)&Q>F1c=6`x{S@;UJ8c6AKWQFc1G@NgrT>!v@N3%Zy-w4Qc7q19xqOM zBb>52H>5J%i!+mR|8ZAMQHPtb($U`A`60{<2t=_UV3M{$qo#8cAS?!hSPYqma47Ws zUbZPnxau*f+jp>Z^QEx-leYtR24+eJYF}~=c>`0Nh?8H9ee;XUn}2$1`iT&fmB z&Emq*4ZT5iI~lREjP9kY_8lotXs#<$2BpsBFWS5%#c=2j&9LKM-Kl^l$#6WQU#G_J zU#3R218klgE@Ms1jv(|aH^QD?c_qN@e*Ieee?V_V{7A>Q-DLsF-mW@csvl{unk ze3D8iE>i3=pd`KwLp>yWS$7FArudhYB%(Eb$-d`@&o>MKG~~pBCCB=x9A=LISv|G3 zVHHmj%x3l`Vz3tzuG)k`K*kPd_U6kX#)C3>3Bv%HsB(E5+#3YD1IP*HwnT>;+KYhf z<$U&&S9jc*mT>XRkDW!HDnZX6#_d*nS_xZFlFfEWQreSLw%@gD+WIZl^H+NG z)Jdsk$Sdz!*M*i7nxWk4w~5mE8le3=*ZJ5@C@>4;S)c-8Xu)jKD6?BLlqeSE6ACRp-}(uRB!CNL|&efq2HMtRO9N?-&@asE=g zESK6))fe*KEVMq3N6g~Wx z%=(@6ZK@N^xMuUZlK;vpoto`p#i25R94VNuY$71YC;=^Y~#cKcaUbQ_Bhpr)aB zPnyDxof(5(-kJ9r8ypX;0a|cyY?}|Z2SV)ho1O@{60D5hTsJyl*;0#4aqpI6e-*KR z5DuXge3Dc4X$$W&hPTxq6JjA?4*P-4(VbYkArB7NUaPEr{$NHpYM+H+PLLdIqSZQ`z&ytr#}?PuhBv*p}D={R>-w3YwLR6?NjtZ)3Dy0)WS z{FN_YaDe!7Z(1J^Mgpa>ww|7zJHY-l1Z4*RL$q8ukL-GN-|Ao42DMgV+a%X!F2B@0Cku@v{_YR>>^x``e399e(tKRLjRWG$~t6ijPkUsr=e(VG%6i}#o zo^6TRPqB7#06Z)xK6v@Hw-8&(*&}yLKht&`?=D63D_+tOW+ByRUxQnBmY)8INZRd& zShw<%en7Ru6XWJ2{MTlZ%r_y#k+<;rA^<_x)uL9Yr9+ z178o6Nnf(NmWSZV#ukbel3aTXxmA~ELNo9y1)pTUNXk9|s=_7!xEwU0zv-zGL(hn~wNzBU`-CPl z{N=Vvo)Mk_9pIzSdXS=5c4tK@SBlmA)22uzyggCN*e!cY^KLlJj&7e&!o}Jy*$M}+ z(Oi!=>vph9)=JbxkEG{l$I>ka3%%e#sezA{R~z*HCRqT3>p#lTHH!ddJg?J#Y28x< zD>Vitdy&f5VlPQy0&Rs#4(Vf&59!oudsbHWq7YlLG6y26?jhnXF-Y1Z_j7p(0*frD2BaYh z145HmkCl{$ZazM~ETG^eEUPk|@gA7L*f({vc2$$_p-k4>+K{bsTJqiuqdNGQFHrn0 zAxr{n47u1k1P*4HP3Ku*fT_*{uQ?tKdk$d~>HH=rXz;q(h%PB;HRFi}!f838K+pM8 z1R7zaZ``tEkfN{mI2`Snd}Z-uyivz|7iVJ`%H%ycEl@0YF$foIC%xOu%dapeKUi{F zv8`=Qq}rXy9Vns5u9$7%A5wnESgj3odfd-7^@GR9tT3o?e3ZYgSLV?N8X3Z?tNw;{VjC8dJ|G1v8l?f%I|7^}O)praGWP720Bw*Fn)8H2k`Mr_cw(D0J& zP7k^Tw1dM$V#>~swNtHTAIB{ukDJ6k%O6#W9s5?4jz8pwC1wywOF3KO7?q&4K6{?qVSxU*aFkW1B0 zF2vR`z_u6ya>BFXYRXEkvgMD%lVkZOv|}1ej*P{P3rvAwCoF2^xX4=j*35A~#gIv{ z`>U)|Hb|_wWvniS%yC*mKPivTO`Hd2R8wmtZwfqy1OSzH(0yxby)i(<(H{}3h0reU zqc)&3@fl{$<@MQe+jsKf2<-J{@8<74IA{9Bj(sV7T8H(s>T`@X9WZN~ChRnE9zC!D zEGt`dXo#mIR&DxPl-gPfkRrL`w)MvSG1I~KiQsMX@kO8-bv_m;@la`Xrl69r#%wd2EGJ}u6lL7>3r&o| zOJd+%%>$5p|{Flj+Ik@jMZj2?Zr27iWsO0Eht_f@W$v$N@6!PQ5>wTc& z8)9mF>V_SZl73h`y-zpKE+m>W2@?3{~W zLD@t-{KEiWt9nh}w!JR@9M`^S4t;3|=YGi(b{aQrG!$%z@9QStLPU(V1RF*^ZW9~E zrTu0L5@*$pp(Agw&SIJipI}6dQ`VnqCEK6mkuo&VffGH=9u%)ahq_rL4%AxAQ<)CL z{q64Vz+C1h*I>0^HE4kP7Yn4f3IlE7+IbP!$=%h0-PwlGRb`v6rr_AcST*vBmC>8R ze&>mL^kL(K{{M@u^A2lb>)Jlxi5@}0qco{{RHR6;1O%js9gz;wMWiJZ=~5C91XQFP zr5S{PNGJ5(f}kKEHIUE)(h0qj5cu}sdEWPVuj|VnDiX-do|(PZUhBSpt6)9A-?WU1 z-AmwYopHs_=onfgUV3hNA6IkuByl2K>5%z#Nm|`poutw-wD=@Zwnqc!m!7Z)2|#&1 ztIhd-tGt?Qo@U?!cF;Daf@lqR*H)i`jZ;1f#4MG?CNB5WLPbu)5mDfdYYh92|I<`t z&b%K}8j~;W4TKo{MO>%YpAglUcBsL`Ru=tGqc)%H%mt~8oY)gLEt{1rTb8-{6zKz zT++^3cB0Fy3Hv954?klc?cTH$=yiIY`uK$0{8huX`YYW@Lg{Vz-8D&+X!eD#)HtS6 zi?+E9NqS#c!$6&d>u|D$-&B!ev|jj)5?IyYr;_?VxH?XEPw>3j`YP$S;(Bmom4_)8 z`vCT%A-zzSrJwp(U$DdC44nOl07u5Lra4KY!NFR$d4741@?xf+E1Ns7;BOm*QX7nZ z3}9h>CE@LaaNJa(UXeH8L#b2qbBljVS&mcnja`S&M#paua4T?<$$0nK-uyDIKYrC# zy0_^yRxVnvPR#Es>0LEzbyK)Sx~pQpVd&TdZC3nEKm^r2qOd=z^AS_BU_mq=f~rh3 z^{d9<@GxI;U**TR^+kC-EV1Np)4e)n5m_^EjBh<%Q4ej`<`GgdgsWK0l`zoR0l!Px z=H%gH4QRC9DWj5@+h0v64F)BV9DTjiB5SKE#Rn;Z9nFQgeOx{6f;`8Y-FMHYL5UjSP*K>?1l3hI?%QE25Y?LUJaQR zrC~LRxGCR8!mn`Uir8p55Cr#n%`4sJ^Y*O6C@gXgKYEqiD_)g+X|VpNnswTt)^CaJ zJ--sIqSaUgWe^(}u;#q;O4UfJ2V?4lEAMw4J~C+5e65XNn#8Y`eVK2nc`+jVTdv>0 z6I3!3)hFBsMQRM}uP`QmVuur-uC93pv(#WI4{{hlTduWJfa8ca9>&6XZLkqztMB)9 zKyd^cZi>*6a zFLzT_O8Vets!!6HGpfs?L*`EX|**92JJJ-;X%Bnf}83Q^dy*5^_ta8pK*kREqsoo7C6w3;K~G zEf*YfX&M2Fm@;aT`%D|jd@XZG9TifEjY27NBu2D6-MFf>t`p56ZH1@o56?o?Pi0cl z=uEO|2v6Xvv7|jTfx5$yy@MD;Xrjc(?0#ed zo+$@N4D3xv;rvJHqqlr%EFGpa7CY3Sv_Y7~(ZD9=x~UdV9(kKd6|c*3Z1Sb;@Gl$o zAKPWwB|vEAr=OrQh47(!c3L9r|!``pwsTIa>FRCvS_s8-&+wrWk$R;9=_@ z#kXJHV=+M*^DlwKLB;H~ELq;eSEh$OYIrr`UcBKAW$MjN+_SLE*Q4oa(m~ch()c*p zHz&p|d8)i*Xf>q(bJmGv3{IoIDP*M`F;H|Vj;K{u1C(#l+mwVCfd!iqjUK(KgT7t#lv~5}j_oSS0=?b)$dyABBw`9d+s~D{WdI=g8Cs#(|*) zh;aYuDO&-_lqy~c0VPpr$3Nr?56XGs#n1b2ObOM-KQa_r`k2d9t0E}5(yjbD(qP^WgLL?{s+OUvb&8k-tq z8{#PD53#M@USBs;uaM};^vp~3Pf!|aSs@R(pWnc`o% zC??;OpVNvueygebax|NKnyo@j@v`S&A)Ex_Bhd@21ERvYqfu~!!M{vh+u*r*hLh&% zyP^!H$6un8cxrZ6TNT}Z?OW=kO)MZQQ#5hY!NI}Sbd^wQl>YwkT$8;0Q)u(R(2_j3 zB8tL5_Tb@i3y0GC6k;Kivn=3_4mF#_ zSu8Hu^QC}zls451h9&uh*Ncagbi=_um*z5c44dM1QZscxk$q9g%+V`fW%3kDY&uLv z)ney6>Lk+4*D+`nqhW*}70m{DLDnrUfevDcPyJ@9YyK4j@BTuo+-65y%8rqwqD-5l z8~&BoePaXKL*v|?x$)lBC#`QQJVZ5+iJlG8*K^PDs0+)29rivYRi*$NltKO$hsyt)9ydpL6_XCE((bH?%@E5fa4 zJ(tImN=geRKkuPSB;yS--Yh@&fx~f@M$4K_-k=Ga}dX{1R#_$raZjr-*(q z(M2N;4-gF);HW?!$``NwhXSOP)@{z2}gXMv}>!# z<}7IU0XZ~Be$!B~yy|WTuEo1edajEVGbXx(fz`jqYEp|aLTs_d{)TO~**TZkEUpgj z?uC^6eIU~rIuK#rA`!6+#twfQ1;UFS42dn5ZT3H|aK*kRB4zOlv@ofnUQ z-QHz<`BRUKv&2{}$Ir4+YaZAG+@)KLJ>?aY{OVuT8AG~gkFerIV#jx45d+>-H9qf* zb9qf};3nR>jYsLCGr{iVknb(VLM-rBII5V-_- z97b)RU6VkHObS4;BLjo!se`(@n;r8>9+rn8Z6`uXJVQC819SX8Gx>}uj`P&mvG?gM z=nkgoj(OehV|Vj?#Qf^5cn8-X3Of@YP@)M;^`(NxE$ZOvAW8y;%deE1ZTFh$8Spg> zPuS1vAE!uZ>@dxxYC71$s&BuvgOMAa_?~q(%o=L&<#feHxhy=epmo)poD%67@cB(< zbvyo>RnWooiui}~^{A7!#ZytY2St>5mO7Z;?AR(984Skqd^sMNOPntP*e>bP)f6kl zo-C_1mzv5$m=w;?_BeBQ%&&tg;V(mR53LghggetGrNtanWihctMcsDh`jEC)T&-sQ zQqE=#b>51T!UiSfku(1`!akC=fFO} z5w^B*R-EWt+Hz~WydSyIY9hk?P4ol~DR3C!E;u9C@AaB^G%tSDN@cp3b`BTpwq2;2 z11Cv@nF(nY{rdiTsVnyxDKP~g51?1~?-CkQ)`Aypp-e^^nC{w4r&Ek@%zq$EVH$eb zJ%~8bd#5GJ&d!I(q>VlUSWlgdJ0;9sy-R#p-F`8!{m$>0R z+Q0%sag)ejDB-?%{S^7MsUnWL-s@i!f4(h$5nXP%_p)%B&!&?M0n`8n(d}P>n<}_lb+u-_#Ij>ysG3U zohlQ(_Iu)92y--HE$x{0lNtt9Y2{Xvy|#-(<)8f0Uxq*UdL4GMVW40}jyl(vtH zmj<{9&+(YUPgp(zlL(@Ay(TBNYPE)&B(Pp}Z?fk-11k5*VbQREB}h2sGd#9R-cq2( z+YQY46Tn-jHr1X$2~Lpr6oRO|t^SC#(KTQ|9C#tw3Pe5tw$NDs0MSV+-wOa$IGt6& zd;NK96@XnfQsYNrMqZ2`mm!8a#9XZDOIxz48A`2lgTqpB)!v))vyG{?c~=fYWq1F# zv<)Z4M~>E%1Q+i~LcVbNP`fw$Qn0=UwAcfo-#>HP#)HZ`d0v*YQNrD!^} zB4qA!L7EndeMobm6xvSPISMcg)aNSP{op6Nj;HGmW@Klp@y{=9fx0Jzt+*J%%I`vO zZ~%iH=G7hQ00iTUoT8$1%9jY+9#Iy5YAj?zD1(bBi_T@ zN$2zCQBVOiY3;hrb3vvq<)9ghd<7|}l0qL!t2g>$^T|0_!=lcg5h`Yw?AYbl>2kq8 zdPDx0+K$_dY(8%opaZPA`yp>=?M~tR{!Y3y+e1%wfctQ?clchL$5?y}e5mcqt-U?m zvx(7;^M0!z7n=`iqhgl51SPkoE=}4m9wn{}M~gGw4L%*^cF;|({C<9*q;-Q_0YJVo zKvog;3-Np{ ztC{07+lX#s!km~fdF77Xr1-q5F{Ke6??5wwCmI0ZZcMfkvdbIuh@xsld1ZCkW#Wer zO4q)ef)u}$NV`E z_#eXW)}AY>(qN9PT!C4 zRC1pEvwt3S)L_BNefR+N1F~))mBu?9s#L*LjpLZo`TA@F?qC|$=UE-D0CII)p}MrV#e)`dAXPboQldGfQgaWM8YC z8=1Uspe;(ZXh%y`8UdVMfmJJKS#A3UPy)M&qcc9bE`%msgD%<3XrlRs?&`1;>MFF$ zdv6z;xHQe=5ULDjKGP3~2Qyy{9)HVy8AjVc+h~ z8ZW7c=iJUrazgKbrT}5)dP{_W#6Ts_e6@>0Uyny=ZKK^zSkMj|l29BI&OcRU;$_#i zQHoI*+tZ6Fm0Y-(JDD>3g7@eWzk(b5!JzN)76TtMF8SO|n+KWh?1c`+wKF%|ItDN6 zhHuJVvFJ~`UnS(cAaq>LW1!)gsZw@V>RGZ4Jk7!V({hm`t#j99M5E;c&Nz4J4RH>T z8(88p^xbl&W*C!dbaldJZ?2b_!(%sGA~3{6dCy#4G3BgS^mE% zWG1W5QB^gNg19yOF5{yU%|{ffgbv$$qic)3K;p$NY9!7#GVeC-^wzrZIeb`h3f>bi zI%C+RZ3s;DfaJAD6w{CkU(KjS7*Co`pJDzYrgWL#K*csX$RP#q>H_6cFDpYEf?{sy zuBjAK5Y{>K0DfVeK{UrAIV3?2iORTJ{ zKy;J-eqyCba4U02Ki8zcZ|JE}Wc#WVl6c9$=Yl<^t6h!l7yJ6#wa)_=OEqv+b_AhV z5J?w;1i4c5QO)Sk)u*Vgm~)bo0e0#z-(ygyX!!nhuW6~|yRfipd zyVe;)k_PsaC01`E^wVa((RxMK^xeU^>ti;i#cXW`Uawy6J{H;10b0`G$1N)gTC7ke zjqw!X_Mr^x=szD)mJDu8&}uvG`su8D-WwM9_RWwL!O%+Kbv3<{r3R2%NcrKSe^>>Y9>!KmE&Sn4N}mN!GH(W$Ka$trd%!H5Ki8=ku61pt?(b!u#jx?-wu z(VlNf0#ZEU@c@Z}ZQ%y`Fk^G}*KY&A6-b?U0d{#*-C#ucV}bKO?|$Oqr&O=CBR#4I z9jn^Fef#xD5!t}5J|t|wbDJTL&-!QFm`+8!-!%)f_58~})h^@$cRP8Q`;x9KC9X8$ z=_dfv3nP6O2!GoxZQgKPW@vP(Y|H&kt0qlv54dDV6V-Y`-+M;&P7gMiI^?aDcBrTg zyAjkS;w}x?8ZKG6@1pQd$Ez<8U%YCEbD2yvAsMp;i;vph6F$emm?P*I1gpGM|UJ_})0TLKX`zfb=)(g5jXthdY_bKa3W^oo&CzFR+@uCS+8 zCA6YAjzqdiK&%4oa}OomGhzz0)>56rF2jmJItI;kt6i_u!fQtUEbe2M_ENfwuSRju zvfOkfHrv!@$N0!SD4#=1bj&*u7BCzX(2b=|I9)tMqnll!`RzJiStj78r(=Y6+kjEf z6^A6#m?yG?9Ixj^ZaW!cit$Cvi&^G#AQY?ZCokTd{=zA}UUh}E#Puf6Z`-DNTkju&JsAtDYHQe|zsjy3nrSSB7*pbe(huAIo@Zoe8DR&`sU8kry_caki z7dumz=Gh(r22CKflFK>Dnsm)u*!t^z1#X??i(vvu;)aFaG_2y!{k+Tell{fpL(a^K z$dCO8to&Ccw^uhJK<1`n2P8roR)L)7nqoQOP>G59tZ2D)iS8{GIfYMGnb9Kt*4>zE z?693nGnpX?S+k~&EunC_u=84kkhz&Cs%G4!o#VVC4pA;q$(dKPX*8#57o8n$<1#7v z<%!qs^O};$*isEsY}I0AtAUD)=WP%VG*r?ntFyCV1?>p!9WOH=lrEH)v-#bSZ@0WKOi%e9LpSTGR#Zm)_jZEw<{hq&@z1z~3`=;?O>$D?AB5CeN*?BYwYrYqO_m~8IYuNaR-Lwh)VzA8&m)5K^Tw~;rfcL)@s@ZDQ`v%B z-eij)IDW7lcQdm{$^nsguE+CQm6v~ipp3<^Gw&uq@a<@cV<+$sWG*^21Wk0pt+F4k zF8&!{<}LjAp*S~0k7lR{@ZNl`)l_^W9Qb4FZqgY`?>q*z&I*FSt*KVE)Z8sVa$nSO zNG~DXmXymdY%vMMd~Q$gR6rjfSEh_6UBAM(wsm)AsGMTCr}^i|c)UjH*5!|Pwyb<5 zqd)i2MCR3QEMj$5Q5ql(P5SFlSKtvgk8xjd^I|R<@B7Uv-T6rc_)&pEvZJ@k1Hahy zcx6f5N!nn11R})v`7WreJAMkSDUYV4ic`4cclnP+0kfRkG1xHswW`@lC5<^h>IV?^ zokQP$4|Z8f7drN4-b_G+mY2gO;ry+&|Ey=5qvn}h2JQ?Z1g93THM8LK1P__;kISh){morP|X#v6~R z*V1rK(p8dC#65R$_oWGz`osrJRLu%{pUXCK+0emwDc8<(8sVh2hI0EGqDWc?$JkzvL+oUeIr zMBmRD!6ZdKahN!Q+A_t8;(zPJh#t}w`BFLXOBSbs4hU?MTRR%yN_qj2i`+tKmzj5B@~npcpk_hkePXK%U0^n{si1zRUX4G0)ny1Zy&7vn);F z@zpWJ6?wFsx@5&{Szw0WTqL@xKQxAruHiZUv?{Wb#YK*s&$mvq2A*Px;XHFCnfC8y zLl|JrEQ)QI>cB1q%y?HsaNg?F{^Lv6Sz+bvXfX-}T%^|9|SM9|%}f$r2XZiA~# zNWuFV=B?(FvbZxN3goH=*ur%bTbdkAg$x|ZZLNfn6 zVr$;WH&L;H1%=wZuQI6***&?{YuXGZ;fy=Xik{z;-Jq@ki%$7_xmyc^G9RTZ0(jT! zKkO0hhvIPDy)n8ehV<*9W=6c%Y$ID^8&6$)VGT9jm#)V4T6mMp6ZNS)M6RRi?Q+}#yYG${o`Phj5RrKw|p~Q;*2f(C~IJyTq2Am zI^9=g)*GXH_;k!HT-ltqsAbsBr$xa#v_ z_Cs?hZ>h}TP4^l%$;p%}L~l{on)xJT63wBh1D$B1xRH&<4ZS^nhmv~KxG6k!SCm|N z#7%N$guQC3^?SgsN5|~0M=hPjz(e`M@mZOcbcQ4ps?sJ+q!t6q;9 zgyNR8uJ_4nO zW|-Sg52dR!bpfRYcuvhm3XQ6nzXazX-)zG!(;W;(^~u8ncS>Hsg&`|+57!YwA3AiQ z{%-?C)w!mM(o!OQug6JhQVq{_4M*0iKsZrSg~i0^?GIVb8*`l=y8?^im>@dwiycYr zjaY|3ibgwYWFWrPrmw7Ig!!u|C9f z(EB5wHM;i;Mb9DPw~nyuJU3>ni(?Albc>Oa66G@cg!8J(l&BH>(<@iV*itsfP@JVU zexd5#%ce{NzhMn{s?pc7p?@5LtEVzAV*dD{C%~DnpCn_T)Wqy>{6q)-RIjRX$n7|& zm>Zd)iJiN5m2;K7AE(f&CDoTR-$l3jbx!!QKMV`3{d_~bdS45q4X$&|u^3Hea`CON zzU-twnm@!GLd&{>#(rMNypBQHD zsFSa^MyRyzl4dSP@cIw>I z4C@qJOnv}12r(l1+!oA67UK+FF9a&6C9Hu}v1ZQE8qwz5Ic&7I(jE%#ibVF(mcMa# zd>*&T;VK-jPRF}~!dyVN#oDml4zt4Yk5i8E+L?`|z1|&M?^yHj-%x5HZVnARv`NjG zks}OAR}T`@=M~+)-;E<+L-pLz4N>CR;H&6V6LK z(|-HqwX2}R9Tp*aEHeA_eb|o%>*R(y+ti>EEY1UQ*(-C3GOWGeZd$*`M>y!N)LUGt zW8*Sf#|RYm!-H2&@H3ltLd`;Wxu}Uyj+b&G@=ovIW((-Q5sWCC;<-7;avi%kye5NR zneFfel5ZV#ZRBC2(q5bRDQO_pvxwB^8TolQszY`w^mcD`ueT6uWC+~U6&}ss9ziRV zNN16(>;d{IiUy(Of-4xMaUtLS)C-p+wK|Ci<&dw>j>d}QC+JsQ_t?w;<8^-oQckCa z29m!EOLL3+Z0!aDTB|2l-D0Xhp!l`vGasI|FAKWWV|=JYvBaAOietf>2< z6Fo}DkqS{|PLgm{fz2biKIhC&3vOGLib!Lc4>Ke!9H-I=C}!nM_P%3*QCaF3$roQ3 zJ~25saQx6MdP(HVqgF$W8cd8|U_JXGq9VyfUW_bmWTH_5Md5Jkc2 zul#6(WJh~WBStOQoxyI0GOMbvO5iOFZBZ*RUy4CQP(E7<3-iZ@wLEMp@y{^ho5_K@ z;n=jgrmrq2c7eo^e20c!@FEi4CgH7eZg-b!P7RXUhyx0KLJU)0G&}K%e$lY=XfNiO zep306N>edUEs$j$t|8$vS2Ev8JrUUYZgSMZb=snBI^VjSsaceZ#f-GSeo-Bx=(m#! zuwi>V!;@%36;Mac#tn2=9(nsuo{%E=2+gpb5R<+m6kzs!55Vh{XL64NFQxMuWLE@& zhc*~?;B7#6V|ex%^V+GG91O>hcK}~;;h=iq)h9a(nWPEa*L9UCP&bQNlVWndb>UH@ zOIdWjkmm~p=E>9n5Q`Q!xoe#^+L;y5t7yY2Daisg7Vn{7pE2|Vz1@I7rVdcLdoJk> zQW}frq9ag^qO-u9xso}rpgH67d8oc4^0} zw{fDX@FxvvUmEHt)L1m&M;`h<>9Q$nzMPqpFZe6p92o`|XWlFQB0HxYq_SjCW<&d0 zXw=yf0-J4^`iXOz&);{5cCJ9W8IyY_-PVTW<9oERo`V~isL&?#PAHbf&cI+R28yG_ z;fO!7*{rfHgqbr$ULylBo~(iPfXcO%*%B}73gE~=C4sJ5qk8bfumD}4(MwDBk@0o}f@p#v~)gvWGY&O!~Nedsjf11vLq+nr(l8z3OvX zd0G*qy0<U^d2m`%aSZp?t>l+R}q_E&65s?x6{@6CJ4T64h-tlYr<@?i8b0nQgBrK+qqTP99okjtAR?0U%od0;=*CSbLxZ;gBXfg> zm$)UeVB!{v^@{0byIEczt^w| zSOS+~VV5c+c+qEX!3M;xYMGp4z&2^hp#Jq7i_~e@i0&yDz!bj^I({IMG}^XA|GcQ+ zV~xHG?!gUX+u?G~wD5njvD1BE*&1iM$s8QS__(VWp+y3QO6$x}hk>1gR%!1x|GdKs z*K@Fv_`Vry98TdsoawVZGp4f>)Rr8wrJQkr7F}8^A*x#QE$IsLl6Z9Lq6}<(Z8ABo z@O8gCbDmd5RH0b04JM?N6KJ?tmu@asEJmpG%qFdMN6I)naN)K8^XhUPjh|8(u^C_a6CMgt|P z!&?zIRnUMLfTni9O(l8nm@7@EpCsk2XQlhiq!-rj<%Ay1&) z5})+$)iXF69bYW{oR)^D!6;XJw*cw3ie|Ld3n$RAgr9jh z<$KiapSd4$y)fD>xt+BSw+-9e{Zjukcr6;W<0b2rA?*q>G^Xl+u~d+9j0v~ek+iaH zy#YFaL;-D%ZjIE7@@Fesp@_p3;z2J-l>=OuYhZ+4tE%qj{S&707^X`Ih)Kp9ZRQ(m z^bC~*l-q&q22+W?s$tvx>4DsncM?(IU?BsSh?B^oy@e;QUoKrZs2isPTQaB zSMLh0XS!t>3KDxBvAD#xF8{Nyumc=4%V5U`3Vua~ZD`ynv;6@sQn?$CxXu%(%ZPH* zmoxG3hHReX?}txm8JckUg86$h^C1N?KV6vUyhp`{VPVR=i{?IGbBQk!uD(vf)uh-rj$p*ke4WGjn2*TVq zC>?p=6s}Mt9o3J!#C}+OvwXvScN=}o{Mq(Mbv&kbl}LpQycHmyvgHa+slvp?dlLDT z(f>E%_kNm2$DZHug-}X&Nv5Q=&smkWfb0!$dJMX(;JPTloCIH-H&)gC+H_T8-`-{X z6Vl{F_hEHEyY<;-U>f*^NCm+Q8#=T_8)w;T#0mQeboNrCaZ?oXHjBX_;Pa<9l7ub- zk3s;;%{kv|#GM(FpV8(Y6R-YokicS&|1vWB^1dX1FjHx$slTHc=5U{K$_U;VwsBQ_ zXEnz~(~BFnpl8OsIG~Wc`pIKeItr$Aw`{i4!J=ETpAQd7Zy7%EEvLF59j^fPnC#2d2v`=`33 z%Ozd_UIQv?yS4{h*G`v%%)|D!fnQPDW&exJ55@kp3ruTZnD?UvDy@P^T#<4I+ro@| zl&)2`8KRMg>|QSpC}oDuju{ZegO8flhkRw6Eepp-b{(iWK8;%E#P{dSmQOYpw~)w z4edTiFq)Xzn!*fmF~!1hMi0R){2&*kE}#@lE~kAtTbHcJXx7?JHL!Y`Y*4W~vV_WV z9$vh-@q9dPkrCGBP*a{~D^612pEmXCx*@KkPFsFFreOcJS?%$nksydma~7BUCUh7y z4d>Dy_ncpjHZYs*w)JyxH!a?O{%$TG)ONvB2RenE2Pp7m9dNoCQUB9f=b>Nzabzf4 zJ;zg;@7|GXexdE^bldD%7p)|h=|TK+I|kucP#l_lkPHM_j7j1LOO`ykR%E9>DQ(z} z!NCGhSGdmKRdD?Q#9K4=+r}a7Urt_r8)>8w`QQC^l1>>_>>dHxM?!523pY4~JE(i7 z-W{lz7;NSL`1116)Q>S$bxd&W@@KXGZT17$oY42uayNsZjHiUDy*UxOT+JF=Icp-| zU*M(7!)TZE!Rx74n$xKYk16wQ-AX-;eW{%f9d1q=QZCCjy8_?_&Wfi-jw~-;MgQAe zCi;#t&&(|-!~LGFw0|*nalc>b5#-GVvaNq#{+pl#KXa?+#@2zQ8(p|zbHBr^hW_47 zCvVStoQgXQr7Q4v|MPx^Goc4+BY%m>pB>@VF;h|NJb2^6lS} zzRuKY_a{|AEd;%ix_`qvX0D*=@ev;qXnwyAO!FZ0wEL};bUQt#N~PHNk$(S#|7Ia5 zazRaontL*J=zMPazu$K7+cZ5mp97j^8J4gDbsd7>Z&z$P&v-g=YMPcHqRkI|m-Cp9 z;}w*3`4-mY^;_@OnYz3B!|Zpvd)@aiJ~jZVYvfM|Xa{{N9)fB{44<5v@M(~m;f2^u z2SIPvVE0=NF%xB9fF(e)Y9{>W6na9|EjP+&zt8?{%9G-Nc7V-s;fe$xLDvSTWqW^- zO_lNnkfaUEIg9~egCa~<=3glpbOOq(g6M4v%LN-)icR~c*>1q)R%`}|lMevM{sj;% z&=UWr^VPy5)FZLwY{hh(-_+4lLKE}Yex~mhe(ftKv%SZ&H%LaGW=XzVgJn66@qX4Sr)?Wv~S(X=2gNPoy zGLH5`QyV06&%wTZm@dm;%$r6GQ3?R5Wi;%ub~%1aFA{)cuyVAj#Rv3b%H=EB2jO|u zB=a+@_gv;;b-U93Zlj9Qa z)fuWkT>`A}jkap2<7jQ|2+WP6^H^X)R!NRBF5sJy=i*RBZofV3-sEblr03dg{Lu|# zqpy0#27%q*dwTRVO(e=knPemy2Z4rfHH{&!UA3v(%TSXB%4Y84aqT*kd7$}m=4B}+ zgZ>IYht+2!4FK3OxPmk|D2FOInju955dkJ%1_HWfpOb3$@Y;Zl+cMY!;hz@eX5~cx zbO4F{rSc8EO^-*+_b76+)Z~BF!VJpMg&_~dRC%@3VG6|*+tuFA4EAhD;P0QKuwN=> zsJT@#5roBMyscXYm@<=2ZONyN>Q8}sL=M74nm{UXH%l!BU8t{u4AkqvW4tY1rmCR0 z$>}Bx!7&f@pv8W$*wIUp3j;;;MLFPJ-$CYqDgGXN=wT9b$ohCezZ|fb=3o|K^W+#q1Aer;katFR1XalW8 zB9T_hi&aaN&Z()rhs#zC`m>c5U*yMHK5TYsPFqf=eWmu7y2CY^PVx^D2`3QEvfvW92`%u)jet(` zyjYO2apY5Dv3>+`ov^4)LmBDK_^UY|bNm-WC2MB_x)BZ;5N3MI$=K~e3VDFK;GizQIJ@Mnt8&K+Zh0k7{h(V++jv&#bSCy60z8Pu>ZJ=R1j!nodD=IU+6r3hx93ls3&FQwLcojHY7KI55F)F z!LJi&H+yihcNRF}h)xCCptRl|wjr;N=ir#>UAj;A=yAduJJs}x%Vd27rsxeH4ZK%L zf|=Q+G&VbAsx4>?;b?MK zBdzzO-BFm?M&v_!S7sgp7HHFvxDYc8xc-jzwV*+3#R@3IO<~x|&@092ip=atGV_bp z_ZQT7XpO`xT|2YMN$ui8`_Q%*&2DQ3@`1(%kj_{JO`T0YXeWZJ0=>Osxx{!E%%O`J zp82(S{S&xJ<%&vK9}cnvLg*OYrkqqkpRZa1FGd+1?s<9*JPkA!m;i!+SE0B;ln!Gic z9MC>6>TraRiU0O9RE}njkJDc`uJBmLVHDI88}qunneT`x^D5>S4V;%V%eVkHc)J1c ztCa-^;~5o;AFFGC8d6m-F?TgzH~Pj!FbxnhXf(kKGV~WW$2Hd)13?8BEcQOD4F>on zkge>%({q|D+3edr^uGA7R^t;uZ*J*ogQ2DSu(aNVf5Hv!ZyK+s#+tc+XY%B;mlj>E z@2KKP$qS;LK7cDLlfd~dJd-mIRu7pE8Y@h^CZip5$W0ZMrGLS`;Z8qqEt-m6y)ql` zR6DC<$Q(E5wAKOIk~s3UaGViP^eyLg8Z2!KQw7|ya1D-*fHAprfRH!o@hqE}Bo!z5 z4Gqc3N&a4pE01lQf}5%$sX8VBpB1D+)iZfSwNSQ(i;O0Ex&yPy&~+~OmILljQ$XEs zTg{-iW0lCgrKO9O5BbUyuG)laq!N~%0-(BGPOSFrX}&#uLAa=^X-}9s=B#RPc|i+& z7nfb#j)Avoa4dnT)=iReCbfOZcUr!!U7b{Kqp_=1q=@8kK9TGlC_xTij&91op(jwu>HOTpi%6x`I81+WFG2Y#&Q$-71{pdTXI{n& z2+dmP_`n`+Bt1gOQ7n>R&U!3gG{qydU!f@91DV#&MuYZvD9a~CY=<}ev!jySj6Z>` ztMXmVH_F8b0Woe7Y61tF#j>^}A0QS=@0Ai<=zD}>^jZ+y>Gm3jZSS5Q3+ZrIDOEik zQ}>ytZ){27_=9XgJ9@iBFoHI>mA+~D)p{^CEqZI&lWG~EK;(Yj%Mt^$g;=DEiR4F7 zVf)FGRltonT)RGKP9w@9_6H;!sm5Ldg;t^RT+ts9zQ$@dKTnEUiis^~H1+N+RQo{c z|HgpH3PhL~TT3X@K+Ik6i9%&?amV7?RqiPj${c16Gc9_=O=9@bZb+_GO}atf|L|cU zFe!HbtD6ki7m2&>$Y7t3yX++#_AgBms^aP~CFE4dC5hYPv&wiQywmJ7;c3>3x<$&r z_6sSDu>v`>jN#PgtEFKAw?xW$bRzZH(CeK|i0F*qV1akD$q5LHCf%xAs|wPc&Y*wy z)2%1>*`|JlyecU6<(5wr_`;#1dLd2d&jpnPf$;uA(qi!@)2GEY!1HPNeGhj?F5tm8 z;hW!giCO12G#u#n#7@v>6A!&t3;ub@*kR^D5%~qxbQfeC;go z7884oQx@+`{NJvtrojTmL)7o~<_P7xDMDMfRE!l~T}5PRu)hmK9zn_-GmHHY(Be7d z9HO=aGC*OWe{E%7WKIj+;4&436~taL{MBuTQsFW_EUo}esNrea>aJxMV4udH6n}E- zz7P14aR1H!#5dhE&;7b||M0tPgE@I+P+zIA+iMFJgQ{!_6OCY_Btf!CVCuuAGHe43 z_^=`n_d&ACS493QQ;$oBilv3G+UygP+ccus)6$yHk?Rk%RvA=AoD$!@z<2 z0$Ro*Ay;Bpthh1pi}d;dixKc}-Pk63CdiIixuePO>xN5j31dCnrK zcck5>Cqv6Iry41^xvaT9s`=Fe9*sNldd@(jsZ$Oxd)?bY1pz}GhwM3)f=e%GH)Rv( zz5C<`^`x$1Np3*DcDO4@G0waWUgzySd#LM<M0rFSKfuPH~Yz#0p;M}LFkQ2yo} z8Hpo<;0_Xw`2C2jwx08mcT;C@Ga1Zl>1pBL_<0sQhDk+ZPW*Bopqn3Tv|PvkJEg&( zH|^=O32pQJSI=<+_ZM^+9+kR4p~>G+Zd`gHUf@R4!LB^vPzi8MCGbOrG)-0D;kpB< zI6PHCqxDx7*%u@d6&ceF_a44txjS z_Rj^3U+7~yna!1GRsR|b{U4k=aEK+fZckiPj6Mdcd~{I5fnK7(Oyyq)>h_v?c*vBhgA^RUL>Tct4Z7UMIPgo z&M7$U1YOeN@#*+~ahdw;!XT1@5===4J+I^B+!4@ygFkF!IoT3@fYd&1aOnFVQGx;8 zC%`F+KAq`IhRkK}sZ?(nkf(|j`k)7Go=9$J zD-E*7ooJAjx{ywIdT{#|bHGwK++v{Zg1?)oX#y{+z>T<{i3)?Ttjzm^a)<<|OSFUj z<$17PC`Lab8SZFJ!u`Rh=d{WK>G|z9Ma!vXX#$xJVUB2wg-Z;Oj^+bXmo-U zEL9RG{6D__J0PknXdlN>gC-a?g`%LKQ3OFCAWhnW#)`1?UQ|TN!XjlsI$|sl0V7R7 zSfol>dR>|gkluS!R(kI&uaJC=g-~mkCH(pb4iGwjPdi-N_=}KxrA$9%i)DFy5l|Lfyd!VR5gimjGKbR7JFOFZ z2Cba$JoLRy++R0DLDkW02b20_L+szkoO*f8MMa{hw&v$HbeN-FFXNV~g&KHSN zer?n#*>|y%ec0UGP7_6iri@%MYhnK7YB*3B@v0zPTBR6a%^1!1($t;&=;xC`Ns5@XA7?s((`zL zRXvQrIM=2!+wddGRRbV$ZJ3egba=Y4M(I3s{x;0N^Z8w6L=V*nf`yq)0=JBXtjo0K zVjY)V$=|09az8FlLVIY(mX(xg;gsq$b3|~BG|9eog|coCianb_%Fo(Fs~Z1w;sP=? zuake=M_mtwIG^!gFxR%roCcv!cQu#<uvk>VQ=Q3YD4^n!1XRp6uk|HUjpr-C& zIzKr9{-qMJ8%aF(>)mS>XVFUy#7$qyB{3^Ox$x%z^IGv}P#;z4o~Vd+Wo10Nn_dE@7I1uMmsW#h4x}Z4fh2{xUvfQav$H>_77~P2==Rr+ zlbT5)o0fY)YlRqBa6;C!LZk210;PLkN)L4bGi#R=4wG(-T|CWz2rG4dE#bZB&pBK< zES=}zXodOj@$^}W~qLs zAY#qtjbn45vCKG(BPE1Nk#dAE+6NRKI7mBud5mRC99>U&AZOE+c?+u6tD&#V%5RXldRc?)tla8LZy+DwJvP_ur9h*3BhMfy$JFo( z_|=N3$p`kfKL*Y1Yb_*0DXD?X8~2r~kbdx{4m^YHY-c%Dn)*3)aFwwu`CKJ0)Cl(L zd5UKM;GNJ4_2Vg7?}FM>(0u2r0;qqqk|oBO_4vi7cPO1E?f^h^q&f5I5j#3u9EH); za{%hWEzs~tpRCu25JPB}M@nYHU0ZcXG&9xQ9B)aehSWiSuLi2X^u8Vvu&2}*{GcWi zu}e-^1=QKc*r0lDuj^xheL@9&LoM?$J#AkH+9&uQK_1dPlpnf$ol4*z*cUn~ywbxWalzeljhmkNOgY zxR4Sxf{K)8t0PtlRjdba-0H7deMw zT++^%7_vS>ewwBu_k5%_+*td$`t7biJr8~Tte+PrCRQ>>U%02YFCv{pBGjHI5D5N4 z_5znv2yD4pb2_c|6@0h|8Pe=$w6)rodHu!q{XYGmc2p=&c~-A%czej~RJpa1)@WQ$ zjSSCnMt@UNQ&*a6A>c3TMfNX6f}DkQcH2Aly6I$qs>E~`RIpp0c5jyG0mX8`K_sI0 zDbKeZg@VQGzwl_XH94sWJtG}mL=DbbY!>^Rg%e+P>Nte_oT6MnnfSYeWnb~s4Jo{y zdmPuUF`3H#Y@zO@PiIlWFUEuQsfn74O7>hWZu2k{Wvu*Pk2v{jN0vU5V-fVeEuLy` zYMout4yK#KTLH1inchAWITnb$TiAv9kKW2#jV^(_^m5ZpZ^%4p?f#06!g)TzV|2MK zK`2!bV7S7)(3V*Yr0j2XrW*^>K0o4ta?orb!*#aZ4}G)MRPDA46homtK!-;h``uo0^UjSTr{n(_` zjTf?Egd+ou(ekqTSvM~%04jeHL;|qFC3Ek-fV|mNwD3B&)31<0-3xaLieBK{NiWu& z3EHu1ci|E9)7|2yp8B1}c%37| z^yyJ1#c{X^{$e!7CyPn+F))0RhZH>SEiI?WpqJ!F}ZAHIZt&!1avk+4SiUk0IZ|dB+_wPGCcWqpU9? z`M|9>z_cQ5`U*w$^KJAUmfLmtpz(w1#el=%b>V0DioQHo-ULsQ$rb>5QF~gEafuF9o~3--+z-2}LXRw?x&bh{JMsf48!>!|yzEdRCF3(?zI#8$rcV8~Hwe8Tql4|D#eRCX0;t=tx02M*_K=j;8@B={PT z6)6i(8X(=l*mKt7ZZ91-Lpk1m-CZ`w_#H)}A-%hnu^jUc^jIKYXR ziaT_pl`X~&(Lib=f}t@2JqHCBe?ES(P>d*Te^bAv#0W&uKX3Qga8gBkWe=kZ;dzXh zq}{+2@-tJa7`gQSNqhHPMNNTXj*f#f*}v(~_7sfJYpfD#Z)x(~3o-Mn+3u@&-4PH8 zyavxYIijuUT94u=2p+VVtJS?2-vUlhKbNiBE?dxot5%Wf4~C{{?-M9DkTkC#if%;5 zRf;?>pHkTJx%F zQKKx+Xf)nD-+$q?W8OF@Tu?^Z^P&@5t!pOrB6vcL)61%qi-et3Y>a#Dcxww%A>@xa zy+rv8Q1&&XiZYO{k;8Mf>OO<|)6;sulvcJ)FX&M|xCw2Fh#<~=`7ClsD3$){RaoNyG{0`c&*{V49a{>OL(YWy?CH^=n7=jrY5u zM~RTxbS=Mhio%Q4scy5HC~t$2s|bmHn%2p z_CS5k4b&KQW}bpX{V@@yVDU#s5|?c;J*w0vi#Au~Gv*?!2W50V)~KE@!5Ah^KQ%5c zJgv17!DA|Q1oKkYdMoK#_|OQOW&m{5x_rI}!9f?s{EwH?5>AS~JEnUEk)v%<-4rYG zuHi{#)l{^(v|6<#Oxs%$mw9c$%cNL;Hwcz4y^-?FIvbSetcMdNT%$&w2&UgLYk$12 z6r4J|96VP+c_#aGz!BL#J?fc2h4t55A_lpy^&Ke;cOC<(`OtspY#_wbQsbkp5a0Wg z0?SaBo|l0gc9xcRs?@l(G}i#wRIzo|7Qrx-vTQ&nFMb&d1hIUj5w6xG+{J=Lu zlK--RwHFl{*Wi9RVT`28Q>}&z-v#Y9Q@O+u>yx}QlI70Bx2D?B(2peI#s0{p{E@`Q zv!jQl*m3U+sey~}pK`_yCQ6LXGinF3RnHEy5(NSp3{~`C^AZ2y8j;YUuM)u`vRra* zqVi1r(s*mXG(NvKVzLaiU6AJ3OMWEs-4_k(t!XzzIY{B8{h9=))LxsjI~Ca$`WdO`gPg((PdX2$Ou(f)yTlzoM&R>rXOgbqNOt3yhb)H$ZFCHBRbL(JOXMBBv8aX5Iyb6!S#Mz1{lt&c zFQ^aaN*s(^n+Ae!7u%ZLwaHr4a6N?6DSqLYNBP1vgtOWJMX<3lODnm!oa}{D8~`8k z7lV7p2hrv2oDtN(uBSJ{d(nQO;~sq+nPR}1l+evBqRe@scC7@SOfD-kY0i9kzE8_Z zLFc#&#EtmPiPQ|pieAQHAey(fX)(-uq#e12lmc6`a!b1IK>D&=N9Sx~oP^eZ^Hz%J z;m-Z4wUPU*MneK4rggfXNVM8gZd%J1#OqJzdi4G@YMMtO7zcBNRDh(EQEG<0;|M7RW#7 zlh&~rY)^bS+H4?WIyrb&XTp`upww_=}9H8pu^gzWifpRlA!n@xc$id{) zYbM^bWgx0j15BSdAR9WhRFR=@N*JYAbkwC8dpd$-(J@x@jx*WXRrBEio|#Il0yUm1 zY>2ixxSBkYb~{}_BU#c(Z�RV@kyaN=+}J)^%NaM?2Sfh2teg)lUi7F`HD>6t^u3 zgoY4JcB+vakLcRpziIs^bQ&7;pJw*;Fo^VSAA$J)FXb><{=n1lHUx&Ao@ux|Q%Kpr zdQwvw^lIR@r)tvkJ#_1fF_)*KmeL4@H7EyyX=<#RPd6jHLMoio><;=NP zX3%rBKmE!KDzs4XBgX^-Dp>R;+4rS=Sa3m~gCEx*Xsy&6>}fALZBo)TT%Y?zu10A? zdpL7>vUB6?p`z{Eu4y#c`2wUsxEet{+kY<ubm1?Yq05A`)Y`YvyIzt`e$oB(3qK=sxoa@QX z8adPS^$WSld=maJ|)&YbC69NM<^>m2=mN`@8p98)0rKS>T>;fIOqKS+gix ze4aVG;=b{2aQJeJe|HDXOaH1vpl%}@1|*`=E5Ei1oekX9l5)KU9m=ak9Yb7_N3~hp ze|TeUjzyis;Bnj`5)~#<45P&nLnA1nRj9hW=49U}YG6|Yplxf$J;ofl*;evkK%wQQ za{GT;#g6r%&QLo&V~<)%zh+-3ab0{4uR;n}sjpPIzP?_`2@UlCFk^II4U}Jb5oyQz zMytH3C&{-2y6;&|J?i3DOq;&o`XumB$AEw2q$JC8fsbi4P+1D9tVtTF+EK63cwWgq zYb5tPxJ7fxn{86r0m(<9HJ)>w$FOmY>v+VIVF{kp@zXs8=}L7GqXA(L%q?7Hz%h%2 z$Zr{E9{k*!xk_8ICu~}?mFzv_phW%O?V`+>j`&5qY2q?DMthr@nu_aayJFKP)caiJ zKs03=8BB8TP*>(;B0o0u9Do1CgfPEv|+S*QlqMRy%2|5{80{u|5Krld4b_DMX#~DFojL>bZ7LE@pEkQ(PM=}K1OKEwRNsyQ3+N<>eFPGNl7-;0TtMxw z$>KP?8w`pdpIg1RoBz*8P_NE(NvA2u-Z;OtMmNPc80wtC{Z>g)q2T)+>n0OYi9sh2 zCvyR@ULsI7Y1#@{EOpyE!!}7Z*cin`K+(Jf3oAX5ku=i8%C}2UJfW-MdLDeJX8`Rf z*`G_3{xhggP|l#Gsp%Pf@c1EFXB&sv($$mj#u8CHZmA1N9tY=(+4fN z_Lu*JxZ4RA_$tLPhp|CA1FeSt`wxruUU_lDx1$ArM~4p`<4)fduT2=;*h;l~81&4i z>H6&nvHcW9O^K%m`KhDFJ_VoHxg*Fd_8~^*keBFjNrNKJeU@?I5&V|F9@n|bEGHTk zuKq?n-Q?2c`{jQ>@jpzpkWhc0>^pKW;Pb$>m>qBL{NkW$ib?G(&@b(7Y{j}@iZ{l+ z1~O7AOx!UWjXk(oFLL)_X~#~cqrXC+vVB+RXE>U)wFpDKT_2&XW&qJ|7eYHMmS$JO zpCQ){p0@+S@v&^=i$lt*;0ltWfHzoneGBN52MpnAPUTy)-GzH@)68D{^AUjv4EqAF zdEav2hSmE-SsJV2tQce{7^1e2aLfEq1YT^>WIDXB#iEfJseT-0(_{P7F^&rBL-wo5 zRU!_=gRLT`cQD2Lu3yD3ARw@r`^R~4rW&KH@;J+5`(no6LZ3m(sO{uIA%yV&W!d=a z4WQdLMT?+0d9NLz(G$?W%=ikRiFtPR!{6kGr;5&`kC@th55@x>AAteRbRj9U+4`6~ zfLw#}tI!jy4^@6awy$5RY~DW;;(x`})`KmAWt%tueN1>WAOCMrIUtQd4c81y#gWA0UVsZ^b~VMPVCF}HJ?d< zC-Fq}-YBH5$PmwiQe0x*6@#x22-jKwlDuNGRod9d$Vi)(t}X|*U6_ zuL7awywKGvln_1L$t?Py_2l26{&UxzUu72=EXkzFshIO_1x4r{w%^V-_+_wv&S*nn4VG^I?UF!eb8((u&qyuf{Ld(50qay( zTYDJRa!PhFMHaohaq)1hAVkv@LW&(O+sthFy>~4)@*wE+|j2cx1wYHYhl5 zp{zx$EFd(IAfRCgE^8#%`ABhOS^in4h6m*SGew@@p=sC*Ea@5Wgl>GZ@_t6ELJAVW zgT|}SzTp#Gr1|9ZU^yo3AJ3a_IW70m!<_-V{p|-qKN%+Z)@_)xcnF&n0HUuuqTnIz0gIr? zao{ZZ%(v@EEDJziVjW~;W&!n6R0HI8=`|Vy7dnyt%eOE4iK@~lT5V9Lu^}24vj2$8 z7o>t0?K%?v?>kzo8a(o!&&&XVg@<-?cmS?$T=A2gDSVIWJkT`RK4LOZlrjc1f-%EC z_z?Nv7@FvgXp*CU!Qqp}7|9MX1GCG$FPedJV?VgHQqT`AF10ZS;N)M$A1+}B*1f)+ zG9N#nU_IZqw-55-#uqL;hy)I0Dy%9$b|Dtr_IJZi#@8SH)tZ-tFP@y7^t86Iae~+U z4}Ss92;PMjf&^hgiwI4@e-4FTEu|eJQiHzT&Gf;dym?8ca1Reut9`A5&2*UB@$WAb@->qy+|*RSVVf7#c} z#P3)EiGl}cW&;4)TWD|gLe>rp5gy`SbVo58rw-D_%KN$h?~nnt=teq;hc}eAf^cT860TVR=&`?v4pw21y(?VaeY=M>C#TMU2sRmr9glb$RK7LkFaOWJiyZMXcl^$#ujA&UQGmKPtE+$R zNH^vRjVYc&57U)(yzW&70>T)Z6ClmiB0$GcbNJ6vbxHzi@cJ7&F{>iqck*m6at9Q! zQ8L3x3I7-`(lWfzVMum#B!;yNpv?*y%I^|3q|v6TTAphG76=cyQo6F3>N+nN;ijPf zu^eNnfch@CLZMY5(7o2c4os;`Q8a@%sbly z8@khjrUgk2q?hv+)oz;Iw(_ZyMr2A)3l@UDwjll z-*K=iQqq=1IcgB!@bYX~uMOc$dORUF-8aJi(;_TNuauemVzNH{KEXJhntRc{-`=+ANpA<5+I3 z?JcHKOj+uAysI}nUM__!&WreDI^#_@8v?esnwZ4~kI#CGJOflucnL9gAck2=%l-4b zczD(#^xi$7+``)lYkjHlWu8ragoIakv&>32)a|`%3AMGs%sVuDY^KRjHw}n5lZ|#q zyErqeq7DoQbnErRlF8(Hg%2IrUR{NrM@N#5FWH#%CZD#aYH`e4hzb%lj0yx&+b1D+ z^}dBY--|Oue>gBOV-t2(5$T6rWkc@2>D$d)INJsfnK^alo#N1usyMe7oS-zb-@iYY6H6A$u2`X#3}Zfv_aZucRLNy;0Zfr`R+E$kB`8w2jM%T&PgsL7T; z-d5-MG!c3>k!sYKLNc7Isk!=3z&BS-#eV?$mB`q|jcE6o`PL+&R}VHQ+H<8_azj8e z#8Bv!_RJn0k4zP+_|{U2cB+SoP)I9avxzGGDQP-(z~e}VVWk+S;wcnCZxr@#B9ddS z8hJO!OPjY8_8@T}Oo&FAWK1od=|a4z_4op>y~klzIu#&KNtC|f{UgKG z^%?jCwJ-~<5B74bTRq>|9*Yn2-zR8g?87kx6d7k-Q_s9czWdEL`yWqAbB0N)0_#1N ze$7}hDO}#&`J?&!2II!hK|A!-)pXxl|5fEK8D{LP|1rvCJR$6%QKw3{SOwN`-)gwB zL5v>d9AC&n9*Xe}HHkciWX2=3!dqU6#*6TDED*1wMXoshR~0qS{x2jvniOW_@E7r9 z0<(~9B$DyP?#+VEhJ(Kt%KMDSgj!x3%00opG>vCTR4zN3UFkFpdp&RPX=*9Vr4zoop1$QZjrVXPuTE_BlTse&wy9jCIU|4*s1>sC9eAC z#kXfZt0aHfntOkMCVoXp?JvVO`2{M%6YKgL&00bpt+)E;1n|`*=Cz^EYVE+Fd$~=t zox-S?kt#{Uu34wJV}u*onmY9wA`E^nEGtt;3lZY12sw$|z=W(rOONhXUf0XKzM~u{ zQi_2s2V080sRm!I(l5-RB;M&GE`6Vq#BP509s{*Jx-{`>gI^HBj7=!Db!c{ORM<#s zOns2STzr9)R8e`N;YrQ)9n0nPjq=r2aTX>+yM&IEo=OeXmcnLh3FzW!z%d&2x5q$6 z$F$7DnzCEf&pU8UN63>sF^&vd2?{eCQlurnIcVmJTYQ8fE5>mJ9EBwkE`dz$K|A`W zIVAhMQmzxS+p`UR>OJ^&KF3nx*)O(n*KMx#et55XGWni1co&VPU~owk0|YgCt$#co zXq1U1#brGwa96~zSF&&eBHjtMWzzRkMgYcj;Y$Zot{Z>*x^+m&-T9#oF+bl4s1{gq zB`6PQv!57q_M&KpKlyOy@A1{Nm_^2|BT@p2CQLonhi`jJzvg-d zWWNo$uMZF-cS<_>Xeuu=9l?r*odQ2?LRRj9gyHK889Q@hb!u4-TFa`8)`e5T?7A{v zsr+Q<$_)K-bFJ{Ov3f;9Rn(fTO;@#1sEDc8+q*3+>()epq!p{-rZQA)!gH{()7<&e z*vobeL#5k!Oi*EdYx3+^p-frjA0~kNbiFImHF2%Lvi->;VXcMh7LU$pIB%|7JDi?9 z^OjJbCdV?6k`+;7rR2nXk8Mp?KU*ga7q_TpTn(5Ijnx=IMJJbPHSD-5%KLJ!m4ATs z;nt#koUXZT_Q*km)HI(2-?Y%SA)R}c%sU_zGq6E&VCi`{XzvDePYmk0i*pa|4f^P z;jm8shtZ=3&VT^y^__#XE$QA}QmU<%PKeN{YXzX=r*jKBB#gdAO9;X z#=a9Xle8~#W=WGN0UF;n8LDv#{^swMoF}DFA>mR!ZnE)t^!>KC8MWBV5m=0s_xgL| z!wWAIGC!!6x%i6xtw!uIPA2p8u0i!&@VUhg$S*y^vRq76ewusB%=PPZfN*6Ng^HGK zM;<;W=QbIhv8pBy!ym^^p#}J#fVuwh&&N@?%dd?vpG(*y`@cmZE+l2eThvDkBb0Kn zDv;*@Q5sO5tC$rZg}^Xm)gK}JVp5@i|7)1a0K;zGM92zwpk94r$Q3~JC(iS3V2Bjx zLw+I;^Zv1bOidi%fIa&QHmlCAuCXeAP>ga01q1?Q*6*CLXh6QWGkxv=odN4?2Q{vv zV-4TNlOI0-@!g;*Xsacx?8|;0ysQr80*5gx^4`|b@*9~p&y^k@BFXx_=?VGFl0YzK$qV%(|kY`3oM&|qaOlm>oNiH^u|cY;9kdW{bFZQYI^#L_i7)o0!a6^a{@jN zAhD)+GT)|q2zm0*sARNwls%6%RvV(ju~f9{nB4u$Om}I5KlK9#@)rfhmj|=Zyh*XK zz83A%YUj@^uYfWS0K7{OeNb_!dVieK@C>!?W&nQ8;~c@2emVtxP?xn|835q*Tv;Gy zqTv`jR4&tf(4ivX5s>8S?m$Llo)p`Do1~?zSR?Lw?u4fQS`7nBasfv~%Hhl9L7`PN3qoOLFO?wAW1k&{ zedLK9kTcSYin?9eZG!_D107?8n%rUeuD$pKR4-R0P7uSOAC8JMQD*BBc?e;`#yE7V z*<>|70|hY{Qd-)QW*mEK|FYOcEDAt+J^q1V&Oo>(-%9+^u_B=$Dx}4d3Y9XRVHRlo z)n;@^2E!8*6T+9>syU)y+CVfTL$FQfNN=C}(O3!`OH-nXiVC1U8aDM&%qU>PLlc}W z4k9<%3rb_W!UqOS$KYJq^4^0 zh~H{z{9@C}bk<_a`o%@Jd&aDnvOEPUWZdgC5I}yijrIX{O(TfvvHt%4XUpHfGn4&% zn-6pd!5}5Q$sxbc)G(pHk|Rt67lYs5&jqPqG;3DG0bhxtXeb zds=gcT3q(H9*UZYy)U|D1^_|!Y?5$Qa7#>&zMRJ+v8jQ=A{ve>E-ZFAJc}mS-BlsO zCvmtnpR-DjIR294^&Gl%ysn}@LbNzyij7QJO}giJU*5Gvt9u$z_b0RoCcrWZ%2$?M z{UW+Vx0Wq9S6omA`JK)Ah4%2V!_(w0vJ8hYN4u-on=<67(t2DiJ=<@%4=sv0%Vpti zRyz&9;7us{!=Kh8KxA4nPV#mamhhaHmDOO__;x#QZ!)z^H~oNP#qzv2OC)S}?~NQC zVa6^(Mr6~0_pe1JpQ$M7yQ~pR$>IjU?~0$Z84Rm;$0F*wT(K{Hf8`3urme;%{Zz9U zjXnl$Uvkk1P#kz3Nu}mJ2-h zVU*2pl21i9pqtIge451o!fb)kpA)5=homBcI~@q8elEY4TRtDWF+nR9zWhAjV=~%w zqY)O$)n?Sagg(+7Ie69Wy#Xms!a4W(fMn;hlV+7qe=tOANzqkfuU4Lie=F=G?~;VT zCiDS*(FZbi?|&IxM96z%m5@vOx~>qmeP|U}mMqFBVX*9L9!nrR1)k-fybb*zbmEn= zkT(jYl=H0scny|1U0W0=eoe?-(FHJu+hgvn4U=T7d5ufA@p;JnGe zI~>(Bjah$E;l{H5*iL8TwLLvrD_nf~OGD0$S5MyhWKb07Xx1Mg1!^zv%okl<>>-ukPBEb(I?xt^7 zPQ2HpWjDX?0-7kbAmh0mr#3yQ{QIKKt=pBvq8&6k!!>eJrF-q_dm>V>`ABN-`hlW> z65W>fyJ@tz`FM$p^1qix7}=PZJJvVSOwI~DE&>AfT(zs)A-&!EIKL$I-vH{cms|4% z4yu)~PQJ$ub^jav#!IJ7>AL>A-uEj}E+p}0`FLQ}1ugTk11C>RGygyvG|4(pajuOC z>%XKGra$qQ+3kBMHf-|QbknRFc%mW21M3$Ltedlgo6pY~Txpd-`3&}TY}ytjg??0k z_mLRd?tL0wEEs79CPv37<{I=N@MyKhYDZmeIti#VhaCEon$m;aV{NRKyftYUZ6%du z%ZMLYEQIj;h}WL*F0oDy697H3oj5^i&o^kAyx=JDF6U_0gvNVk^8~(taJ1El#TAep zm}AYR^PVRXkn6E;3bQ)jrHd;0O&O3k|I00J0)&SfF)@|g9c{j06Em__{|2Me`#VAw z9`SgMB^9x1NaAee(MDbGOZL$DU9&&J5StWAK7Yztio{WaI>qfOMPjO&e9oS&uYZpA z{XphuCmV`fxz%r7#227{4MEQSURDOU7-)KuT3^CjY8xD!5h6~CgMN^rQSvU8@+d=` zUI?5k3Hrklx5vrg`;S9WgI73ti-CxBVjE40Htul? zBCU^ttsF{<(jGfFQ6YER1^FKQ09bY0ez`aAsVdj%Z=DCZi@uH`Yf$C0veCWRhebmz z-rw1kE_X=Ef8ftBM+G^0jCUMz}gv=(Vi~w^Q)Wy4a25)ZdhJs-}KGZ~DQ&?wn9X z>hpoy%0V4hBRZNPBe$33s)drsKq+)gxiM2RGbP4Ip1SQ~4hbs73FzN(f>fec8U=jk z^U5((g0U=+|jFAFS6-02^dQGww}NWvBKh zZ6%ZGjO66%Mx4iWv(mdK3#6>;jrf`0O4)RMYOHOz^7fAqLo-t@<_rmZ4s&K+bVnzh z4g8l@GxigzT)Hy4*mxFeV8pIDHi?RB&nBYM@BGj!%gOAu$S4o1J(G4F=-_qjW9eLh z7C{c}$?ZW6o$3CGWJ!ZE%jVe35vrNf$;F zB;XsSx1MC=O&G4;>N7Nm@EBc2{flSa&q7cX zZf8O*Ma%~{7-?YmubNJZ!bZ`z(K7r}k99j32k4B@X<rvs^4d>1Z}KHvGqD z$7X=mcf)EFB?4!aH(o;3i5}3Vwhy&3R5W77_au(>>O4Dd%nJ~P?v;>~Tpx#!vJdb- z&oV((qQdklDzRE_jn0M0oz9$*Yfq`nWc}wNOSf634DJ`7ka&^P<-t4T-$nqT(u{sX3_Qq`}E)-9^L= zToaFqa`X`9tUbn^b4-DQ6n0VpZxL_ox8|05O{d(d^VD?xsbY>H$5u&$L<%qOYGi0G zHf}?aa5&KOm6=tz0*dwhC%onxw;2j!csJ)L57j8ihV1C`lV?Fndi`oGz3uys4{lM` zHT!$>S{Gi_s9P50Wvt0q5+ktbTw$804h<@aG#kZMdfA3xOPeG23V2RD26y|maX_v( zzzvx?j*CdBu`^3cU%$Jrsp+Q*`ZdLX2!bmGEY8Xfu3?Rce?qy+^GPL6WyXv|HBpf z(i?BrJFZ_8+I?p6%i@yJ(CFrsd^w?+SEF0&r-eeF-&($5o|`?|Gq6I6x1~&LSJm*< z2KObAI86OsknEO|mhE}f4Z zrr`W+UJrykdBEPnt7u2DoMNJ`Jp#gCMU3E-!q&oKzx0oQr+FtXi_eu>mIjtTrMdCY ze=2ZZjk&jk%6Ev^>>bOtbRPPrb=M+rPR=zjdJ7PYr#l1Y=fes&)@t8~%;Md8c}W3U z3Q>-nr57B*4J`0Vx93bV!N51v=3;R_Z_abPAl85|+93xauk}{qL!;hh8No94l-|2U zXb!#Hx^}p}pqw`S4EJjC)nd!pZo>LnE!@_k7m`ReQP|S3BkeU-CS{ntR=BXyl8qP= z)JQxzx!yCzvuZU$!F?p$!ULd?n1ZH*EjiG1XPXkRv|rYavn4M1VA>vRv!ktlMw)#n z6hgJGrx`R(k(MVR45Dc@#s-l*3v7GY9fY!ix&Y<-oYZOT5=E@c^_Hh7+?|WT4x0ZH9ON!6QcElVo?7_~ zPJo0h+;qK61eCHadJkoo=4>&0LuCe!kjzcL_ zU~g_iRKXFXgXAMv$+`cyxd$APp#}msuTc3G6Ob|6DXbuT2yH@mCdNSjMcC+TJYpZqnmdCzmg=+F&Mp{ml#jGo5uZ3`)Gw6?SpDC)sQtqBR zW*i2jYMC!h96vo1-eI5V2vFNGmscK><9p;x@&Ukjh7;U!`1>x`#%FHmMMZovpmUWg zl3ZLdssNH2&v2mm;PR)Dq5V(2J0~lBsW(U2=?*O-XZAMrib$#7k<@<_#Wu@V)Oc5c zI@~{yR|thn=hB7tHt?;6UGzTq0sz-PjrQ8wm9GsQMa(O^tc|cydIuxe(~ul4N_>9R zcpf+$)Nv?&fQ($Utl^wa+OhCFH+FX~PdaUN!>Z4~pmBM*&){BbuEl5QUU&gAuhqO^ ze;V2M5ju^%4x97(`yDR0o?mGmB?`Gn3}UU*w93St;IM>vdI$loayl2@NqGH7CvFl@1g9Rr;=)^xJ$` zPGqGkHMNQe!Yp$7(Cui^SBoj1v%7}2Va5Ek5XW?;I|gRI?|ofqES~yET|G^)v6LcQ zI_NejgrRj5lnp1zD-AcFapGl;Z@-`Fn^mpTINiLsA)SePJ1QRaLy8NpbhMxEtkspF zj-H9Px}B=au`e!aYlj5xsZg@0uxYz#*n3J9wH4jCdpVs+@+wfZj1)0nCTf(71wWYn zw7$^xqRvx@$?C1kUxUB7eSW~P**4Jg{3Z;+kL%27BG$}Lm-nX2+bcWlZNjNFyx+|C^4=Y1JZy3MM%sSs;kp>1rg*G7}c*>4ykXj~U7m8?pgV(iP< zGBo03D$Z+(%i6g!;Il-IEj9?d@Qjv4=`3BO?Xg#r4x@zC>2l8JXIc}sl=?BcQ zLUT68ZmE-FH}{uz_p{Q~?u)5&46gKo;nwUn=^Gi1Oq{c@FDqsGin-AxnQC zhH#0HTdpnSo|z|WeW*b58ScjYVZI9E7vTXC5hlScoRi7Zb^;JOZU&OA>yFt+u`?HW?$2!etExmZRgNAAJwBAx<7Mv zJAWhjOTJ?6&PEoX>8t`MznQ&u$lERl1aL5=s{`(y*M1vx^hOHc#7Z+8t_tRso2u+~ zS2j-L-*o<*kL3~}$2r;Q9TqT+(a-v+m}ls-iuyV%MIY(0L#y5yJTm@!V}x10fIz{D z=9P38D0?p0&A)8k8-foeT=Q)14lD5Ohl=A>S1Q=biKO+|0;v!u8(Y5hcN(266|9}j zU>QcsFKY|8-`^KXjL*vSujF`K#iJIL{E{>5X!nrJOup<4%LZr@?kj4E73(=`Nk$k% zpw;I0#X8lZuiBR%&19|d?qq&VV#`~}aLYH{nR33LtEVy@I39|2%|JYq^4_GDry}dd z)c@Y?kM=VYx8fw_9rLpuQaxsIk)dUgGYOHn=d+X1n44p6RQcv{#7T1c(`ETDO<;d0y=?a*Mjl{n2z4?QE zrlI{`g(VBE#H}{0P?>p_fZycf8r;1lly*Gjwg+a3qUpPpmB(d=+vue`AFTW4iCk|! z5WTxR?28+FaJv_Dq`E?!Wtp}E+{}y4$!}tMJC;^;&!jZLOiPE9A#$2_j(^1Pa?MIVRl&SZB~>pZ zzfout!5KP&wWO!{5j5dC2%hI}?my#!XIQO)dCa+1s zal6d1uAYLZz!fv|Y|oyyF=aK%aa{4*nc=)^L|*Tr@y#Xu(`Sj;Oq)RKAcxrV$-?x&pL-Dj4J zdV3w+na>6deZJCbHaX%RF!(o(cf6=%LTUNc=rYR}ftk3``Hlp_!eLgaY`uHY_NaIR z5<^{Qy1(UItKHrjCvGLz-))+gZgS&#avcKQv0Cwm;t1P-!)FE()%?5cT~2a3DjDOu z?lwuP7Wp<$>}RA07^m>F?`%;#q?S4gs61x(d56tC{zWnKC&X{x_pgT&n!;!kx4zm* zCPY!VC-&-k&hB*#kW6P62U|c0tPeQA{lJBI7XjychE+cE$}UTIgnC`TaVzkf;QRkq z9T%JvllH&sw&0iiT!@Q#pl-eD8#Lqp0wL%-;P|INY`d}}!n^d?x2y^{A$Xtvu~Gy< zfptR%s>Rs;7y9|n$G`pt)tA9P8FqJ#f0B{-K3&%n$$1d)j^^zR9pZ|9hHGHt_H)wubA!<%XlXPSf&Sas0Nb;eT%L zU-W1psGy98LDE(0aUKwlm!N$vNZQQybO~5oEZ?aA8B<<9l0n-{Hl3PVoRwcoT_aET(qm$$)}n#10d}!RHJ7JeaEGD=BzoW*)g=F0MWpsx zDK6>ZVJ4?*7Z$6|mBl|T-m=Hob~z;xS5B^kHZhh5e2o7REQYL|Es$zVS}7Dp_rGeIeSNO^+%|58-o$sOellixYf0FHH}>77cxf9*Q_~ppb|!i)XCYm&vXPvU!lK;N`weKvujK8~zLV(I)5V5aOg?k^^4VJ-pJje0 z%4|9e+*Yri$S4KR9xUX9#*?B5Q09iQ1$wRK64GXYhX@V{^DdKQ6w}1yY74o&gBvLx zJUovshx<5x9)Sxm#pKd9xF$U(tTtv2k7{CbK1uov z00swtVN4-D8dYL@3SI4emFKe7)~Z15{;crtK%z@9@hhD_SvQ}YUy~7!uOk>`$z(2u13WokhVwQ61l$4V&NV1= zs>qv^kv)8KGNCzZIXv-!MrqZsw!+|iGa~w-n-nCJuZ=P=Tc4JdFc(@5R(|?Gx%{xE z=n>F(!*X$PdHzm-TB!8w>=u<5zrPh}-GqY4O&Ku&8tLJd^7V#dEFS|nC2B~(;75)i zXxNYeD+CZilBZ5}w~)}Ml9CsxJ3dPUzWqwhux*_iz~RFc)UCEje_fCXuS=syz$*r{&H95LlTttxbFSez8?R)Y`_EZZCHCY>G1y{6aRYBQ%FfC8LAo>@&6p|}$0 zQ;CO;Bwn7qVJoTT3m<;Pu372w7m^fn0$$O0g}mlT!D($!f;%qq-BB}^P{|s)ACSruyv5-++-oS3~AdzagFu9 zCYL-mnQYLGMY9ndG2fLIYzitY6Ic#HHHSpq*}>AhooNgR`>a;xe?KS4~#Z$RYS)QlxuApt}IlD_=vlx5f&T``fioj7^l^X8zBW|~k zqilC|^$87?0VF2ZI)k%y-B z0m+9!6r!LJss3Tr4YnsHFdl5NX`SxxY%W4azXCWO>zXV1aA{~u@X9uH;y|NpDjwo9cghf>IPBBxXc zId!s8ksLAxl_VzQFqFfvTD6&tD3ZaIxmU|D`cA{G~7R^AY=58RyD-~N)_ zPaqaYyj$H0QqA$^Y}x&pQB7_Qr1V`@m>LMQnCWvtL%c)V4!&<;Ih|5kl{mS4P~KIO(c@qi>3fAoff*u1NpNdEqec$1 zM~HfRE}#sueVzFmJZ?eo#69#O6Unei)0F4J%%0UrZqr(^C&?SHYmCax;XN}g{^R+t zVI+)LoCui6Fiqj#T?uTjbSG)6`!5|FENLJ2>C+F_r2Z^vq2b(NPyHLDCVq?6aygUD zhyXgHsP=68Re&!`(^?VkqbEoJaN_xi-oD*-?H5`Hw7#zKuorcfcJmevx{lkHZr+BW zC|p~sDm_6Jn*4Om2>xCNbY1TVe;C4Npc5Ir@sasP4;WG}Df+(aQL-sH+-q>VBGO#W zrSTBaDAHP?)GT`FXUJM1Z~sKn#2@wNCRD>bnxHe3JE^ZTe~zUZlZlxC7*%I|p?)Q( zL8s@S4$lf=<=l$A1g*N4el$RokFX)l+VxTa-aKt543xatBz>gVBhD!GWEm1t z%v7_KsPQPDtS~%e?VfuHhBgwMC+D7>OGdFQu*CYNwinkzVr4VWbBc3hv!C z&+O!G#B@ZD>{LJNAui`YcOxWtP-Az66U-|SoGx}VEjp-7<1RE@m7hJ0ErC8ERhn*l zE4YmAHjGMXjVx$n(sNLSm~GTQD%xy-iDtW3dkH;rzdGqa#&yxht!2k)=t`MBm!=xa z6CN3%Ns?c$cQjp{Zf$d@_Bg}CxjafX;TF#}xZ*~Uk|Vr8|NDZccC?%$s53G+7OSwu zTA;^rO_j~lu5-cAfr(r$WKkF}-a4}~3#jrZ`D$!Y5I7E=a}AcuD+=VY@;zu?j47Y~ zkx%3Hf7ZdeKQUg`O4d*8)u4!!e&*!HO7M5?| zEsS-ao|U-v<4suSnH>s{?=`G`!IGM3zH`QV-qAHlEjUHE2s9E9Od7~8TKi3RY@LCg z)KSUDQ{f;HPgMH<*W-#DV0rr-F+2)|0&)W)0D|q`YqiTee2Fps#}H-Z_f~?BmA_Se z_n&tG;)Ty$?JL0%>L0!0uuC=AE-&xN>j7Ok2>kISq=`d>IP>!(-$o7BpB0b(YaRTK z-@MV+ZTSB==I3+c(H|_!cl}qGWE+2EJ1@vsK~;R&_4D^w`G*5v9yCOC{cV_oq@pYk zRrf!Cu(I!$8xgslgWK}Wr`h*F6SK?vrA4W41FsKIkBSzG{YUTlm(vS8y)vzt+bqt} zdDA6adju!~zk)CVd}fqv1;1ANf7$ha`eskm=hOb{KuCleU_C|sUnAVWyz%^FN?+q3 z;KOu39QGZ(uQ}EpAoR^?AUDHyhH~PY`@3?2yjwQg21Xx@2hzvTNXI%7yMPK{KFK?5 zblumN*l!q+ZU}ln8&<8SbVh2!q;y81{gwq)?m@r}{DervA*#OAW%rK{^KSsFuO6gd zwh&CL)ST(0=fbI{36mg1@RRc=x9WiP9*i!_TVN+|n$|k4@Szf9^Z?%eI4{M<9#Hvan7e5vJc^kL_YP;>DbPXrKp zr1{>xd#xbGmoG$g66P+5kcw3wtEMFHhSPL*$L6ewjrTlM^W}Mm+_Qp?O zQboCBzh z_~|-tnCc1bZ4}g#ZjL^uId8gpr+FHQV`Sf?9N~H0DyP(!w38)zTf%52jls@b8*k^Q zG~_3kk=$D!%`K_m{E-toBsb!4AZnU2wCC1(v;He{!?Roe_H4vk~ZI*v2e%Il=GOUP!EAW(j70$miy1L`{$e|^b(IoYI}vLciA zNmdgxoo_)XP={DvRngG4%~KH+ym&xBBp>CSu(+aM$DalU{|{CL*REf`4zQgGFvaj- z745S!k+wI^%+4-JlsB=qW)y{ukNgoHSx|ntvCQnMra7wGn*i{Q^M$AOSXaVD3ntJr zL7HG~#Azm1S?uwTVt2~+#x)W3{1mI1&7DPK>VqA{`?M3L8J+3{7WxGVT))&2IqjUI zb$b^}O7YPz{6Nca%DU2|40EoEY~G|XhYP!2dUWWRj!=Pom-dMnzmo9jvb*;bvH~Prm0#ov% ziVO%W#og-|J}d&H-3j772Y!#-X(<}|w?@F?f*`6^5k->ejk7BC!FEox-fGJwb)gkZ ziVXt3S)?5>Wy3!HFr{6@W-X6)gPNld4d(a4mIli{Hz7_5iQsPn^mw zGgTX_KjW|~;Hro9F@|Q5xj5&7C!~ztjcPUeP*4UrR)s|JFufuy_0a<5G)_N7HbuLP z!(iWu^UzuNTj-dg^+IX#1Z`&1%9z175VY~JqB`lpsHB^m9Xaeh_2+`3z}CN}DZ59M zK6IZatd~oUx({{}e@BQqm0rV#o_3tt9x@Yg{p~Zmc8BV8vU>{!8t4kKS|du7gzAfU zCdP7W;g(u69qZKb3T7PZF!`xHF)eo%C71Eu@gX5Tg7!;``@zoWheHQ$E$s@=nA;_n zW0LoNWU#7Wgs=@Cfns=>`5iILthpkw+iE6_TKI-@u1R%Yej~2OU(8*5Z1GVO&b%A{ z?(puK47*Al?;@$DYn1BE(OOX*Mnq1FcHyHOZO^k~MUGu-_bi^hmZO3d?RM|a+{rg^ z#$bxw-6O>cu1ZIBP-Oji4Y#MZM5M zhC4{(i`@^+Y`tToHD&tP!==5zS(?@j{+2&dqRh)E6|QE6moPtNv_5c?J4yBovy#i& z?nu~p5Lz{YE1$w)*1$v)VN8TY~Wg7_a{aD>sL>x7>Al1`fJs?)=?%pah#C{9xh0fN}G9B_$%}j z+ZyZ7Z>2y%?KS$6j%`s6u;535MlBvi>ZqsSaDta~^55a1L`8E@){K4}R_a8}+|TR) zl#GwsvCsA> zk?^8;6gsZ&phKc^X|w{z1qu)dIvmD=u2Bj~yjb*(H)L4hUB z>;S_pVfR7PJF`9&G}NyJh))j_uQ5J%sL0!$zp^hgizuMZ1cy2?cc!)5 zTM^jRC}6(%0n5tC$!XlHN77b^>P-|=exF~j9XrD$9~|et@4VR)Dotw&#S%SaTT25F z6+xWGUZaF{ln#N6aA;yt?2YpUL&;;vxx2*Mm9bakf{>iuvbxEB7;C>j z_8YsSh>2^jz-C((#9+e0*P4C$!T4f5MUY&WbNI#MJuV`I-1j0sTzBpGIGPrf4>;}j zvE%%I0%IGwE_dDJdVzoO8(M>WM5*BD?VK^e?;Nu$S2fO@ls5Gq^R9&igqXJMY3Zq_ zoNAlADk|sb!U4kttGnV6fUH#wKj zXQ8mGoIRC>=8fVGH`=nMiv-yl1U4#J7aelFXS-$K{;ak(B>bwTw4rNDIvP(Lfushq zo`SqEI+h*N?ozCfZHAunv28HiIKBG*Xt{jQ;_|b%Ec6`MPd*@@(&uLJMj;gP2;1Bh z@?73Nz8;_X@)0@PRB-69F43=Js4A#K|!mEnwr?7 zn3$M*+Bj#E?T7CbGtDuUn77Y%xQP|sCd+)PdxaB+kt9L+yAva{x$sR*7cY;qA41U4rb~iF-Qz?4W+GOt$dY@ILw?qAE zf!||+h(I-(nz+(8RHFqwqRU&uW+=wz9v%=```X|H>Z8mkQFFtlO8Ey0Ao@42>J!b0 z$ja)3o6s63@Su``#T55mXniY+r$N`>G2(utD@mOR=^;_~xwkBP#tC0>DicOSddbZP zIU&sH3QC>(_Tg!g_jUf`BQ_7Af*p+R+7up&kRPuu9*pR}v(4oPN|Z}6m34F>$#9`` z4c|a4QZSLs=Cpqm4k+3U{rsWmg!%sL^vc0A_pG*O*{241wf=1R%98(&<_=^8V0H-M zKCO|uQGEgrZ=V09I)qQC*sJ(x9dh0QJ=?l|pbR4*$=*25-$DUf+y{l_yK?RHVKRVZ zv~$r*7d9#fO=-&6>+~)ri&*>`;1c5QV&Y(3P(^koB&2Zk6|#Nrg-Lj8;V0i8tp9Dh zf@dEHAOtDh=Qkd~jU9hA07K*9i!e3CB8{B3HxGOj2-bAKuWoa%TYI%f*{peBV!BmU zl)q2@M#{$lq>f@UPQGlaE4zWz1rtMto+JMY=$WR9-!$7{%vj6Zv^G;1ZOSru=OoWc zxrw&IDs89fpMKSkq|&t}8;)H%Ww=q%#W9YJ!f=p9i#iiGnJg8IRzd`Cva9X~+( zrbNHuaJ3I26pQAh3XJ#ykLMDR`E1=jLz4p+I-@IpmO6CJxJo_1x|v8BI%aprK^FIG zFZ5lxju4AAeKg>8{hmLSr-I;X(E64TNmBa&IZmDUadZSestBag1>aveu5el8aqh=I zi?(%wXB@`+-B1~YNUUSpfec%kiS{itd&=5(I8yYq=_h4dxu#w(0r9NhF%b*&-%J&4 z_l_iUJW^U_M7 z&c5%kE>8Yh&h$h0daTal>DEv-f8+;ZBZpniu8}I={~U>A!guHV5eBNVNx?eS?8Bd+ zg#vx*xSpwgdpiYl-3hx^l2xTH@-uu!dABIjtM-tWZ^!yuWj$WKOhW;6{Lz`MctaH9 zt!MZLb!5q!u;u>fE9g-tQ_=)p+Pc5nJqqH+8z8nUPPCdPMrnza{_s;53vl;$N|aKC zBW!-Z1#+y{9k<5n3vr9xlB-*G>Uu{C@!d-;t(yJe&;Ga(86tU~tjVx*s49A(j*bki@VF*z+@lC2C<$j)EdF@icVR%>Oiw@cz zZe6(RjYG(5GU!(2dn5;)U7P+eb;`IfkhiTY1Vuhh0HTw^c#D&AnrJ-I-w(@MgioSw zwFaY=v5sNSv||b9xpWX-2y58nqc%Z$z5&s}N9$ZAm{NZ>A-D)i?6kD@XuoxDoS{`V z4mEqL95b{iH8s8&dVNi5QZawjdj!nJJG_|s7@9(6Rc`7=IltLGaYTxgb391t6>2=2bnVs0PWB#tpXC75FYZCQL ziL-WaoY7OxeU{v)mu9GhA!j?(G3qNP52j!qmMlG@9Vni;u4Ap>tLP>++r&@^ZytR$ z{bq`vZy+Wu94Eoc=`G3@9zgebmD89N#1WQR8l zFSyN~oSNNy#v2UA*xg9;`dXG~k%(>Cje+kVDmxaDU8vdMSoT6p~NonQ$_@H;eF;RC} zB|O7mN zrKJ~&FRU7bB;GKRnEoF`DLx+eSMwRHS6D7qBiYc6_mTQP2vJUcm2dt}1~U74+sy0# zN`(P;Gd_8xU;=s!1PuH6TYlMf%~QK*#EDIbmVn={e9>^aMtjlNDA9%eggB&w_Q1% z&yQBM0Yhm~{VU3>uGG0@NN)!KrC%e-qFs*b2Gzuu*k3(Zigp6%4d4i|R=Fp|9_CLE z0KNW*nYMwJE^i1 zMH~Ul1p@kW;YCAgbb!umQ*nBP;4|C7-;OmWd&3uaV-z3Q@Dufyk?YhHFlw|vqy=|*M=P-kM|y6HrxZD?b)rZh^|MX7}cZB6wgB0>13@# z)wfd1=*f17@`p+NOEVfydw#rvVQ@}(RW@K z#Uz0K1c1#mzYaaF_$V5BijYXIwu0h9VdH_?y=!U(s#$(ipY}RK7UuovW2&8aR=Xby zF4>MkM)|P67T@xzPMUw0;)3gTdJ;`QQ&4=b6(LF_kT%_1_%BDcY`V~*F~_o9Dq`;`zR<$;au0B{c7mi3J^GlQ6ZV!w z;r_a6Ak_AzBgnSqUDVJE-XBjn5~{FerwZ`UD)z3hdU?43AHp|(V0F`{7I(`GXvg+W zCS3dklyfQV5gP$iIT$Z#%McWE5Ug5Pd_mEsdIZ43oqTAhIM$qU8Edr&+%|HUAwjfd zNWAoc3o_6eAGwP|)_lB;0h%|(#KerysgConOt1m|pFZkY0R5#VX)Kl+c~iPC*PNyr zM*tSWQh^mGg0+kXRp-bsbzUT^wLS3o&_4_04|?j&0Z7%6Ya z+817}6)!*is(l(Pfp`sFuR4#`I9fXfKw=aZgAkl`$cnYa26m_A_FDt?d?q8%7xi4r z;@0w+!hZuh0|O74SbNl};4;md+$=tbcUiWidLL-Zy2T%!{~Q+Ft%+lxN#Pz6i)5^> zMBGvEY3Cl?f+kgMS3;((|CE`|nY`R&gj}2cHYw^OxHH~9M?xjM8QIgzGEpQN%#dKNcUCLCvGY{4mECipIBK(WZ#+7^$%xUeb^Vujff-SE^T zNl29f}v<@$$^7r;#IIeyRX z@Eoq(Y?f~J>P*q+RAoY+hxDOEQpGj%52ohr(c|>!iW_0K+fe~9i)lY2Ms=cSLBsU$ zpblkBMts)dLuOWDA)pg7I!WMR1D6F2L4@lE=SN)y&at)@udWcXdY<{2uYJe0QtvLZ zP-CKqR~Se~?aIbTO`5Zlwl%4+UV4F7yJ&kP4I62b_m+Ib55vC&oiD%+YuWI+55z&b%bK})6TO~sq-f} zo<^BO&+w?&&QFYU2C6O{11!Xh{L+u~WcJTgsBupGwJC8%1F4-(PPKovxGs7x8<@Oy zTvVQPx0bhNAsIh#Ksb~D3%qn{<}d=dQiXPX$6Uy?W>1xfBvzfkCSmh7q$OxzGiyo0 zgSf`hPe}f5cW^G|Ca}^$IczOgyvG2kNl*AIw-NB_R5iUp@SHZajTck9`ZsE2cs*Nww| zG<~(*T8@!k`?z*3K7!jFSex(w<$(*%SK{hGpSpM82EN>;$Gwp|6Ovt4#p4iSkq6l?` zY(P~aTcX;|9o7{st4|>gW(bcP9}V=X*}$_0KDI?8X-`~cYd5KCpL3B~w7jMJD=jFM z;%H0|Dfg%I8SiV^N4Hs=2c)BL)XyUvv{F}F$O-V6nL3}?29p>>Y+o;{`OjIj4pp1m zovEDMZ&`z^dTHloVp~T>K=z@uC4_#BQc>UHxiG_QGsK$8w*;&nIm;+L&Xo2jm<=zBg}KW)|1)0BD<=u zd7iGd(rPbLxRGccSa60ucAVBljE&bP7VT@nb3fpN(SLWl%M6MSq0$;D!tOb5bv74W z^|HN|iMc+9e#ki4KJ7@ehx%& z&z=Ym>#TWKWVA<9D9d+5?kdx@^1R81?9=9F?N~CqSu%5sR3DSMhcm9`*h{STF>)80 zcFt6l5S<<2=Q;eM>=0GCIV_oTWbWXjtOXPi>$!n$;U`&LIdz#{?3GlaU}RT$sy)C$ z#6%mcFlS~Qw%;6CCt=iePJ*jwU~}F%f;HnY9_M*RaBj|MsA>k&WFKuU>aOdB!ye%J ziZ0*lt=AOKeU;RVECPhQDogb7{!2$EUXVvx&5-A(u@*_5Xm&1nOMOoTbFTVS0M} z?S8v4pWHil?zB2*4;K(kP>c#@%J?1{&6K&>FzXkU;=Qxbdww2m~jBug73-40Kj%2|&otUFJ5o}i*aFaO$IfTH!ruw(=^F0z@ z-L!Q;VU;7l;N(l1C*v$6BAvn_dqcetc1HtwQ*R*CU57ToQT}*?oZI zjn-NSceL`oCb?G1z47+cP3v~o@u#=kwd^XJC>4F?T5s@g<+p59q7{h#ZepT-8m;EW zy~j_Y3vRq7Rlx4m?*4dud|_C;LeDTO&FleY5KMl^ZF>q9w)#-@kIt zwX2{hoY7~iSlOP!@11eQ#&qD@9Nf4-S+^Syr;lIJwVW6u=dvDVTV;9gmP_{E`>Z4W z=>Zgl)YVIFa2tLM_sCq5k?f{LcY8QfO7$=47!4)OpKbCnaO}40FG_PO6)RRuN$!%k zjNRlKVMJFx&fKhY-rq@!A?G${CYdEPB9}JN=-ysVO-`H67q(45nqy7mylQhJC!8v_ z(8%05W1d|)-k&sLYBYB1_sC;2ChzOc$=-?|7T+Dv+SBLdzpK+iy3gE_ z(k`Qgbaf##p*6Z=kR{&Qd^i+FSQi+-5gl7u))3SyQoVHAB}bB>AQRq)8Kp2Kb%17& zgTGg#OwC0stHWJeLNkiYs16YP{9x#TSazW8?NhDF{BB)nI?ACy-70k4L+l8RK-p)_+&t12SBxIi~?kuaKiI0<0Cd7s9| zF>u$0PGfUM^E|L)a`Yuc;e$g^b^GWi`*M30C)0JN&fE1U+ae(VY8{A>91m(!M%TpO zErAoj(Iv5ZSuSpoErem`LPmeR(TsfYpTHl|=7xfXk5c(m zs}&A}MTG?!l@KHr5Ze=YYJJ)f#L)p|W##)yh0HEmrsCf_Cl)_9x{)C$wM2By2NL>a z%gTn_2v$~IkNtFM8k_QBVPANekl9)AWQcWTgwvyWH=pF%rL7Zr*}6E}(|gWyJz{T> zuFTPTha0#bk$#`O;zeFy2WzPGk=b9kBZE5V@}T8_t)tJngdQi*a}&}spTx# z@C5C!?gOD_v^xJO#4ZN>{mI+oiDOXPkR3Q)K z?(?G}suGBTWtpW-k-pAQq|DG+Be2fux#Hs1^ZSh}P5jfH#qty5 z`3pUAeJ25nlF?V_&I{wflXavfZAWB<&&WWCZ0;34G~6$y;H=2Jzp{O`u#Q>cnHhZt z%fQpv82Q4Wnj}n2+7@i%6Lwfwp4idhzDV>i^Jw|Ohp)~x&b$Si9KX(LiQ?{iaz{sx zg!bS~voX<;Cj0RI_|(z{vjMgPM=O;TGkrNc-c?#)4tFM*9S6+?HHfvB30o=g0#YCN zDl_={{Dar4n?>b|!9@Ob`dd3a6hF56Zi~+k&aWDfW^PAc)06!55${kp5o)xNW;JTB z(^Bgum0GYJ9f5w63;~0*!E1cxo;Gk{^_~M*a~|N0Q7`&tAoasFrJc}|;s1H0=mM(+ z5uxEw29r&JDF1x`h|Zo07NGu#niJdf3sqZqfm-^^nM&8N$by^!M$~j6I$%yrCz7WJ zAf#T?Zms4fg(!|UPY-Nwu6A9;(!2frTt<*NLbzMnYMpyIxOlcZgaLJGt2JhCO$JJ@ z>k+Qh^c>znmt?d%MdnOVAKEC1$+UI;xx-SP&|#3|!+I9Bi1zL;PBxy7zdCbF5y&kG z_dZxvBhRVprGOhwLKJ%$;31xoahFzFd-QDtKpugjUEl zY4cr5Sro7v}pe7x?mjQ;=A@@#6ABUg$vJL8iAnKSt{5woaiz91C|_X z?qcXBHYAXTESz2K^cJBb9y`dC&1mqoJRhmobwc3bVDZtet+sR377I+B`Nr@Cl9q!2o?5WjRSTt^X`n#W1?=7B-%UWgsHOC zZ@Xn>(s!h+4gkWVl^A6%=%8rFnF4n|fUz7S-jMS9q*sOQ3{~rd-jWS67n3IPbxHgQ zgl$gzh9c{R>jE!W$n19}yd-G$9+i1ac=^Zb+t8C9u;+Hp+cKJGfMuc??Nt%0wPw{j zBDVQL&ELR7Z!l_aZseS?Z+M)m;Y#Kc;g7gS9nXi$Les;h_%xCmy@SgRPBNadB3nhg z6a^k+P}71&1SB)dG@AvF=USC}O)`rPc1Z;9>(xAy&Fc5l`bn5hFWMMvQ+(9tWYy8! zQNr{<@H)YpK$WJ{h6ql_8?Sr2P$t*QG4phpKh4?&`Kr7dQ0-B3n-%*id=wXJIOdOi zB0GXz!#LOKZpPTedP>qdO&#T?HhyI+g?<|g%Xm|?l9^xCn~edF9@|M zJktc}wN7ZIld47q*v)V3uiJ)DFHl({#OH}`SvlpM^xcL0Nd%QlV#w;0rp^m_j`w~# z%$6@c8^6`aLa&>bTI^Ad+#TXuJ2Z{R=}^V20=KgEWWL93UX(U&8ixMiVmvC4?%&*b zxNl?--ZYl%59#b5IAsXA2zzI>wSc4n(LB{r&%yUp`h(V);DKw_p75R}(>Z4ks%9VU zcpGrKFV|f(|86jvR);%lme33Cu=2Jx_e9)XvB719_S8%>37@UW#$z+qbgXqb&c6za zrq5(G*5{W#PD@btsWCJjU?5#=ic;pYF9w!h!U0&n*&7H2s-z|JONL5zV%F)uOTuQ8 zvwgv>S?P!E!UjTIf^Q42(P}L-#)5{o9ywqp)IcD|@(W%)tds3SJ}DB+C@Yt-^JFI*z|7ZIdMfnz_u1(=j2IGr@3}~M)|XL7D>}Le z?+-gY`1y|KH z;U??C3(;Lp=N_+nl;tvvGj1@TSO`geP zoVWgQHH&G$6v^l4V>jo&ERJ`5UoqV(xbK~Yh5z7|eF0B3P`pV#G7C&SYgH)&i}`lD zSf^)RFywrs|FU`3aA=WYe9NV1a8E#ehIa9|W=aDl9e+MHU^usO!PN9BHMTC@7`new z#}eC{|Mbmz{7`G>fK8)+i&>^VXX`JEXY)r%g69TivYrhO`RmO{tZ)qY5`{4T43zS~ zAo{8`E)~Qc{fOveqfBM^hRHMO}#*xzRz#U={p*x^&DWQP7b|2=~-bX>QOac2~3JAE^|a#W)I zZa+5QNmwVwOA(c>HKyG(Dw10tF(qnS*{lAh()>gBe51oyQ4G{~TG7uFYMJ|N<;&K( z!yB-jR=T_WELOrci&R8g>~`+v?q-X$cTPWLZKnC6nbY~(*hW(hdCx*_a*vj4UY9r{ z_@@_$5>+z2C1_C?EzPKhL%YjVFXQ*t$e7!@scX8Abo*McKID=JBYVrD9B1wcyE9Jf zSEpmiXG;>C9Wu1M!susdR?Nf^()(%4Ds^%HG~tkPrEEXduFl2N`enAxTE(;`6FN7j zGu3oS5$Cux$G#4l3a@`C-C4`|z7ZX_5$W$z^3&JS1fIWn^}UvS>+R7iJ6^5MN2y(X z6>{a{o3>-u@*#Rvt-L3t(eCbSr|0PVoM3-yU$UfW`|X>%BaN8CI*;o2Dj5GMy!Kl6 z%jCub63umHru5T76KN?&s`@*Hb-c=C=D<34@K+_q^qzB44L_5dPZ z3V&Zyol(s&uE~_?c)i>ad+pb#qpO87_eM$+bw-MJ(yX(!ou&4<(o2;jD70bRJF@`g zk>=^>tYLHf^ueE+bDOFkW!q&P1X@Z#^W2`9*pBq^cbr{fBQ@23hEx50XY%+hM?4JQ zjXxn36=KBj#bFX%vC0z7)v5mJ)bQ$y9Do(!qbl!Ni={yrP62XWF27LED%x%2~Z>vN0hG47^B0`8YX44^Zf?F zzbyI<-7JD7(KY77Bl>ps22I+eP>Exe`Ru*U=YL`BVoOuc(PuEyQxCHi2DA_XOxNO~ z=Y)R_8j%(8JQ8&sfJ+eAozb8}{4Vq>00T564i0%B%8z>!EpIc5M6L6$hDyb%UbQam zpWm)~>m2PJ*iqlmvnU(d;{%Y#GRy#}{?|IhKNf12o>J?D&wcKy`+|A}(e-e$lB74@ zXW{3WKa{x$#8sd<)=rqu*a_gKTHW=F!}Z8=)7G&`d#!PTBD6U_&~$}-pLF!1dc!&K z`WLymJY$b9ik!sX0ZMA6fPT?nCQEI|B6^I z2I#lV1ea;@GWYt3gHLUZysiTyV2O(uhECS4di2MWWY_P9o>z*_LN7Q{G+ zUS2zK7b2vAwYm01E!WN?V9C_tgoWkSqP@sL#4y8p2JvFzY1Tms^HYG>8a^L!Yp*qY z8X=0ss}gVi@QXv>T32L7;r$5dZe6(%Pr>sGHv7JBTw>wh0`m~fhWGT0!`Jyb_`!-0 zWXd97^EV0u1ISF`!uM8!5=j?*FCL7?doSNRuWEB6x^sr1u%W#BdFpo#Uzmj4+M3m+#^O*iUn2 z=h8}JxeEvuW4SXmVCjQBZm}v&f1xBThUVVr6GQV#;$E}ih)C#9Xb_)mkFlT}?`tV} zn0u@4SC57x%$MpnHpJb|y`{O9Pllh%@!#{6U_mR}sc|zRt0{`*f8Ud+uB3Eh!(Zwo zt-EC@NLTIGR;ZNzO)ArvEWe@9PPFmhW-x)zomtw#I-fB&RiA+2mimt-N8o^9HMcaz zE}xuOKV#j;G%B-TGrRmh)!-Iq6D+t3uT%;-w?+&X+jVHObGBu(&zI3HUZUBk}t>1M!SBCTru zb)9H4=EQ+M${wBCN))NVL>w4G*k13QflZeP#X5i%!O_nx48toz*S9?~sy#J(Vsx|J zeDH37|E8%`%J3z&K;}m1yhTW>!cG{rsI!&Z{PwB%D8IMau;zv|f0E|5`-(irrEd&c zXPz6n+Kj@b@wd$Qo_tezU6oOfQTvt_{}VM^npj`GL`8Skb4Wu|lQ!QXBIQ3H;Q}3^m@{{A6BD2Q@HkV>CHsQ;(tg^{HWso`s#1GHg`7!U zH*G4Z8akSj4|$~?ljTPh=}ZwS?!_2_wN#>#+(~0OLFCXgoyTm)GUV#Gca2_D*y*^! zq4Rb8l8E^_6JvQ3rF&%px94ODYx)e`h~44QtiR+Mi;dNu$Ic$-%vW)TdjH-}+qBTC zLD#3g#S5<3=sh5R>j6A+23SCEjM9Nnkq)wFO~Gr{UIC8ehXt*TuXD<2Myp6vYB^@E zcne=c^MA{AOVv-V;!6c0x7P50kp<_wNfkt2vx1%mx9|ytr+kmn&#(2GHFXmHeb1Kl zy~~W22oCnSaAPL@3vBIx4E;CSh_BP~_E)L<* ztQ1TJpyNSD;?mkj0}APQEPAgg@_sw5G#TgKWzud!$!R$jSK#Q1lV*%iZ0n z4j?&3l8xFq8U3pgFBnYCNGRP|H8*x}8KxLW{CNlC^}zSJuIIA`pyiW-SjrdNO8_%) zd{hk7czD)U{ry*Us7LsO4OgDxaGUS=9u*_bxu9xaRx%-=BCTxG%9i799iW?c0k1-B zTTrj4x^@mDG#BQo#JERJ#vx*_0~fY9Na)&n&3?KB=DCe~Wce89K)kc(8V_E6Ya?9p zfLk;j&TnOd$c5JM9z}bDE<(+B`Z}0i_ob~o*xt~K@4q^*3~|iGJxf9g4mL^hNLe2o zQslC!T;Ywb>{)?8Ic((WPvSP2TjXEl@Ddrjkeiy0%YD7~kt((n%pOro7kA)%ap2?R z0c zShSbsAYsoj%(7KrS7~EA=|+B?1$eZO{_uQeS@wo*XROVL)`i?2N2#Q#sRuHhMi!FO zZHs22$(*y5`F7VNY74!$$7ea`gASwoG%UrJ&_XXfZT1}-M>$$S)uxReP~uXC5vRo# zG#7a-#)!J>JiA{Yq^UodZL;2J?DCceUAt|q0D=GyIC#E;UoRn`Ja&HG2hsU%;Eo_d zl(|dcyaz@7Q1r80TdThFu9N*i26%zSKe3Gm#l^*Az%1!Qwp29w6kaT|tgNiI;4O4i z=OUp@f%-`l7=*90iW3V+2pLMw%gd`Ra%*xxIxNqBAMc?EZLw9wI=exUH7?t$kvfw8 zphu2u@x7H1Gd?Q}F`lPOIB*&k1t}F!(Y#b6n6bSeff(8vT1b8*>>90Pxz#QvJjV#u zZL=waS>`cTJFeTgy;zJCO2~TTm6Ocjj=#O@zfWavSJuprx~j8QV!E<< zBd*?OoI4lGTKrDq2VFm2SeU`M`~R_&Q0N>H&;zMTwuP*=%Q$-qy|nk2MZBr(;xZI$-OwSkB~|i?cd3ZT|(lTX{AV zy#j0mBz=dKmrjE~QWDf99eC!0x1YYo-lRkb}$RuLLI^+lsv1|Mx@{F)$V9w}S@-J9>_cbl zJV%Gh8m>u59JH)V%FDR#W_WdK<3?I(g}G4yx^*5B0qZ;zXca!9v!mYStn~5MQj7b0 zn@XqY7-^b`&d!tffAAPMg^ai9CKH|GIkVsGU@T8X{_lX5@-dyVc-Ayrn_a$yd+f2e zv^BJNSPlWBvPjrW9Q9S=;B!A@Ge~0)+@r*HKv*h32L6k4Rw!KXFIk z;Ldo1c}*PxGZ|ra*PmFLG3i9zW6BjTDy0C-d)Q;du${j2cKDzI(ybL}F14ipbXTOI zpyQ*0@FkDV`8(bV{kJUMaNc+8H%xl7u;$t-RUu3dZ1tL#*i+(-%4$*S^{jeev>O;fcDJ$l-aW1D{!9!dpH$HOoY z_Ib|Wz|`-%XL5>uk@LVNkv-_jn9T(7M)J^vAWA`TJHuA)t%o^upV1t{bzBX6fuqup(VM_ZVY{&Bi#k{Jc}Wb0We>`vXeb zT4-B6)W8X8C-AHzm-mIEG-J`s)Sf}fjU!Cx86LYeSt7KU6R8~;Q!|PX^9JwuXV3wh z7vesJOEIsCw()U%T->lb8okL~EU%RYb3XymBH}Es!^|jcapax*dIS>C=Ppf$Cv6XH zvBfu1yM|`Kle%C24lX5+N|QR6SEDGX&IA+1;0JQnZpIeYR|{#Sp89VXJLGo6$OXy^ zxH!f83ICv~)^X!lRceUs_iYpphbr>#w;Khr_uTGP_D@T6)PF1Fbrx}2qG)l3^KY@z zvxIf)MLJr?XM+Q$R}U1OEwZ7=7+)9475-S-7iHzAEykav@G)C#gYe<-48Ke%4`_Xy z!U1~Tx=MWp;iIFi#{4s*x4Kg|7ul{%((I<#XwG+h{(snXMv^YwnOvQ{ zxL7+AAS?(a=OxWUYIwFryU9X8B#)mxwyOpUV@%86H{E4ZhGXal_(z+IzT>@TyO5Pk z1YTlvvq3ZHj@wE7h)YME+x`3`(G+nZc?)`;z2SxYVDcXG{l>2<4u5JFabvN7jSsiD zM(l@{vTQ6#^1=4QH(t^(MB#96fAB(lfEk--<=jQL2l`n&^BWuMi5d^SrZhmnM0qJF zSZ4i=rVHjF>|P;C6h{?5P3*IBEfsOE3zxF^CD4NP1bPb9dh5<}cd^gQrK9winL7NB zN0{e?e(dpWDp?q>0oe}J4!60>@c(n6)DSK6EHfdXrO6_Iy{%LxL-f_W{02#uYyII* zK9GH94vSR#C^vOYIg)I-3JVR#go1Y~uqu{Z4Yz4($j*)DRwqyV;aI|ilTmq}8gjdB zBvR{C&zZee4;_BGhFq(LwTGf*DjuB7XlSd5Y<%&;K>V&@kDH3uWk30Cw`)v%yRpqC z?tZzwk1GxK1wemTomH76kSVj?tY{z5}vzu*Q<58X&hw=v*j!dB)i_Q zNHCx7>f^{~l=_~YA^NBJX-inr-n6HL?o^onaB30lSXPS9xEVLtTSg}MN4aJnnY?ei zG^~y{sO?;`%l>MdslF~ha5xnd)a6}MOR`pb=K@w+?Gvp|&B#9XF6__joGX+bjiKtL+IykO&LjH9U}&#o@W{|>2$iP^aPcK8_0QPHQwYszZWmnnT*HmCPTw@1fZ^h(N<1dHx;Ica*w=KIM?LI zW!b{Rp`2;w=FJ$p*(|gEZfob?=QFkC$#3oPq=)DX+QODIQBii&s18`>gd*oX1|iAE4U*+3Y?Y;EQT&j zDbvt3x1jK>ZTswn8T-$jZv{Jr^Ud7#*YpXjt9&&8hPHF_LnA^FkVSr3eu2kJsL3gv zYDw1ZXwn+>{|Lfem%_?brN=MYAR=F?ps1Gu7C)i;eDd>(KW5qmz+N|`ORrd-JNGvT zz(L;n7caWh-Lz^@Qgu*gNe$n?k-3p!-rNt(z5prl{2kr&ocAX8bCxVO?|^gi*(u0Pg<2wY_f{tRHe7b+hg8y=}})wjY_YA?;z z-$fgSF#Y;WJ{};1OiY)+BrI(q-g3f^m`JMA(XIqXL)Bgl2c*@x;%C>Ky@3!(%}*UC z)KTAhohJO!Qd@ehylbw`+fRGc1w6V5(IGb5e`ibaC-;o>1gaS5uMF_64Fehf2>wS( z9Dg^GIpf4n_~=C3!Q5;V$HuABE>IY!ULEC^^WdN8zIa)`*xmf1vZSWfs#jNxO{Y?N zG-pZ zv#%HkPT+my_t-N8AM^M(rnvZk?HkRxp20!oZqanGhya_01gw9QqP2K`9H%iHC+yCA zYmLpaCy@*jEet$jzGv4f{k*8RM55lQdC zXLnsGC=6UcHbc;BJz4|S9opXhtt~C%6KR1=1UNWD!0=4=qS)ehZ$ZXZ?7ka87YCkO zk2P~ji&&XAmo(POxM4xc>W=4Rxn3fbZ0w)R#C2T4t8-riCwUHs_ z7CpU5N{t|i-ClZVqc^h@>|pRl=grKpdWL?XBSegl@V&0ry0~;)SDiFBOiZhVj z0jSK6m8ZhiyvZd^+{Yf;p&%gI<=K3OpHc6~F~y9+v=FS$T=UM+x{BrV{>j0;@5yl( zdVN$%X~RXOZHbefD$gQCa1Lwcuu~4d;g$Jxjgb5=k}`q$$n(Sc-lvH%K^aaX8KO^> z`S;MWEqh=veths^>l5YJ;sYSKFB6!|u+OL#J3mK8l**xG%|BWS41t+k6r? zOIvuqxj(R@I+SQ-h}3?<(X^6Mo$X9MU1_q>A0(-NM+j!11sa@m=7?tF9aIB!`|f)E zTMFktm{uSr(|xLE_N9#8J291&2ng3PO6EF^fOsP!M&8SL*J!~JDeP^69lib-+9FA# zfFq~yQo_5Ci20MHO`B?1JcCjj>4zHZj}+0lx~*F5(mqJCwaEN(GI3qi$iV;{i3Drroy$3UWu)^uN4^A&>~< zkwf_c!z>G3VD+h!rfOjIc|hul@A=2Ca(W%^!V*-b1A)7>60BawdGJ=pPfb5hTeDUo z%dfaKlD%vk`i@V-1sX;GNdR?|Z5p1}9v{otM@bzvO~Ix!<#;5Mp>gSBTKY^CH&_e(Xt@q+>5&%03)r9bhl9`AB-9cw0Sj> zq(_lM7iy8DW+8Gl)3dpkm}~};493lrHUo{3x6KP6OW~D!Flo;aX&I7%EUZt|>c(;| zD#B=Kg5hzAmt%sqp-sr|mfkIcqzvBxj+css1T_BMnO_I;m&zlwHxiDl990qd&6Zy! zU@UKlwugi6gM$`Dqx7==KknZ9t;wwW9tIJ05REfZ6a{1)l`5zp0)`?gC@Q^o%g{mT zB%xWr4kHpAr3y$Vhy(-@B4Puimna>jCejIkguuIR(C5+5^<3XS;N>?j1G&pNXYalC zT5DT-@}@R$W<#&14=W|H?0>nH@6d19IJMKBAHfKpfZQY}Gjq}f=EL=GO+JF)rWyGx z`(;ijOLNwXpwS<~oYh&IxT<2P(fuEu=Z*OS)>q*www`7Le9f{iTAR8aTr)Ms&I;fv zV5Uho$iiR$F${Q4H~5OY-r4A9%lX``#BAsm7q95HUF?5-^;%=7;-CgHL(i6}(aXNZ zo_%)u|90A-_msRFHNHg8rcAX^Nc1F*007oENYp1)(0- zZ5VsCPIbC5Vf`#un0I4avY8pC^Nu4TkpQg27v{EwQ~-XnY5T!6zr--b(`Oe;^2=!I z%p@=kQ^*UOby`~1UTp-;?p!%mNMapTt0@*&@V~G>gzn;@4HHb;G&j*Z0U@GY1c&%O zsKE#@@D!Y$(G;5NR;kZ8KR=L{bcJUQ*UnhhSYN(8)}X#(Q3!87nXns>*QNPvUUfzq zg1mw)-^La1Tql|cJdk|JzYTI8VOs7uF56?7;ulQ)mX||fIwu%d_HSPt7^w5}7VBe- z+;<)9+b7_z*p$*o&1{_3?s()JuJyIeYT>{qMe?-Uyw#M*jY`*JxeA#EJHARf|Cx0y zZSi20dDdC3oa=hi&ur)>+ z)8m#0%Ee}H#%)h8uc%_LUNKvY6#A5*?ecu>DLtN13T~M)xAxh;@~fVs4kNpFB|QK7 zWa7oc^r}ddwVl1aIE-zya&>mT2@FU9FoD=x2Ba@Q8(1IigB{QxZ5v!SUC$NcZ)xm= zJpFl3-O{c{5j}|jTU16?BH~cUPAv%|;OF$lI-K@+{&+^ZtAPWHP7!q(4NaN}{ZyRq zvz#=zx}mnI!V3G=5>RYea}DgVPJ*dbp)VlFJN_`yqBUqNAH_g2_$3vQMJZjg;{5aW znj_y4w~;ZJ9L3ppb+Gc;i-!oS?9w7jQmWLZRvu)0+pGIzn_H0<>% zd}t1?*Ea@fM8U_f*fz;$OX$SFh{E%1-!r;Z4_uEJ8HQQ=n6S5`ixew*1RBK-4o_bo z+SQZV!2oYUCGG*fWzDyaXB>cSizRAI_a!vgr|!CH{BKA8h33E=&LeHnHM-@A7u8rx z$F$S2+Z_{{1KA6Hf!2|O7+a!zkb0h5xl!grZ|+@+kF@f<`RA@VB9?3($1*ceXI%Ef#zkuk4j5=T_l52sg5wWZLKh4gMyW3Fv};XJuve?LDT>1A!6d zGhYi7ne7S!mGfazmL0*{S3N;v`x*71Lab*C=w?3c?8t6`CPH4u<9YyHKPGZb!mM#w z`BtArC^8Ch0QuwZ)Mp$7KaCSI_SAf^R#NhHv%r@GbVTQs?I)i^xU;n|hTcn~P9>X; z%yk+o^9>;qoHtk`=#M>}`z;6y<71BY7-34ew$!*8xD|-=BN8H#fF(@AD!(FQPyFr+ zW^y~s_uV;;KRKOb*l0`+3$|!tkMDT7pd|RRbxS&p``JRanwpx&C$NvM5~IKbVdCNq zVY>pc3o!GLSbB(|%4^7;h8eq-|MF$ij$+6)pDCfC`ma>-B1^84`HsnilsH1gvT+vFTmJ zs~>I*{ockg=IZKf>(sBjxaqeXjEuoVVhGDc&5SX3*l^qP@y>JC{!| z+#hyy+tgSVqTGg`u+zUs*MAZWkR?7`&-a(>{H1g++}9n&`3`AoGI>7V(c`w*WJnXR zF>7#I031*@?mW3b@408U>c)6!XAz?_o+DfW94{lX0a`u1$z0CkN+x!6FQHr~Ss-8(Fyo+9RjZ^?5Cs zJ9#4oTTuk<*7od9Q08K5%%05ia0PVxnGe+g=iBDHt!j0?v621k+^H*FROB_C%>PCT1!s9j5F6M7YeTN za?}O1?u3@>RDYRZu32MQw7Ff-Tkzv+$?t`s9IAG-&3EZNGLP~P8{{YU_j3qoHeAu9 zb;Nb-N`-sU{i&We#g>}29a!}l?-i#Kg}Xzvnm5v?WKGnbom z#EFbF?^@n4xZ1)%g)=Ss&X0LGo35}rQ^Z2d7Me=I^vYhCud?#9a$Ja03Yv|2 zBtK<~e;kDIUC)nh+=H+&)X)W`{QO^dYF z&?*(s7QUcJ&Loq`)SDu#daAa?EdHe3UH3;W-!s8X0pz?7;o$Uw27K1g-%lM2?^Fo0 zloL5P zO_6l7f-->{Yie9fDk5}*#m^lk-8WEytu_F44&$05OPxu%;^=^Z{C4V(=sYB>{(Ppq zlf~2+*)2qU1qJ5wuCw3_I1TV9bvk;z`TED0o$Tml7axttcVJ9a8q!A?YRt%vxjLZk zUV@?~#P@!Vyu^?wiNSde0Tfc{Jv?KQ({=gfc*Q*DR8PryvCzdUZUkul?#Q6eW*{SviWr@^wWei>c`Vd?TiK4F$x*dV*`JphY5BwO%&v(Za=H1Id9~h! z`-6}5j&xOkLH`aj?5?{zRi>{>=poY}YB$!s{iaAMWKIXeAPe~o4sOBK5B89U0`ea+ z|6F=2AL7VuyJ>4;ZZDWYx|i1f%de1G*IGea_=e6;h^R1oWj)Ah9Gw|vZjN`ZXaXuf zLt2^S<*4~tY9wVwl~@Hd#@x*soKgKe4l<0bv*i5S+lh(YgZPbH`w5{F({m1wDq6yi zR7xvK4OfYUjkcnV85VdL8i=%~9TYQxA;)uabksX$kt2PMp_D0;o5 zYE^x}BmjNiuG7r3l&cTcs>nypQn96`-d#yU5~tXVS5X@&6XCf7L745Ux6--}xs|H; z$Ld~FFjhoXf0~PqMA1@7=PbWXqj_QJ%t;R~uae|ve+_HTIqJf+AkQGlu`a$z>6gKC z-z;V9OWOrsnl|)TWZs7?>Ndn)47_t~O3moV$cSk@v;*Yy+dD^D&DXWCqA@%3JG1uZ z<>irSPs8$QPZ`Ik0(jwid1*eg!18nd9(?PakwW&nwqc4iL-XD-$SW_I6r&3R(>o+6irH<2)+0CIT!%wu{;w%h={v*v1MP{)YmFx zp9Xpfkm2+c{`V@rS>)&X{pyB%UvV=V_Y{+HdVV;xRdX`@J zM&2dC54xMzZ{{Mt;;}N{Z{ZPSx9Cz8CA-{yjq;rISdmlNW^V7%JN$M;YftD)nKZ)# ziZv%oXSe)L&NIwfTB6{WfmFxEm1#=cnaUMLN{RG+SI@aZ*ps|v(^z)j4a_c>Z(xvf zj`F-3&aW-#ZI#YVA4I_*?nTpIvk7ANNhwYHakKY}9E$FWC`sE%>!%ZV25zh2t^RZR zp+==8GxlvDpKKJaQ_fCodR(rel6IJ@^>&OJ)lwbP?p-_cTAXjklm})DPur_yKVen|G}P^O>j;E=>T?GQzpVKObEC%iN3L7a|HF9t0}zOO7KM z`+sg8GR3V)BSk-dgJ>@<>E~~li=xE;@`05D`THHEBQ?Mz&sI2-6dn!&LFbyI=9LRV z=u1DJ;K5_`-M@Um2}S%RS&a$hIO%b5@m~r8mW9JMgRZ2*iyweAiu@QzA%g#8+K>DD z{X)in-yK{&vf6-&m2x*($l%F4^mO)5*UrtQ+4ke2hL>JafBKW#pA<53k>_&os+FdP zY8lH6E&%z_gj?d_3d@EJY~_tCjrCG4{Cqc}^VQ07+}dx!B0u$?-P@OhG`-dm!#Wg0 z>Lz|k0z#KK@q0`fbi{)%YBj@wc>>EkXyb1G?(X&r9z^fKnn1k;b;z#*T^vB%OQj)x z+<~>`olZ%?e=|>cfDH#LkbYx!y9GGSqa~9s#JbrM^ivydl@K5FY`sxqzP)33V#gkG zF&I;3xbw^Xcyby`-p#+mv+-k;BZ?DW^iLQnLf< z?cZA8{)$Zr=98s=diLzu2pC4+^?cbMvGHp2ApTy;9)gyf7{81x?$hyJV-~;DiQauj zP4M@sP-nnUZslhsTVGkA{6{&_>QFk20ESuIC(HtW)x)(gMCt-L9$cY4=|L$hp!l8u zQ~anB{!N2(lI8}w-1aUW9z@a>GSf7~+SiGY!7`dfWl4~{1Atv5La#a)>-Q&e2G%?XKKAZ`|;)8ZW{Q znIuY#GQ#vbn8)%)=qYjG)3C7L=#92M)4p>3uGOo8xu4$g4$2S{Uw9Byx`_+1ZCFEc zscV0v5AVS$l`F9_uY{$QEX?_MT?PAWN<0%7yV?~#u&&_1^&^YB7S?iSbPeCy?2w)p zdIHyxT0Ax@xWZmLl~#6?D_6YRZ+~~vB1O>3b471^ z1`l$3Owoi>vf0j+V{`S%3DRq_rUKjxOz!j~*gItjjmSlx5fv4k>cOdA`EtGOMQN!@ zPjd;JKDP;V_MI^C%MTj5fo|sJPEHvfgdBP>0h-?)?06NQFLJ}9i!PUL-KSQ78%LmC zoM`HFY*ANx``_;~&((KoUy4|?NiT}2X@3q_^b~%k^TFWll2aC_sj<^3$2>A;T*~wH z$3_=bWBi!juh|xv?!*gL+ghIMV>l$YM*1B+{!BkJc_iM>yqCZz zY6!FlwT+{mDh)MHOE2hNR4Q9a^QJWmx9JlYbEf%on;Ym%1NH+(Q(3Xhjnh)f1Qz>q z9o=bVE3=Gh!SD3L4h+QTk!)+ZOX=$4WI+)nR}<1heUWozAcV(s2#Nezwv%=vr~hHq z!^5pJ;5vq3tTQFl!vRNkd~6m43U5_ARWE4r;+Lo6zz)XAr6ayVbqIk?e7Zp3*B)cR zJcFKy@3;U?cdV`4cOsqJlts}sp0fA;h~IprD`zU^3r z4Ja)O25GnQCF&SU?d%cY{S_PjUXxCj(NUQxfz7P2WhG?0B)eQ(BOZRdclUme>ygnY zTT!uq>5BoVaRjgmxOMWvBXG9jpeLJlJqRsP6uEY?XYwD_hqIh#O$xVR0Oiv*sz#J* zQo9o0^_GB}^;r|Dy@b&XMfpv;AMD0oXHWzFIhoYxHY=)#nH_1Jk#b3znUJaL6qPR7 z|90dP_zr&>5oX;tf0BMLBxNFm)7{p)MtthEi)|+(pf1+R)9&nNO#9DaT8-Inr)T-O z)F*=zD8q6rCzHF^#0O<8_%N;&hxD}>)D157#Upxoc9Z%U09SFOk|UhU@-EyF3I(G_ z3$WdOR7Ws8L-|tKMS9X9Oh;A~>8)>)x`A>SUM4kYcoZ6Hjb= zWWJ*os%58AW3J=P`3F3#VZOta6Qoval}iE#w_MVl7Q;I1@z{USFk1J4)?#?JeyPA( zFE_Ur%&S9%ZEQAhO@w3(cOCDn?WdY&dk-bamAJR!;UvwTa(E=>+uXaii5Vc(Tb16} z%N_i;V0@cR8w;Dlm9h9mm{MRP&^ODKcfY0T*lDYA`othO`i&h~K1$O{nDpbr$wX&! zdF$vz1}6pDg4e*ci{J@Taz&u$U%rcgd#nwS54-=~I?_XKdS3(c zL)&Cf;yYzZx{h`P4D0@s-8#9yDao)pwlG_jA98t4>^$p0#Y6Fg^$#L?9~wofPzE08 z$wG!i8I(ZP+~7WDsDH`!$<+zg0efw11}}HpI+{|3!z^$s{_ez$(9hf5#+v2?SZ;d= zj{t*Gm{NV#mii!a&9rP#RPYAc3Ph3ya~?hg*RXYYmKtv`^M%F5l*c;M7bmrAy(k?2 z+7sadWaXCe(&8M^qq-)ZpSNLJ5KAa}R zI2kvZfU5AkdRN0x-IKAUOscg?>k{8Zln|NVOYpUIwB2a?1TP*m z@VoV9aqmX#nFrcsIidoOM)g0xa@YJAX8&<+RmQXC$@sE$ggbb_ZDw0`^MC0^usE45avd3cMfXkhN1`L_ z%|CZ!Bs*{WwEy^}zjz`~iM+G**s=LSzQlQ=2c$)4rWQ5%g1|toX?oWMUUfx&LdU15 zHilb;1u=45D<$l>gmN#=M}Jpm@7A{?hx*l@20Ed)KY84W9{%bmq3_q}5l6Zg{P3rzk|@2dzon~P`EuMGoMPg7DiRU*v$oHlw~IH)1)Vv#CrUmo zJ^k%{FE6hN81_O73f9)vHrLV7!Lq4i%FKJL7MQ5|rX1`i89FnD<$n*N58=WIvf6Sl}G3K5QP;k?(f4**{kNv<&3Y zPsg(L?MZiyCZ1>J5qqQBI3_A(lv5q{xnkADXWXKqsU-${_DN>?wim3>w$n=R;L@7F zn6hkG)hy`wbgk5mZTy3ab?2rh6w?1%R&RIOKR{^0YTOGIzTS&o`d2?>pX!*g^t6#4cOj#mU1(^Qh4qA%8V&ZEFhMrZeg~D#k<1ra*c*+HlQr zDIw=!nnU`;MvC?8v1(1%ZGHUqhqiFLjLMAckoL``5)8uH?1k008K2WEGbruI5NOYM zP$tma)#d(PDCfch%E_R>iPtlxMxH&h%w^&t1({v1nfE6UU3elT$`ASDW`gly;eA!g zsCV%lV0;+5IGC1BDqUnP;MYBl$ntV^EgZbOImCkym2o(5aq7LCFnFD5e`3a=8pO|? zoq`ID@zGQRbV9W%_zRh!J0?4+Vgh+5{bmuX*XE&=HXf9Zm?4l|Pa0*CepD zDq<6z@fhYBb$XLe&h+hb$@GaG^`$6kl+;jXdCLguW z_1je}&0&JazoV={zD<`>e*sSr6zlrp4wys&sVdklmWWph@3-0JrByl|5*2O*XqZ{3 z82`)!Kd*YrnFLj0hH_CwYQh?5_U08&fR?D;$1?m2aO+P%Ln}{oYl!$gvF>h9#Jg_r zRP{^_j#q1kh)Awe{sX+f9A+9!3jl1?^5=Xw0*dl?X`A5=ETJzmA04Nl3#3; zKt4Om{02n$Tg;Q_u}9y!Z9Q#YW4~x!&afMV$_0($4eXTqkn3}lGuu*Zi%u{tE~YC< z5DDXvVjB$PU8RU!B-Q3c^napogiF_Wpo;n4kC@lf^$92oJ3SyWG*3%eH&|`vdS#xl zzUUocfjk&=g>~;NK8h8>ob2Gj&?lDN7D5qE-Y_fE|EBf>^?oY|;L=<*8$W$A-1%yg zrsG$$3fG@es|3~<2EP5j5Zg^J{a^ZS`7bYI{elxB6~oV+hNc&I0PP$ke*k0k!M_4( zYMgg_fBA+IvBi5ofpLfCrZ&pJU;HmlxO>Onzd(6$_8Pr#mTFtVl0CX@oj?Gx`;Zgi zN7M7s34MSr|9c7Q!A?(p{)Tr^xHcy2xf3lJ`cY8H2#s|=p)BaV0Br4dw)vchjmFLk0za+Hbtvjhm?xnmo1~ zkH)qem1YZ$EM?1-*a{-uhbaHC4nffEDR#WPa-p@O!<8)t*+#AQAT9(ES8d#1LL^$2 zO4|>E+UY(oIRK`7ihmY$umhzP@4w86Ua$B0c4XC#7fw-Q<_*IJDwlTmeurd_3|S(q zd^k8mk31C10RD`qsO98FV;*IzS9I4l&HV*<49|gp;`-sSzT4gFZBvUE zE;m@sT{xB- z_wZVoni-`q4YS5N?9)R+Rx;nV7}Zgj{C1m0qvh^t_o+w&a?P#mq%}_GwBBA`vgxI`e?C~gA9YdsNQTeo()Hm+ zI)~^D?Kq1iV0&ANVTS&7%KZkd+jrJ1o#9P_<*3KQ=AAS;-J_e}2Nc5M{d~pQ%pAMa zp64BezSIU({19Z&MgG()s&-5*k2unDEIyA@Mk&J^WpWs$O>FI90|yIo05sTo=5Ko1 zB^8iO2$0krdVJWUgO?Fk#59x|vy$HQuUxjdQC3nC$Y!kUGKGn>9jcf6!UkOi5vbIT zX6E_%LkZI14pHF$P`-LJt*k-m_E_Vu6Q3Nigve@?dLt?Iz*&lA&F!8w)j$UNeWES{ ze%u=jZR=0p8tEz<~oraRabod%P3tlg#iV zfn#nS9`{OoKOc~`KUE9anEzec010jK_lJfybG3yl*#QSaZ1Y>$(KuUOwy%e4ZFGkw zp^2diK9YeHR5hKD=AJ$K?erpwqD^50ZnJSm;~=O#6n26jemoczT04$Gokv5Nl2I(YesO^%<_b=!5A?)|TC6fXiaROx+BHJO!}Se;14 zrO~ zeCUd;{H*j4RzhE4q0jKSjk>q428@l32|0f(zqdoV!=MgkVHWhqwM3}xZ>tDqyMGu~ zK(D~|U-q7hcP_n}c*;fl5BBAew?hqW3Uw(!WB7zN>ND4>1-$$Xw!VC&Z*Pn(VEHYcg<>60#EmAUYlt>yRkFXqzxB!q3=5pL9^$7_V@~) zYSu$%LopFeKtUrF@j*#W9BCzgXlL{oEo6ODk zVN1761DwE2xrqdipbwE`vn@(#5^vBWIms_D#m{(WTG!DSIp3iK#5bxoC##v==kY9T z1f&JV#_426j-|g;PcYNARwrtF$sITrOChH)aB|3sBUpah1OAh!;|=G%=tXWVH@Pqh z$Fv`)c`?r?aigq$z3%_j^1QxO3evwX>9ioALtuHYD)kbs5=4Z`Tl=1&@;C!A`c`6A z;LSA{a#vC_L*k8KvT>ui_C=Wu84GDKxP0eL%K2hFe66O3Mjr1SQxDwIbM4+aKjTgp zv9Cp?F@hFMiTYa8y22QE%T#*Dtk~xwml!#HaHa9)4KWob+XGmR)zeY!;m>ieVnO}CIi#Np?#s@{3iRJ<)dJKV zg5*8}&QqJ=j&=(=fG|dD7Y>ko`OW||XnRwrUtgctmnPoX+}v!uFRp!v$JAe9NrWsvt3K&7Pd0hw z%b?AWwFK8DsrWpTV?TG@Nc^`(cik;EMqJR1st5{^=a^Bg8$~LQl_vb=L!^giwie&$ z@lkzepBgEpD5v>>P)8r15GAHY7@MQ~%^_+Kyq6BI`G7*5jIx}4I5_y_1qzOlWV1GJ z7-r?2A(Qd0_j#p}93~(nA>HVqk8D{2V8J=hpBoyMB|@DPpAQ!dajW{m1F0aG=piTP zkHccI=CEEH=ulFWsj8}eNv&@QqSN?#TVPt7#lK+VOs)Yk_noMbb|mfcb=Rd5rd#S$ z4$eM4Kdf&QWEWL5@PKMc3vOgYj6J(>Ox3Q_q*(u}{uav*SsJiQ3a-db2tY#v`TS zA{?KT`@|kMDX*noeU0a9lU3&_2m1_d7^m*>EEjtreGgNdH;w-BQT(tCsHNt&@)ZNN@xCu9-U>w zPNH{Jh}_9L`CNk>Wb`ZM7{BAW(%3B#;y>{ZM7I5@&i;1j3A3c4V(DsWI`=NOA8F6c z=f*#uHU~Cc7}4JTXD`B2mLF^ZtwSopGPZho*^$J1&GF3!jMU75VC&#pv~{#*O_ z=)%4E3?3keadCa_pHML9D%BV#;@*_VV3V&mAoYHj)!UuTTnd**BoYpAj=V?t0-NBR zmK@5RJ5yB093Y&PIKu^GG#7}vem^dc!eIyeLdD|ISa^n1P%DfA5u`7;`irZCO^xM{ z`X9v&M)HhL*V0${eI6X(PPlWtl1N^39rJEix_Z|<0!OxMKxLCB4or-^q>u|Sc}ZQR z_3g2DirsAA-?Gc_i`^}4PFIZ@Az7KDk29Jv^OKL;V|P+tDd{Q^DyiRL?$Zdi`DUN0 z+*Fkeb(akf{P*Qe+6y8$w0@u@|HzZjrJp}|BJLj0MqU}jy-&tBNQ{NvVMIS_4-T9{ zo+W*E1-h-B!szpI=S zYtuH7&qLOdhiy^*K#@KjE+CoVYNH*`N!Ay zYVhB<*s107$j6A;cyJAiR-Oe-&3}GOcz>D7V7lf1Pybo}sX|T1iZ$HZ@R`-We(xt1 zLg;9ZQVeZqZvfg;o;Yax@{-W4p7i(1y-xI`iWhb58X=D9-{$Y$LAK4Orz$Az!m{myLteh81#^sZ6EpNjdIj&R7id=OZWO zz@5ZGWLNz7z&-1QpZP_HW>@K$3MOr*748`7h4~^oTWUxR@mx|BE(zmRSd)-GdtEnC>75&`hQUs7DAKz`4Xm*%p=t0Zu)o?Npv#ZH zFPilI0j>P6sBLi0k0;c$Q9$?o$oK4Rg`OgEz#qAp|2)6@3vH|ay@G5gj{jpW$4x{g zjW$82O4g&d0^P&MMclf2AFEKz%9X6#M<{zBSWi<(;D{Y1gcG(lx*l`My=ovhc5ta%J(V%4{+C{yPZO zD9Db+>oAh_{V}P-lKATf*pgB2kq$%?{M7+2td275vm2VkmT0m7z= zocyvH8rbz*DsAUZ7J=pdHgk_=+0PX%vP>eyA36L+^m=pi_x2quz&D$~)+!aKK#Dyr z9>6GTf&pz`iJnOA9mnM`@?$Zb8@F-#Z}b}FUm@b9%psH^jJ7b{(spWH6=r#}56q zVPk+*RZ}a6H(oy5B>Aw2V&td-`Q21|O#!-zgP zQ?@z%GC8`qxH!M8tjvy}zjus!eM`+ulbtP1&8B@2Ke6h`A@8^Ki~i zr+8`c$=`ZGCCiC`qHeSJ(W_WJTI&=zTL&Be8%nDy)XK5(=YVA}ee5)P^EDl`wGyfb z7UDkER8;6rTY&kCD`3|22*5CRV5rXTh?{qDtTy>9I3#=}N+Qd&G@Y%D)&^nkg<4uL z2UtcY5Lr~7I2zN6xsy#Dg()TbA5pEyr)*OQ;RWd99^PX_>Pe`5?;t`Sw~blAxkErq zYfl%K=Rrj=CQ%^ye(Pok=DY&k-nDY=6`^1+kqY&(9BfTvlJadxo}VI6liP5Xs9#=) zdV)3j23WG6who0_0ZRiXUuW$sHO6c=8CxPpx9bA56HQ=4Ns)Kou~d4W$2Na2wKi>! zK0;Gjhvl$j>*n+gwQ-Z^f7_RgMsPH_3V^z-&9L(fI%}_f;!fC(T{XY;^3aGodo~hd z>+?#R_qbm$M7P!VW6zK?GC+||;LyuSFAj-lgy2Z+-Nu|UdOp20VlpJhoC)6W9+sDc z*`ym2GHr%*uCVYKBp6VT)==D?ev6gOyit~ zu$Xn`Cel65%Obl*SFc_e$}<|+8~3e0k2SBJUJ!DsUxh_Gd(VAwcme{H!4npH*>s7r z5pE*ctVvshYu#oaT_;`ii4nO6;xxl=o}{UFz+BB#9x3yqe<4a*Rp1tQ(fC@y`q-Sr ze2$#_C`_!p75CH`Ai^wiY}@V-i<6L7954xHu-P7V#StvdU}XnE-+7-_+Ot?2dDtF7|u0pR%KeSBZu<$dj)(^74G+ zkx&uv*X?ZEoKN5?yV}WjQuvRa0Ny}0CP~_2jN6G!5j=v*3UL(&sRbW4sRw%PQ~2>Y zz48jgGQy6=xqN&C(N@Nl^+w+4`0ewbk9b>)R}-3*`#^xRh?SBr8U>xQv9>41GyC>o zN6d~@T1>o^0`8F1wj;(Uqq+raNyKbn>Yr|s^7E_Ve1|u;E|wyQ5~(%#e#M$#^^(gX zyed@=q#Cnwq0^3*k7ZP5=Q_RK>yde;IVr3g!zgS`+*3kw$+%?)d3Jytv2iqK4B=$H z(;FUsynkT5#=I8k;W&aTk_0|4cBHQj^owVMcI^wWZPcroSyW?k@=sTw0G z>qVtUH$_!yDQwL22<@2M{qyauw0)z+X?{7HzS}k!N9%`c^ODW-ZGtL~mfn!ug{#`6 zJiE5fe(GpWt1vXPf>y_^< z{>aHzln|?11QBlW+xmWX*83pLTiu#!9PZ4E5j^4ppye(v`{t`nZ->VHU`OABkjeL~ zNTO8mprV zv2^y%#22ZlRdXnT?iU4%7n{-I(ytdN+9G`DoyB&(;t#YN_lu>gK36Z&Sz9 zk3`tG+jRPody-q`d{H{$76lGkNxL_XNUULYxDhP#nQ6UxUStSBd{Dg0> zW|h&Qd^QnUgCJDgV@H$AaqxXGl(iX~wilZ*w?qnD0RCBf@omY%gL8TVGu|)dJdHk z#qKr^OW-WN3~MZx$_XDt4zMijCr_fz5u1Q*1t-;i6g$6yBcuHH>}RlgnVVKfgb(-2 zS2|OZ`qHj`=#Ou8(Y~QJrdL1lM4*1k+S6;S5q5BQU>2M77S1&rp_~8-7;1AbZdyzG zjWFM7I;+Z!v;xl7*uc6Zk7J+z!*vk`FQF#_7^>7Qof4bc@*Kxc3?j3Vh=Z43dXNKr zZ6q+4cj1;Lw~1D$^IPmr`jOIx0(;wbz5b&*Qmr(EXSU@@k{BJfmXvA*b7tm*W*CS2+S%kDPHsM+YuX=%0}oG z%zhlrD>h3$C})v#*zmGauJsXqM5h_UQsoU0mbcqU7`ztotUdUgTc~a5wk>At*~qJu z{^$-Fvs}p|4KKzU3NO_{{KQOG?*nq->y$D^(4^fcpG_oc@5swzS^*14x(0>R?x>^9 zhippnDQ1|m(Ac(`UR9)Eo#Ogl1hL#KsFXLgr3W3`x8eiFaj&MW3McCS!RxPNfcNuh z;|I((`nZJ%N{$Ts>~z!Z7hmjKUyK{?QrY;FRZvA6%?h*l#1jOp5VY1oDJ3psN{ac; z<0b}Fo~wK(rH>42QK6w*Y98Ft*(rad0Sdw|>5`|}A_ifTK)@aUE%5eL0GNXYc|D$v z_2`uWt7)j`oY7Tut!`#m^fy>%OAwE1%c@dUR?Rl1lx9G&e;t`n0z&OMU@lOumr z=<{_yiS9U+bYqf}T3m)G$2qYi=7Tw|lYu=&{;ff?jhaW|nZPdfPyu4>1x$jmVhMJ> zZ*8MEQnA(s8SszPiMM9@>avZN?N^|wAmdeP#hPYQ0~*R}Q8P~7kt=Tt?|SC9&pwrn zZydRv@4T@lFGzIc4_4mhn}F}1mU$KEore? z%)0Bp4M(b*?NagB5Y!z7eff88-PFg6?xjWRMHU@-2CPG`S#lM&^)3^pmu-=gjCdP{ zpz-gF_*UQeGL~Rv%S2z9ksW zxv9jBqw#!=d+B@n$*1kgF}LV`s*&~-XUk3#<+dpp&-{EWabIk+KhFuKrq&hSke2cA z{ES94elp~G6<#>ivB2-#^3m%adt5Ihbau)}?ew%|K5fJem5EFDrf+H)M_LkrS=P_p zPFA$mbbS;dzR}sweK}EVZ-4mr0&aFaIxQzGaTgaWwF6z?W_rXu;CWB$2VvAnecaQQ zY0?)jWdl)MG4g2stJsTJD(cq(Z0W7bBY)J%oQxxtBONK4zCG8PUL%$Fifjw{4aj^E z1)lGmLHQmo%_|6(I_}RW#yg0qW>+m&aGtQ9mGo)#!>fqWDl8&^h`F4>oNCHSpe_-u zW_L_3a}~H){j8=RV6)%RCrNiGtl^*r>x~nLizaCuf4tRB;zf}3Hi7+%dx#&@IEvl_ zADqX#N)LZTD{N6@9-7fWI>2y+8c41)Kg5>h*38V$&o^H(9S&C_zF%B8`o`D|jzCkr zRJ?O*7?kTLTArP~13mWELzFVa@2&}fNa~&_H{4$Udx9_M)hpwQ-UO%>Yc|0H&$SDY z!er*;)Oyc)Mr9fQ`&GEjP$m_Rn{Co*+N9jIMHD1fJ%5~l?ztft_YO*k9)j#Aa8u?- z1i}0n<3d!Qh(s?N9vtzYYxQVLMxJny^9C&AzIx!KLlH2qYQdEO%ll05;otL~-><|H z3Cf5a2L!@GQ}|*Kx*yFZ5TcMO5n8(^&29ZmNg18sfZ_3Byb&;>FME=4-=&1e-$0an zP9xvhQ3#NT{1M4M9B5geR#9bi^CU>&;gdu{)X#FXi0=x_6;$k!lIyLA7I2*LTzLVI z*x?cRo{t7(hAQgWIN%c8jSE{+S$wtj=j?1`RbRRS>a{yWSxp0%$g(jAV#wh)#SI(f z9t&e&Z8SjziCD8p_E;st9(%8+xx5H1fnV^)@0=?H9bEZC5TUIbEx|?lX>sx4C&E@) zM4}QfM-dvy)8BVX({1w|$)e=+Ch=8K=gN~bas7XV21GbJEgP|cm&-vRP=SR&sEOu1 zYM25sftJRur^(1H(x(74wYIN+-9yHvLMHvz?H}IKJ9R3XOpLRZ$jFj~sfOqyg z%gaP+O9IoOh<_+^4>(>Ur64E?c|`8wLB;k~&#?8=CtU>*j`#lylD%j3Wp|tj@`Asn zO9K5v^X<&>3>cK`(_qjC{lY)wxnmdpkMD^#qCJ(;16o(1qjro7=-}p34|8#G3}q^F zE5(S%(Q$)dty`j!wxTNJq$E-y5Z|PhU2Afj+>!YPIW>P?xd^;&gabNO?Sd5cS#dREP6#t(faS$R0a0b&e{C#l^F+X45PyW2Q>z`7ExcYLkVB=gvyWSeQ z*WPQxIG>-B^TLB~FL=U9Jq8E)dnQISgC4$<^!Z7N7sxoU+nPy4Nx^=Hh zQOsYSOD|?p89z+}jbhOvoFfHYF1m(whZ0WCoO823vRo8$hFT14yAISaV0}@@mg#)x zhOR^Ag}L2#6D{|?G&+NI{a~EXLZ@q|Jmb716cX)QcXu_=35MhZYKB3y=5Xs08QZWN zm_yAO59vOw8kvulwI(#Fi<;lG*Pky_bk*RMTEz9V_tQ!FE@Rmq9dYq`Brwf+1<9#Q zt)ZU4(RSt(n8bNpe{flH0tBnp=TawZuQp{Cla@ojo1rb}0J4hcf{pCRi_^7u&=8E_ z)sm79*1^SN2EAeKKrNz^)rgn3F8&y?uMIWa@r-d%(?qKgf^kQwVtm$v`=Ma0^L6)a zV*^X=M8v(Ty~UbQw0mZW+j1*M@CdzLqtNl zJM{B-fUC-b-*Ob*%Q1gXm4NfQqf29rR zd(nj=U+qXdpF3TFtK816b-8Jjpua-DJ3$VUAzpaD8Os6fOe#R|(mfq@4H=~>EfHOw zK=VSzd=pMI!O1hGG!1+ni<_bYc2kEe!Z2KXEyYD>mTYxTaBz`)zPbbz9|a*}gJ2tjZbVSdQLPity8 z({;R1n`OcfOJ(~ljbrk>ficZPdUN7^6Qr5?t3FD?(};#R-=SdW@VULi+P5MB855RI z81`{dKGXufa5>Q=nYl zZheAU&=_C)of`jaDk6rd6?tHN>ab^*b1CwYq5*_KT21Md$u4rUw%L)Dv&sf7X7fzM z2mL9)EAMqq&XpXQh3Lgxo0_m>Car5Lo8_MT$InIq7G1`w0Tq1O{>u$f%aQ4_qjJe6 z&fCTYqN!il&GVBDKql*t?sgIR+MiOTdcDe0X7thJ`H}M^QpJOaul^Nsx!3f{pA|Wl z2U{OmEJg*3RUDQYV=37L6v~PVl@t6M4+QVoq@5^GY;6@>MHN2nGPq{mmEF+mMSK__ zew5WKyD4IF;{5Z6bHVns-j_vdFNRB$Bi*o8>4v|C>IOxnu)M8g-ckLPODsq5iXh%~9`Tg=2P7B(YFO;pby;J}1vo48NZX6L#Upm5O za48tUhA?PthnIck9io)FbJtZM9EJ=M=oJZ4A6*Kfux4gOX4d!FWt ztFNlXI+$ z8AOIwWClTo1Q`VaQK_YZfIvc!A&3|PL#TLw$y$C;5jW4? z`+4r+x_(dM5B~VV^N{}UPypFU`Xf_+>U6B7=CK)5FdE_ZTj84AbKO57ma@bjh z{{tEdEIYS00w&OVh@LquBIH;m$%N{q+>!mMcr6bn{~rz)71tHILCDhuLlescrFngo zc2(m%BtsJ1$spRHV*Cy@E_<@?=Zjr(pyXi2>jSXGvHfRt%MW_EUlPhGbAFW6Au3Fn zLOmfXNbN5?%DVTl8ats%S81A!a|f&(O7{k%X;Nx48C44Im%Vb7M{CYn2%M<|?n@?e zUjqE-YG1_IUQQC{WeoXG7@mlDBtSnC4$fjQ-^iD#W;E_9+nkH|#7M7SzwXfu`TfQ` zMG3LstU8UTmabrKu}?1 zX@0eCi2RxJ3FAOG{KK$O=5$%jtaIaJ4#UiG$BE&`m-D=hzZ347(!Hk6bS(2rvUt$i zt3lLnC5!h@i-^jBdv5OC%vf<{zx|bOd}OK}czhvZY~?_nY4ru^rMZ4h8r_ldZDnRT z!Job*m6C)Fj<34X+FO~rCB=;C%F4HT0%^-RNUN9U2rb~dJxBidR2orO3D6i=3+; zmj*%Xy#o0S6b?U=W+2$1jW6I<1{SzroGaw_Lk%io$`@^_Ao>px*hq7^*ZU<@=7Rgm zyiDEavwycoML1TG5FT`sJ=8b+Bxtsvd$-s0-KMA}T9_N?8 z{@4rd@}|jEr`8K2m7N;5pv66Gj;pQf*NmIYUJWlr7gBbadp6$j`Lxvk)Tl{?ziFek zrX0?LOMUGJ?J=Ymi{$b5pvBEgPei6NrA8pt0T{mE)>fpzI%w@|rQPrM!??P4f7LkB z{Z0*7vwejkU&sNnFWP*(GCTGJqR-gmvi_a`nscNy;Hzz7r|nH1X;&Gp@(U!4vk=-S zE#Hh0w^EWq47_b;X7gd@7x7cAb2;)@VloGHV{K%U!N$^l6s`o8NW1Dk#Vsx_A~_LP z?ttX{Tz?k=sN2{0P=5hngLwd)>|2glXRZ&;5q3kLmP95iy%YbTC|{+HFHV#PW~$t- zMW5c331e1IL8+n(j+Uv)azJOgLr_?wx#zgmz~oaQ-W(Xc!CM9Y)n19$Q)?V%0^-a# znNl(um#K6ZG8Io<=pQVb8}qt1vLk-o@jIDb`0CG1)mmA>SaBBHEK47I zDGL@bg!v{NQZrPkjtORF269F22eIqKa1}lkc@q5>UjDibABaq?q%FKWOGo8em)e}) zbf(%|p3go;R_G!2&6B7iXmD(P@_c;LmQXl>xQTeG-cu|pBwNyd_sS9(AMUmUFRy1E zjCHxgTS79oqwnIKToCUH)1#?oT!7KXH7nhQinaZctx9d^=c^+J{yQG^9V*ff0-9otnNeNNF8&iGacYPeV2mTg8i!IR92^sA!d`4y-TDAmXd{&4W2(X$+M zpfP{fkNtQxj>8`#UIe46A^f4K#v-g|nn_NDAy$(Sh>4rN(|=4(*E_@Nr-y74(wc$n z@PHxSa*v&rh@NSumSRcYRUZBi;_5+i_tXMC2?ajf7DWIRrk8jvA&|gbtavM*$s-|C zRgT>J0A<1kx+P`q74Qb+H4%4?*_n;kO6-QIA&3VqYTFxw8hB!lk_0?e}r!#>&D$Oj=vo+m#1ZjP#&U_a;a!d7-Hb9+PULAGdDY9J zr`55`0as3`2}#R|+Z=9zciam#vH+9ERZ6McBhB*(l8#g@S`0noDc&5XMqKo0Xf+ct zZ+}`6>Ds4mgi4_SOm$K~c7fAvRjji37>W3|r(^C+ei2KN#Wtk-qV1%3@8Z#r9x`$X% zTa_J?R+e4ZI#ZuEAKnCx&WmVTdAKJ7LRS@yTzggaD@0l`=Df%*oqla;?MU`-%spC# zOWvs^T)=z#))K>MT}&}U1rrdw^;xVSTQVf40u?z$4P&C(6oJv(rh9#}0j+oMk`<(~ zo{-A2E1D#(b$xGAa!{k|FEpf$^|?5r%hdwAh3OSFL+sMbEN|)@uArd6&?n`HlCtt2 zVe=(moGwB1Nry9VMwGtZ-km-&akWNsf!q`qkxiuHaPjf+nWIpB94(`Z7GI4gBkmuj zBAnrR6dXb{aba|mNUkkawY4qw^-FcnTm(Fz{pSL8fo(pjM0s0WtNH#U)+?p)rfaOg z{s%kIwH>s9Kp`o|!kR-2oc9ZMQQEfDGK#3|ffvl*aEAyN&hHsn^ke2o;Ms;^#Fk=x zX~N3!VwW6$2DStnjwkF-nqnj|^)!8QFkV?^QqL!a1oIW+g8(H%WC~yvR06|(V@0vIc4C8Sy)X zQesmu;avZ;_phnXl;@ZORdcN1A1;2Ef@c{tsaWba_A-i2hB}6e^sM1?>fN(izexdG z^a`GcJ^#?GV2x{y=9zo&Ns!y|>b34v>Rd4Ch$z|hnC+`b0f6J%f+q5F|7ZVo=SCQ<4W3YljJUd>ArhO*Hs#~* z3chA`dRRV}Xes8QeL!J6%*c%~U$SlI%I>b=A_lGjM>#FD+>kf5hPC_?4$QFDo!Bf7 z#{=OvT4$Kwtd@~Aq=g=q%};!AO_(WPgW`YXwu1rpYZ&Wd9&~g5b%|V}Ptv}rQxTlw znCtydol54a(e4&EbplF%Qa9yH`uy5&M9CoFURPci2rk4qQQnc1HBL3GOK2I$tN8qD zKcZEAecM39_q_>4P;D-fr~ejH(JS(NIm%8~lF{o2--2)-1jGa~U60cYF*T0w8t{OTG10ZdtwMVP8ium?7?mzBOJBU<6cI9Q?uTTPeZXCtcjfu6Po>)wvlFh^gce|?<@|_mm zcfy(JEmVeM-_qbDEjk9;|7X|Q_8U0(%43H|%lJ2Tb zEeA}!*s+-0Zg*lGAAU{bYI6rYd{L`vjL@4fie2qfq*mIYB2bdd7hA|^1QloB2vy(=fAr1h++}q&ljE&A zA8KuubVX3EZCoZA7c|4qb8B2!V=prUX{f{n7vCTD+!h~~tc-q}w6du_ailrc9w%Pnaq8QQMkt31mlj1@zF)zt)jhW;H>=HLr-b57M8SNSj` z8Dyh>PZ?|`AO_a=SkZ78tIj@WXJR)XdSf;_vG$i*(?4U+5WxT?-}1@=4jN>Ym{_ba zhR5Q#S#$(jc!z|WRKRml>)#FOMhI1vH=$XofMclr^D2rQtbLS6Zh3%l;MDtp+RnLG zBH=SvK@K<0yt~8m!g_ot0+?1DgO2zkhjo>2^ta5udnVP4C@I zjCc?+?h_vp!}nPmE2OOUxg@-sn?mtjk@NPq zjwc89;p&x{GUK}KR(>L!x4O3wMd#epH}iM!cGa@f?sodnIgN$v$h3G73BQ@njQ$_4 zNVqQ{K{u_c^Wc%buR+L;<@<1?2Lhl+Og$`>?5`}q4lqh02@xwUZF=+eld%|2RQ zA9a!c8mB9_M@P#VEXaZM{@f22&f+bf7!EX__hfCohM6jfBU#DX zw|Lnyg{BO@zC(yNcs?1|Z-P96(4c}xQ010}p{>yK(%AR~+nx)yq;%_uyGbH)DR~Hr zh5>Hd+i72?j^&=)yX|-LIiCxC2d_V9Peh7X+)vE4FDm?rWso2RfWAC%!W%~dlpdK% z6=zQEoHjO;&9hKz0-JM(Db>vc$T&ItD0&XHAD-_q!MYWe@^Q2blKk`l3?6d*Yzm z`MZ8VPf)=-)c~pveP&ryJ>qoBWdF^H_wUc5kkG3zBM_a@lVFtTG|=7e;8uM5`;;8TU496qzC#(q$fklB2U&gALPg3-qXW3=DR1$n zIF?QznC2=wv(vH`Lj%Ik+VL}xRf_nIV{W`Ieuk4tqU&&yV^@@xapy*vONp%%7uzN1P`IdZO#a-&pW31qT;w@<_7^ zk_zuQ!c$7zkN&BDc$;IPX6bf~_vWQ*9SJf!9<%0SSf-MX`@9G*bwot2ubju3^>-~b zE7uo}Gz#Dwll)>~Kn`-RJw?F?wfltN>x>+(aDVq%G3DOaZHmW-5Ap~m2_jW`<9k0ooc% zL$p9N9up&|W2n{nXB2oM(Hl)ef_P1P2wHD;Ga;Z<>Vj&!oK0zL%rXPfnq(J6|koVBzGEH5S{b**2W{ znfntuKpSZ6zZ_H3|6t_g+z~p)HMf0INYXV1y*~HTe4M-R_a%H-m)*F+jndFYh4HWN zAK&?T;RwNgY_F)sau(g;q~n^hjP4zm!GPy!w9ywHf$Bw7@YuknjZB_#NzPM--lRSv zBFg>I<&VC`eX4%>Wf7oAnB6uJ&>2{&VfcJ}{z0dWOqL4%R;zrq0wyjZlRZs~$~uXt zl^V680&agS`b4fFVjQHusuKh<<2{IOC>41&5$rQ!M}l)h-Zy3*pc4XZL}bPcUsCiS zza-9ys6ma6GP%?s`zvrFDD1;({*2f(|tLp^q z5cK*VaW|&*NKqQb0H&tpiD_R-9>x_KXT@KF#{D?FI9&*Z^4KGo%~%APq&O)AirsGy zG|0GL0TaERPt(!^Z2ZlxM*#bM6#1yt;azl zIaC!*ncTnM%*38c))|7p;iAahqBSmv`adF{^s#ODtS>BI+%BhGHZ@iw!AoZT#n|=9 zDgO~!na2g0_sH3EN(s1_GmA^90vYE11D;uaLN29l)jlUQE79L|WHH>N>CajI(zRiA z{Wz_x)Vqx)dQjLK_nICy`vCUSM1>%UDlB+?Y6vj1Hq#}^?T1%3t%J?=!qO>O1d;1w zM1|^$Q$5w=Aw)$xg`Wbu>cEP#N>WW?zm#U=DR+n7%~JR73HPRiuGq*_J92az^F+i? z?sg0$TY@-OSVH4s9r|v5cGVRiI;2J*Z0C|%|D+C@_DmwiIBnpV#8pJPhm__yAFii- zk&+{%U%9a?3@irz0zT_S`~=j z={~mfi%?xg%uWKO1-!EoS7x-mjLAmYhJ{Z&{MH;;{~^EnlmBRp_A8|8h>VeD-Pese z$NJu~(~5<$WLomhc1IVA#n`eJ!7hA#XekX1z33I6odzeRaCI)VA{NfsVtq7g@iPXX_Q!YIYR2ATt%% zK2Z8V`KK_@Fc%vwL4G=*!#?L-lRKLiR1K=kn+wZ#2$)g>Bj&Lh1t|0codwDQSc0++pHz;MD6HT0mO^7CnoaBWGww6Z zS9Oc=tycV@sJks3>^FGgU`1f5S%@OXtVlyvcfeAS&N2;?X6pBI{$w^x{uZ=;v)bz+ z;kK)Ne%IxC>hb=<Ah{$TZJwVV6Yj(RBX{^r%=NEvoEN{9(WLrbL55r zo<);lm9s`}X2jgH+HbM$YO7||h$V+9@0$(Hb$fZqYIDD)3`qiYBis_ z4|NtlS7Uy)@{`cvPV}k|a;!Wg#3;>duJ5fvL-X(zH!s54xIfIl=x8jht9yts>K4Lu zd0pe3PJ0oW`aJ9z5!4{5v53W`cu*6f0xGn6?B(zeHV`}QNLV5L?lpI;R4|A%zdh22 zOk(={@Y)~l99=+|m&y~(zKiVpi0_Ja(wqkmdu0r|*SCvbxsX>OBj#MMS3m}sXyR%! z3!QzAW`H?@YTt)c(kVx%T-uIFug5&S6{)_5&J6;VsNA9XN+Itbq5+m+?&F?5d_oj? zfW)WM$R^X+({pvPprgO2>kxY;>XHmi!vVaDz!^$OMkPi$@z%0@qvk`aZ?#vJ=G5Ko z#(7J+yNC1ASWA>wO!63W$}BWpav1hHC2l(qqYlyJ7d<>g{%IjV+5$0OrI-&pILtiMw2GqR@3p9?UckE#Kv&DTZSuwaAZ-1jYpc1|dwj&I7r20`&I&9;%b+uGK{+5*HG$IT(h%6@5iur(AjFpOfvy=rRC$IS|+cEHUD*e{n7$!nS4hVnQy7MI8i{&Xl- z44+&Z_{eKMn*}y#Ib)9CIJShH5c8Y9HymtMWw5OZ)_j!fB3F*IcAJg@*XKdV1R+ZJ zCohe$se#%Suc6~ayaN#TQrUWeCW&TG4cag4Gs7yqt67W=E>kw*804GMTP zf&&kv@~e%s`>U3`5Qj~s3+L#?z9W0r?4r)I7Qi*RH?MX$d?1>{j|0o?5sjl2lIdeI zRz71@BZ*ECtAXkMwmWtc;9bp2&|K@=9IU3l`y|_?nI|_b>m>e~+u?71RX%k29w?{> zszb0kV*j;m{G|t1lFX4*JLgT`)WQsBH=sDHgT+jkoaUY0ue-@5W&hXlt9|dR?Q@hB z3oj124B4|56jIXgoCjVc)n{Q3v%UJl!V%*Ks<2Um`tu9P*<}`E>gg6Cd32FV@S`B3 z?&=N*_a>{agf0W_ei$3vnYcJvMgaMo{Z6uUY4F_qsCN#V1~srPdz0*^vX`atPnl_x zxl|UWbBQi9C0;ar$T&!(_I=BBCb^u-6WNVj?oftsB)kduJL?U|YJc2VgLfo$gomynk0KRHOnt_|2Je7mkq4t zJ;_|RURwVrjAs){yXl_n1S(yW`LGyWd!FeaNYFvmL;<>BDgDpkOOiuK3033gE_1LN zckYDsi?q`dL23anrG&0LcmLH*Liso6L7-BkR| z&zq{JkYfGk=Y6bqg3M>*qZJ7#7{ProKkL(<@bDBzBQl^*pKMuV0@Gig z|Nob;6#u6d;lF=-LuNldnLIpC-Y^E2v!bDm p7KrKNW{LcG|2x1b(NkUPBBILy-3uMogUCNVqj&BUPRBX=e*rJ%AJqT= diff --git a/test/integration/connect/envoy/docs/img/windows-linux-arch.png b/test/integration/connect/envoy/docs/img/windows-linux-arch.png deleted file mode 100644 index d1c05533e51f21a971153bbcfff5ae81714bbae9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61475 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 to work) - # 1 - is not truthy - - local val=$(tr '[:upper:]' '[:lower:]' <<<"$1") - case $val in - 1 | t | true | y | yes) - return 0 - ;; - *) - return 1 - ;; - esac -} - -function get_cert { - local HOSTPORT=$1 - local SERVER_NAME=$2 - local CA_FILE=$3 - local SNI_FLAG="" - if [ -n "$SERVER_NAME" ]; then - SNI_FLAG="-servername $SERVER_NAME" - fi - CERT=$(openssl s_client -connect $HOSTPORT $SNI_FLAG -showcerts /dev/null) - - echo "WANT CN: ${CN} (SNI: ${SERVER_NAME})" - echo "GOT CERT:" - echo "$CERT" - - echo "$CERT" | grep "CN = ${CN}" -} - -function get_upstream_endpoint { - local HOSTPORT=$1 - local CLUSTER_NAME=$2 - run curl -s -f "http://${HOSTPORT}/clusters?format=json" - [ "$status" -eq 0 ] - echo "$output" | jq --raw-output " -.cluster_statuses[] -| select(.name|startswith(\"${CLUSTER_NAME}\"))" -} - -function assert_upstream_missing_once { - local HOSTPORT=$1 - local CLUSTER_NAME=$2 - - run get_upstream_endpoint $HOSTPORT $CLUSTER_NAME - [ "$status" -eq 0 ] - echo "$output" - [ "" == "$output" ] -} - -function assert_upstream_missing { - local HOSTPORT=$1 - local CLUSTER_NAME=$2 - run retry_long assert_upstream_missing_once $HOSTPORT $CLUSTER_NAME - echo "OUTPUT: $output $status" - - [ "$status" -eq 0 ] -} - -function assert_envoy_version { - local ADMINPORT=$1 - run retry_default curl -f -s localhost:$ADMINPORT/server_info - [ "$status" -eq 0 ] - # Envoy 1.8.0 returns a plain text line like - # envoy 5d25f466c3410c0dfa735d7d4358beb76b2da507/1.8.0/Clean/DEBUG live 3 3 0 - # Later versions return JSON. - if (echo $output | grep '^envoy'); then - VERSION=$(echo $output | cut -d ' ' -f 2) - else - VERSION=$(echo $output | jq -r '.version') - fi - echo "Status=$status" - echo "Output=$output" - echo "---" - echo "Got version=$VERSION" - echo "Want version=$ENVOY_VERSION" - - # 1.20.2, 1.19.3 and 1.18.6 are special snowflakes in that the version for - # the release is reported with a '-dev' suffix (eg 1.20.2-dev). - if [ "$ENVOY_VERSION" = "1.20.2" ]; then - ENVOY_VERSION="1.20.2-dev" - elif [ "$ENVOY_VERSION" = "1.19.3" ]; then - ENVOY_VERSION="1.19.3-dev" - elif [ "$ENVOY_VERSION" = "1.18.6" ]; then - ENVOY_VERSION="1.18.6-dev" - fi - - echo $VERSION | grep "/$ENVOY_VERSION/" -} - -function assert_envoy_expose_checks_listener_count { - local HOSTPORT=$1 - local EXPECT_PATH=$2 - - # scrape this once - BODY=$(get_envoy_expose_checks_listener_once $HOSTPORT) - echo "BODY = $BODY" - - CHAINS=$(echo "$BODY" | jq '.active_state.listener.filter_chains | length') - echo "CHAINS = $CHAINS (expect 1)" - [ "${CHAINS:-0}" -eq 1 ] - - RANGES=$(echo "$BODY" | jq '.active_state.listener.filter_chains[0].filter_chain_match.source_prefix_ranges | length') - echo "RANGES = $RANGES (expect 3)" - # note: if IPv6 is not supported in the kernel per - # agent/xds/platform:SupportsIPv6() then this will only be 2 - [ "${RANGES:-0}" -eq 3 ] - - HCM=$(echo "$BODY" | jq '.active_state.listener.filter_chains[0].filters[0]') - HCM_NAME=$(echo "$HCM" | jq -r '.name') - HCM_PATH=$(echo "$HCM" | jq -r '.typed_config.route_config.virtual_hosts[0].routes[0].match.path') - echo "HCM = $HCM" - [ "${HCM_NAME:-}" == "envoy.filters.network.http_connection_manager" ] - [ "${HCM_PATH:-}" == "${EXPECT_PATH}" ] -} - -function get_envoy_expose_checks_listener_once { - local HOSTPORT=$1 - run curl -m 5 -s -f $HOSTPORT/config_dump - [ "$status" -eq 0 ] - echo "$output" | jq --raw-output '.configs[] | select(.["@type"] == "type.googleapis.com/envoy.admin.v3.ListenersConfigDump") | .dynamic_listeners[] | select(.name | startswith("exposed_path_"))' -} - -function get_envoy_public_listener_once { - local HOSTPORT=$1 - run curl -s -f $HOSTPORT/config_dump - [ "$status" -eq 0 ] - echo "$output" | jq --raw-output '.configs[] | select(.["@type"] == "type.googleapis.com/envoy.admin.v3.ListenersConfigDump") | .dynamic_listeners[] | select(.name | startswith("public_listener:"))' -} - -function assert_envoy_http_rbac_policy_count { - local HOSTPORT=$1 - local EXPECT_COUNT=$2 - - GOT_COUNT=$(get_envoy_http_rbac_once $HOSTPORT | jq '.rules.policies | length') - echo "GOT_COUNT = $GOT_COUNT" - [ "${GOT_COUNT:-0}" -eq $EXPECT_COUNT ] -} - -function get_envoy_http_rbac_once { - local HOSTPORT=$1 - run curl -m 5 -s -f $HOSTPORT/config_dump - [ "$status" -eq 0 ] - echo "$output" | jq --raw-output '.configs[2].dynamic_listeners[].active_state.listener.filter_chains[0].filters[0].typed_config.http_filters[] | select(.name == "envoy.filters.http.rbac") | .typed_config' -} - -function assert_envoy_network_rbac_policy_count { - local HOSTPORT=$1 - local EXPECT_COUNT=$2 - - GOT_COUNT=$(get_envoy_network_rbac_once $HOSTPORT | jq '.rules.policies | length') - echo "GOT_COUNT = $GOT_COUNT" - [ "${GOT_COUNT:-0}" -eq $EXPECT_COUNT ] -} - -function get_envoy_network_rbac_once { - local HOSTPORT=$1 - run curl -m 5 -s -f $HOSTPORT/config_dump - [ "$status" -eq 0 ] - echo "$output" | jq --raw-output '.configs[2].dynamic_listeners[].active_state.listener.filter_chains[0].filters[] | select(.name == "envoy.filters.network.rbac") | .typed_config' -} - -function get_envoy_listener_filters { - local HOSTPORT=$1 - run retry_default curl -s -f $HOSTPORT/config_dump - [ "$status" -eq 0 ] - echo "$output" | jq --raw-output '.configs[2].dynamic_listeners[].active_state.listener | "\(.name) \( .filter_chains[0].filters | map(.name) | join(","))"' -} - -function get_envoy_http_filter { - local HOSTPORT=$1 - local FILTER_NAME=$2 - run retry_default curl -s -f $HOSTPORT/config_dump - [ "$status" -eq 0 ] - echo "$output" | jq --raw-output ".configs[2].dynamic_listeners[] | .active_state.listener.filter_chains[].filters[] | select(.name == \"envoy.filters.network.http_connection_manager\") | .typed_config.http_filters[] | select(.name == \"${FILTER_NAME}\")" -} - -function get_envoy_http_filters { - local HOSTPORT=$1 - run retry_default curl -s -f $HOSTPORT/config_dump - [ "$status" -eq 0 ] - echo "$output" | jq --raw-output '.configs[2].dynamic_listeners[].active_state.listener | "\(.name) \( .filter_chains[0].filters[] | select(.name == "envoy.filters.network.http_connection_manager") | .typed_config.http_filters | map(.name) | join(","))"' -} - -function get_envoy_dynamic_cluster_once { - local HOSTPORT=$1 - local NAME_PREFIX=$2 - run curl -m 5 -s -f $HOSTPORT/config_dump - [ "$status" -eq 0 ] - echo "$output" | jq --raw-output ".configs[] | select (.[\"@type\"] == \"type.googleapis.com/envoy.admin.v3.ClustersConfigDump\") | .dynamic_active_clusters[] | select(.cluster.name | startswith(\"${NAME_PREFIX}\"))" -} - -function assert_envoy_dynamic_cluster_exists_once { - local HOSTPORT=$1 - local NAME_PREFIX=$2 - local EXPECT_SNI=$3 - BODY="$(get_envoy_dynamic_cluster_once $HOSTPORT $NAME_PREFIX)" - [ -n "$BODY" ] - - SNI="$(echo "$BODY" | jq --raw-output ".cluster.transport_socket.typed_config.sni | select(. | startswith(\"${EXPECT_SNI}\"))")" - [ -n "$SNI" ] -} - -function assert_envoy_dynamic_cluster_exists { - local HOSTPORT=$1 - local NAME_PREFIX=$2 - local EXPECT_SNI=$3 - run retry_long assert_envoy_dynamic_cluster_exists_once $HOSTPORT $NAME_PREFIX $EXPECT_SNI - [ "$status" -eq 0 ] -} - -function get_envoy_cluster_config { - local HOSTPORT=$1 - local CLUSTER_NAME=$2 - run retry_default curl -s -f $HOSTPORT/config_dump - [ "$status" -eq 0 ] - echo "$output" | jq --raw-output " - .configs[1].dynamic_active_clusters[] - | select(.cluster.name|startswith(\"${CLUSTER_NAME}\")) - | .cluster - " -} - -function get_envoy_stats_flush_interval { - local HOSTPORT=$1 - run retry_default curl -s -f $HOSTPORT/config_dump - [ "$status" -eq 0 ] - #echo "$output" > /workdir/s1_envoy_dump.json - echo "$output" | jq --raw-output '.configs[0].bootstrap.stats_flush_interval' -} - -# snapshot_envoy_admin is meant to be used from a teardown scriptlet from the host. -function snapshot_envoy_admin { - local HOSTPORT=$1 - local ENVOY_NAME=$2 - local DC=${3:-primary} - local OUTDIR="${LOG_DIR}/envoy-snapshots/${DC}/${ENVOY_NAME}" - - mkdir -p "${OUTDIR}" - docker_consul_exec "$DC" bash -c "curl -s http://${HOSTPORT}/config_dump" > "${OUTDIR}/config_dump.json" - docker_consul_exec "$DC" bash -c "curl -s http://${HOSTPORT}/clusters?format=json" > "${OUTDIR}/clusters.json" - docker_consul_exec "$DC" bash -c "curl -s http://${HOSTPORT}/stats" > "${OUTDIR}/stats.txt" - docker_consul_exec "$DC" bash -c "curl -s http://${HOSTPORT}/stats/prometheus" > "${OUTDIR}/stats_prometheus.txt" -} - -function reset_envoy_metrics { - local HOSTPORT=$1 - curl -m 5 -s -f -XPOST $HOSTPORT/reset_counters - return $? -} - -function get_all_envoy_metrics { - local HOSTPORT=$1 - curl -m 5 -s -f $HOSTPORT/stats - return $? -} - -function get_envoy_metrics { - local HOSTPORT=$1 - local METRICS=$2 - - get_all_envoy_metrics $HOSTPORT | grep "$METRICS" -} - -function assert_upstream_has_endpoint_port { - local HOSTPORT=$1 - local CLUSTER_NAME=$2 - local PORT_VALUE=$3 - - run retry_long assert_upstream_has_endpoint_port_once $HOSTPORT $CLUSTER_NAME $PORT_VALUE - [ "$status" -eq 0 ] -} - -function get_upstream_endpoint_in_status_count { - local HOSTPORT=$1 - local CLUSTER_NAME=$2 - local HEALTH_STATUS=$3 - run curl -m 5 -s -f "http://${HOSTPORT}/clusters?format=json" - [ "$status" -eq 0 ] - echo "$output" | jq --raw-output " -.cluster_statuses[] -| select(.name|startswith(\"${CLUSTER_NAME}\")) -| [.host_statuses[].health_status.eds_health_status] -| [select(.[] == \"${HEALTH_STATUS}\")] -| length" -} - -function assert_upstream_has_endpoints_in_status_once { - local HOSTPORT=$1 - local CLUSTER_NAME=$2 - local HEALTH_STATUS=$3 - local EXPECT_COUNT=$4 - - GOT_COUNT=$(get_upstream_endpoint_in_status_count $HOSTPORT $CLUSTER_NAME $HEALTH_STATUS) - - [ "$GOT_COUNT" -eq $EXPECT_COUNT ] -} - -function assert_upstream_has_endpoints_in_status { - local HOSTPORT=$1 - local CLUSTER_NAME=$2 - local HEALTH_STATUS=$3 - local EXPECT_COUNT=$4 - run retry_long assert_upstream_has_endpoints_in_status_once $HOSTPORT $CLUSTER_NAME $HEALTH_STATUS $EXPECT_COUNT - [ "$status" -eq 0 ] -} - -function assert_envoy_metric { - set -eEuo pipefail - local HOSTPORT=$1 - local METRIC=$2 - local EXPECT_COUNT=$3 - - METRICS=$(get_envoy_metrics $HOSTPORT "$METRIC") - - if [ -z "${METRICS}" ]; then - echo "Metric not found" 1>&2 - return 1 - fi - - GOT_COUNT=$(awk -F: '{print $2}' <<<"$METRICS" | head -n 1 | tr -d ' ') - - if [ -z "$GOT_COUNT" ]; then - echo "Couldn't parse metric count" 1>&2 - return 1 - fi - - if [ $EXPECT_COUNT -ne $GOT_COUNT ]; then - echo "$METRIC - expected count: $EXPECT_COUNT, actual count: $GOT_COUNT" 1>&2 - return 1 - fi -} - -function assert_envoy_metric_at_least { - set -eEuo pipefail - local HOSTPORT=$1 - local METRIC=$2 - local EXPECT_COUNT=$3 - - METRICS=$(get_envoy_metrics $HOSTPORT "$METRIC") - - if [ -z "${METRICS}" ]; then - echo "Metric not found" 1>&2 - return 1 - fi - - GOT_COUNT=$(awk -F: '{print $2}' <<<"$METRICS" | head -n 1 | tr -d ' ') - - if [ -z "$GOT_COUNT" ]; then - echo "Couldn't parse metric count" 1>&2 - return 1 - fi - - if [ $EXPECT_COUNT -gt $GOT_COUNT ]; then - echo "$METRIC - expected >= count: $EXPECT_COUNT, actual count: $GOT_COUNT" 1>&2 - return 1 - fi -} - -function assert_envoy_aggregate_metric_at_least { - set -eEuo pipefail - local HOSTPORT=$1 - local METRIC=$2 - local EXPECT_COUNT=$3 - - METRICS=$(get_envoy_metrics $HOSTPORT "$METRIC") - - if [ -z "${METRICS}" ]; then - echo "Metric not found" 1>&2 - return 1 - fi - - GOT_COUNT=$(awk '{ sum += $2 } END { print sum }' <<<"$METRICS") - - if [ -z "$GOT_COUNT" ]; then - echo "Couldn't parse metric count" 1>&2 - return 1 - fi - - if [ $EXPECT_COUNT -gt $GOT_COUNT ]; then - echo "$METRIC - expected >= count: $EXPECT_COUNT, actual count: $GOT_COUNT" 1>&2 - return 1 - fi -} - -function get_healthy_service_count { - local SERVICE_NAME=$1 - local DC=$2 - local NS=$3 - local AP=$4 - local PEER_NAME=$5 - - run curl -m 5 -s -f ${HEADERS} "consul-${DC}-client:8500/v1/health/connect/${SERVICE_NAME}?passing&ns=${NS}&partition=${AP}&peer=${PEER_NAME}" - - [ "$status" -eq 0 ] - echo "$output" | jq --raw-output '. | length' -} - -function assert_alive_wan_member_count { - local DC=$1 - local EXPECT_COUNT=$2 - run retry_long assert_alive_wan_member_count_once $DC $EXPECT_COUNT - [ "$status" -eq 0 ] -} - -function assert_alive_wan_member_count_once { - local DC=$1 - local EXPECT_COUNT=$2 - - GOT_COUNT=$(get_alive_wan_member_count $DC) - - [ "$GOT_COUNT" -eq "$EXPECT_COUNT" ] -} - -function get_alive_wan_member_count { - local DC=$1 - run retry_default curl -sL -f "consul-${DC}-server:8500/v1/agent/members?wan=1" - [ "$status" -eq 0 ] - # echo "$output" >&3 - echo "$output" | jq '.[] | select(.Status == 1) | .Name' | wc -l -} - -function assert_service_has_healthy_instances_once { - local SERVICE_NAME=$1 - local EXPECT_COUNT=$2 - local DC=${3:-primary} - local NS=${4:-} - local AP=${5:-} - local PEER_NAME=${6:-} - - GOT_COUNT=$(get_healthy_service_count "$SERVICE_NAME" "$DC" "$NS" "$AP" "$PEER_NAME") - - [ "$GOT_COUNT" -eq $EXPECT_COUNT ] -} - -function assert_service_has_healthy_instances { - local SERVICE_NAME=$1 - local EXPECT_COUNT=$2 - local DC=${3:-primary} - local NS=${4:-} - local AP=${5:-} - local PEER_NAME=${6:-} - - run retry_long assert_service_has_healthy_instances_once "$SERVICE_NAME" "$EXPECT_COUNT" "$DC" "$NS" "$AP" "$PEER_NAME" - [ "$status" -eq 0 ] -} - -function check_intention { - local SOURCE=$1 - local DESTINATION=$2 - get_consul_hostname primary - - curl -m 5 -s -f "${CONSUL_HOSTNAME}:8500/v1/connect/intentions/check?source=${SOURCE}&destination=${DESTINATION}" | jq ".Allowed" -} - -function assert_intention_allowed { - local SOURCE=$1 - local DESTINATION=$2 - - run check_intention "${SOURCE}" "${DESTINATION}" - [ "$status" -eq 0 ] - [ "$output" = "true" ] -} - -function assert_intention_denied { - local SOURCE=$1 - local DESTINATION=$2 - - run check_intention "${SOURCE}" "${DESTINATION}" - [ "$status" -eq 0 ] - [ "$output" = "false" ] -} - -function docker_consul { - local DC=$1 - shift 1 - retry_default docker_exec envoy_consul-${DC}_1 "$@" -} - -function docker_consul_for_proxy_bootstrap { - local DC=$1 - shift 1 - - local CONTAINER_NAME="$SINGLE_CONTAINER_BASE_NAME"-"$DC"_1 - - docker.exe exec -i $CONTAINER_NAME bash.exe -c "$@" -} - -function docker_exec { - if ! docker.exe exec -i "$@"; then - echo "Failed to execute: docker exec -i $@" 1>&2 - return 1 - fi -} - -function docker_consul_exec { - local DC=$1 - shift 1 - docker_exec envoy_consul-${DC}_1 "$@" -} - -function kill_envoy { - local BOOTSTRAP_NAME=$1 - local DC=${2:-primary} - - PORT=$( cat /c/workdir/$DC/envoy/${BOOTSTRAP_NAME}-bootstrap.json | jq .admin.address.socket_address.port_value ) - PID=$( netstat -qo | grep "127.0.0.1:$PORT" | sed -r "s/.* //g" ) - tskill $PID -} - -function must_match_in_statsd_logs { - local DC=${2:-primary} - local FILE="/c/workdir/${DC}/statsd/statsd.log" - - COUNT=$( grep -Ec $1 $FILE ) - echo "COUNT of '$1' matches: $COUNT" - - [ "$COUNT" -gt "0" ] -} - -function must_match_in_prometheus_response { - run curl -m 5 -f -s $1/metrics - COUNT=$( echo "$output" | grep -Ec $2 ) - - echo "OUTPUT head -n 10" - echo "$output" | head -n 10 - echo "COUNT of '$2' matches: $COUNT" - - [ "$status" == 0 ] - [ "$COUNT" -gt "0" ] -} - -function must_match_in_stats_proxy_response { - run curl -m 5 -f -s $1/$2 - COUNT=$( echo "$output" | grep -Ec $3 ) - - echo "OUTPUT head -n 10" - echo "$output" | head -n 10 - echo "COUNT of '$3' matches: $COUNT" - - [ "$status" == 0 ] - [ "$COUNT" -gt "0" ] -} - -# must_fail_tcp_connection checks that a request made through an upstream fails, -# probably due to authz being denied if all other tests passed already. Although -# we are using curl, this only works as expected for TCP upstreams as we are -# checking TCP-level errors. HTTP upstreams will return a valid 503 generated by -# Envoy rather than a connection-level error. -function must_fail_tcp_connection { - # Attempt to curl through upstream - run curl -m 5 --no-keepalive -s -v -f -d hello $1 - - echo "OUTPUT $output" - - # Should fail during handshake and return "got nothing" error - [ "$status" == "52" ] - - # Verbose output should enclude empty reply - echo "$output" | grep 'Empty reply from server' -} - -function must_pass_tcp_connection { - run curl -m 5 --no-keepalive -s -f -d hello $1 - - echo "OUTPUT $output" - - [ "$status" == "0" ] - [ "$output" = "hello" ] -} - -# must_fail_http_connection see must_fail_tcp_connection but this expects Envoy -# to generate a 503 response since the upstreams have refused connection. -function must_fail_http_connection { - # Attempt to curl through upstream - run curl -m 5 --no-keepalive -s -i -d hello "$1" - - echo "OUTPUT $output" - - [ "$status" == "0" ] - - local expect_response="${2:-403 Forbidden}" - # Should fail request with 503 - echo "$output" | grep "${expect_response}" -} - -# must_pass_http_request allows you to craft a specific http request to assert -# that envoy will NOT reject the request. Primarily of use for testing L7 -# intentions. -function must_pass_http_request { - local METHOD=$1 - local URL=$2 - local DEBUG_HEADER_VALUE="${3:-""}" - - local extra_args - if [[ -n "${DEBUG_HEADER_VALUE}" ]]; then - extra_args="-H x-test-debug:${DEBUG_HEADER_VALUE}" - fi - case "$METHOD" in - GET) ;; - - DELETE) - extra_args="$extra_args -X${METHOD}" - ;; - PUT | POST) - extra_args="$extra_args -d'{}' -X${METHOD}" - ;; - *) - return 1 - ;; - esac - - run curl -m 5 --no-keepalive -v -s -f $extra_args "$URL" - [ "$status" == 0 ] -} - -# must_fail_http_request allows you to craft a specific http request to assert -# that envoy will reject the request. Primarily of use for testing L7 -# intentions. -function must_fail_http_request { - local METHOD=$1 - local URL=$2 - local DEBUG_HEADER_VALUE="${3:-""}" - - local extra_args - if [[ -n "${DEBUG_HEADER_VALUE}" ]]; then - extra_args="-H x-test-debug:${DEBUG_HEADER_VALUE}" - fi - case "$METHOD" in - HEAD) - extra_args="$extra_args -I" - ;; - GET) ;; - - DELETE) - extra_args="$extra_args -X${METHOD}" - ;; - PUT | POST) - extra_args="$extra_args -d'{}' -X${METHOD}" - ;; - *) - return 1 - ;; - esac - - # Attempt to curl through upstream - run curl -m 5 --no-keepalive -s -i $extra_args "$URL" - - echo "OUTPUT $output" - - echo "$output" | grep "403 Forbidden" -} - -function upsert_config_entry { - local DC="$1" - local BODY="$2" - - echo "$BODY" | docker_consul "$DC" consul config write - -} - -function gen_envoy_bootstrap { - SERVICE=$1 - ADMIN_PORT=$2 - DC=${3:-primary} - IS_GW=${4:-0} - EXTRA_ENVOY_BS_ARGS="${5-}" - ADMIN_HOST="0.0.0.0" - - PROXY_ID="$SERVICE" - if ! is_set "$IS_GW"; then - PROXY_ID="$SERVICE-sidecar-proxy" - ADMIN_HOST="127.0.0.1" - fi - - if output=$(docker_consul_for_proxy_bootstrap $DC "consul connect envoy -bootstrap \ - -proxy-id $PROXY_ID \ - -envoy-version "$ENVOY_VERSION" \ - -http-addr envoy_consul-${DC}_1:8500 \ - -grpc-addr envoy_consul-${DC}_1:8502 \ - -admin-access-log-path="C:/envoy/envoy.log" \ - -admin-bind $ADMIN_HOST:$ADMIN_PORT ${EXTRA_ENVOY_BS_ARGS} \ - > /c/workdir/${DC}/envoy/${SERVICE}-bootstrap.json"); then - - # All OK, write config to file - echo $output - #echo "$output" > /c/workdir/${DC}/envoy/$SERVICE-bootstrap.json - else - status=$? - # Command failed, instead of swallowing error (printed on stdout by docker - # it seems) by writing it to file, echo it - echo "$output" - #return $status - fi - - -} - -function read_config_entry { - local KIND=$1 - local NAME=$2 - local DC=${3:-primary} - get_consul_hostname $DC - docker_consul_exec "$DC" bash -c "consul config read -kind $KIND -name $NAME -http-addr=\"$CONSUL_HOSTNAME:8500\"" -} - -function wait_for_namespace { - local NS="${1}" - local DC=${2:-primary} - get_consul_hostname $DC - retry_default docker_consul_exec "$DC" bash -c "curl -sLf http://${CONSUL_HOSTNAME}:8500/v1/namespace/${NS} >/dev/null" -} - -function wait_for_config_entry { - retry_default read_config_entry "$@" -} - -function assert_config_entry_status { - local TYPE="$1" - local STATUS="$2" - local REASON="$3" - local DC="$4" - local KIND="$5" - local NAME="$6" - local NS=${7:-} - local AP=${8:-} - local PEER=${9:-} - - status=$(curl -s -f "consul-${DC}-client:8500/v1/config/${KIND}/${NAME}?passing&ns=${NS}&partition=${AP}&peer=${PEER}" | jq ".Status.Conditions[] | select(.Type == \"$TYPE\" and .Status == \"$STATUS\" and .Reason == \"$REASON\")") - [ -n "$status" ] -} - -function delete_config_entry { - local KIND=$1 - local NAME=$2 - get_consul_hostname primary - retry_default curl -sL -XDELETE "http://${CONSUL_HOSTNAME}:8500/v1/config/${KIND}/${NAME}" -} - -function register_services { - local DC=${1:-primary} - wait_for_leader "$DC" - docker_consul_exec ${DC} bash -c "consul services register workdir/${DC}/register/service_*.hcl" -} - -# wait_for_leader waits until a leader is elected. -# Its first argument must be the datacenter name. -function wait_for_leader { - get_consul_hostname primary - retry_default docker_consul_exec "$1" bash -c "[[ $(curl --fail -sS http://${CONSUL_HOSTNAME}:8500/v1/status/leader) ]]" -} - -function setup_upsert_l4_intention { - local SOURCE=$1 - local DESTINATION=$2 - local ACTION=$3 - get_consul_hostname primary - retry_default docker_consul_exec primary bash -c "curl -sL -X PUT -d '{\"Action\": \"${ACTION}\"}' 'http://${CONSUL_HOSTNAME}:8500/v1/connect/intentions/exact?source=${SOURCE}&destination=${DESTINATION}'" -} - -function upsert_l4_intention { - local SOURCE=$1 - local DESTINATION=$2 - local ACTION=$3 - get_consul_hostname primary - retry_default curl -sL -XPUT "http://${CONSUL_HOSTNAME}:8500/v1/connect/intentions/exact?source=${SOURCE}&destination=${DESTINATION}" \ - -d"{\"Action\": \"${ACTION}\"}" >/dev/null -} - -function get_ca_root { - get_consul_hostname primary - curl -s -f "http://${CONSUL_HOSTNAME}:8500/v1/connect/ca/roots" | jq -r ".Roots[0].RootCert" -} - -function wait_for_agent_service_register { - local SERVICE_ID=$1 - local DC=${2:-primary} - get_consul_hostname $DC - retry_default docker_consul_exec "$DC" bash -c "curl -sLf 'http://${CONSUL_HOSTNAME}:8500/v1/agent/service/${SERVICE_ID}' >/dev/null" -} - -function set_ttl_check_state { - local CHECK_ID=$1 - local CHECK_STATE=$2 - local DC=${3:-primary} - get_consul_hostname $DC - - case "$CHECK_STATE" in - pass) ;; - - warn) ;; - - fail) ;; - - *) - echo "invalid ttl check state '${CHECK_STATE}'" >&2 - return 1 - ;; - esac - - retry_default docker_consul_exec "$DC" bash -c "curl -sL -XPUT 'http://${CONSUL_HOSTNAME}:8500/v1/agent/check/warn/${CHECK_ID}' >/dev/null" -} - -function get_upstream_fortio_name { - local HOST=$1 - local PORT=$2 - local PREFIX=$3 - local DEBUG_HEADER_VALUE="${4:-""}" - local extra_args - if [[ -n "${DEBUG_HEADER_VALUE}" ]]; then - extra_args="-H x-test-debug:${DEBUG_HEADER_VALUE}" - fi - # split proto if https:// is at the front of the host since the --resolve - # string needs just a bare host. - local PROTO="" - local CA_FILE="" - if [ "${HOST:0:8}" = "https://" ]; then - HOST="${HOST:8}" - PROTO="https://" - # Fix in the CA_FILE parameter: for Windows environments, the root path starts with "/c" - extra_args="${extra_args} --cacert /c/workdir/test-sds-server/certs/ca-root.crt" - fi - # We use --resolve instead of setting a Host header since we need the right - # name to be sent for SNI in some cases too. - run retry_default curl --ssl-revoke-best-effort -v -s -f --resolve "${HOST}:${PORT}:127.0.0.1" $extra_args \ - "${PROTO}${HOST}:${PORT}${PREFIX}/debug?env=dump" - - # Useful Debugging but breaks the expectation that the value output is just - # the grep output when things don't fail - if [ "$status" != 0 ]; then - echo "GOT FORTIO OUTPUT: $output" - fi - [ "$status" == 0 ] - echo "$output" | grep -E "^FORTIO_NAME=" -} - -function get_upstream_endpoint_port { - local HOSTPORT=$1 - local CLUSTER_NAME=$2 - local PORT_VALUE=$3 - run curl -s -f "http://${HOSTPORT}/clusters?format=json" - [ "$status" -eq 0 ] - echo "$output" | jq --raw-output " -.cluster_statuses[] -| select(.name|startswith(\"${CLUSTER_NAME}\")) -| [.host_statuses[].address.socket_address.port_value] -| [select(.[] == ${PORT_VALUE})] -| length" -} - -function assert_upstream_has_endpoint_port_once { - local HOSTPORT=$1 - local CLUSTER_NAME=$2 - local PORT_VALUE=$3 - - GOT_COUNT=$(get_upstream_endpoint_port $HOSTPORT $CLUSTER_NAME $PORT_VALUE) - - [ "$GOT_COUNT" -eq 1 ] -} - -function assert_expected_fortio_name { - local EXPECT_NAME=$1 - local HOST=${2:-"localhost"} - local PORT=${3:-5000} - local URL_PREFIX=${4:-""} - local DEBUG_HEADER_VALUE="${5:-""}" - - run get_upstream_fortio_name ${HOST} ${PORT} "${URL_PREFIX}" "${DEBUG_HEADER_VALUE}" - - echo "GOT: $output" - - [ "$status" == 0 ] - [ "$output" == "FORTIO_NAME=${EXPECT_NAME}" ] -} - -function assert_expected_fortio_name_pattern { - local EXPECT_NAME_PATTERN=$1 - local HOST=${2:-"localhost"} - local PORT=${3:-5000} - local URL_PREFIX=${4:-""} - local DEBUG_HEADER_VALUE="${5:-""}" - - GOT=$(get_upstream_fortio_name ${HOST} ${PORT} "${URL_PREFIX}" "${DEBUG_HEADER_VALUE}") - - if [[ "$GOT" =~ $EXPECT_NAME_PATTERN ]]; then - : - else - echo "expected name pattern: $EXPECT_NAME_PATTERN, actual name: $GOT" 1>&2 - return 1 - fi -} - -function get_upstream_fortio_host_header { - local HOST=$1 - local PORT=$2 - local PREFIX=$3 - local DEBUG_HEADER_VALUE="${4:-""}" - local extra_args - if [[ -n "${DEBUG_HEADER_VALUE}" ]]; then - extra_args="-H x-test-debug:${DEBUG_HEADER_VALUE}" - fi - run retry_default curl -v -s -f -H"Host: ${HOST}" $extra_args \ - "localhost:${PORT}${PREFIX}/debug" - [ "$status" == 0 ] - echo "$output" | grep -E "^Host: " -} - -function assert_expected_fortio_host_header { - local EXPECT_HOST=$1 - local HOST=${2:-"localhost"} - local PORT=${3:-5000} - local URL_PREFIX=${4:-""} - local DEBUG_HEADER_VALUE="${5:-""}" - - GOT=$(get_upstream_fortio_host_header ${HOST} ${PORT} "${URL_PREFIX}" "${DEBUG_HEADER_VALUE}") - - if [ "$GOT" != "Host: ${EXPECT_HOST}" ]; then - echo "expected Host header: $EXPECT_HOST, actual Host header: $GOT" 1>&2 - return 1 - fi -} - -function create_peering { - local GENERATE_PEER=$1 - local ESTABLISH_PEER=$2 - run curl -m 5 -sL -XPOST "http://consul-${GENERATE_PEER}-client:8500/v1/peering/token" -d"{ \"PeerName\" : \"${GENERATE_PEER}-to-${ESTABLISH_PEER}\" }" - # echo "$output" >&3 - [ "$status" == 0 ] - - local token - token="$(echo "$output" | jq -r .PeeringToken)" - [ -n "$token" ] - - run curl -m 5 -sLv -XPOST "http://consul-${ESTABLISH_PEER}-client:8500/v1/peering/establish" -d"{ \"PeerName\" : \"${ESTABLISH_PEER}-to-${GENERATE_PEER}\", \"PeeringToken\" : \"${token}\" }" - # echo "$output" >&3 - [ "$status" == 0 ] -} - -function assert_service_has_imported { - local DC=${1:-primary} - local SERVICE_NAME=$2 - local PEER_NAME=$3 - - run curl -s -f "http://consul-${DC}-client:8500/v1/peering/${PEER_NAME}" - [ "$status" == 0 ] - - echo "$output" | jq --raw-output '.StreamStatus.ImportedServices' | grep -e "${SERVICE_NAME}" - if [ $? -ne 0 ]; then - echo "Error finding service: ${SERVICE_NAME}" - return 1 - fi -} - -function get_lambda_envoy_http_filter { - local HOSTPORT=$1 - local NAME_PREFIX=$2 - run retry_default curl -s -f $HOSTPORT/config_dump - [ "$status" -eq 0 ] - # get the full http filter object so the individual fields can be validated. - echo "$output" | jq --raw-output ".configs[2].dynamic_listeners[] | .active_state.listener.filter_chains[].filters[] | select(.name == \"envoy.filters.network.http_connection_manager\") | .typed_config.http_filters[] | select(.name == \"envoy.filters.http.aws_lambda\") | .typed_config" -} - -function register_lambdas { - local DC=${1:-primary} - # register lambdas to the catalog - for f in $(find workdir/${DC}/register -type f -name 'lambda_*.json'); do - retry_default curl -sL -XPUT -d @${f} "http://localhost:8500/v1/catalog/register" >/dev/null && \ - echo "Registered Lambda: $(jq -r .Service.Service $f)" - done - # write service-defaults config entries for lambdas - for f in $(find workdir/${DC}/register -type f -name 'service_defaults_*.json'); do - varsub ${f} AWS_LAMBDA_REGION AWS_LAMBDA_ARN - retry_default curl -sL -XPUT -d @${f} "http://localhost:8500/v1/config" >/dev/null && \ - echo "Wrote config: $(jq -r '.Kind + " / " + .Name' $f)" - done -} - -function assert_lambda_envoy_dynamic_cluster_exists { - local HOSTPORT=$1 - local NAME_PREFIX=$2 - - local BODY=$(get_envoy_dynamic_cluster_once $HOSTPORT $NAME_PREFIX) - [ -n "$BODY" ] - - [ "$(echo $BODY | jq -r '.cluster.transport_socket.typed_config.sni')" == '*.amazonaws.com' ] -} - -function assert_lambda_envoy_dynamic_http_filter_exists { - local HOSTPORT=$1 - local NAME_PREFIX=$2 - local ARN=$3 - - local FILTER=$(get_lambda_envoy_http_filter $HOSTPORT $NAME_PREFIX) - [ -n "$FILTER" ] - - [ "$(echo $FILTER | jq -r '.arn')" == "$ARN" ] -} - -function varsub { - local file=$1 - shift - for v in "$@"; do - sed -i "s/\${$v}/${!v}/g" $file - done -} - -function get_url_header { - local URL=$1 - local HEADER=$2 - run curl -s -f -X GET -I "${URL}" - [ "$status" == 0 ] - RESP=$(echo "$output" | tr -d '\r') - RESP=$(echo "$RESP" | grep -E "^${HEADER}: ") - RESP=$(echo "$RESP" | sed "s/^${HEADER}: //g") - echo "$RESP" -} - -function assert_url_header { - local URL=$1 - local HEADER=$2 - local VALUE=$3 - run get_url_header "$URL" "$HEADER" - [ "$status" == 0 ] - [ "$VALUE" = "$output" ] -} - -# assert_upstream_message asserts both the returned code -# and message from upstream service -function assert_upstream_message { - local HOSTPORT=$1 - run curl -s -d hello localhost:$HOSTPORT - - if [ "$status" -ne 0 ]; then - echo "Command failed" - return 1 - fi - - if (echo $output | grep 'hello'); then - return 0 - fi - - echo "expected message not found in $output" - return 1 -} \ No newline at end of file diff --git a/test/integration/connect/envoy/main_test.go b/test/integration/connect/envoy/main_test.go index a1aaa060b894e..b81a72e37ddcb 100644 --- a/test/integration/connect/envoy/main_test.go +++ b/test/integration/connect/envoy/main_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build integration // +build integration @@ -7,9 +7,6 @@ package envoy import ( - "flag" - "io/ioutil" - "log" "os" "os/exec" "sort" @@ -19,31 +16,11 @@ import ( "github.com/stretchr/testify/require" ) -var ( - flagWin = flag.Bool("win", false, "Execute tests on windows") - flagResourceAPIs = flag.Bool("enable-resource-apis", false, "Execute tests with resource apis enabled.") -) - func TestEnvoy(t *testing.T) { - flag.Parse() - - if *flagWin == true { - dir := "../../../" - check_dir_files(dir) - } - - var testcases []string - var err error - if *flagResourceAPIs == true { - os.Setenv("USE_RESOURCE_APIS", "true") - testcases, err = discoverResourceAPICases() - } else { - testcases, err = discoverCases() - } + testcases, err := discoverCases() require.NoError(t, err) runCmd(t, "suite_setup") - defer runCmd(t, "suite_teardown") for _, tc := range testcases { @@ -63,7 +40,7 @@ func TestEnvoy(t *testing.T) { } } -func runCmdLinux(t *testing.T, c string, env ...string) { +func runCmd(t *testing.T, c string, env ...string) { t.Helper() cmd := exec.Command("./run-tests.sh", c) @@ -75,35 +52,7 @@ func runCmdLinux(t *testing.T, c string, env ...string) { } } -func runCmdWindows(t *testing.T, c string, env ...string) { - t.Helper() - - param_5 := "false" - if env != nil { - param_5 = strings.Join(env, " ") - } - - cmd := exec.Command("cmd", "/C", "bash run-tests.windows.sh", c, param_5) - cmd.Env = append(os.Environ(), env...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - t.Fatalf("command failed: %v", err) - } -} - -func runCmd(t *testing.T, c string, env ...string) { - t.Helper() - - if *flagWin == true { - runCmdWindows(t, c, env...) - - } else { - runCmdLinux(t, c, env...) - } -} - -// Discover the cases so we pick up both ce and ent copies. +// Discover the cases so we pick up both oss and ent copies. func discoverCases() ([]string, error) { cwd, err := os.Getwd() if err != nil { @@ -125,84 +74,3 @@ func discoverCases() ([]string, error) { sort.Strings(out) return out, nil } - -// discoverResourceAPICases will discover the Envoy tests case files but will contain -// a filter in it to only return those case for which functionality has been added -// to the V2 catalog resources. -func discoverResourceAPICases() ([]string, error) { - cwd, err := os.Getwd() - if err != nil { - return nil, err - } - - dirs, err := os.ReadDir(cwd) - if err != nil { - return nil, err - } - - var out []string - for _, fi := range dirs { - // TODO(proxystate): enable this to only include tests cases that are supported. - // Currently the work is in progress, so it is wired up in CI, but this excludes any tests from actually running. - if fi.IsDir() && strings.HasPrefix(fi.Name(), "case-don-match-me-on-anything-yet-because-i-am-not-ready") { - out = append(out, fi.Name()) - } - } - - sort.Strings(out) - return out, nil -} - -// CRLF convert functions -// Recursively iterates through the directory passed by parameter looking for the sh and bash files. -// Upon finding them, it calls crlf_file_check. -func check_dir_files(path string) { - files, err := ioutil.ReadDir(path) - if err != nil { - log.Fatal(err) - } - for _, fil := range files { - - v := strings.Split(fil.Name(), ".") - file_extension := v[len(v)-1] - - file_path := path + "/" + fil.Name() - - if fil.IsDir() == true { - check_dir_files(file_path) - } - - if file_extension == "sh" || file_extension == "bash" { - crlf_file_check(file_path) - } - } -} - -// Check if a file contains CRLF line endings if so call crlf_normalize -func crlf_file_check(file_name string) { - - file, err := ioutil.ReadFile(file_name) - text := string(file) - - if edit := crlf_verify(text); edit != -1 { - crlf_normalize(file_name, text) - } - - if err != nil { - log.Fatal(err) - } -} - -// Checks for the existence of CRLF line endings. -func crlf_verify(text string) int { - position := strings.Index(text, "\r\n") - return position -} - -// Replace CRLF line endings with LF. -func crlf_normalize(filename, text string) { - text = strings.Replace(text, "\r\n", "\n", -1) - data := []byte(text) - - ioutil.WriteFile(filename, data, 0644) -} diff --git a/test/integration/connect/envoy/run-tests.sh b/test/integration/connect/envoy/run-tests.sh index 900d3cbfd33b7..ba0d6fa810902 100755 --- a/test/integration/connect/envoy/run-tests.sh +++ b/test/integration/connect/envoy/run-tests.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail @@ -15,7 +15,7 @@ DEBUG=${DEBUG:-} XDS_TARGET=${XDS_TARGET:-server} # ENVOY_VERSION to run each test against -ENVOY_VERSION=${ENVOY_VERSION:-"1.27.0"} +ENVOY_VERSION=${ENVOY_VERSION:-"1.23.1"} export ENVOY_VERSION export DOCKER_BUILDKIT=1 @@ -179,14 +179,6 @@ function start_consul { license=$(cat $CONSUL_LICENSE_PATH) fi - USE_RESOURCE_APIS=${USE_RESOURCE_APIS:-false} - - experiments="experiments=[]" - # set up consul to run in V1 or V2 catalog mode - if [[ "${USE_RESOURCE_APIS}" == true ]]; then - experiments="experiments=[\"resource-apis\"]" - fi - # We currently run these integration tests in two modes: one in which Envoy's # xDS sessions are served directly by a Consul server, and another in which it # goes through a client agent. @@ -270,7 +262,6 @@ function start_consul { agent -dev -datacenter "${DC}" \ -config-dir "/workdir/${DC}/consul" \ -config-dir "/workdir/${DC}/consul-server" \ - -hcl=${experiments} \ -client "0.0.0.0" >/dev/null fi } @@ -798,9 +789,6 @@ function common_run_container_gateway { function run_container_gateway-primary { common_run_container_gateway mesh-gateway primary } -function run_container_gateway-ap1 { - common_run_container_gateway mesh-gateway ap1 -} function run_container_gateway-secondary { common_run_container_gateway mesh-gateway secondary } diff --git a/test/integration/connect/envoy/run-tests.windows.sh b/test/integration/connect/envoy/run-tests.windows.sh deleted file mode 100644 index c4dcff6ce486f..0000000000000 --- a/test/integration/connect/envoy/run-tests.windows.sh +++ /dev/null @@ -1,911 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - - -if [ $2 != "false" ] -then - export $2 -fi - -readonly self_name="$0" - -readonly HASHICORP_DOCKER_PROXY="docker.mirror.hashicorp.services" - -readonly SINGLE_CONTAINER_BASE_NAME=envoy_consul - -# DEBUG=1 enables set -x for this script so echos every command run -DEBUG=${DEBUG:-} - -XDS_TARGET=${XDS_TARGET:-server} - -# ENVOY_VERSION to run each test against -ENVOY_VERSION=${ENVOY_VERSION:-"1.27.0"} -export ENVOY_VERSION - -export DOCKER_BUILDKIT=0 - -if [ ! -z "$DEBUG" ] ; then - set -x -fi - -source helpers.windows.bash - -function command_error { - echo "ERR: command exited with status $1" 1>&2 - echo " command: $2" 1>&2 - echo " line: $3" 1>&2 - echo " function: $4" 1>&2 - echo " called at: $5" 1>&2 - # printf '%s\n' "${FUNCNAME[@]}" - # printf '%s\n' "${BASH_SOURCE[@]}" - # printf '%s\n' "${BASH_LINENO[@]}" -} - -trap 'command_error $? "${BASH_COMMAND}" "${LINENO}" "${FUNCNAME[0]:-main}" "${BASH_SOURCE[0]}:${BASH_LINENO[0]}"' ERR - -readonly WORKDIR_SNIPPET="-v envoy_workdir:C:\workdir" - -function network_snippet { - local DC="$1" - echo "--net=envoy-tests" -} - -function aws_snippet { - LAMBDA_TESTS_ENABLED=${LAMBDA_TESTS_ENABLED:-false} - if [ "$LAMBDA_TESTS_ENABLED" != false ]; then - local snippet="" - - # The Lambda integration cases assume that a Lambda function exists in $AWS_REGION with an ARN of $AWS_LAMBDA_ARN. - # The AWS credentials must have permission to invoke the Lambda function. - [ -n "$(set | grep '^AWS_ACCESS_KEY_ID=')" ] && snippet="${snippet} -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID" - [ -n "$(set | grep '^AWS_SECRET_ACCESS_KEY=')" ] && snippet="${snippet} -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY" - [ -n "$(set | grep '^AWS_SESSION_TOKEN=')" ] && snippet="${snippet} -e AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN" - [ -n "$(set | grep '^AWS_LAMBDA_REGION=')" ] && snippet="${snippet} -e AWS_LAMBDA_REGION=$AWS_LAMBDA_REGION" - [ -n "$(set | grep '^AWS_LAMBDA_ARN=')" ] && snippet="${snippet} -e AWS_LAMBDA_ARN=$AWS_LAMBDA_ARN" - - echo "$snippet" - fi -} - -function init_workdir { - local CLUSTER="$1" - - if test -z "$CLUSTER" - then - CLUSTER=primary - fi - - # Note, we use explicit set of dirs so we don't delete .gitignore. Also, - # don't wipe logs between runs as they are already split and we need them to - # upload as artifacts later. - rm -rf workdir/${CLUSTER} - rm -rf workdir/logs - mkdir -p workdir/${CLUSTER}/{consul,consul-server,register,envoy,bats,statsd,data} - - # Reload consul config from defaults - cp consul-base-cfg/*.hcl workdir/${CLUSTER}/consul/ - - # Add any overrides if there are any (no op if not) - find ${CASE_DIR} -maxdepth 1 -name '*.hcl' -type f -exec cp -f {} workdir/${CLUSTER}/consul \; - - # Copy all the test files - find ${CASE_DIR} -maxdepth 1 -name '*.bats' -type f -exec cp -f {} workdir/${CLUSTER}/bats \; - # Copy CLUSTER specific bats - cp helpers.windows.bash workdir/${CLUSTER}/bats/helpers.bash - - # Add any CLUSTER overrides - if test -d "${CASE_DIR}/${CLUSTER}" - then - find ${CASE_DIR}/${CLUSTER} -type f -name '*.hcl' -exec cp -f {} workdir/${CLUSTER}/consul \; - find ${CASE_DIR}/${CLUSTER} -type f -name '*.bats' -exec cp -f {} workdir/${CLUSTER}/bats \; - fi - - # move all of the registration files OUT of the consul config dir now - find workdir/${CLUSTER}/consul -type f -name 'service_*.hcl' -exec mv -f {} workdir/${CLUSTER}/register \; - - # move the server.hcl out of the consul dir so that it doesn't get picked up - # by the client agent (if we're running with XDS_TARGET=client). - if test -f "workdir/${CLUSTER}/consul/server.hcl" - then - mv workdir/${CLUSTER}/consul/server.hcl workdir/${CLUSTER}/consul-server/server.hcl - fi - - # copy the ca-certs for SDS so we can verify the right ones are served - mkdir -p workdir/test-sds-server/certs - cp test-sds-server/certs/ca-root.crt workdir/test-sds-server/certs/ca-root.crt - - if test -d "${CASE_DIR}/data" - then - cp -r ${CASE_DIR}/data/* workdir/${CLUSTER}/data - fi - - return 0 -} - -function docker_kill_rm { - local name - local todo=() - for name in "$@"; do - name="envoy_${name}_1" - if docker.exe container inspect $name &>/dev/null; then - if [[ "$name" == envoy_tcpdump-* ]]; then - echo -n "Gracefully stopping $name..." - docker.exe stop $name &> /dev/null - echo "done" - fi - todo+=($name) - fi - done - - if [[ ${#todo[@]} -eq 0 ]]; then - return 0 - fi - - echo -n "Killing and removing: ${todo[@]}..." - docker.exe rm -v -f ${todo[@]} &> /dev/null - echo "done" -} - -function start_consul { - local DC=${1:-primary} - - # 8500/8502 are for consul - # 9411 is for zipkin which shares the network with consul - # 16686 is for jaeger ui which also shares the network with consul - ports=( - '-p=8500:8500' - '-p=8502:8502' - '-p=9411:9411' - '-p=16686:16686' - ) - case "$DC" in - secondary) - ports=( - '-p=9500:8500' - '-p=9502:8502' - ) - ;; - alpha) - ports=( - '-p=9510:8500' - '-p=9512:8502' - ) - ;; - esac - - license="${CONSUL_LICENSE:-}" - # load the consul license so we can pass it into the consul - # containers as an env var in the case that this is a consul - # enterprise test - if test -z "$license" -a -n "${CONSUL_LICENSE_PATH:-}" - then - license=$(cat $CONSUL_LICENSE_PATH) - fi - - # We currently run these integration tests in two modes: one in which Envoy's - # xDS sessions are served directly by a Consul server, and another in which it - # goes through a client agent. - # - # This is necessary because servers and clients source configuration data in - # different ways (client agents use an RPC-backed cache and servers use their - # own local data) and we want to catch regressions in both. - # - # In the future we should also expand these tests to register services to the - # catalog directly (agentless) rather than relying on the server also being - # an agent. - # - # When XDS_TARGET=client we'll start a Consul server with its gRPC port - # disabled (but only if REQUIRE_PEERS is not set), and a client agent with - # its gRPC port enabled. - # - # When XDS_TARGET=server (or anything else) we'll run a single Consul server - # with its gRPC port enabled. - # - # In either case, the hostname `consul-${DC}-server` should be used as a - # server address (e.g. for WAN joining) and `consul-${DC}-client` should be - # used as a client address (e.g. for interacting with the HTTP API). - # - # Both hostnames work in both modes because we set network aliases on the - # containers such that both hostnames will resolve to the same container when - # XDS_TARGET=server. - # - # We also join containers to the network `container:consul-${DC}_1` in many - # places (see: network_snippet) so that we can curl localhost etc. In both - # modes, you can assume that this name refers to the client's container. - # - # Any .hcl files in the case/cluster directory will be given to both clients - # and servers (via the -config-dir flag) *except for* server.hcl which will - # only be applied to the server (and service registrations which will be made - # against the client). - if [[ "$XDS_TARGET" == "client" ]] - then - docker_kill_rm consul-${DC}-server - docker_kill_rm consul-${DC} - - server_grpc_port="-1" - if is_set $REQUIRE_PEERS; then - server_grpc_port="8502" - fi - - docker.exe run -d --name envoy_consul-${DC}-server_1 \ - --net=envoy-tests \ - $WORKDIR_SNIPPET \ - --hostname "consul-${DC}-server" \ - --network-alias "consul-${DC}-server" \ - -e "CONSUL_LICENSE=$license" \ - windows/consul:local \ - agent -dev -datacenter "${DC}" \ - -config-dir "C:\\workdir\\${DC}\\consul" \ - -config-dir "C:\\workdir\\${DC}\\consul-server" \ - -grpc-port $server_grpc_port \ - -client "0.0.0.0" \ - -bind "0.0.0.0" >/dev/null - - docker.exe run -d --name envoy_consul-${DC}_1 \ - --net=envoy-tests \ - $WORKDIR_SNIPPET \ - --hostname "consul-${DC}-client" \ - --network-alias "consul-${DC}-client" \ - -e "CONSUL_LICENSE=$license" \ - ${ports[@]} \ - windows/consul:local \ - agent -datacenter "${DC}" \ - -config-dir "C:\\workdir\\${DC}\\consul" \ - -data-dir "/tmp/consul" \ - -client "0.0.0.0" \ - -grpc-port 8502 \ - -datacenter "${DC}" \ - -retry-join "consul-${DC}-server" >/dev/null - else - docker_kill_rm consul-${DC} - - docker.exe run -d --name envoy_consul-${DC}_1 \ - --net=envoy-tests \ - $WORKDIR_SNIPPET \ - --memory 4096m \ - --cpus 2 \ - --hostname "consul-${DC}" \ - --network-alias "consul-${DC}-client" \ - --network-alias "consul-${DC}-server" \ - -e "CONSUL_LICENSE=$license" \ - ${ports[@]} \ - windows/consul:local \ - agent -dev -datacenter "${DC}" \ - -config-dir "C:\\workdir\\${DC}\\consul" \ - -config-dir "C:\\workdir\\${DC}\\consul-server" \ - -client "0.0.0.0" >/dev/null - fi -} - -function start_partitioned_client { - local PARTITION=${1:-ap1} - - # Start consul now as setup script needs it up - docker_kill_rm consul-${PARTITION} - - license="${CONSUL_LICENSE:-}" - # load the consul license so we can pass it into the consul - # containers as an env var in the case that this is a consul - # enterprise test - if test -z "$license" -a -n "${CONSUL_LICENSE_PATH:-}" - then - license=$(cat $CONSUL_LICENSE_PATH) - fi - - sh -c "rm -rf /workdir/${PARTITION}/data" - - # Run consul and expose some ports to the host to make debugging locally a - # bit easier. - # - docker.exe run -d --name envoy_consul-${PARTITION}_1 \ - --net=envoy-tests \ - $WORKDIR_SNIPPET \ - --hostname "consul-${PARTITION}-client" \ - --network-alias "consul-${PARTITION}-client" \ - -e "CONSUL_LICENSE=$license" \ - windows/consul:local agent \ - -datacenter "primary" \ - -retry-join "consul-primary-server" \ - -grpc-port 8502 \ - -data-dir "/tmp/consul" \ - -config-dir "C:\\workdir\\${PARTITION}/consul" \ - -client "0.0.0.0" >/dev/null -} - -function pre_service_setup { - local CLUSTER=${1:-primary} - - # Run test case setup (e.g. generating Envoy bootstrap, starting containers) - if [ -f "${CASE_DIR}/${CLUSTER}/setup.sh" ] - then - source ${CASE_DIR}/${CLUSTER}/setup.sh - else - source ${CASE_DIR}/setup.sh - fi -} - -function start_services { - # Start containers required - if [ ! -z "$REQUIRED_SERVICES" ] ; then - docker_kill_rm $REQUIRED_SERVICES - run_containers $REQUIRED_SERVICES - fi - - return 0 -} - -function verify { - local CLUSTER="$1" - if test -z "$CLUSTER"; then - CLUSTER="primary" - fi - - # Execute tests - res=0 - - # Nuke any previous case's verify container. - docker_kill_rm verify-${CLUSTER} - - echo "Running ${CLUSTER} verification step for ${CASE_DIR}..." - - # need to tell the PID 1 inside of the container that it won't be actual PID - # 1 because we're using --pid=host so we use TINI_SUBREAPER - if docker.exe exec -i ${SINGLE_CONTAINER_BASE_NAME}-${CLUSTER}_1 bash \ - -c "TINI_SUBREAPER=1 \ - ENVOY_VERSION=${ENVOY_VERSION} \ - XDS_TARGET=${XDS_TARGET} \ - /c/bats/bin/bats \ - --pretty /c/workdir/${CLUSTER}/bats" ; then - echo "✓ PASS" - else - echo "⨯ FAIL" - res=1 - fi - - return $res -} - -function capture_logs { - local LOG_DIR="workdir/logs/${CASE_DIR}/${ENVOY_VERSION}" - - init_vars - - echo "Capturing Logs" - mkdir -p "$LOG_DIR" - - services="$REQUIRED_SERVICES consul-primary" - if [[ "$XDS_TARGET" == "client" ]] - then - services="$services consul-primary-server" - fi - - if is_set $REQUIRE_SECONDARY - then - services="$services consul-secondary" - - if [[ "$XDS_TARGET" == "client" ]] - then - services="$services consul-secondary-server" - fi - fi - - if is_set $REQUIRE_PARTITIONS - then - services="$services consul-ap1" - fi - if is_set $REQUIRE_PEERS - then - services="$services consul-alpha" - - if [[ "$XDS_TARGET" == "client" ]] - then - services="$services consul-alpha-server" - fi - fi - - if [ -f "${CASE_DIR}/capture.sh" ] - then - echo "Executing ${CASE_DIR}/capture.sh" - source ${CASE_DIR}/capture.sh || true - fi - - for cont in $services; do - echo "Capturing log for $cont" - docker.exe logs "envoy_${cont}_1" &> "${LOG_DIR}/${cont}.log" || { - echo "EXIT CODE $?" > "${LOG_DIR}/${cont}.log" - } - done -} - -function stop_services { - # Teardown - docker_kill_rm $REQUIRED_SERVICES - - docker_kill_rm consul-primary consul-primary-server consul-secondary consul-secondary-server consul-ap1 consul-alpha consul-alpha-server -} - -function init_vars { - source "defaults.sh" - if [ -f "${CASE_DIR}/vars.sh" ] ; then - source "${CASE_DIR}/vars.sh" - fi -} - -function global_setup { - if [ -f "${CASE_DIR}/global-setup-windows.sh" ] ; then - source "${CASE_DIR}/global-setup-windows.sh" - fi -} - -function wipe_volumes { - docker.exe exec -w "C:\workdir" envoy_workdir_1 cmd /c "rd /s /q . 2>nul" -} - -# Windows containers does not allow cp command while running. -function stop_and_copy_files { - # Create CMD file to execute within the container - echo "icacls C:\workdir /grant:r Everyone:(OI)(CI)F /T" > copy.cmd - echo "XCOPY C:\workdir_bak C:\workdir /e /h /c /i /y" > copy.cmd - # Stop dummy container to copy local workdir to container's workdir_bak - docker.exe stop envoy_workdir_1 > /dev/null - docker.exe cp workdir/. envoy_workdir_1:/workdir_bak - # Copy CMD file into container - docker.exe cp copy.cmd envoy_workdir_1:/ - # Start dummy container and execute the CMD file - docker.exe start envoy_workdir_1 > /dev/null - docker.exe exec envoy_workdir_1 copy.cmd - # Delete local CMD file after execution - rm copy.cmd -} - -function run_tests { - CASE_DIR="${CASE_DIR?CASE_DIR must be set to the path of the test case}" - CASE_NAME=$( basename $CASE_DIR | cut -c6- ) - export CASE_NAME - export SKIP_CASE="" - - init_vars - - # Initialize the workdir - init_workdir primary - - if is_set $REQUIRE_SECONDARY - then - init_workdir secondary - fi - if is_set $REQUIRE_PARTITIONS - then - init_workdir ap1 - fi - if is_set $REQUIRE_PEERS - then - init_workdir alpha - fi - - global_setup - - # Allow vars.sh to set a reason to skip this test case based on the ENV - if [ "$SKIP_CASE" != "" ] ; then - echo "SKIPPING CASE: $SKIP_CASE" - return 0 - fi - - # Wipe state - wipe_volumes - - # Copying base files to shared volume - stop_and_copy_files - - # Starting Consul primary cluster - start_consul primary - - if is_set $REQUIRE_SECONDARY; then - start_consul secondary - fi - if is_set $REQUIRE_PARTITIONS; then - docker_consul "primary" consul partition create -name ap1 > /dev/null - start_partitioned_client ap1 - fi - if is_set $REQUIRE_PEERS; then - start_consul alpha - fi - - echo "Setting up the primary datacenter" - pre_service_setup primary - - if is_set $REQUIRE_SECONDARY; then - echo "Setting up the secondary datacenter" - pre_service_setup secondary - fi - if is_set $REQUIRE_PARTITIONS; then - echo "Setting up the non-default partition" - pre_service_setup ap1 - fi - if is_set $REQUIRE_PEERS; then - echo "Setting up the alpha peer" - pre_service_setup alpha - fi - - echo "Starting services" - start_services - - # Run the verify container and report on the output - echo "Verifying the primary datacenter" - verify primary - - if is_set $REQUIRE_SECONDARY; then - echo "Verifying the secondary datacenter" - verify secondary - fi - if is_set $REQUIRE_PEERS; then - echo "Verifying the alpha peer" - verify alpha - fi -} - -function test_teardown { - init_vars - - stop_services -} - -function workdir_cleanup { - docker_kill_rm workdir - docker.exe volume rm -f envoy_workdir &>/dev/null || true -} - - -function suite_setup { - # Cleanup from any previous unclean runs. - suite_teardown - - docker.exe network create -d "nat" envoy-tests &>/dev/null - - # Start the volume container - # - # This is a dummy container that we use to create volume and keep it - # accessible while other containers are down. - docker.exe volume create envoy_workdir &>/dev/null - docker.exe run -d --name envoy_workdir_1 \ - $WORKDIR_SNIPPET \ - --user ContainerAdministrator \ - --net=none \ - "${HASHICORP_DOCKER_PROXY}/windows/kubernetes/pause" &>/dev/null - - # pre-build the consul+envoy container - echo "Rebuilding 'windows/consul:local' image with envoy $ENVOY_VERSION..." - retry_default docker.exe build -t windows/consul:local \ - --build-arg ENVOY_VERSION=${ENVOY_VERSION} \ - -f Dockerfile-consul-envoy-windows . - - - local CONSUL_VERSION=$(docker image inspect --format='{{.ContainerConfig.Labels.version}}' \ - windows/consul:local) - echo "Running Tests with Consul=$CONSUL_VERSION - Envoy=$ENVOY_VERSION - XDS_TARGET=$XDS_TARGET" -} - -function suite_teardown { - docker_kill_rm verify-primary verify-secondary verify-alpha - - # this is some hilarious magic - docker_kill_rm $(grep "^function run_container_" $self_name | \ - sed 's/^function run_container_\(.*\) {/\1/g') - - docker_kill_rm consul-primary consul-primary-server consul-secondary consul-secondary-server consul-ap1 consul-alpha consul-alpha-server - - if docker.exe network inspect envoy-tests &>/dev/null ; then - echo -n "Deleting network 'envoy-tests'..." - docker.exe network rm envoy-tests - echo "done" - fi - - workdir_cleanup -} - -function run_containers { - for name in $@ ; do - run_container $name - done -} - -function run_container { - docker_kill_rm "$1" - "run_container_$1" -} - -function common_run_container_service { - local service="$1" - local CLUSTER="$2" - local httpPort="$3" - local grpcPort="$4" - local CONTAINER_NAME="$SINGLE_CONTAINER_BASE_NAME"-"$CLUSTER"_1 - - docker.exe exec -d $CONTAINER_NAME bash \ - -c "FORTIO_NAME=${service} \ - fortio.exe server \ - -http-port ":$httpPort" \ - -grpc-port ":$grpcPort" \ - -redirect-port disabled" -} - -function run_container_s1 { - common_run_container_service s1 primary 8080 8079 -} - -function run_container_s1-ap1 { - common_run_container_service s1 ap1 8080 8079 -} - -function run_container_s2 { - common_run_container_service s2 primary 8181 8179 -} -function run_container_s2-v1 { - common_run_container_service s2-v1 primary 8182 8178 -} -function run_container_s2-v2 { - common_run_container_service s2-v2 primary 8183 8177 -} - -function run_container_s3 { - common_run_container_service s3 primary 8282 8279 -} -function run_container_s3-v1 { - common_run_container_service s3-v1 primary 8283 8278 -} -function run_container_s3-v2 { - common_run_container_service s3-v2 primary 8284 8277 -} -function run_container_s3-alt { - common_run_container_service s3-alt primary 8286 8280 -} - -function run_container_s4 { - common_run_container_service s4 primary 8382 8281 -} - -function run_container_s1-secondary { - common_run_container_service s1-secondary secondary 8080 8079 -} - -function run_container_s2-secondary { - common_run_container_service s2-secondary secondary 8181 8179 -} - -function run_container_s2-ap1 { - common_run_container_service s2 ap1 8480 8479 -} - -function run_container_s3-ap1 { - common_run_container_service s3 ap1 8580 8579 -} - -function run_container_s1-alpha { - common_run_container_service s1-alpha alpha 8080 8079 -} - -function run_container_s2-alpha { - common_run_container_service s2-alpha alpha 8181 8179 -} - -function run_container_s3-alpha { - common_run_container_service s3-alpha alpha 8282 8279 -} - -function common_run_container_sidecar_proxy { - local service="$1" - local CLUSTER="$2" - local CONTAINER_NAME="$SINGLE_CONTAINER_BASE_NAME"-"$CLUSTER"_1 - - # Hot restart breaks since both envoys seem to interact with each other - # despite separate containers that don't share IPC namespace. Not quite - # sure how this happens but may be due to unix socket being in some shared - # location? - docker.exe exec -d $CONTAINER_NAME bash \ - -c "envoy.exe \ - -c /c/workdir/${CLUSTER}/envoy/${service}-bootstrap.json \ - -l trace \ - --disable-hot-restart \ - --drain-time-s 1 >/dev/null" -} - -function run_container_s1-sidecar-proxy { - common_run_container_sidecar_proxy s1 primary -} - -function run_container_s1-ap1-sidecar-proxy { - common_run_container_sidecar_proxy s1 ap1 -} - -function run_container_s1-sidecar-proxy-consul-exec { - local CLUSTER="primary" - local CONTAINER_NAME="$SINGLE_CONTAINER_BASE_NAME"-"$CLUSTER"_1 - local ADMIN_HOST="127.0.0.1" - local ADMIN_PORT="19000" - - docker.exe exec -d $CONTAINER_NAME bash \ - -c "consul connect envoy -sidecar-for s1 \ - -http-addr $CONTAINER_NAME:8500 \ - -grpc-addr $CONTAINER_NAME:8502 \ - -admin-bind $ADMIN_HOST:$ADMIN_PORT \ - -envoy-version ${ENVOY_VERSION} \ - -- \ - -l trace >/dev/null" -} - -function run_container_s2-sidecar-proxy { - common_run_container_sidecar_proxy s2 primary -} -function run_container_s2-v1-sidecar-proxy { - common_run_container_sidecar_proxy s2-v1 primary -} -function run_container_s2-v2-sidecar-proxy { - common_run_container_sidecar_proxy s2-v2 primary -} - -function run_container_s3-sidecar-proxy { - common_run_container_sidecar_proxy s3 primary -} -function run_container_s3-v1-sidecar-proxy { - common_run_container_sidecar_proxy s3-v1 primary -} -function run_container_s3-v2-sidecar-proxy { - common_run_container_sidecar_proxy s3-v2 primary -} - -function run_container_s3-alt-sidecar-proxy { - common_run_container_sidecar_proxy s3-alt primary -} - -function run_container_s1-sidecar-proxy-secondary { - common_run_container_sidecar_proxy s1 secondary -} -function run_container_s2-sidecar-proxy-secondary { - common_run_container_sidecar_proxy s2 secondary -} - -function run_container_s2-ap1-sidecar-proxy { - common_run_container_sidecar_proxy s2 ap1 -} - -function run_container_s3-ap1-sidecar-proxy { - common_run_container_sidecar_proxy s3 ap1 -} - -function run_container_s1-sidecar-proxy-alpha { - common_run_container_sidecar_proxy s1 alpha -} -function run_container_s2-sidecar-proxy-alpha { - common_run_container_sidecar_proxy s2 alpha -} -function run_container_s3-sidecar-proxy-alpha { - common_run_container_sidecar_proxy s3 alpha -} - -function common_run_container_gateway { - local name="$1" - local DC="$2" - local CONTAINER_NAME="$SINGLE_CONTAINER_BASE_NAME"-"$DC"_1 - - # Hot restart breaks since both envoys seem to interact with each other - # despite separate containers that don't share IPC namespace. Not quite - # sure how this happens but may be due to unix socket being in some shared - # location? - docker.exe exec -d $CONTAINER_NAME bash \ - -c "envoy.exe \ - -c /c/workdir/${DC}/envoy/${name}-bootstrap.json \ - -l trace \ - --disable-hot-restart \ - --drain-time-s 1 >/dev/null" -} - -function run_container_gateway-primary { - common_run_container_gateway mesh-gateway primary -} -function run_container_gateway-secondary { - common_run_container_gateway mesh-gateway secondary -} -function run_container_gateway-alpha { - common_run_container_gateway mesh-gateway alpha -} - -function run_container_ingress-gateway-primary { - common_run_container_gateway ingress-gateway primary -} - -function run_container_api-gateway-primary { - common_run_container_gateway api-gateway primary -} - -function run_container_terminating-gateway-primary { - common_run_container_gateway terminating-gateway primary -} - -function run_container_fake-statsd { - local CONTAINER_NAME="$SINGLE_CONTAINER_BASE_NAME"-"primary"_1 - # This magic SYSTEM incantation is needed since Envoy doesn't add newlines and so - # we need each packet to be passed to echo to add a new line before - # appending. But it does not work on Windows. - docker.exe exec -d $CONTAINER_NAME bash -c "socat -u UDP-RECVFROM:8125,fork,reuseaddr OPEN:/workdir/primary/statsd/statsd.log,create,append" -} - -function run_container_zipkin { - docker.exe run -d --name $(container_name) \ - $WORKDIR_SNIPPET \ - $(network_snippet primary) \ - "${HASHICORP_DOCKER_PROXY}/windows/openzipkin" -} - -function run_container_jaeger { - echo "Starting Jaeger service..." - - local DC=${1:-primary} - local CONTAINER_NAME="$SINGLE_CONTAINER_BASE_NAME"-"$DC"_1 - - docker.exe exec -d $CONTAINER_NAME bash -c "jaeger-all-in-one.exe \ - --collector.zipkin.http-port=9411" -} - -function run_container_test-sds-server { - echo "Starting test-sds-server" - - local DC=${1:-primary} - local CONTAINER_NAME="$SINGLE_CONTAINER_BASE_NAME"-"$DC"_1 - - docker.exe exec -d $CONTAINER_NAME bash -c "cd /c/test-sds-server && - ./test-sds-server.exe" -} - -function container_name { - echo "envoy_${FUNCNAME[1]/#run_container_/}_1" -} -function container_name_prev { - echo "envoy_${FUNCNAME[2]/#run_container_/}_1" -} - -# This is a debugging tool. Run via 'bash run-tests.sh debug_dump_volumes' on Powershell -function debug_dump_volumes { - local LINUX_PATH=$(pwd) - local WIN_PATH=$( echo "$LINUX_PATH" | sed 's/^\/mnt//' | sed -e 's/^\///' -e 's/\//\\/g' -e 's/^./\0:/' ) - docker.exe run -it \ - $WORKDIR_SNIPPET \ - -v "$WIN_PATH":"C:\\cwd" \ - --net=none \ - "${HASHICORP_DOCKER_PROXY}/windows/nanoserver:1809" \ - cmd /c "xcopy \workdir \cwd\workdir /E /H /C /I /Y" -} - -function run_container_tcpdump-primary { - # To use add "tcpdump-primary" to REQUIRED_SERVICES - common_run_container_tcpdump primary -} -function run_container_tcpdump-secondary { - # To use add "tcpdump-secondary" to REQUIRED_SERVICES - common_run_container_tcpdump secondary -} -function run_container_tcpdump-alpha { - # To use add "tcpdump-alpha" to REQUIRED_SERVICES - common_run_container_tcpdump alpha -} - -function common_run_container_tcpdump { - local DC="$1" - - # we cant run this in circle but its only here to temporarily enable. - -# docker.exe build --rm=false -t envoy-tcpdump -f Dockerfile-tcpdump-windows . - - docker.exe run -d --name $(container_name_prev) \ - $(network_snippet $DC) \ - envoy-tcpdump \ - -v -i any \ - -w "/data/${DC}.pcap" -} - -case "${1-}" in - "") - echo "command required" - exit 1 ;; - *) - "$@" ;; -esac diff --git a/test/integration/connect/envoy/test-sds-server/Dockerfile b/test/integration/connect/envoy/test-sds-server/Dockerfile index 73f72667b95a0..5ea87089c7047 100644 --- a/test/integration/connect/envoy/test-sds-server/Dockerfile +++ b/test/integration/connect/envoy/test-sds-server/Dockerfile @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 FROM golang:latest diff --git a/test/integration/connect/envoy/test-sds-server/certs/gen-certs.sh b/test/integration/connect/envoy/test-sds-server/certs/gen-certs.sh index 2c416ad146db6..bf46e5da0abf5 100755 --- a/test/integration/connect/envoy/test-sds-server/certs/gen-certs.sh +++ b/test/integration/connect/envoy/test-sds-server/certs/gen-certs.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 set -eEuo pipefail diff --git a/test/integration/connect/envoy/test-sds-server/sds.go b/test/integration/connect/envoy/test-sds-server/sds.go index 6223d894449d2..6c1ed208cd521 100644 --- a/test/integration/connect/envoy/test-sds-server/sds.go +++ b/test/integration/connect/envoy/test-sds-server/sds.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package main diff --git a/test/integration/connect/envoy/windows-troubleshooting.md b/test/integration/connect/envoy/windows-troubleshooting.md deleted file mode 100644 index a3a83e088808a..0000000000000 --- a/test/integration/connect/envoy/windows-troubleshooting.md +++ /dev/null @@ -1,90 +0,0 @@ -# Envoy Integration Tests on Windows - -## Index - -- [About this Guide](#about-this-guide) -- [Prerequisites](#prerequisites) -- [Running the Tests](#running-the-tests) -- [Troubleshooting](#troubleshooting) - - [About Envoy Integration Tests on Windows](#about-envoy-integration-tests-on-windows) - - [Common Errors](#common-errors) -- [Windows Scripts Changes](#windows-scripts-changes) -- [Volume Issues](#volume-issues) - -## About this Guide - -On this guide you will find all the information required to run the Envoy integration tests on Windows. - -## Prerequisites - -To run the integration tests yo will need to have the following installed on your System: - -- GO v1.18(or later). -- Gotestsum library [installation](https://pkg.go.dev/gotest.tools/gotestsum). -- Docker. - -Before running the tests, you will need to build the required Docker images, to do so, you can use the script provided [here](../../../../build-support-windows/build-images.sh): - -- Build Images Script Execution - - From a Bash console (GitBash or WSL) execute: `./build-images.sh` - -## Running the Tests - -To execute the tests you need to run the following command depending on the shell you are using: -**On Powershell**: -`go test -v -timeout=30m -tags integration ./test/integration/connect/envoy -run="TestEnvoy/" -win=true` -Where **TEST CASE** is the individual test case we want to execute (e.g. case-badauthz). - -**On Git Bash**: -`ENVOY_VERSION= go test -v -timeout=30m -tags integration ./test/integration/connect/envoy -run="TestEnvoy/" -win=true` -Where **TEST CASE** is the individual test case we want to execute (e.g. case-badauthz), and **ENVOY VERSION** is the version which you are currently testing. - -> [!TIP] -> When executing the integration tests using **Powershell** you may need to set the ENVOY_VERSION value manually in line 20 of the [run-tests.windows.sh](run-tests.windows.sh) file. - -> [!WARNING] -> When executing the integration tests for Windows environments, the **End of Line Sequence** of every related file and/or script will be changed from **LF** to **CRLF**. - -### About Envoy Integration Tests on Windows - -Integration tests on Linux run a multi-container architecture that take advantage of the Host Network Docker feature, using this feature means that the container's network stack is not isolated from the Docker host (the container shares the host’s networking namespace), and the container does not get its own IP-address allocated (read more about this [here](https://docs.docker.com/network/host/)). This feature is only available for Linux, which made migrating the tests to Windows challenging, since replicating the same architecture created more issues, that's why a **single container** architecture was chosen to run the Envoy integration tests. -Using a single container architecture meant that we could use the same tests as on linux, moreover we were able to speed-up their execution by replacing *docker run* commands which started utility containers, for *docker exec* commands. - -### Common errors - -If the tests are executed without docker running, the following error will be seen: - -```powershell -error during connect: This error may indicate that the docker daemon is not running.: Post "http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/build?buildargs=%7B%7D&cachefrom=%5B%5D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile-bats-windows&labels=%7B%7D&memory=0&memswap=0&networkmode=default&rm=1&shmsize=0&t=bats-verify&target=&ulimits=null&version=1": open //./pipe/docker_engine: The system cannot find the file specified. -``` - -If any of the docker images does not exist or is mistagged, an error similar to the following will be displayed: - -```powershell -Error response from daemon: No such container: envoy_workdir_1 -``` - -If you run the Windows tests from WSL you will get the following error message: - -```bash -main_test.go:34: command failed: exec: "cmd": executable file not found in $PATH -``` - -## Windows Scripts Changes - -- The "http-addr", "grpc-addr" and "admin-access-log-path" flags were added to the creation of the Envoy Bootstrap files. -- To execute commands sh was replaced by bash on our Windows container. -- All paths were updated to use Windows format. -- Created *stop_and_copy_files* function to copy files into the shared volume (see [volume issues](#volume-issues)). -- Changed the *-admin-bind* value from `0.0.0.0` to `127.0.0.1` when generating the Envoy Bootstrap files. -- Removed the *&&* from the *common_run_container_service's* docker exec command and replaced it with *\*. -- Removed *docker_wget* and *docker_curl* functions from [helpers.windows.bash](helpers.windows.bash) file and replaced them with **docker_consul_exec**, this way we avoid starting intermediate containers when capturing logs. -- The function *wipe_volumes* uses a `docker exec` command instead of the original `docker run`, this way we speed up test execution by avoiding to start a new container just to delete volume content before each test run. -- For **case-grpc** we increased the `envoy_stats_flush_interval` value from 1s to 5s, on Windows, the original value caused the test to pass or fail randomly. -- For **case-wanfed-gw** a new script was created: **global-setup-windows.sh**, this file replaces global-setup.sh when running this test in Windows. The new script uses the windows/consul:local Docker image to generate the required TLS files and copies them into host's workdir directory. -- To use the **debug_dump_volumes** function, you need to use it via Powershell and execute the following command: `bash run-tests.windows.sh debug_dump_volumes` Make sure to be positioned with your terminal in the correct directory. -- For **case-consul-exec** this case can only be run when using the consul-dev Docker image on this repository, since it relies on features implemented only here. These features are: Windows valid default value for "-admin-access-log-path" and `consul connect envoy` command starts Envoy. This features have also been submitted in [PR#15114](https://github.com/hashicorp/consul/pull/15114). - -## Volume Issues - -Another difference that arose when migrating the tests from Linux to Windows, is that file system operations can't be executed while Windows containers are running. Currently, when running the tests a **named volume** is created and all of the required files are copied into that volume. Because of the constraint mentioned before, the workaround we implemented was creating a function (**stop_and_copy_files**) that stops the *kubernetes/pause* container and executes a script to copy the required files and finally starts the container again. diff --git a/test/integration/consul-container/assets/tproxy-startup.sh b/test/integration/consul-container/assets/tproxy-startup.sh index 974d9368cbfdf..1e5963fe9fe9e 100644 --- a/test/integration/consul-container/assets/tproxy-startup.sh +++ b/test/integration/consul-container/assets/tproxy-startup.sh @@ -1,7 +1,4 @@ #!/usr/bin/env sh -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - set -ex diff --git a/test/integration/consul-container/go.mod b/test/integration/consul-container/go.mod index 8fde4fd94d8e7..6b54e847e8afc 100644 --- a/test/integration/consul-container/go.mod +++ b/test/integration/consul-container/go.mod @@ -7,23 +7,17 @@ require ( github.com/avast/retry-go v3.0.0+incompatible github.com/docker/docker v24.0.5+incompatible github.com/docker/go-connections v0.4.0 - github.com/evanphx/json-patch v4.12.0+incompatible github.com/go-jose/go-jose/v3 v3.0.0 - github.com/hashicorp/consul v0.0.0-00010101000000-000000000000 github.com/hashicorp/consul/api v1.24.0 github.com/hashicorp/consul/envoyextensions v0.4.1 - github.com/hashicorp/consul/proto-public v0.4.1 github.com/hashicorp/consul/sdk v0.14.1 - github.com/hashicorp/consul/testing/deployer v0.0.0-00010101000000-000000000000 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.2.1 - github.com/hashicorp/hcl v1.0.0 github.com/hashicorp/serf v0.10.1 github.com/itchyny/gojq v0.12.9 github.com/mitchellh/copystructure v1.2.0 - github.com/mitchellh/mapstructure v1.5.0 github.com/otiai10/copy v1.10.0 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.4 @@ -34,198 +28,66 @@ require ( ) require ( - cloud.google.com/go/compute v1.20.1 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.1 // indirect dario.cat/mergo v1.0.0 // indirect fortio.org/dflag v1.5.2 // indirect fortio.org/log v1.3.0 // indirect fortio.org/sets v1.0.2 // indirect fortio.org/version v1.0.2 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/DataDog/datadog-go v4.8.2+incompatible // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/aliyun/alibaba-cloud-sdk-go v1.62.156 // indirect - github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e // indirect github.com/armon/go-metrics v0.4.1 // indirect - github.com/armon/go-radix v1.0.0 // indirect - github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect - github.com/aws/aws-sdk-go v1.44.289 // indirect - github.com/benbjohnson/immutable v0.4.0 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/boltdb/bolt v1.3.1 // indirect - github.com/cenkalti/backoff/v3 v3.0.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible // indirect - github.com/circonus-labs/circonusllhist v0.1.3 // indirect github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect github.com/containerd/containerd v1.7.3 // indirect - github.com/coreos/etcd v3.3.27+incompatible // indirect - github.com/coreos/go-oidc v2.1.0+incompatible // indirect - github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect - github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/emicklei/go-restful/v3 v3.10.1 // indirect github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f // indirect github.com/envoyproxy/protoc-gen-validate v0.10.1 // indirect github.com/fatih/color v1.14.1 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/analysis v0.21.4 // indirect - github.com/go-openapi/errors v0.20.3 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.20.0 // indirect - github.com/go-openapi/loads v0.21.2 // indirect - github.com/go-openapi/runtime v0.25.0 // indirect - github.com/go-openapi/spec v0.20.8 // indirect - github.com/go-openapi/strfmt v0.21.3 // indirect - github.com/go-openapi/swag v0.22.3 // indirect - github.com/go-openapi/validate v0.22.1 // indirect - github.com/go-ozzo/ozzo-validation v3.6.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.0.1 // indirect - github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.9 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/s2a-go v0.1.4 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/googleapis/gax-go/v2 v2.11.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 // indirect - github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706 // indirect - github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-bexpr v0.1.2 // indirect - github.com/hashicorp/go-connlimit v0.3.0 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/go-memdb v1.3.4 // indirect github.com/hashicorp/go-msgpack v1.1.5 // indirect - github.com/hashicorp/go-msgpack/v2 v2.0.0 // indirect - github.com/hashicorp/go-plugin v1.4.5 // indirect - github.com/hashicorp/go-raftchunking v0.7.0 // indirect - github.com/hashicorp/go-retryablehttp v0.6.7 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 // indirect - github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 // indirect - github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect - github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect - github.com/hashicorp/go-syslog v1.0.0 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/hashicorp/hcp-scada-provider v0.2.3 // indirect - github.com/hashicorp/hcp-sdk-go v0.61.0 // indirect - github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038 // indirect github.com/hashicorp/memberlist v0.5.0 // indirect - github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0 // indirect - github.com/hashicorp/raft v1.5.0 // indirect - github.com/hashicorp/raft-autopilot v0.1.6 // indirect - github.com/hashicorp/raft-boltdb/v2 v2.2.2 // indirect - github.com/hashicorp/raft-wal v0.3.0 // indirect - github.com/hashicorp/vault-plugin-auth-alicloud v0.14.0 // indirect - github.com/hashicorp/vault/api v1.8.3 // indirect - github.com/hashicorp/vault/api/auth/gcp v0.3.0 // indirect - github.com/hashicorp/vault/sdk v0.7.0 // indirect - github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect - github.com/imdario/mergo v0.3.15 // indirect github.com/itchyny/timefmt-go v0.1.4 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.16.7 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/miekg/dns v1.1.50 // indirect - github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.0 // indirect - github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452 // indirect - github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect - github.com/mitchellh/pointerstructure v1.2.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/patternmatcher v0.5.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/term v0.5.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect github.com/morikuni/aec v1.0.0 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/oklog/run v1.0.0 // indirect - github.com/oklog/ulid v1.3.1 // indirect - github.com/oklog/ulid/v2 v2.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0-rc4 // indirect github.com/opencontainers/runc v1.1.8 // indirect - github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect - github.com/patrickmn/go-cache v2.1.0+incompatible // indirect - github.com/pierrec/lz4 v2.5.2+incompatible // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect - github.com/prometheus/client_golang v1.14.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.39.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect - github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect - github.com/segmentio/fasthash v1.0.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect - go.etcd.io/bbolt v1.3.7 // indirect - go.mongodb.org/mongo-driver v1.11.0 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel v1.16.0 // indirect - go.opentelemetry.io/otel/metric v1.16.0 // indirect - go.opentelemetry.io/otel/sdk v1.16.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.39.0 // indirect - go.opentelemetry.io/otel/trace v1.16.0 // indirect - go.opentelemetry.io/proto/otlp v0.19.0 // indirect - go.uber.org/atomic v1.9.0 // indirect golang.org/x/crypto v0.12.0 // indirect - golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b // indirect + golang.org/x/exp v0.0.0-20230807204917-050eac23e9de // indirect golang.org/x/net v0.14.0 // indirect - golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sync v0.3.0 // indirect golang.org/x/sys v0.11.0 // indirect - golang.org/x/term v0.11.0 // indirect golang.org/x/text v0.12.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.11.1 // indirect - google.golang.org/api v0.126.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 // indirect + golang.org/x/tools v0.12.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/ini.v1 v1.66.2 // indirect - gopkg.in/square/go-jose.v2 v2.5.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.26.2 // indirect - k8s.io/apimachinery v0.26.2 // indirect - k8s.io/client-go v0.26.2 // indirect - k8s.io/klog/v2 v2.90.1 // indirect - k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect - k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect ) replace ( diff --git a/test/integration/consul-container/go.sum b/test/integration/consul-container/go.sum index 026ae8db72f30..d194eacdceb58 100644 --- a/test/integration/consul-container/go.sum +++ b/test/integration/consul-container/go.sum @@ -1,56 +1,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg= -cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y= -cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= fortio.org/assert v1.1.4 h1:Za1RaG+OjsTMpQS3J3UCvTF6wc4+IOHCz+jAOU37Y4o= fortio.org/dflag v1.5.2 h1:F9XVRj4Qr2IbJP7BMj7XZc9wB0Q/RZ61Ool+4YPVad8= fortio.org/dflag v1.5.2/go.mod h1:ppb/A8u+KKg+qUUYZNYuvRnXuVb8IsdHb/XGzsmjkN8= @@ -66,93 +16,39 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1 github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/datadog-go v4.8.2+incompatible h1:qbcKSx29aBLD+5QLvlQZlGmRMF/FfGqFLFev/1TDzRo= -github.com/DataDog/datadog-go v4.8.2+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.156 h1:K4N91T1+RlSlx+t2dujeDviy4ehSGVjEltluDgmeHS4= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.156/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= -github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= -github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.44.289 h1:5CVEjiHFvdiVlKPBzv0rjG4zH/21W/onT18R5AH/qx0= -github.com/aws/aws-sdk-go v1.44.289/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/benbjohnson/immutable v0.4.0 h1:CTqXbEerYso8YzVPxmWxh2gnoRQbbB9X1quUC8+vGZA= -github.com/benbjohnson/immutable v0.4.0/go.mod h1:iAr8OjJGLnLmVUr9MZ/rz4PWUy6Ouc2JLYuMArmvAJM= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= -github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/containerd/containerd v1.7.3 h1:cKwYKkP1eTj54bP3wCdXXBymmKRQMrWjkLSWZZJDa8o= github.com/containerd/containerd v1.7.3/go.mod h1:32FOM4/O0RkNg7AjQj3hDzN9cUGtu+HMvaKUNiqCZB8= -github.com/coreos/etcd v3.3.27+incompatible h1:QIudLb9KeBsE5zyYxd1mjzRSkzLg9Wf9QlRwFgd6oTA= -github.com/coreos/etcd v3.3.27+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf h1:GOPo6vn/vTN+3IwZBvXX0y5doJfSC7My0cdzelyOCsQ= -github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -167,405 +63,107 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= -github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA= github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= -github.com/frankban/quicktest v1.13.0 h1:yNZif1OkDfNoDfb9zZa9aXIpejNR4F23Wely0c+Qdqk= -github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= -github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc= -github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo= -github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.3 h1:rz6kiC84sqNQoqrtulzaL/VERgkoCyB6WdEkc2ujzUc= -github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= -github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= -github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= -github.com/go-openapi/runtime v0.25.0 h1:7yQTCdRbWhX8vnIjdzU8S00tBYf7Sg71EBeorlPHvhc= -github.com/go-openapi/runtime v0.25.0/go.mod h1:Ux6fikcHXyyob6LNWxtE96hWwjBPYF0DXgVFuMTneOs= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/spec v0.20.8 h1:ubHmXNY3FCIOinT8RNrrPfGc9t7I1qhPtdOGoG2AxRU= -github.com/go-openapi/spec v0.20.8/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= -github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/strfmt v0.21.3 h1:xwhj5X6CjXEZZHMWy1zKJxvW9AfHC9pkyUjLvHtKG7o= -github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= -github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= -github.com/go-ozzo/ozzo-validation v3.6.0+incompatible h1:msy24VGS42fKO9K1vLz82/GeYW1cILu7Nuuj1N3BBkE= -github.com/go-ozzo/ozzo-validation v3.6.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= -github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= -github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= -github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= -github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= -github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2 h1:AtvtonGEH/fZK0XPNNBdB6swgy7Iudfx88wzyIpwqJ8= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4= -github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjdKDqyr/2L+f6U12Fk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= -github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706 h1:1ZEjnveDe20yFa6lSkfdQZm5BR/b271n0MsB5R2L3us= -github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706/go.mod h1:1Cs8FlmD1BfSQXJGcFLSV5FuIx1AbJP+EJGdxosoS2g= -github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69 h1:wzWurXrxfSyG1PHskIZlfuXlTSCj1Tsyatp9DtaasuY= -github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69/go.mod h1:svUZZDvotY8zTODknUePc6mZ9pX8nN0ViGwWcUSOBEA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-bexpr v0.1.2 h1:ijMXI4qERbzxbCnkxmfUtwMyjrrk3y+Vt0MxojNCbBs= -github.com/hashicorp/go-bexpr v0.1.2/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-connlimit v0.3.0 h1:oAojHGjFxUTTTA8c5XXnDqWJ2HLuWbDiBPTpWvNzvqM= -github.com/hashicorp/go-connlimit v0.3.0/go.mod h1:OUj9FGL1tPIhl/2RCfzYHrIiWj+VVPGNyVPnUX8AqS0= -github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.0/go.mod h1:xvb32K2keAc+R8DSFG2IwDcydK9DBQE+fGA5fsw6hSk= -github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c= -github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs= github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4= -github.com/hashicorp/go-msgpack/v2 v2.0.0 h1:c1fiLq1LNghmLOry1ipGhvLDi+/zEoaEP2JrE1oFJ9s= -github.com/hashicorp/go-msgpack/v2 v2.0.0/go.mod h1:JIxYkkFJRDDRSoWQBSh7s9QAVThq+82iWmUpmE4jKak= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= -github.com/hashicorp/go-plugin v1.4.5 h1:oTE/oQR4eghggRg8VY7PAz3dr++VwDNBGCcOfIvHpBo= -github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= -github.com/hashicorp/go-raftchunking v0.7.0 h1:APNMnCXmTOhumkFv/GpJIbq7HteWF7EnGZ3875lRN0Y= -github.com/hashicorp/go-raftchunking v0.7.0/go.mod h1:Dg/eBOaJzE0jYKNwNLs5IA5j0OSmL5HoCUiMy3mDmrI= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-retryablehttp v0.6.7 h1:8/CAEZt/+F7kR7GevNHulKkUjLht3CPmn7egmhieNKo= -github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 h1:W9WN8p6moV1fjKLkeqEgkAMu5rauy9QeYDAmIaPuuiA= -github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6/go.mod h1:MpCPSPGLDILGb4JMm94/mMi3YysIqsXzGCzkEZjcjXg= -github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 h1:cCRo8gK7oq6A2L6LICkUZ+/a5rLiRXFMf1Qd4xSwxTc= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.1/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= -github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo= -github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= -github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= -github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= -github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/hcp-scada-provider v0.2.3 h1:AarYR+/Pcv+cMvPdAlb92uOBmZfEH6ny4+DT+4NY2VQ= -github.com/hashicorp/hcp-scada-provider v0.2.3/go.mod h1:ZFTgGwkzNv99PLQjTsulzaCplCzOTBh0IUQsPKzrQFo= -github.com/hashicorp/hcp-sdk-go v0.61.0 h1:x4hJ8SlLI5WCE8Uzcu4q5jfdOEz/hFxfUkhAdoFdzSg= -github.com/hashicorp/hcp-sdk-go v0.61.0/go.mod h1:xP7wmWAmdMxs/7+ovH3jZn+MCDhHRj50Rn+m7JIY3Ck= -github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038 h1:n9J0rwVWXDpNd5iZnwY7w4WZyq53/rROeI7OVvLW8Ok= -github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= -github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0 h1:kBpVVl1sl3MaSrs97e0+pDQhSrqJv9gVbSUrPpVfl1w= -github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0/go.mod h1:6pdNz0vo0mF0GvhwDG56O3N18qBrAz/XRIcfINfTbwo= -github.com/hashicorp/raft v1.1.0/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= -github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= -github.com/hashicorp/raft v1.3.11/go.mod h1:J8naEwc6XaaCfts7+28whSeRvCqTd6e20BlCU3LtEO4= -github.com/hashicorp/raft v1.5.0 h1:uNs9EfJ4FwiArZRxxfd/dQ5d33nV31/CdCHArH89hT8= -github.com/hashicorp/raft v1.5.0/go.mod h1:pKHB2mf/Y25u3AHNSXVRv+yT+WAnmeTX0BwVppVQV+M= -github.com/hashicorp/raft-autopilot v0.1.6 h1:C1q3RNF2FfXNZfHWbvVAu0QixaQK8K5pX4O5lh+9z4I= -github.com/hashicorp/raft-autopilot v0.1.6/go.mod h1:Af4jZBwaNOI+tXfIqIdbcAnh/UyyqIMj/pOISIfhArw= -github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= -github.com/hashicorp/raft-boltdb v0.0.0-20210409134258-03c10cc3d4ea/go.mod h1:qRd6nFJYYS6Iqnc/8HcUmko2/2Gw8qTFEmxDLii6W5I= -github.com/hashicorp/raft-boltdb v0.0.0-20220329195025-15018e9b97e0 h1:CO8dBMLH6dvE1jTn/30ZZw3iuPsNfajshWoJTnVc5cc= -github.com/hashicorp/raft-boltdb/v2 v2.2.2 h1:rlkPtOllgIcKLxVT4nutqlTH2NRFn+tO1wwZk/4Dxqw= -github.com/hashicorp/raft-boltdb/v2 v2.2.2/go.mod h1:N8YgaZgNJLpZC+h+by7vDu5rzsRgONThTEeUS3zWbfY= -github.com/hashicorp/raft-wal v0.3.0 h1:Mi6RPoRbsxIIYZryI+bSTXHD97Ua6rIYO51ibYV9bkY= -github.com/hashicorp/raft-wal v0.3.0/go.mod h1:A6vP5o8hGOs1LHfC1Okh9xPwWDcmb6Vvuz/QyqUXlOE= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/hashicorp/vault-plugin-auth-alicloud v0.14.0 h1:O6tNk0s/arubLUbLeCyaRs5xGo9VwmbQazISY/BfPK4= -github.com/hashicorp/vault-plugin-auth-alicloud v0.14.0/go.mod h1:We3fJplmALwK1VpjwrLuXr/4QCQHYMdnXLHmLUU6Ntg= -github.com/hashicorp/vault/api v1.8.0/go.mod h1:uJrw6D3y9Rv7hhmS17JQC50jbPDAZdjZoTtrCCxxs7E= -github.com/hashicorp/vault/api v1.8.3 h1:cHQOLcMhBR+aVI0HzhPxO62w2+gJhIrKguQNONPzu6o= -github.com/hashicorp/vault/api v1.8.3/go.mod h1:4g/9lj9lmuJQMtT6CmVMHC5FW1yENaVv+Nv4ZfG8fAg= -github.com/hashicorp/vault/api/auth/gcp v0.3.0 h1:taum+3pCmOXnNgEKHlQbmgXmKw5daWHk7YJrLPP/w8g= -github.com/hashicorp/vault/api/auth/gcp v0.3.0/go.mod h1:gnNBFOASYUaFunedTHOzdir7vKcHL3skWBUzEn263bo= -github.com/hashicorp/vault/sdk v0.6.0/go.mod h1:+DRpzoXIdMvKc88R4qxr+edwy/RvH5QK8itmxLiDHLc= -github.com/hashicorp/vault/sdk v0.7.0 h1:2pQRO40R1etpKkia5fb4kjrdYMx3BHklPxl1pxpxDHg= -github.com/hashicorp/vault/sdk v0.7.0/go.mod h1:KyfArJkhooyba7gYCKSq8v66QdqJmnbAxtV/OX1+JTs= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I= -github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/itchyny/gojq v0.12.9 h1:biKpbKwMxVYhCU1d6mR7qMr3f0Hn9F5k5YykCVb3gmM= github.com/itchyny/gojq v0.12.9/go.mod h1:T4Ip7AETUXeGpD+436m+UEl3m3tokRgajd5pRfsR5oE= github.com/itchyny/timefmt-go v0.1.4 h1:hFEfWVdwsEi+CY8xY2FtgWHGQaBaC3JeHd+cve0ynVM= github.com/itchyny/timefmt-go v0.1.4/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= -github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= -github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -575,7 +173,6 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= @@ -583,39 +180,20 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= -github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= -github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.14.0 h1:/x0XQ6h+3U3nAyk1yx+bHPURrKa9sVVvYbuqZ7pIAtI= -github.com/mitchellh/go-testing-interface v1.14.0/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452 h1:hOY53G+kBFhbYFpRVxHl5eS7laP6B1+Cq+Z9Dry1iMU= -github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= -github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= -github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= -github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= @@ -625,48 +203,24 @@ github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWK github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= -github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= -github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs= -github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v1.1.8 h1:zICRlc+C1XzivLc3nzE+cbJV4LIi8tib6YG0MqC6OqA= github.com/opencontainers/runc v1.1.8/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= -github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= github.com/otiai10/copy v1.10.0 h1:znyI7l134wNg/wDktoVQPxPkgvhDfGCYUasey+h0rDQ= github.com/otiai10/copy v1.10.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= -github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= -github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI= -github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -676,647 +230,174 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= -github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= -github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= -github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= -github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 h1:xzABM9let0HLLqFypcxvLmlvEciCHL7+Lv+4vwZqecI= github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569/go.mod h1:2Ly+NIftZN4de9zRmENdYbvPQeaVIYKWpLFStLFEBgI= github.com/testcontainers/testcontainers-go v0.22.0 h1:hOK4NzNu82VZcKEB1aP9LO1xYssVFMvlfeuDW9JMmV0= github.com/testcontainers/testcontainers-go v0.22.0/go.mod h1:k0YiPa26xJCRUbUkYqy5rY6NGvSbVCeUBXCvucscBR4= -github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= -github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= -github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= -go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= -go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= -go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE= -go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= -go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= -go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= -go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= -go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= -go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= -go.opentelemetry.io/otel/sdk/metric v0.39.0 h1:Kun8i1eYf48kHH83RucG93ffz0zGV1sh46FAScOTuDI= -go.opentelemetry.io/otel/sdk/metric v0.39.0/go.mod h1:piDIRgjcK7u0HCL5pCA4e74qpK/jk3NiUoAHATVAmiI= -go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= -go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b h1:r+vk0EmXNmekl0S0BascoeeoHk/L7wmaW2QF90K+kYI= -golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/exp v0.0.0-20230807204917-050eac23e9de h1:l5Za6utMv/HsBWWqzt4S8X17j+kt1uVETUX5UFhn2rE= +golang.org/x/exp v0.0.0-20230807204917-050eac23e9de/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.11.1 h1:ojD5zOW8+7dOGzdnNgersm8aPfcDjhMp12UfG93NIMc= -golang.org/x/tools v0.11.1/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= +golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= +golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.126.0 h1:q4GJq+cAdMAC7XP7njvQ4tvohGLiSlytuL4BQxbIZ+o= -google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e h1:xIXmWJ303kJCuogpj0bHq+dcjcZHU+XFyc1I0Yl9cRg= -google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:0ggbjUrZYpy1q+ANUS30SEoGZ53cdfwtbuG7Ptgy108= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 h1:eSaPbMR4T7WfH9FvABk36NBMacoTUKdWCvV0dx+KfOg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I= -google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e h1:z3vDksarJxsAKM5dmEGv0GHwE2hKJ096wZra71Vs4sw= +google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 h1:wukfNtZmZUurLN/atp2hiIeTKn7QJWIQdHzqmsOnAOk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= -gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= -gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.26.2 h1:dM3cinp3PGB6asOySalOZxEG4CZ0IAdJsrYZXE/ovGQ= -k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU= -k8s.io/apimachinery v0.26.2 h1:da1u3D5wfR5u2RpLhE/ZtZS2P7QvDgLZTi9wrNZl/tQ= -k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= -k8s.io/client-go v0.26.2 h1:s1WkVujHX3kTp4Zn4yGNFK+dlDXy1bAAkIl+cFAiuYI= -k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU= -k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= -k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk= -k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/test/integration/consul-container/libs/assert/common.go b/test/integration/consul-container/libs/assert/common.go index c10cb7b9b4793..5f2431f6ff2f1 100644 --- a/test/integration/consul-container/libs/assert/common.go +++ b/test/integration/consul-container/libs/assert/common.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package assert diff --git a/test/integration/consul-container/libs/assert/envoy.go b/test/integration/consul-container/libs/assert/envoy.go index 05add74c92b0a..eef407c25021f 100644 --- a/test/integration/consul-container/libs/assert/envoy.go +++ b/test/integration/consul-container/libs/assert/envoy.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package assert @@ -14,12 +14,11 @@ import ( "testing" "time" + "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/go-cleanhttp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/hashicorp/consul/sdk/testutil/retry" - libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" ) @@ -114,7 +113,7 @@ func AssertUpstreamEndpointStatusWithClient( | length`, clusterName, healthStatus) results, err := utils.JQFilter(clusters, filter) - require.NoErrorf(r, err, "could not found cluster name %q: %v \n%s", clusterName, err, clusters) + require.NoErrorf(r, err, "could not found cluster name %s in \n%s", clusterName, clusters) require.Len(r, results, 1) // the final part of the pipeline is "length" which only ever returns 1 result result, err := strconv.Atoi(results[0]) diff --git a/test/integration/consul-container/libs/assert/grpc.go b/test/integration/consul-container/libs/assert/grpc.go index a41ef65af620e..ec72f0a651fd4 100644 --- a/test/integration/consul-container/libs/assert/grpc.go +++ b/test/integration/consul-container/libs/assert/grpc.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package assert @@ -26,7 +26,6 @@ func GRPCPing(t *testing.T, addr string) { var msg *fgrpc.PingMessage retries := 0 retry.RunWith(&retry.Timer{Timeout: time.Minute, Wait: 25 * time.Millisecond}, t, func(r *retry.R) { - t.Logf("making grpc call to %s", addr) retries += 1 msg, err = pingCl.Ping(context.Background(), &fgrpc.PingMessage{ // use addr as payload so we have something variable to check against diff --git a/test/integration/consul-container/libs/assert/peering.go b/test/integration/consul-container/libs/assert/peering.go index ab000268d7900..2cf842a4aed2b 100644 --- a/test/integration/consul-container/libs/assert/peering.go +++ b/test/integration/consul-container/libs/assert/peering.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package assert @@ -10,8 +10,6 @@ import ( "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil/retry" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) // PeeringStatus verifies the peering connection is the specified state with a default retry. @@ -54,8 +52,14 @@ func PeeringExportsOpts(t *testing.T, client *api.Client, peerName string, expor retry.RunWith(failer(), t, func(r *retry.R) { peering, _, err := client.Peerings().Read(context.Background(), peerName, opts) - require.Nil(r, err, "reading peering data") - require.NotNilf(r, peering, "peering not found %q", peerName) - assert.Len(r, peering.StreamStatus.ExportedServices, exports, "peering exported services") + if err != nil { + r.Fatal("error reading peering data") + } + if peering == nil { + r.Fatal("peering not found") + } + if exports != len(peering.StreamStatus.ExportedServices) { + r.Fatal("peering exported services did not match: got ", len(peering.StreamStatus.ExportedServices), " want ", exports) + } }) } diff --git a/test/integration/consul-container/libs/assert/service.go b/test/integration/consul-container/libs/assert/service.go index 35fad6bfb15ba..135403da913a4 100644 --- a/test/integration/consul-container/libs/assert/service.go +++ b/test/integration/consul-container/libs/assert/service.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package assert @@ -34,7 +34,7 @@ func CatalogServiceExists(t *testing.T, c *api.Client, svc string, opts *api.Que r.Fatal("error reading service data") } if len(services) == 0 { - r.Fatalf("did not find catalog entry for %q with opts %#v", svc, opts) + r.Fatal("did not find catalog entry for ", svc) } }) } diff --git a/test/integration/consul-container/libs/cluster/agent.go b/test/integration/consul-container/libs/cluster/agent.go index 6ffc4d4f8c289..6753fd8c017e1 100644 --- a/test/integration/consul-container/libs/cluster/agent.go +++ b/test/integration/consul-container/libs/cluster/agent.go @@ -1,23 +1,15 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cluster import ( "context" - "encoding/json" - "fmt" "io" - jsonpatch "github.com/evanphx/json-patch" - "github.com/hashicorp/hcl" - "github.com/mitchellh/mapstructure" "github.com/testcontainers/testcontainers-go" - "google.golang.org/grpc" - agentconfig "github.com/hashicorp/consul/agent/config" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/lib/decode" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" ) @@ -44,7 +36,6 @@ type Agent interface { Upgrade(ctx context.Context, config Config) error Exec(ctx context.Context, cmd []string) (string, error) DataDir() string - GetGRPCConn() *grpc.ClientConn } // Config is a set of configurations required to create a Agent @@ -95,30 +86,6 @@ func (c Config) Clone() Config { return c2 } -type decodeTarget struct { - agentconfig.Config `mapstructure:",squash"` -} - -// MutatebyAgentConfig mutates config by applying the fields in the input hclConfig -// Note that the precedence order is config > hclConfig, because user provider hclConfig -// may not work with the testing environment, e.g., data dir, agent name, etc. -// Currently only hcl config is allowed -func (c *Config) MutatebyAgentConfig(hclConfig string) error { - rawConfigJson, err := convertHcl2Json(hclConfig) - if err != nil { - return fmt.Errorf("error converting to Json: %s", err) - } - - // Merge 2 json - mergedConfigJosn, err := jsonpatch.MergePatch([]byte(rawConfigJson), []byte(c.JSON)) - if err != nil { - return fmt.Errorf("error merging configurations: %w", err) - } - - c.JSON = string(mergedConfigJosn) - return nil -} - // TODO: refactor away type AgentInfo struct { CACertFile string @@ -126,39 +93,3 @@ type AgentInfo struct { UseTLSForGRPC bool DebugURI string } - -func convertHcl2Json(in string) (string, error) { - var raw map[string]interface{} - err := hcl.Decode(&raw, in) - if err != nil { - return "", err - } - - var target decodeTarget - var md mapstructure.Metadata - d, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ - DecodeHook: mapstructure.ComposeDecodeHookFunc( - // decode.HookWeakDecodeFromSlice is only necessary when reading from - // an HCL config file. In the future we could omit it when reading from - // JSON configs. It is left here for now to maintain backwards compat - // for the unlikely scenario that someone is using malformed JSON configs - // and expecting this behaviour to correct their config. - decode.HookWeakDecodeFromSlice, - decode.HookTranslateKeys, - ), - Metadata: &md, - Result: &target, - }) - if err != nil { - return "", err - } - if err := d.Decode(raw); err != nil { - return "", err - } - - rawjson, err := json.MarshalIndent(target, "", " ") - if err != nil { - return "", err - } - return string(rawjson), nil -} diff --git a/test/integration/consul-container/libs/cluster/app.go b/test/integration/consul-container/libs/cluster/app.go index 001880b85f432..f434fcff135b6 100644 --- a/test/integration/consul-container/libs/cluster/app.go +++ b/test/integration/consul-container/libs/cluster/app.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cluster diff --git a/test/integration/consul-container/libs/cluster/builder.go b/test/integration/consul-container/libs/cluster/builder.go index 945b2bcd9ea02..72228a26d6134 100644 --- a/test/integration/consul-container/libs/cluster/builder.go +++ b/test/integration/consul-container/libs/cluster/builder.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cluster diff --git a/test/integration/consul-container/libs/cluster/cluster.go b/test/integration/consul-container/libs/cluster/cluster.go index 66e9ac5c2ddbb..aedf0ac9267a5 100644 --- a/test/integration/consul-container/libs/cluster/cluster.go +++ b/test/integration/consul-container/libs/cluster/cluster.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cluster diff --git a/test/integration/consul-container/libs/cluster/config.go b/test/integration/consul-container/libs/cluster/config.go index f46be0429541e..505811d35e7f3 100644 --- a/test/integration/consul-container/libs/cluster/config.go +++ b/test/integration/consul-container/libs/cluster/config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cluster diff --git a/test/integration/consul-container/libs/cluster/container.go b/test/integration/consul-container/libs/cluster/container.go index d444162364730..7ed88b0d824f5 100644 --- a/test/integration/consul-container/libs/cluster/container.go +++ b/test/integration/consul-container/libs/cluster/container.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cluster @@ -8,7 +8,6 @@ import ( "encoding/json" "fmt" "io" - "net/url" "os" "path/filepath" "strconv" @@ -16,14 +15,11 @@ import ( goretry "github.com/avast/retry-go" dockercontainer "github.com/docker/docker/api/types/container" - "github.com/docker/go-connections/nat" "github.com/hashicorp/go-multierror" "github.com/otiai10/copy" "github.com/pkg/errors" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" "github.com/hashicorp/consul/api" @@ -62,8 +58,6 @@ type consulContainerNode struct { clientCACertFile string ip string - grpcConn *grpc.ClientConn - nextAdminPortOffset int nextConnectPortOffset int @@ -178,8 +172,7 @@ func NewConsulContainer(ctx context.Context, config Config, cluster *Cluster, po clientAddr string clientCACertFile string - info AgentInfo - grpcConn *grpc.ClientConn + info AgentInfo ) debugURI := "" if utils.Debug { @@ -243,28 +236,6 @@ func NewConsulContainer(ctx context.Context, config Config, cluster *Cluster, po info.CACertFile = clientCACertFile } - // TODO: Support gRPC+TLS port. - if pc.Ports.GRPC > 0 { - port, err := nat.NewPort("tcp", strconv.Itoa(pc.Ports.GRPC)) - if err != nil { - return nil, fmt.Errorf("failed to parse gRPC TLS port: %w", err) - } - endpoint, err := podContainer.PortEndpoint(ctx, port, "tcp") - if err != nil { - return nil, fmt.Errorf("failed to get gRPC TLS endpoint: %w", err) - } - url, err := url.Parse(endpoint) - if err != nil { - return nil, fmt.Errorf("failed to parse gRPC endpoint URL: %w", err) - } - conn, err := grpc.Dial(url.Host, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - return nil, fmt.Errorf("failed to dial gRPC connection: %w", err) - } - deferClean.Add(func() { _ = conn.Close() }) - grpcConn = conn - } - ip, err := podContainer.ContainerIP(ctx) if err != nil { return nil, err @@ -311,7 +282,6 @@ func NewConsulContainer(ctx context.Context, config Config, cluster *Cluster, po name: name, ip: ip, info: info, - grpcConn: grpcConn, } if httpPort > 0 || httpsPort > 0 { @@ -406,10 +376,6 @@ func (c *consulContainerNode) GetClient() *api.Client { return c.client } -func (c *consulContainerNode) GetGRPCConn() *grpc.ClientConn { - return c.grpcConn -} - // NewClient returns an API client by making a new one based on the provided token // - updateDefault: if true update the default client func (c *consulContainerNode) NewClient(token string, updateDefault bool) (*api.Client, error) { @@ -542,10 +508,6 @@ func (c *consulContainerNode) terminate(retainPod bool, skipFuncs bool) error { continue } } - - // if the pod is retained and therefore the IP then the grpc conn - // should handle reconnecting so there is no reason to close it. - c.closeGRPC() } var merr error @@ -567,16 +529,6 @@ func (c *consulContainerNode) terminate(retainPod bool, skipFuncs bool) error { return merr } -func (c *consulContainerNode) closeGRPC() error { - if c.grpcConn != nil { - if err := c.grpcConn.Close(); err != nil { - return err - } - c.grpcConn = nil - } - return nil -} - func (c *consulContainerNode) DataDir() string { return c.dataDir } @@ -613,7 +565,6 @@ func newContainerRequest(config Config, opts containerOpts, ports ...int) (podRe ExposedPorts: []string{ "8500/tcp", // Consul HTTP API "8501/tcp", // Consul HTTPs API - "8502/tcp", // Consul gRPC API "8443/tcp", // Envoy Gateway Listener @@ -630,8 +581,6 @@ func newContainerRequest(config Config, opts containerOpts, ports ...int) (podRe "9997/tcp", // Envoy App Listener "9998/tcp", // Envoy App Listener "9999/tcp", // Envoy App Listener - - "80/tcp", // Nginx - http port used in wasm tests }, Hostname: opts.hostname, Networks: opts.addtionalNetworks, diff --git a/test/integration/consul-container/libs/cluster/encryption.go b/test/integration/consul-container/libs/cluster/encryption.go index 79e7133fbbd0b..3adb5a317700f 100644 --- a/test/integration/consul-container/libs/cluster/encryption.go +++ b/test/integration/consul-container/libs/cluster/encryption.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cluster diff --git a/test/integration/consul-container/libs/cluster/log.go b/test/integration/consul-container/libs/cluster/log.go index 59e69a64efdaf..f2a185d532f4f 100644 --- a/test/integration/consul-container/libs/cluster/log.go +++ b/test/integration/consul-container/libs/cluster/log.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cluster diff --git a/test/integration/consul-container/libs/cluster/network.go b/test/integration/consul-container/libs/cluster/network.go index be6f34c77983e..e0ee10f4e35ff 100644 --- a/test/integration/consul-container/libs/cluster/network.go +++ b/test/integration/consul-container/libs/cluster/network.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package cluster @@ -20,7 +20,6 @@ func createNetwork(t TestingT, name string) (testcontainers.Network, error) { Name: name, Attachable: true, CheckDuplicate: true, - SkipReaper: isRYUKDisabled(), }, } first := true diff --git a/test/integration/consul-container/libs/service/common.go b/test/integration/consul-container/libs/service/common.go index 0e0e2739571b0..add9f1395d241 100644 --- a/test/integration/consul-container/libs/service/common.go +++ b/test/integration/consul-container/libs/service/common.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package service diff --git a/test/integration/consul-container/libs/service/connect.go b/test/integration/consul-container/libs/service/connect.go index 6d283eac67d9b..4028309acb3ec 100644 --- a/test/integration/consul-container/libs/service/connect.go +++ b/test/integration/consul-container/libs/service/connect.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package service @@ -172,15 +172,8 @@ type SidecarConfig struct { // "consul connect envoy", for service name (serviceName) on the specified // node. The container exposes port serviceBindPort and envoy admin port // (19000) by mapping them onto host ports. The container's name has a prefix -// combining datacenter and name. The customContainerConf parameter can be used -// to mutate the testcontainers.ContainerRequest used to create the sidecar proxy. -func NewConnectService( - ctx context.Context, - sidecarCfg SidecarConfig, - serviceBindPorts []int, - node cluster.Agent, - customContainerConf func(request testcontainers.ContainerRequest) testcontainers.ContainerRequest, -) (*ConnectContainer, error) { +// combining datacenter and name. +func NewConnectService(ctx context.Context, sidecarCfg SidecarConfig, serviceBindPorts []int, node cluster.Agent) (*ConnectContainer, error) { nodeConfig := node.GetConfig() if nodeConfig.ScratchDir == "" { return nil, fmt.Errorf("node ScratchDir is required") @@ -287,11 +280,6 @@ func NewConnectService( exposedPorts := make([]string, len(appPortStrs)) copy(exposedPorts, appPortStrs) exposedPorts = append(exposedPorts, adminPortStr) - - if customContainerConf != nil { - req = customContainerConf(req) - } - info, err := cluster.LaunchContainerOnNode(ctx, node, req, exposedPorts) if err != nil { return nil, err diff --git a/test/integration/consul-container/libs/service/examples.go b/test/integration/consul-container/libs/service/examples.go index cc37cdb0a750e..85505c5dccc5e 100644 --- a/test/integration/consul-container/libs/service/examples.go +++ b/test/integration/consul-container/libs/service/examples.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package service @@ -127,42 +127,6 @@ func (c exampleContainer) GetStatus() (string, error) { return state.Status, err } -// NewCustomService creates a new test service from a custom testcontainers.ContainerRequest. -func NewCustomService(ctx context.Context, name string, httpPort int, grpcPort int, node libcluster.Agent, request testcontainers.ContainerRequest) (Service, error) { - namePrefix := fmt.Sprintf("%s-service-example-%s", node.GetDatacenter(), name) - containerName := utils.RandName(namePrefix) - - pod := node.GetPod() - if pod == nil { - return nil, fmt.Errorf("node Pod is required") - } - - var ( - httpPortStr = strconv.Itoa(httpPort) - grpcPortStr = strconv.Itoa(grpcPort) - ) - - request.Name = containerName - - info, err := libcluster.LaunchContainerOnNode(ctx, node, request, []string{httpPortStr, grpcPortStr}) - if err != nil { - return nil, err - } - - out := &exampleContainer{ - ctx: ctx, - container: info.Container, - ip: info.IP, - httpPort: info.MappedPorts[httpPortStr].Int(), - grpcPort: info.MappedPorts[grpcPortStr].Int(), - serviceName: name, - } - - fmt.Printf("Custom service exposed http port %d, gRPC port %d\n", out.httpPort, out.grpcPort) - - return out, nil -} - func NewExampleService(ctx context.Context, name string, httpPort int, grpcPort int, node libcluster.Agent, containerArgs ...string) (Service, error) { namePrefix := fmt.Sprintf("%s-service-example-%s", node.GetDatacenter(), name) containerName := utils.RandName(namePrefix) diff --git a/test/integration/consul-container/libs/service/gateway.go b/test/integration/consul-container/libs/service/gateway.go index 61bc4d31503ad..fda7b7a92693e 100644 --- a/test/integration/consul-container/libs/service/gateway.go +++ b/test/integration/consul-container/libs/service/gateway.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package service diff --git a/test/integration/consul-container/libs/service/helpers.go b/test/integration/consul-container/libs/service/helpers.go index a524d9c040bff..d7168448c208b 100644 --- a/test/integration/consul-container/libs/service/helpers.go +++ b/test/integration/consul-container/libs/service/helpers.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package service @@ -9,7 +9,6 @@ import ( "testing" "github.com/stretchr/testify/require" - "github.com/testcontainers/testcontainers-go" "github.com/hashicorp/consul/api" libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" @@ -52,7 +51,7 @@ type ServiceOpts struct { } // createAndRegisterStaticServerAndSidecar register the services and launch static-server containers -func createAndRegisterStaticServerAndSidecar(node libcluster.Agent, httpPort int, grpcPort int, svc *api.AgentServiceRegistration, customContainerCfg func(testcontainers.ContainerRequest) testcontainers.ContainerRequest, containerArgs ...string) (Service, Service, error) { +func createAndRegisterStaticServerAndSidecar(node libcluster.Agent, httpPort int, grpcPort int, svc *api.AgentServiceRegistration, containerArgs ...string) (Service, Service, error) { // Do some trickery to ensure that partial completion is correctly torn // down, but successful execution is not. var deferClean utils.ResettableDefer @@ -80,62 +79,10 @@ func createAndRegisterStaticServerAndSidecar(node libcluster.Agent, httpPort int svc.Connect.SidecarService.Proxy != nil && svc.Connect.SidecarService.Proxy.Mode == api.ProxyModeTransparent, } - serverConnectProxy, err := NewConnectService(context.Background(), sidecarCfg, []int{svc.Port}, node, customContainerCfg) // bindPort not used + serverConnectProxy, err := NewConnectService(context.Background(), sidecarCfg, []int{svc.Port}, node) // bindPort not used if err != nil { return nil, nil, err } - - deferClean.Add(func() { - _ = serverConnectProxy.Terminate() - }) - - // disable cleanup functions now that we have an object with a Terminate() function - deferClean.Reset() - - return serverService, serverConnectProxy, nil -} - -// createAndRegisterCustomServiceAndSidecar creates a custom service from the given testcontainers.ContainerRequest -// and a sidecar proxy for the service. The customContainerCfg parameter is used to mutate the -// testcontainers.ContainerRequest for the sidecar proxy. -func createAndRegisterCustomServiceAndSidecar(node libcluster.Agent, - httpPort int, - grpcPort int, - svc *api.AgentServiceRegistration, - request testcontainers.ContainerRequest, - customContainerCfg func(testcontainers.ContainerRequest) testcontainers.ContainerRequest, -) (Service, Service, error) { - // Do some trickery to ensure that partial completion is correctly torn - // down, but successful execution is not. - var deferClean utils.ResettableDefer - defer deferClean.Execute() - - if err := node.GetClient().Agent().ServiceRegister(svc); err != nil { - return nil, nil, err - } - - // Create a service and proxy instance - serverService, err := NewCustomService(context.Background(), svc.ID, httpPort, grpcPort, node, request) - if err != nil { - return nil, nil, err - } - deferClean.Add(func() { - _ = serverService.Terminate() - }) - sidecarCfg := SidecarConfig{ - Name: fmt.Sprintf("%s-sidecar", svc.ID), - ServiceID: svc.ID, - Namespace: svc.Namespace, - EnableTProxy: svc.Connect != nil && - svc.Connect.SidecarService != nil && - svc.Connect.SidecarService.Proxy != nil && - svc.Connect.SidecarService.Proxy.Mode == api.ProxyModeTransparent, - } - serverConnectProxy, err := NewConnectService(context.Background(), sidecarCfg, []int{svc.Port}, node, customContainerCfg) // bindPort not used - if err != nil { - return nil, nil, err - } - deferClean.Add(func() { _ = serverConnectProxy.Terminate() }) @@ -146,52 +93,7 @@ func createAndRegisterCustomServiceAndSidecar(node libcluster.Agent, return serverService, serverConnectProxy, nil } -func CreateAndRegisterCustomServiceAndSidecar(node libcluster.Agent, - serviceOpts *ServiceOpts, - request testcontainers.ContainerRequest, - customContainerCfg func(testcontainers.ContainerRequest) testcontainers.ContainerRequest) (Service, Service, error) { - // Register the static-server service and sidecar first to prevent race with sidecar - // trying to get xDS before it's ready - p := serviceOpts.HTTPPort - agentCheck := api.AgentServiceCheck{ - Name: "Static Server Listening", - TCP: fmt.Sprintf("127.0.0.1:%d", p), - Interval: "10s", - Status: api.HealthPassing, - } - if serviceOpts.RegisterGRPC { - p = serviceOpts.GRPCPort - agentCheck.TCP = "" - agentCheck.GRPC = fmt.Sprintf("127.0.0.1:%d", p) - } - req := &api.AgentServiceRegistration{ - Name: serviceOpts.Name, - ID: serviceOpts.ID, - Port: p, - Connect: &api.AgentServiceConnect{ - SidecarService: &api.AgentServiceRegistration{ - Proxy: &api.AgentServiceConnectProxyConfig{ - Mode: api.ProxyMode(serviceOpts.Connect.Proxy.Mode), - }, - }, - }, - Namespace: serviceOpts.Namespace, - Partition: serviceOpts.Partition, - Locality: serviceOpts.Locality, - Meta: serviceOpts.Meta, - Check: &agentCheck, - } - return createAndRegisterCustomServiceAndSidecar(node, serviceOpts.HTTPPort, serviceOpts.GRPCPort, req, request, customContainerCfg) -} - -// CreateAndRegisterStaticServerAndSidecarWithCustomContainerConfig creates an example static server and a sidecar for -// the service. The customContainerCfg parameter is a function of testcontainers.ContainerRequest to -// testcontainers.ContainerRequest which can be used to mutate the container request for the sidecar proxy and inject -// custom configuration and lifecycle hooks. -func CreateAndRegisterStaticServerAndSidecarWithCustomContainerConfig(node libcluster.Agent, - serviceOpts *ServiceOpts, - customContainerCfg func(testcontainers.ContainerRequest) testcontainers.ContainerRequest, - containerArgs ...string) (Service, Service, error) { +func CreateAndRegisterStaticServerAndSidecar(node libcluster.Agent, serviceOpts *ServiceOpts, containerArgs ...string) (Service, Service, error) { // Register the static-server service and sidecar first to prevent race with sidecar // trying to get xDS before it's ready p := serviceOpts.HTTPPort @@ -223,11 +125,7 @@ func CreateAndRegisterStaticServerAndSidecarWithCustomContainerConfig(node libcl Meta: serviceOpts.Meta, Check: &agentCheck, } - return createAndRegisterStaticServerAndSidecar(node, serviceOpts.HTTPPort, serviceOpts.GRPCPort, req, customContainerCfg, containerArgs...) -} - -func CreateAndRegisterStaticServerAndSidecar(node libcluster.Agent, serviceOpts *ServiceOpts, containerArgs ...string) (Service, Service, error) { - return CreateAndRegisterStaticServerAndSidecarWithCustomContainerConfig(node, serviceOpts, nil, containerArgs...) + return createAndRegisterStaticServerAndSidecar(node, serviceOpts.HTTPPort, serviceOpts.GRPCPort, req, containerArgs...) } func CreateAndRegisterStaticServerAndSidecarWithChecks(node libcluster.Agent, serviceOpts *ServiceOpts) (Service, Service, error) { @@ -257,7 +155,7 @@ func CreateAndRegisterStaticServerAndSidecarWithChecks(node libcluster.Agent, se Locality: serviceOpts.Locality, } - return createAndRegisterStaticServerAndSidecar(node, serviceOpts.HTTPPort, serviceOpts.GRPCPort, req, nil) + return createAndRegisterStaticServerAndSidecar(node, serviceOpts.HTTPPort, serviceOpts.GRPCPort, req) } func CreateAndRegisterStaticClientSidecar( @@ -339,7 +237,7 @@ func CreateAndRegisterStaticClientSidecar( EnableTProxy: enableTProxy, } - clientConnectProxy, err := NewConnectService(context.Background(), sidecarCfg, []int{libcluster.ServiceUpstreamLocalBindPort}, node, nil) + clientConnectProxy, err := NewConnectService(context.Background(), sidecarCfg, []int{libcluster.ServiceUpstreamLocalBindPort}, node) if err != nil { return nil, err } diff --git a/test/integration/consul-container/libs/service/log.go b/test/integration/consul-container/libs/service/log.go index 4e64bb7e54bbf..86e10a3fc719c 100644 --- a/test/integration/consul-container/libs/service/log.go +++ b/test/integration/consul-container/libs/service/log.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package service diff --git a/test/integration/consul-container/libs/service/service.go b/test/integration/consul-container/libs/service/service.go index ca186849728c6..5e1af3ab14c73 100644 --- a/test/integration/consul-container/libs/service/service.go +++ b/test/integration/consul-container/libs/service/service.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package service diff --git a/test/integration/consul-container/libs/topology/peering_topology.go b/test/integration/consul-container/libs/topology/peering_topology.go index 1d11851753a2f..bd88ea58e66e9 100644 --- a/test/integration/consul-container/libs/topology/peering_topology.go +++ b/test/integration/consul-container/libs/topology/peering_topology.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package topology @@ -194,22 +194,13 @@ type ClusterConfig struct { ExposedPorts []int } -func NewCluster( - t *testing.T, - config *ClusterConfig, -) (*libcluster.Cluster, *libcluster.BuildContext, *api.Client) { - return NewClusterWithConfig(t, config, "", "") -} - // NewCluster creates a cluster with peering enabled. It also creates // and registers a mesh-gateway at the client agent. The API client returned is // pointed at the client agent. // - proxy-defaults.protocol = tcp -func NewClusterWithConfig( +func NewCluster( t *testing.T, config *ClusterConfig, - serverHclConfig string, - clientHclConfig string, ) (*libcluster.Cluster, *libcluster.BuildContext, *api.Client) { var ( cluster *libcluster.Cluster @@ -247,10 +238,6 @@ func NewClusterWithConfig( serverConf.Cmd = append(serverConf.Cmd, config.Cmd) } - if serverHclConfig != "" { - serverConf.MutatebyAgentConfig(serverHclConfig) - } - if config.ExposedPorts != nil { cluster, err = libcluster.New(t, []libcluster.Config{*serverConf}, config.ExposedPorts...) } else { @@ -274,9 +261,6 @@ func NewClusterWithConfig( RetryJoin(retryJoin...) clientConf := configbuiilder.ToAgentConfig(t) t.Logf("%s client config: \n%s", opts.Datacenter, clientConf.JSON) - if clientHclConfig != "" { - clientConf.MutatebyAgentConfig(clientHclConfig) - } require.NoError(t, cluster.AddN(*clientConf, config.NumClients, true)) diff --git a/test/integration/consul-container/libs/topology/service_topology.go b/test/integration/consul-container/libs/topology/service_topology.go index be0af12cf086e..6aca247f296af 100644 --- a/test/integration/consul-container/libs/topology/service_topology.go +++ b/test/integration/consul-container/libs/topology/service_topology.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package topology @@ -7,16 +7,14 @@ import ( "fmt" "testing" - "github.com/stretchr/testify/require" - "github.com/hashicorp/consul/api" libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service" + "github.com/stretchr/testify/require" ) -// CreateServices -func CreateServices(t *testing.T, cluster *libcluster.Cluster, protocol string) (libservice.Service, libservice.Service) { +func CreateServices(t *testing.T, cluster *libcluster.Cluster) (libservice.Service, libservice.Service) { node := cluster.Agents[0] client := node.GetClient() @@ -24,7 +22,7 @@ func CreateServices(t *testing.T, cluster *libcluster.Cluster, protocol string) serviceDefault := &api.ServiceConfigEntry{ Kind: api.ServiceDefaults, Name: libservice.StaticServerServiceName, - Protocol: protocol, + Protocol: "http", } ok, _, err := client.ConfigEntries().Set(serviceDefault, nil) @@ -39,10 +37,6 @@ func CreateServices(t *testing.T, cluster *libcluster.Cluster, protocol string) GRPCPort: 8079, } - if protocol == "grpc" { - serviceOpts.RegisterGRPC = true - } - // Create a service and proxy instance _, serverConnectProxy, err := libservice.CreateAndRegisterStaticServerAndSidecar(node, serviceOpts) require.NoError(t, err) diff --git a/test/integration/consul-container/libs/utils/debug.go b/test/integration/consul-container/libs/utils/debug.go index fac44c4e2e002..146a7e4cacdd1 100644 --- a/test/integration/consul-container/libs/utils/debug.go +++ b/test/integration/consul-container/libs/utils/debug.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package utils diff --git a/test/integration/consul-container/libs/utils/defer.go b/test/integration/consul-container/libs/utils/defer.go index 85d913c7dba24..867de61972a98 100644 --- a/test/integration/consul-container/libs/utils/defer.go +++ b/test/integration/consul-container/libs/utils/defer.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package utils diff --git a/test/integration/consul-container/libs/utils/docker.go b/test/integration/consul-container/libs/utils/docker.go index b807cf66fae26..109205855cd5a 100644 --- a/test/integration/consul-container/libs/utils/docker.go +++ b/test/integration/consul-container/libs/utils/docker.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package utils @@ -9,9 +9,6 @@ import ( "io" "os" "os/exec" - "strings" - - "github.com/hashicorp/go-version" ) // DockerExec simply shell out to the docker CLI binary on your host. @@ -19,18 +16,6 @@ func DockerExec(args []string, stdout io.Writer) error { return cmdExec("docker", "docker", args, stdout, "") } -// DockerImageVersion retrieves the value of the org.opencontainers.image.version label from the specified image. -func DockerImageVersion(imageName string) (*version.Version, error) { - var b strings.Builder - err := cmdExec("docker", "docker", []string{"image", "inspect", "--format", `{{index .Config.Labels "org.opencontainers.image.version"}}`, imageName}, &b, "") - if err != nil { - return nil, err - } - output := b.String() - - return version.NewVersion(strings.TrimSpace(output)) -} - func cmdExec(name, binary string, args []string, stdout io.Writer, dir string) error { if binary == "" { panic("binary named " + name + " was not detected") diff --git a/test/integration/consul-container/libs/utils/helpers.go b/test/integration/consul-container/libs/utils/helpers.go index 7f08b27b9ffe8..5f75e3e4b3f7f 100644 --- a/test/integration/consul-container/libs/utils/helpers.go +++ b/test/integration/consul-container/libs/utils/helpers.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package utils diff --git a/test/integration/consul-container/libs/utils/retry.go b/test/integration/consul-container/libs/utils/retry.go index cfe5ade347cd7..651a195cf116f 100644 --- a/test/integration/consul-container/libs/utils/retry.go +++ b/test/integration/consul-container/libs/utils/retry.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package utils diff --git a/test/integration/consul-container/libs/utils/tenancy.go b/test/integration/consul-container/libs/utils/tenancy.go index 058f9cee0147a..c116a55a4c276 100644 --- a/test/integration/consul-container/libs/utils/tenancy.go +++ b/test/integration/consul-container/libs/utils/tenancy.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - package utils import "github.com/hashicorp/consul/api" @@ -25,11 +22,11 @@ func DefaultToEmpty(name string) string { return name } -// CompatQueryOpts cleans a QueryOptions so that Partition and Namespace fields -// are compatible with CE or ENT -// TODO: not sure why we can't do this server-side -func CompatQueryOpts(opts *api.QueryOptions) *api.QueryOptions { - opts.Partition = DefaultToEmpty(opts.Partition) - opts.Namespace = DefaultToEmpty(opts.Namespace) - return opts +// PartitionQueryOptions returns an *api.QueryOptions with the given partition +// field set only if the partition is non-default. This helps when writing +// tests for joint use in OSS and ENT. +func PartitionQueryOptions(partition string) *api.QueryOptions { + return &api.QueryOptions{ + Partition: DefaultToEmpty(partition), + } } diff --git a/test/integration/consul-container/libs/utils/utils.go b/test/integration/consul-container/libs/utils/utils.go index b3d8382ed45a7..7be336eb8d507 100644 --- a/test/integration/consul-container/libs/utils/utils.go +++ b/test/integration/consul-container/libs/utils/utils.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package utils diff --git a/test/integration/consul-container/libs/utils/version.go b/test/integration/consul-container/libs/utils/version.go index 24e66a8698145..bad097550278d 100644 --- a/test/integration/consul-container/libs/utils/version.go +++ b/test/integration/consul-container/libs/utils/version.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package utils @@ -7,7 +7,6 @@ import ( "flag" "strings" - "github.com/hashicorp/consul/testing/deployer/topology" "github.com/hashicorp/go-version" ) @@ -56,20 +55,6 @@ func GetLatestImageName() string { return LatestImageName } -func TargetImages() topology.Images { - img := DockerImage(targetImageName, TargetVersion) - - if IsEnterprise() { - return topology.Images{ - ConsulEnterprise: img, - } - } else { - return topology.Images{ - ConsulCE: img, - } - } -} - func IsEnterprise() bool { return isInEnterpriseRepo } func DockerImage(image, version string) string { diff --git a/test/integration/consul-container/libs/utils/version_ce.go b/test/integration/consul-container/libs/utils/version_ce.go index 2e5b1b3656b01..2232ed8eb4e17 100644 --- a/test/integration/consul-container/libs/utils/version_ce.go +++ b/test/integration/consul-container/libs/utils/version_ce.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !consulent // +build !consulent diff --git a/test/integration/consul-container/test/basic/connect_service_test.go b/test/integration/consul-container/test/basic/connect_service_test.go index ee045f1286d38..650db9fef0794 100644 --- a/test/integration/consul-container/test/basic/connect_service_test.go +++ b/test/integration/consul-container/test/basic/connect_service_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package basic @@ -7,8 +7,6 @@ import ( "fmt" "testing" - "github.com/stretchr/testify/require" - libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" "github.com/hashicorp/consul/test/integration/consul-container/libs/topology" @@ -39,7 +37,7 @@ func TestBasicConnectService(t *testing.T) { }, }) - _, clientService := topology.CreateServices(t, cluster, "http") + _, clientService := topology.CreateServices(t, cluster) _, port := clientService.GetAddr() _, adminPort := clientService.GetAdminAddr() @@ -50,54 +48,3 @@ func TestBasicConnectService(t *testing.T) { libassert.HTTPServiceEchoes(t, "localhost", port, "") libassert.AssertFortioName(t, fmt.Sprintf("http://localhost:%d", port), "static-server", "") } - -func TestConnectGRPCService_WithInputConfig(t *testing.T) { - serverHclConfig := ` -datacenter = "dc2" -data_dir = "/non-existent/conssul-data-dir" -node_name = "server-1" - -bind_addr = "0.0.0.0" -max_query_time = "800s" - ` - - clientHclConfig := ` -datacenter = "dc2" -data_dir = "/non-existent/conssul-data-dir" -node_name = "client-1" - -bind_addr = "0.0.0.0" -max_query_time = "900s" - ` - - cluster, _, _ := topology.NewClusterWithConfig(t, &topology.ClusterConfig{ - NumServers: 1, - NumClients: 1, - ApplyDefaultProxySettings: true, - BuildOpts: &libcluster.BuildOptions{ - Datacenter: "dc1", - InjectAutoEncryption: true, - InjectGossipEncryption: true, - AllowHTTPAnyway: true, - }, - }, - serverHclConfig, - clientHclConfig, - ) - - // Verify the provided server config is merged to agent config - serverConfig := cluster.Agents[0].GetConfig() - require.Contains(t, serverConfig.JSON, "\"max_query_time\":\"800s\"") - - clientConfig := cluster.Agents[1].GetConfig() - require.Contains(t, clientConfig.JSON, "\"max_query_time\":\"900s\"") - - _, clientService := topology.CreateServices(t, cluster, "grpc") - _, port := clientService.GetAddr() - _, adminPort := clientService.GetAdminAddr() - - libassert.AssertUpstreamEndpointStatus(t, adminPort, "static-server.default", "HEALTHY", 1) - libassert.GRPCPing(t, fmt.Sprintf("localhost:%d", port)) - - // time.Sleep(9999 * time.Second) -} diff --git a/test/integration/consul-container/test/catalog/catalog_test.go b/test/integration/consul-container/test/catalog/catalog_test.go deleted file mode 100644 index a2f4216c1c459..0000000000000 --- a/test/integration/consul-container/test/catalog/catalog_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package catalog - -import ( - "testing" - - "github.com/stretchr/testify/require" - - libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" - libtopology "github.com/hashicorp/consul/test/integration/consul-container/libs/topology" - - "github.com/hashicorp/consul/internal/catalog/catalogtest" - pbresource "github.com/hashicorp/consul/proto-public/pbresource" -) - -func TestCatalog(t *testing.T) { - t.Parallel() - - cluster, _, _ := libtopology.NewCluster(t, &libtopology.ClusterConfig{ - NumServers: 3, - BuildOpts: &libcluster.BuildOptions{Datacenter: "dc1"}, - Cmd: `-hcl=experiments=["resource-apis"]`, - }) - - followers, err := cluster.Followers() - require.NoError(t, err) - client := pbresource.NewResourceServiceClient(followers[0].GetGRPCConn()) - - t.Run("one-shot", func(t *testing.T) { - catalogtest.RunCatalogV1Alpha1IntegrationTest(t, client) - }) - - t.Run("lifecycle", func(t *testing.T) { - catalogtest.RunCatalogV1Alpha1LifecycleIntegrationTest(t, client) - }) -} diff --git a/test/integration/consul-container/test/consul_envoy_version/consul_envoy_version.go b/test/integration/consul-container/test/consul_envoy_version/consul_envoy_version.go index c37dfc8116640..72c4964ffbf4d 100644 --- a/test/integration/consul-container/test/consul_envoy_version/consul_envoy_version.go +++ b/test/integration/consul-container/test/consul_envoy_version/consul_envoy_version.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package main diff --git a/test/integration/consul-container/test/debugging.md b/test/integration/consul-container/test/debugging.md deleted file mode 100644 index 2957b520ac074..0000000000000 --- a/test/integration/consul-container/test/debugging.md +++ /dev/null @@ -1,78 +0,0 @@ -# Remote Debugging Integration Tests - -- [Introduction](#introduction) - - [How it works](#how-it-works) -- [Getting Started](#getting-started) - - [Prerequisites](#prerequisites) - - [Running Upgrade integration tests](#debugging-integration-tests) - - [Building images](#building-images) - - [Remote debugging using GoLand](#remote-debugging-using-goland) - - -## Introduction - -Remote debugging integration tests allows you to attach your debugger to the consul container and debug go code running on that container. - -### How it works -The `dev-docker-dbg` Make target will build consul docker container that has the following: -- [delve (dlv) debugger](https://github.com/go-delve/delve) installed. -- a port exposed on the container that allows a debugger from your development environment to connect and attach to the consul process and debug it remotely. -- logs out the host and port information so that you have the information needed to connect to the port. - -The integration tests have been modified to expose the `--debug` flag that will switch the test from using a `consul:local` image that can be built using `make dev-docker` to using the `consul-dbg:local` image that was built from `make dev-docker-dbg`. - -The test is run in debug mode with a breakpoint set to just after the cluster is created and you can retrieve the port information. From there, you can set up a remote debugging session that connects to this port. - -## Getting Started -### Prerequisites -To run/debug integration tests locally, the following tools are required on your machine: -- Install [Go](https://go.dev/) (the version should match that of our CI config's Go image). -- Install [`Makefile`](https://www.gnu.org/software/make/manual/make.html). -- Install [`Docker`](https://docs.docker.com/get-docker/) required to run tests locally. - -### Debugging integration tests -#### Building images -- Build a consul image with dlv installed and a port exposed that the debugger can attach to. - ``` - make dev-docker-dbg - ``` -- Build a consul-envoy container image from the consul root directory that is required for testing but not for debugging. - ``` - docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=consul:local --build-arg ENVOY_VERSION=1.24.6 -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - ``` - -#### Remote debugging using GoLand -(For additional information, see [GoLand's documentation on remote debugging](https://www.jetbrains.com/help/go/attach-to-running-go-processes-with-debugger.html#attach-to-a-process-on-a-remote-machine).) -##### Set up the Debug Configuration for your test -- Create the configuration for debugging the test. (You may have to debug the test once so GoLand creates the configuration for you.) -- Go to `Run > Edit Configurations` and select the appropriate configuration. -- Add `--debug` to `Program arguments` and click OK. - - isolated -##### Obtain the debug port of your container -(This is required every time a test is debugged.) - -- Put a breakpoint in the test that you are running right after the cluster has been created. This should be on the line after the call to `topology.NewCluster()`. -- Debug the test and wait for the debug session to stop on the breakpoint in the test. -- In the Debug window, search for `debug info` on the Console tab and note the host and port. - - isolated -- Go to `Run > Edit Configurations` and add a `Go Remote` configuration with the host and port that your test has exposed. Click OK. - - isolated -- Debug the configuration that you just created. Verify that it shows as connected in the `Debugger` of this configuration in the `Debug` window. - - isolated -##### Debug the consul backend -- Set an appropriate breakpoint in the backend code of the endpoint that your test will call and that you wish to debug. -- Go to the test debugging tab for the integration test in the `Debug` window and `Resume Program`. - - isolated -- The remote debugging session should stop on the breakpoint, and you can freely debug the code path. - - isolated - -#### Remote debugging using VSCode -(For additional information, see [VSCode's documentation on remote debugging](https://github.com/golang/vscode-go/blob/master/docs/debugging.md#remote-debugging).) - -[comment]: <> (TODO: Openly looking for someone to add VSCode specific instructions.) diff --git a/test/integration/consul-container/test/envoy_extensions/ext_authz_test.go b/test/integration/consul-container/test/envoy_extensions/ext_authz_test.go index cf00105345fa4..3c43cdbdbd039 100644 --- a/test/integration/consul-container/test/envoy_extensions/ext_authz_test.go +++ b/test/integration/consul-container/test/envoy_extensions/ext_authz_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package envoyextensions diff --git a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/Dockerfile b/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/Dockerfile deleted file mode 100644 index 31e2dd93d0428..0000000000000 --- a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - -FROM tinygo/tinygo:sha-598cb1e4ddce53d85600a1b7724ed39eea80e119 -COPY ./build.sh / -ENTRYPOINT ["/build.sh"] diff --git a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/README.md b/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/README.md deleted file mode 100644 index 173e27bf3709e..0000000000000 --- a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Building WASM test files - -We have seen some issues with building the wasm test files on the build runners for the integration test. Currently, -the theory is that there may be some differences in the clang toolchain on different runners which cause panics in -tinygo if the job is scheduled on particular runners but not others. - -In order to get around this, we are just building the wasm test file and checking it into the repo. - -To build the wasm test file, - -```bash -~/consul/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files -> docker run -v ./:/wasm --rm $(docker build -q .) -``` \ No newline at end of file diff --git a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/build.sh b/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/build.sh deleted file mode 100755 index 6affddf298eb1..0000000000000 --- a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/build.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - -cd /wasm -tinygo build -o /wasm/wasm_add_header.wasm -scheduler=none -target=wasi /wasm/wasm_add_header.go \ No newline at end of file diff --git a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.mod b/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.mod deleted file mode 100644 index 703b71414fae0..0000000000000 --- a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module main - -go 1.20 - -require github.com/tetratelabs/proxy-wasm-go-sdk v0.21.0 diff --git a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.sum b/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.sum deleted file mode 100644 index e09133fbccbf5..0000000000000 --- a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.sum +++ /dev/null @@ -1,6 +0,0 @@ -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/tetratelabs/proxy-wasm-go-sdk v0.21.0 h1:sxuh1wxy/zz4vXwMEC+ESVpwJmej1f22eYsrJlgVn7c= -github.com/tetratelabs/proxy-wasm-go-sdk v0.21.0/go.mod h1:jqQTUvJBI6WJ+sVCZON3A4GwmUfBDuiNnZ4kuxsvLCo= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/nginx.conf b/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/nginx.conf deleted file mode 100644 index 06533f75ac1a7..0000000000000 --- a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/nginx.conf +++ /dev/null @@ -1,13 +0,0 @@ -server { - # send wasm files as download rather than render as html - location ~ ^.*/(?P[^/]+\.(wasm))$ { - root /www/downloads; - - add_header Content-disposition 'attachment; filename="$request_basename"'; - types { - application/octet-stream .wasm; - } - default_type application/octet-stream; - } -} - diff --git a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/wasm_add_header.go b/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/wasm_add_header.go deleted file mode 100644 index 91aeae6956764..0000000000000 --- a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/wasm_add_header.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package main - -import ( - "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm" - "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types" -) - -func main() { - proxywasm.SetVMContext(&vmContext{}) -} - -type vmContext struct { - // Embed the default VM context here, - // so that we don't need to reimplement all the methods. - types.DefaultVMContext -} - -func (*vmContext) NewPluginContext(contextID uint32) types.PluginContext { - return &pluginContext{} -} - -type pluginContext struct { - // Embed the default plugin context here, - // so that we don't need to reimplement all the methods. - types.DefaultPluginContext -} - -func (p *pluginContext) NewHttpContext(contextID uint32) types.HttpContext { - return &httpHeaders{} -} - -type httpHeaders struct { - // Embed the default http context here, - // so that we don't need to reimplement all the methods. - types.DefaultHttpContext -} - -func (ctx *httpHeaders) OnHttpResponseHeaders(int, bool) types.Action { - proxywasm.LogDebug("adding header: x-test:true") - - err := proxywasm.AddHttpResponseHeader("x-test", "true") - if err != nil { - proxywasm.LogCriticalf("failed to add test header to response: %v", err) - } - - return types.ActionContinue -} diff --git a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/wasm_add_header.wasm b/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/wasm_add_header.wasm deleted file mode 100755 index 520e7e144ada5b0bc7dc9e1860e1908d88f76add..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 400008 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

`iwmH7Z&?GiIK^# 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⁣Ay^S9AP4qh8s0d22j<^l|2SS9D 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�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ⅈEjV0(FKLGSzUqk&JI&&KHpE5?nU4_afDD6g#nM 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%0Ach*bYFfd=TYiDbCREgW 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

|jfkj2@UgR) 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 z z%An}_?fTaFWHXoa<34o0?kLYrfV=A%Pwph`yY?oSD%jZKE zz)s&G!o_@8K5(T@PaaGEZqLC#<@$>_V~dl2?u7VRrFM=`e%*KNkWDWxN$kD~q0jbX zFZ0`csC6TvI$DS*l6kT492r`_iGz=>GXWL@Q|Z0&TibeAcL^;0Y!4P!*WA77)NAh| z+@E+`xTsr9a_489OtmBZ*O>%iKPk^)AFpEk2^5?I_{$`s-<}viFT~J763)Z$)i(M9 zyl4a%a^@ZJ@d&m<(DOgdh7?*H7RAOyNcn*m%N*$m1$ky04_9$eLBXfO=WDhHb_aXD z?&cPPbFI+nDF}b>07lWUtLaCt}91{b7K|e(echTnZgI! zDmLt_%UQPOCvYGV)@P=R4Kvqx{d?~Cb(u8J@b%3FPiPV`oPBKPF}a+KV{Gy5E#;X! zwpg*?Y?lQsz-5|2sq2I52F24YN{72Jt7efr_xyyHd3x(@P;NA~8mez2lIqxFm0Vl{k$4<|*`I7KG1y!Hut)l# zFFu2A5wMJjba5auBK6^bZ;J@8%IPtF;t9CV#7Pk)E-P&d44_r9&~>Sd&}sh*dQ*8v zv5svO!eKI15eP~>Et}e9rrJ!gXQwKq$JH?JH~sRPRkRBGY`R`!3JE}lBw9fKGyDFb ze2W0fh)ixpT8m^IYF@Ro185U|in%M__x>%Tx`^4p+kASLfboE(B4=bExAXqFmYNc) zmblcpz$ZsJ6Sud_PpI|~XRQ`^-2A^UAebj%qV@;E@UUJbTVJUo9t?|bY2B2)-e-B@ z*cg^&3?1-VM=qDP5!xW%x<$dvw0_#L6Iwj9*Vhv|O5o@d$;qX2beUH?52*e`Eo&Fm z9CxmUuI@CSt5}$fnI8rS%Uo{!DsrR#y!laDxD+;wpJ_TZ;Y_PhEI0`avjrpvTa!I+ z3NiZuBh9c+%xu-TZqozy0PSBIs`;uCJL$CBM8a*~x8t~)Ir993iV5i9wrk)1tqUx7 z`k5fT!hz?s5Z{W?^4?Ml{xTlUa94!}AFqujg!7Hv1G~w5oseNRCWiTAEML)5%_KUg zY$sB$ttOHe%awAYvRWNKQ?=wB=wnbV)bC+2R7?oV)jExMY?CgJ#-$3eCeDtz=kef& zGY-W>tucBO<`z*6un+#C^q3mJ1qr(tC}voS$UA-Peq>|>-$jbC2d!%H%QvR$2GKtD zlLyGrTwl|rtvy}TTuak7vcYG2a}7nlp$XqGK}WAe5@yM%P9EbR`%?W19T0pPTdU)a zUe}MBFs$VUsXciBc`~>iUI#?1;?DpR7vnmE*_)5OTwk^y$K73xXx|$QA!MMVSDM6L zKISR3IU>=xZ;_^5;mR_3p!NpE^8oNCOpm0+-jIcaFpwAN_atV$9tO8-*<>nI6795PA}#|?9>6OH*(#kXUqvvj5bkDKP577SBTpW zcIEd-)5}}*Cygl$eoyT&S-do*uTg{yiZVf@v}8Z|frDGMM@=K*yk{dQR^k9yO&8$G zS}~~Kmq+-ef0CNc!>|t78af!rExPsOs;e}K>LRi71<};}5L0f0c0!A3q0&=f%jmf>?m zPfHC`HZ;#t(4cm$3}BVf1dx&_ngRneL3zpOkBX~9 zimC&UBHL+1Ka<9j`3d(a4PC_`@@oV9;;iY4#)bfN$s--_uq@f z4Jvr6h)5ZPs!R@BVyV7;iv#1*>iUG5Pd{kxCl zpHC+}NKuuO3rdu7QS+@HXmPyNwoou?-<1z3C<(lK{P+nNNtRKMt{^nD&ek!1{_(Eh z*telKeqAH2RU6SO(XG{!Gt2R#`VE;DtrU49Pe)J@e^0YXaI0K~{8VA_**N9)v>-hc zwOgG2b$DrXHMQF{3J(c3+RVrAX&mhrb`<_PrxfV09cyj`UmF0afQ;Y{f+bPZ=WDpSKk&N%n zQZZYt-cRqx1m9lzz~)y~z0kTo`OcNF0c(sFt9ka~yPj!hH}-oN!_1|PqLhLhCnLR@ zPz9D4_dD~tbJ^i1Pn}8-VCt(<^~LoJ3CL6n{L3Q^U48#aK)`iw465g{SaeBO4=*n- zuWru#+SeRO<9E9yz+5{2tObMmx132uT2)_HQ#*icR~)V&jbCE>>GR;lfo&SQR$b>AZa+%gW!U={8GzK6@OXHM&x@=f zeYV;anHGTZg zuNJiI{evEg|BW8r1cEYb%T-&^9n(As`(}3ib-(aoV#4BX!l5xw3UVX=9*c|(Q8&|6 z-8fTVUh8E*2+29qC|wI7=0C%(_bnGaB0SEEbXd+dZ^1z))_mxm4>5M15rcUzv2QlvmWBuPWSdE=Td%w-6!o6x&tAp2mJHS@gx*JmeDoUP8Ya>R(Uojnu(g!+ zSL8cY-qqgBGEo>Dv9v6)By4ABu2|meQZ!KbL^U6|G@EieK$qz5qtKcpZ7Hjl{D0EN zEoC$=^Vjs}U8AjbBNR3^i&hg`J5_0D0=%ApI;I5lWxwj4FD^p?qrds#?Nd@lbi9xBE-Z~5cP8(g%-4) zl3R2Q_1gDI0BNA?l761td7ACT1!`r4r!6`=&dfD2q3?dZ(>{}`%7WZrtE0&UNp_=p zM2~6b)6(P6%A$UNKwo4IjHSM{5J-g4dJF6f8SJP!j7aCjyhKinvOoF-v$Q1JIV6<% z>Mcm^rS%^;-wQM%EV|CWfAT>uyI1s%zBH?s<6%A1s>qr&mxq@Rw>QJNKbj>Ka+vM! z@$m~eI1omiXLxt>bK zwr1A6HsK9juUI8LN`r&RM<{6}$pnq)?a`PulH6YF=s?UiqP+-cR8oYzi zaKVm3bDy1M5^r59fbOO)2-UjqemKYc#mD|@MufDYleo`BEOubSNYRUg9Om=NlNn+`} z$rB$>c$y7}YFo;z_$n96PNZhpQ8hlHdeH-jsl2z$(p}5D$yfbou5gXRxU<{nZmK8e zFPA0I3}1R+A?F2gjsJM#KUx6Hu~)k!`QOj1lsf@QCH2u!YVY~wG~5!Pl3NKG74Vd{ zSNN*I*Owvz>My1W894EJKRAHRYlwk=wk_#h8AR5}+g^4nR@lDtn?s-wz)KSaM;yZ9 zgbj+U@b_zZJ}Ec29C>hpx=t!k*ZGG1Dzg0EHG8eCFJsT8oyhOBRJP@v>WRrm*(95w(ddStnXpCSi}?N?Iz3Z z&E@Ody_>%f-;PtSq%S>M)md0^y#NRqDj8UFa_31o*O{h8Lyq;XM$4vVWNmXNvROa# zh8gMW^RxiN+a|axvI9e|wS{45!&lnY49%hVlrq{nTN3^=YlGQ1Or5-iWQ&K3MkQHQ z)~i-xGII`}rGp#&i8$7w-JD;H}iC3PA7zHZsOt2(rp8px5lRD zaj+%>(PsSxdopN?lra0>pskebQ-i7+_UP;p#EXZ4r;}wie`B^}_uR~YXt!NM$-FOR z*4uvl-G5o+Tk+ew^+h%-Z@uBd4^-!;AuC`+eD;oc*Z<_ z^T3_6&X~?mCV{06Fg~{i5whKw;HRAA6^f?ULzjzH;cj5)D(((o2b!<6rHB~e;w3(> z-^y)*>U$TuyrI!vZ7+YwLjj?@$oL12x(qp52g()KKX*G-s}|l%rRDKH$Gl%bhI2w$ zrEe5qLeET=CtMgNg@so&>k9@ijoL~AD9=7A${Ykww4{$`JrN7Z&tfVrf@5azo;7!KSAsD zl+*|33fn(CCF#~?zqo{}F3oWfKh;^iF}g zleXGUILrSAaHBy6{cBaSeO;-2uhm0fds}PvdblfDrLNRzDn;rS#6dyzF>i|hn&%Dp zS7w%sY{-02Z*tOLnr5%QQ=9S`H+9+;0}9B@2%!SiZ&NDeG?sXl0WHq~n*u&_$HMc|GY2cUbGkb? zvtg5eM|tJ{z;TD!FFI_x51-U5Vs0@n3_r^x(0X!a>%t2J!J&Zr+wv#E%NnCyTzto; z!DDU@@rY(vSK-0B1UkARopL58h~90LXsNM)?QAX$_{SoK%I~0b#j7z!8g+@^*z^W1 zYgGPn;)zHyJQ+r@8lS)i{YN#s*H=l8qJ{U+fv8jIxr#)d7kk(Y#<+&!>(KF|gBn@n zpoYb-yg{i=ub!Rs&&;?VvH`N@GNjx5dk<5_D=W1U4E!WxcuT-Q2S|_l8hlYT_@^rH zU_Ie2(@>|x)b_B>%es+(l_lHxo)z{A=W&0mJ+@=~Tt$tB=@k`&2oxqpvHCOdENKPDp)J*mvXhN*UMF54c|mkVP!<)}Rh0L6{;n0F zi50fBR$lmUXz4ZS;PcM{HpSKJVH3BMh zabZofv!_5+qjV{bP!#;e-DL7IbJ|F1TWp<#ut264C#YIU>mFYIwb;#4=J?&ybJpg# zH7hq-VR{5RxiHVrCavww$g68b*=|WP9`X{RVJ6@4GC%)|qTO|U^_}c`_xjPq1l7uk zU-ePCPqT16m}aSX)Odsp&Y}vIY<>;??n)6I+9bu|LM(q0lX!`_-j9WAfU$Nly^H8V z{LB@$>(Kw$Ef~tEOStLxjTf9Tl|cjTs+#&)P*qRIQEt_mgjx5#lbxrt9vVBF{^M9T zFsl2~IgPrV*=r%=sRtxydb3G4({6y^3J$EYPq7$jPd(bzvCj@8K%=22@DX+;dO*GCoJsP@E;`z@$ z$Q?s-mR7$;(MZmP_W+ZK{jTACF0I0sX|z=DZqXg1rqMtIoL(CLNcMn>MUy~;_L|!g zywr4}zcZtyY!TCpf;5`aUF(F9kNheRT>f4O5ku#?@$&(f&I(JG*&$V9l=vHQ?4!ox z46@eGy1OSmn3)fToiX=PhbjfP zCis&f31az?i4_}4&$7!sQz|`eUi{g`ukFy_V zTc3r!XnxK9Cbw>8KWjEYr49~tZTZ{my5ml0;MCZG^h~1vDW^znFO*Jndr`tcZ@xlv z{VHvYUd`T|dlES|H|9^b_GrZ{#c!lVGUL?;Pxtes%?U2eB@31Yx`u@A%WYrJ{Iy^i zCPR24)mt7tB3xhz;uy0%Ayc}#_jBf7U`b@Y=VV;M|9nf3|5of5_SkYEM25zDzG5g_ zhc*jZoSb!IS^`7M+{Y74yAt_Y&knc`&h3o*FH~*mDmP}(C{u^tDXPwH^67;GDWQtV zR_8F(NR@p8Rx%BxBXWzhn{UBMdJgC*_m|msdjldwOlbTJ>dR;<%ygR-7AA2t-ek6) zTvzO~aoKsO4fo-$=HOvJ08jf~oe7>C{AxMf|FyjTXdC8>Kg6%zdzUR&Av7Z9Ar?ltN-TyAGiZk zWSJLLgS8GwjLjBMY}r=Md}>_E>Z`Wp>H`kMsi8QXBKvy%I3Z+&u>GI{sC2A##{|Er zBrs&hbmu&(d0X#j)}MncE{Anx>*k=p=vC zYoNM{-Yyy(+GR_{MLLWw^(M*M7x{~LJXxM2;M=TuMN?ctvVVx!8Oqi_p72so+AK># z%YC>J`dWuL27pZ12Wp6(-f4w5sHn;8t38W($!>|WcqBpl#c-GQ8zQ0ZOaI2VpY5TW zgcnf$P4ofTT;LXW*ll?#?_C&>t z-qvh*?g{=B9Ag(bq4-9Od1tYP?U_%Ql*|(0Rb? z7L%)AoHgO0vAZ(xN#S{&%({1gae_VZ#M?OGdR-RD@<7biTvy9_oRnk9;$HfYNou~h zRHm0AS+OIP#|;wtCBbJ_uGq2fM35{m(HM6{tjV*>XVX#7BOkzt=`KJ!W@C7-04OP3 z{1kko)pRXfo{VQa_{>Ac?aeOAnTI}bXU|G+`+7?Ef+VMSz1az`C$(KaHow*( zS6~wNZ|wM%^3L5c31cjd1NZP^25hC`^-wG_#s(|UI&|ttdu5FtWUR?i1|TVwN)3hS zoyzA-_A}xu5WCy6x2=OsxoL*B9cysmxZ)0UQQU1e<*_n2J7@aJ_3qLNn&X}nGw}dc z0(bwBPXd{BbMmerJIRKhbNtbMc8;*Pwp!Cow#k&`li0n@ip{JeIf2Jr7p{%zHT}^3+^k54 z1!Y5qucKey?JgphlN7@>R6$EQc7u_<1?jIrDUyE1_s=d|uPQsV+}4?7{E*P4H66cl zGS+@YcMlU1ggTV*lMz4KF1ZR4^?!NC`RMg2QWOBsS!J`#EX@>6V!L&#VL4G6tlpNm z-RHT)X+=yuvRi5HyFr90rvSx_@gw;IkHjEUpfo~;@94)2{QDSjVCAAjEC{Y|yY0Ip znJQcXF|Kxj*+WkwMdG?-+5Sx)U};vO7szG3WW5x;G?1TRHxWaqb(36N4(T4|@2(bm z?KDz(SLl2=cl0b?s{qecQ4TtIeannrwBjXZ!{=8)>Y~1=#S(Bpjm&GN^)fG;Wm@}kzCq&r6RI0+Ltw_=hwxup`UBb} zO^F<}t9)Ycdvp{cFmsJ$3dQ4%jNA*L6=$mfz9-&~?d)Gi4s<#C_ux3qx4j$sTzu~) z9X3MJ>ozU;pUyl0z~MXdXY>PLU|!QUBN>hYq{5$tvBw{G214!b2GVSKO)FZP$Q zjbM5u6_Mr^+0h?=Om|J?^;IN!?%Ke>New!mJn~KDuFV79B$yg11N|r@5)`u0|>yILm%?u4=x0c#XoFK-!Gi@n6pwWVm@~qz=_$olo z(51416%bwsP@reX+pqs%ISBtNjulK%FjV2%{Nn={xZ8%O&(3jzKAcJeI=h%1X0J;q z(3(=oT{p^obwoXsSvDqjk&Z1@PrZ)}mus71E+UgzQ@bvg!RL(utgcz_ z8S)P-lqew5#sYR*_84fdR}Q4W)4?1mkIePxX(Y)+N6g;rFNUEk>J*iLbPs606%Lv& ziYxTGN&gy6Q&=AvHH+W`6rYb%BAGBhVsni_|JxMO9)~`D{8-R=>^v9fC+<(^R*RDj z%=aU(m5Dn1d?rO&Ix-) zUG>el%QmK0<;iT@llz=W@-o-3pF0XfI45`MAyCtg1!j@bRbKUyGg;SfBYhc&ty+yq zk_Bpsx9`O8nJi@4M-1jsfoC?lCj#5}uW~xDaAThTi5X}`{cDi9azU5P%N%uzZ=-nQ zikmVYtTxAsRUj*p**GJ3l zH%Q)65$X-Ez_bTNg7^3{nLKT>OdgpA1oaJ{7RV}yGi~N_BLRMyCr_SK0&Nh;)9%FD z4BA4)Z-a)XN_8*7666fEw8Bj*-5-EGjd)@L6xy8Hx|n8m=bKeERJg&VWhi=sP~8GIZpcIJhVD_* z@mj_AWCisGvxde1r8Ir|dOy(mSGUj}l(NI3KCGU7S0lE+d^;xb9MA{?RTwwn{9J*W zB0_J0;3udUG>H&O6AsiUH72xZCy=YWyLk-QBt|->SKdkO0{wx--aT$kO(spUkmh*) zT8DO~vw%<(dKB+=HDcdrb*Ri}dud?BT?(Kd@G(3Ri_{n~<;mM=OsIK(FDmOA*+*zG zDsHY2%3v4VD9k0o;u0kjehL=a?r*Yt`1eSyd(wCljq)B;;nFl&CkV@MWbxNU9B$6$ zUseif(I9dJtP9BA5?*p)fyVlUkb)8i_MP5bc5nsg0HR;)GklqA46R9h_N;Dn#X=Kk zW55?D2#axp|N8BO)61 z-$X>SjfY#_!2i35=s*7v5d~rw?df8ox%+0onjY`kHXm8=}ku10g!AEZ~SpROeAMIHLO09{c7rjbX^Jdo~25T#DD39w*1x${d;wD@ic-| zA>B_I0`xV1KD?FX`^x0{7#*Pf)RJy<+@WN4AK2=xJV_dAqLi!_kXxz1r0@P!AEwX* zQVG+&)1VCVy>H`pN=7NJZhL7q20fVEKJhm+)qhYBxY^xi2VmKXytnDgplS)Wy0R?j zH*k+~wkVpBX%Mg$OQ4_PwnQducyUR9!Hw&(h*Dh5hlg`?dD#UkcFL-6Zr^ zv%f#`P|deh{LAE-iU%xZTE6sc{H6k8R^cjO0u#1Dl&9fSs$$D_ws~NbNX(!YkPnEcTMXAhTuW;<`CU?z zb2~Q9b$Ww6!);j-L(lUe`N26Z-SSMU=42hR<2HD(Yr+>MepmbIT2qX4u&=ep^!7)u z*x7>FZJ@)j(b<830R&*%BG$3D&3$}Ny!f7#i%6j0v*(RZ#5<=jDKYUlvd|rVX~(dN zNMBFLog_+sR6C`^u7M~pEK&k|@qNVWeN*Xz2zw{5#>j&Arn+uxYoC!DJ1!N0RmPVu8C6>Rt9Mn`1sjDrLQ7Fk!z`q>7fV(JET4x=zBa zl5mKAlog-q4SA(kOCPN`FBI*!ick8HMkIGyhvNK#1$GF8xsg>@+^iq2&CTgxEg-S8 zdou3>vu|@`b`4^v{CXZ^z=iz8YBS=_RinUpYM^>bQmYAL3GY$sA#Iry;yW%%hGD*RAX9bqzNn{ZVc*3R{Z;CH*d!U`J z!soRz^iDlNv7beuP@bCDn?B~Z z*y2(eF6XNQmDKsk;HG@mvRM1*obE`mkvyjSM2|=FPZ$IPd)U^?5|LRA3U28Q&EHg1 z(_4)47MMm+hm~xd-)Y}DCWzf`^(mfQ{qd5fvnz8{`_vn#JLzYF*kLs6jSLF>FNyrY zQJ2rNk!gmF8yxqhZ#g4ozaoNRUtR{dZmm)Ds%ls64Q^OO4{X@He(&77y}GX)(z(gK zq}^efLxfUg2yV|pOm6GUv?k8EOQ$T5G#7;<&xSpJ?zcq0I#iMOM96L)Yjg)5Oo86mQ_Z#3^AInDd`x^6Ud9euBVH8jnx(iy3MGG z`)<9|VbG+6RO@PiuFCwVf<5*;ljlvK@9t!lO;oGNiP}*Lh%_lm#H6RcGf?HpGb-I< zTyLm-*#wtK`hjIj4mQQFh-hLwU-~mull@#vCJG>%tQM*qL zn{anXa z%dQTj$E=WAmP}Zux&5!P8X#`1gW8{rmTI_WoQ!G`M-tW9;k}&~Y}!Jv=J~iO3gi`3 zl#)0cnH>*FO)&9-B@f0C-L{&v&|t&kVYPi?-GPRfld0GakWxjTneB$?s{ODV zUVy0Yl2^xhl8`@@w?h3;w?glSKt|tJveGMg2gHC$V+N7(;O;4<8p@FUp_T}A{ZDPW zGLzeWDrq}?XUfZ(2M;+pGtvF^PIYx}~;*_ni(% zi1PdZZWB@EOnH%D8fI!QeCMlspeyx0aXWI0n@I??b2P&6JH$z7PN%w#Ts?LG(k7xy z`?kSqERu#`c7ts@&YXIqly^FhO$iT8$57oQ#Z41i9usdFt?*^_U+ZGxPn0%_X-RN0 zb0vo6CQ7@1M08y*$eMi7Ks$;MCa`H9WC~L+^ZF!1Y(fdH;bt=S54Wp#*Wfl&%e1oZ zUbFU!hW(OTwOr(I%SEN-=;q-raY0*|4l}K#7`t+k`n`~f%oFia*6%Inn=in48aPX@ zCWJ@P9Jo7n*4kc%@LWnmk@h^7sp(u9A1-vW`ku}?%o1f+j&E_{2eY31^m`8am|LvY z@OJ`_-tY-#!X>`lcwJ&iGS%=f4yk%NbF3d?SD{v2f$JPe@oG{NN$94cJMBLFae%UC ze;fYu!deGGp&L6pMr9ZGV=0|W*8eas?sJQ=OtDsbgmy+dJi_o4t%p|j-8aUeqaod% znxmB|<~eI0CN}_tr}xmM+Cl%9*y<%L=Hl={2WC*3@Tp3sIBY#+(V+3?IMU-meGEVH z^t{-k7t|aaF*=-@N{jdPn0vQEA=J@-I%Ibv`?91@b=xB z;{!cHqd{}G#tyWqe_qGX;r8IF%D2~tk)WA6@X?p?9iahPhI)_A9Sfwyf@T3XljIjO ziAktr|J78xjR5r3^xd4AM2HY)m@8Jr>N8)?L#yef4;PsqULC0^zBvTz{!o)QrgRUs zG@Xa!5&j5A5f>*;Etb@;T9Kt!I{}{aY^2SOOWMAZEWO$kSrg=6Z2jE96w_2`g=1}t z(DOZ)Y-LTBUM)jFn-eiLlfcVLvuqx4B`l0;?DW|8XuOW`#wT`Ch)JJ`A6Y^c+LOEl z%e^SwMh+}!r{^|DPGg(0oMWL+v=E~RZJ`I}sAVrk2beQY0U3j2Q1zw!A~UXW%Q}#g zd29ZPu>s!76L0Fazg9+jpjRATYO9TRsoH12oy2~$%ZIDw80WmQt;b1MrFmss4iyEo z;rpJAZ^f|IEtej&QjKg@zfx26?&GgjV)hBRI}i%L?JZ?-*ENIwGT76>(ICh^I>lmV zs|zlnCGI`Mw8{8GD5f-b70a|39Btnqd3a_qRfLB=2c{D|pN*ffCt;a6dp2(n^Ne9j zqdGH4$AE-jn!Ovt1H!IA(Nd_w@-Se@@Q{_ZtEOQ!SfK6byMZN5?mZ9>7>%(hkq|J* ze`q_3OEoq49MxuwiFkwJH%5IVBpKs9y8~51L5awl}8<; zR(eV`k-Cz}@WbDzPAGFFQ0=Z#rmU@`W#Y{0OhcWSZBr>8pu_WRd%2q}{KzhL-^HMP zt7B%Ir|I3MHnS}80h?vgQ{Uvj=^mRa+gcn@!B>_vSALuK`zcM zyOGdexCC>5xn4+po$sfAk>z(`V`otM=0fognrimI#|B$`f+YyWdR`A=xqVIh zhFa*u3XjE@c;$j*CRty@6w!o&<^?5U zRIuLTxx#sLGGo(?5~F9Hr|D%BhIjQg(>HCsx~axkNnpLH32$RZ@h77=L}Z;yIz2Kh z3oJHFon_nx27?SxxSP}cv#vSQ%81*iUYRcTJWjrJhYP5vhS*~f{DUON{*Ok2UiS^p z{~$n-OOC8_M)>b%cMA@al0P}8w))2HUL9XH%^*5hv1Sr4jyF6WjV;-8=wcS?~Xp%?dgt9?i&=Xm(!Ynvm+ zjxH3FyT$=>A+(@R4{y7T2cXO6(dIQ2*7NzmifjPg&2m*A5CcHxOSCG=$yzi`)X}&Z z#7$G(Ys8-CQH-qu>4pAx?g{BF=BdY-cR0rg(bS^&a(V~XSpm=Q+R6tu;e*bvsy2v; zbXUoYbBV3-u#Q0eE=OKfc7K9OtR)amVGhVz3xGB5-4i7%rQSy||58fzNrBwTliU$2 z1pw#WE?1vcS9cJzAAG6tX7Ob{u}@%P-H_u zj($}x;y5(sn~wdF%VnqKOwW1ene0DTW03rMv;M1i4x7saThUGib4P}1 zX1(k7nS-+-SZ(avu3T2`SCMQUQWNBU9xE+e74GASiF=df)JAlXxth|8m)@>(7*2AH zi9GB&>$9}ZIn|OS+a>s#RWf<8veOuU5N&`zo-PIsHE?|C3WdYo0p|yZqAIXBV3DM< zEt}D=QgsPlf~UF_bxF0AZ3*zN_iF8fT-zyls<$3B6QlEHhA;@`t%VrsD4bKQC>3P_a<=?}*ClL83CpLDI|NzRnL9zf&Gt{ia>IF>i(yWfi79N>C=8Ay_+ z>ps!LJbT@{K;+njU9J5r&^AlcRK%>NEXOf*AjiDj96O16f==G%m}yf@qL6S$5fb5Z zfHr8k>26YEjJq||@j{w11jU)sI*ti4$QY?(SIoz{E)U3RV^j>sz7v=UF0_Q9j4n6A zjALz%Tgu-N(r}gv;tpMwIf2iu0K@u#>Wo4uZLa7getngzrArPp27%({)*37@Ggp6u ze0|LkZ!z9y)3&d^XSR-YXYKq2OIF+uEl^HsDv(T`Ues9eho~%+%&Utq_U64VtOUMe zbP?hiU$D62o|aLu>#Ls~=0uAJ^TohiS0b_0F{ys!H@mG`xy8T^9FK6;z&_rmzNNIi z0p^4B-7fMV0!Z(CG<7L=?J~LNklZ=%=O-zf%?S0Y6p&#|7|dTSTd#m$-0gG%J5_4O zC}_DFVIDZl)0wUjt&^dtFx_)2y7aW1!x?YBWJ$ft__&2_GnE)WRXfqY5*(Y&$X9jK zv}#A?IOn+a=?=O<_$60^u)*M*NU)C2GD)lAy`zor>F)aR-T8Cd?^4tG-@T8@+Pl1F zcWFSGnx4-wSp+e2a##BlxL4t>QxT!nFLGQG8ca7t$GS7o*;R&y!>Per;e4a{9(e;y zvw@!qnf5%wbZYuYc%7i8Y+mxIu;ad+2s}JPw>hr8-t62Kd2pjxb4kd-JDmq zff%SYo#&eX;9=iGx4HY+f9Kz?8X^w+a%~d*h$U|s26RLbhL+pQthh2r_T(?g-#ga36v&%(S5rcXh7GH6uKq z#Ez`PZNA1QEp~j{>`0rT)M#s`OzCo9E2yTsyjS_}m0E@fRQy-ORK|P^X4{^R`uc{| zoZMLHsc%_yWDTpA?>0P%q{;$&=m;#}t+(2Fk_540L7;&uUx~5jHQ+yl=~?2MYs?;S z8`xjNbP0x5c?Ce~NM0hd)jpg#AAvXPk#dkM3@??6xcw-;2|b;cOM%{4N2PeaPUhoFq3$$#EK!Yx4W@UK>&1y>O7)X} z5fYT6Ig+^ipwH{K48@95vwT_FHqz#t4PP#VJ$v=V+LGj%M6DV66C%X`JX+efDk<|D z;4%-#-Aq?~L}0{}z5J3``S!Q_3L{Ye$?g3~nS8_8)vC6Q(P;uOHuBKPVIh{(efifO zLZ+C$|AW7sbA7F&1M zlBq=OmHzan=DzwOq|0C+J;0Hc3mQ04@2{738PVjR*oMK&-;-|t^H@rm32 z4>$22RbeR3;d_egap?2cQCb%0{B#`pjCCfE^{ikXjGWCERsA*}7x`jmbwZcp6Ug{m zyaA!%oy`bgBSWP}zi;+}=86{@TP+ITnsMyPtN5#Ep33x?tijS{Nd}=3lukAAn%;tN z$ERLr(7x_X{GFxTt>p^~CC|n)v)-`Zg4wmJPLw(t-yGV{=e%0BbPGbyW2v#T^y3}~ z>h@=Wl;(3K{AoVC16k73zG|i+)md><> z4PJ5TS0hOx1rYJPvC`nPx1WLoavxf4UT(;>Tj;9ZxMpbm3Ir4?9PrtMo#_=8}O8feS;=rlwqe-Eg7?HubC;+tO!NuHl?ny!)3Uo~zO851$U zlXW%QvigfU;0UjD0}WEQ`;efIeRbT#b-*7NFQcg?wP{Hv?!Lb9&NwqAWb zuRe&~QlSF6nnD=|;YiuljYT(eF6jMJFFWGj_hrdyG~moVC9RiV&wIVeJ#c873g^|7 zaU2;G@uu&u#+mja_a2Qu;+XQ-AJ7vr8F)1sde0DznOt87O*AgVWoe^hIx{rL9Wkds z>2g@16X{#uka=a&r)p$nNXropLr^40Kw88Jt+gUGlKy*5_n6S^604u008ufzo4LA2568(|@YOLk z!cS%SPhpR5_qM#b86=krR1N8PDj(lJf}#QrnhO|tdLi$)&uX?hK3w40 z$H>n~^imR01Q+6og z6px-#3O4WthAY{!Eo0F!4A|pyUTrxyg5=IppI>`@$29x?kr}PyT3}63K!ldSBbok~0}uef|D@&^>^>?iS5^ABR$iANbgwJpYmcjD|pvO7xL#vfQyVCw*&q*kakQ z;@3FG=xPt?$AHRaEm@{;uSpqp^bgdMe*joOXt5X@wS;S9foG4A=imVBv1wX`g(ISe z|Qo1AZ# zIDzXozrFt1CmE#%FvyfZCKO0Ox|)0^SbbNEV`p1E6EVNe8*u|>SFzE{E}r*A&O|IP zk_UC@%EvMr_9p5UC&+$^tX2fBI_>WN6et+&ml0K15$3$k_#Z8RrU5%n344gWEo3}74gC2c$Ia8TZ=6CmrUI1(rMAl}fIsZzN`@%Rb9H@u zrrv#ZT3PeA`;4-eGJpG+=kWo(&)INo_9G|ne9p<^`(*VL5IiGnK2~)_o`N{T9TsS$_E9ulB(@l+;!KDuL8E6C6y%kvSM{( zujnTQQUAb+UiN&lhvmadVJW4i5ge*cJPf-|jjp$%c|$M+$wvfA2oM-K$gDe^#o zP6x>cbr(XY{8`@PPGhO*dDy!bMGcl;a;nm|f@Ul;<&Kdcw>`2{ANjBIuJ>SNq&i35 zgxRWh8?RA{^4T{dM~uXK(>&6x&1Lte`oc`7I%i zQ0F05lvi$TC?WLkkiT=@9`vXZx)D7iF5G1&vD`>wgAsoSZ=Z;ZZeV|*_4Cw_k(Ga- zQmRIi-+F@#@`rYZThlU@FLJ1{)i6unIs?~qv1_QrS0#m760iL@yb)$=zVJ(b^nW~H zSxU$WHsCpZ|Hyu|`ka%G2|q`mX~8AP&2#a=e5K_FIcPzjmWLVj^V1{lT0Bs!x9jF8 zqpK1AcC@J3Y4O07w7q%BaZ$0}xRkmhFXL*sa1WOK8b&&=opG_FY(O0+pok z-|UO#>&-n6uYsCb*OK-@=I?LdT=v+XSJyVSo^fsBVxGOa(D>m*jS@yQB=NNwmZ6lL zIms#X`vE8QEzuBo_RA60S=}SN;N`5Tr#5&UYJSa6nR7;3Png>$J zT56J`b9;kycr~+pkHxrZeZHgu>n-Ad3m05TrdTRfh8*<~#0DDFi}WUe+}(6zMsafp zqga|pou(;7HM`3;%7DR#dr;{6K~J8EHCHX7H$Q6MFObGyqY0(dl-u#!!8uAvN*|6pkfE+Gj_cDyak3y^ygvR~p%htpoTt!I zFCF!rX(%UYFEb{4s|40ajB;oFr}gAQu3$a|gjBWKSEgL%U)96C@RO#I^knYghmkEc zlV9hUm_z@AiF(b4^8S-Ac0^`PWfz1GcpZGyyGOVzDJ4THR!)2;$9Uq=9E{!Gql@gE z1fk^*p{4XZu&{94CVha>HcW5;QW$(Q!lS?Ky!O1RYSs!R(r!*Cgy1yU8x-+L4~ zh5Qh16>!6(JbfNbnGwdyT@}#xC|~baEFI%o?%MMTL=77Dj3U1dxt z!(U@fb4x%wpYH6|b)?a$nDh|V8-t<<=fq9VjM1028{RRT)34*>ax6-{q(;(Fl)2i~ zkEsjLo>3Khy$ZYj3s*|FCJaK|d=)7}$aIzU{y^&Sd;688o|P-hcVwmyY?G|*b{p#J zhC#KCBi%#eo0h=@mr83f6WmWXE@=7_srVZW53GBl9u)1&CV?RI?NVMddC;3|a>Hm+ zleu?Ul5V8n2CH74y@uo9UP$Lz7}3goAY--oxMarRUfr{vtqSsu^#f;t%nLKaTqPJQ zWo=mOyAj()yOBm;@MEyR9oQLo(@@++vz&KD2plA($H}g>ElB`y_r#$kuO$(+Y%silq%HMudN4jD1w{`f>jk@7148keL_!b_Ut7T9}U zxi(_t8GLPX$>k5K+Qux%`XpRW4w_x1&Mt2oFdBUncwxO(>AD+XS(aOzaTs-y>SC<3 z`j=;~)JFFY2LHD0#isW|2m>bCA6pXa(le(v`X)7F-6Y;_wpI6+ie?&R^yCxev3zja zr8zW>PP)oXFQ?HMw^@zmn%)A{%C~VK3Ys<}?kigGDwU|nH5Dzjn=1II=|*wMNc-Iy zmDwJGy4iLZ3L4Pea$_6h#V__1nRk+Wx3lU%GL??|QW~7Ixa^LlEb1%+tJtzx_LuwM zK>oz82U%d3${UiR#Mo~zDX7R!BiHGgweCaA95hwb($`L)zb zWV|V@c`cT@Fw1CM_Ym1ro(-6b&+BJNtv{$XTRLI~EZSC9h^*N~`}K)$7klF>WwN>rp#XA9#R+9-WUux6_UFc&llma< z^3D;Y@C;PNX8xi01OTV(wE?+$J_S`AN3={H{5S%G7}b89+BQXBs*4^m#cw&732}y; z-D$zd?%e}Hw85cbmwj%A)goRCkXB0@eaWz)H1XASVT#Ij_?E*qx7$lhOdO;Rzo+{hIx+w;7(bB(P$Y48BxR0TYqr<|MDC?&htE^`k>OR4MUoF$?~wZ3!F)}i8hu!*5`!;eSB`u{ z#k}*ds?2gmb8D(&Mz#62*M$Y2u;x<8_VGfl)cPO_G}481U-_r=kYA7x#;L-XrI{5l z(-s9)AB#(CLrdiCL%2BChbIkD=$WxubU1-&(laIBcU=ycv5_hXpcXnS* zS)5x+7S}LcAGH+V_`xb_-D^aC$yssD*aY>p__Mn+67L(z3`M4|W#v^}`M$H0EUEIjk{Xak{Gjr_{M`k##!#ZZurQ|bK zyKUzp;p(iB>wU>B_yGy*c7{K0`KDyKox>%}uzl%*8MpmdRhs$394=5Ab}`&c^QxlZ zElfEL^U{2Z8V`QrTaCgqp~Vx^qE(mrJm0fF3jM|Bm*uNLX^@_p*Fp3cpHiW2FB`RtYOO?kJ`B)VHN|*=Pd9RMd`DdM+_6cueLq`2DkD^Tw%1_Bq*bSUYHPFAWiV+aE(&J*v~Xz9@DaXz4qU&Wn8Kw*GM4 zs}APjur6+CpQ5btk?v0Rvk`=0-NfXA4<*(NwY{U%8U%=ZFE?)lO zSfj&A&kfUF6kB~NFl0gQDFxNWh?s`QmML{ul^SFAWp?l|JklyKun4G4gw%85TlLcq@IKBAPuF4Txn}zp zs+3c?ivt&f80dqUh6ousE-0KU3GQP*`WU4&ppFtb%vVEYatCre>PU9Q{1CTP$I3Yh za9XVOQ2%=S-J2}~+NNpQz9|qd%bO%}*te`6onBuP@{D#K8e59ds>f2(t?dnZw`LIh z-TxTDcoCRt;vG)gSnZI$VnuAe`dSoC`qh&Kj}SLOneaGg^^)};EE;R{i>orvQ&Y9S z2b*`qWu~onHb0_ISB%sCK*@ZazQ0{XB~BQJ63RV!LFY6KtL<}Lqls$$g~+Q;9>w@O zp9baRSSTi{*Hjy`0TH7xjk4~Gn9Ak$M4BOf@0xsHNoEhKh;}upKggup1Jnk=uO=5_ ztT2sy=6ZLT4+3ne|H7Ou1zOeTs7`my^!M0*@odg!=&98ZO546FbuY0UZba{lZT&A;?aUUF-!~0g5>_87=9xS6j5Imt+(2&j zN~okQF+D@^sxrxH4&)l%NZ1bwT@v4H(JBkFAY|J=bgRQQW`f|9qLXde^SmRUJ;0&y zf!bW;Pqomy-UrW0&M)?lZ(o!tQ_}%9VF@rhtOvdpCB^9tb^`bTzh+_X{+puk<)L`a zr~P@hazr?UWnjh|o!`&XQlFqY)7uvz^QiXLl=fOeibI*lMpJcEM;4&Npo$+pt8?{? z@n%bJoz_b%O$wg?awIMtR(BE{r3=kVC3mo0JvBzUlbvNj)zg0>Ulcq_1a{U<@5bxn zJ@HwoTw-q|6i8950xb@e$;~S`QFc=jeZvMF4pa??2-Evm7rwuUr*f6BsFI55|H3&% z5OGf50v6o!KeyoTU$^YfN)oRz!OAlXS43EcyWHLKt5k7yKj)lV>OUoed*>w zHbSb>)l&$n$tL2d3BJAq(JklE0=Gw3)kq%&`pr%jc*ZL)nP22Duq^l$TLfjYC)m|Q zx)Y=w-P?a97P~hvdOj&x1t*jQoKTjvo_QvJ7x?{$P>hj?dHNTInyKax$Ubf(UW8ZbW1_Q)fv zp;IxpTM6OW#LBbFScCbOUI6r~-Es*;fznn{GG*R6K%$OZd?|4@4YO|wz09Xh)2s<$_!B=a2 zT7LuQuhl{D(37ue|0)s)@0D9+-szDs@}nDkMd^kCgpsF>AxU@b4m}$x7dB`WwxcPn zwHJ&^+=1q9V8mQ5T!DtS3yU`W2MU!~7}sZkAZKl97GaDTYTHr-Wke8)bFO7X@AZ{r zY%l%#c?Mav#mw*F{*y^8AN4iSR%>!eK_OwFb3ZB@<;kig=5H(z&%J4`S}G8;`myPm zAq%87nC`R1XZlkxRk?uE|6;%VL2pdwJSlRjF_5dq10TgzECr7!p1e@Wu?EgfZ;oETszxVCUM&OhVzegGVH+&Nv zDdP*es4WH|#no>S0M(i5fL}2Jk-!^`$B*cj#9tt#cAcnb&t_}vIycwUt^_?^P2y3J z(CBdQ*B-MI8iA8jVP=n>eaY^v^>VYQtvyRH#>WET{7mlxBB zg_v+q2R+xi`3{+U--(z`qoW~-{Eq1%Li;X401^8aLKH|Ps%P-vyOa@U)p9Rh|1C2} z;%Wx~RSe+u2SfB&lK}VkK31o@I+#ECjn2FbTmJ?ep)!=?W2|jr?`v4=)XlejCHbAB zgp|2${>g%Tf;>t{{9VWF-%3^cp(I^So4=M-41tXduNd9MsH=6Sc3G%s8_UQ;EE^bZ znqO`DClCBcbP2Op)R&I$gr1d3J@pn0?K?-My=gu68NtEWn+D}t9&rub!U*kg%+N)H zfJ;QXv^gzmzg(umsdg1KEPen6_l!$uPbO^ zu0}y|U(at*)RL`H$&aL3o^nNC!rsurXai#aInq_>=uB&n4zrcmNwdHd+et;+bOl%vfqvXQ&h=w@aLt3#zZm9{?CAk2>d`QT4gzhC{CP}&es06tvR z*!}7-c-{`^v4&IeTS<;hc-8CD()4oujSZ%pYCzSGv(k09Ah0LXV~{3V`=tFpcOr<+ z_66}y41ApW7jXK?XLQ6a#mkq2sj|1rAEdBcIXv&)IQK^9+YOG?S2_7}6;G2|TjC47 zloP9m`BE}06oHWlTn>2jT*O)%;7-|fR^~fsKJHC{Nz!w{J~F84lV zGXO<<6_1vbcvNbFZF&jS9^UUXy3m?MGjb2JVGrH*;O}5yhGVbjqh0z5cAz+E%_!nr zbS6zX&m6ILZ_il^np9=O#tG5%iXM1BFf3BQZJ~CA(M*Q*maCVVx)aGLeVMvVm{^&c zhPjciGk@qau%MQ1)j6#rbM+7p4r?9sYAh%mL%?iezmHA{02~S@vJd-n_P;*dhjHFX zkG4ObXRMc>J%rhU0}6=9hYw#YY(W_a2!gIS6^Kngp12U*40UP_a4BjEgsqg?_A>5i zzBg!qGtbUGe>Qy|QUbc2T^Hd=f~(d-5##^qI<&!%F{79}>C~VnxA6s+=6$RooV-VI zX0MI{`$k8Kz(vGf)H=zVe&_Y^L*DRI)tvawctWrDu;Pr7CiY|2hKDu>vt3V#iV@-< zy1BU$?nvp@ks#jv{%NAdx7;lT!PfN@|Cwgy3D4ZFsx`xxiD%_l#>j#rY`UblB+m2! zK<S~q5T9p?I2FXHM7_{x~d)Jqz*ZlT`bRtMTF-Q_*U!amD+4uPQP`Lu4) z$O!(N+mOf~HKJpZTQHBL4WD|Je4{Mef8+3qadNjhC{HQ=Jg5K@e3hlj4E?B6t@1e2 z7h@t6+7==7KYyBJ3Q>_S#4PTG#OJ^B$25+efBb4K>hxmNSvL|**UjQ%Biy?|K!S!G zUcIOm)Hyj@@G_c(@~yD1j+4R>0XR&Y^Rk$JV(UddFttb%wW{^WE&>6mKl7iepq_xk zizKRI&-sB9v>!(bh}af9#Qu1_!clu7)Z*&ehD9Zmn(7oR?C8OYMLjQ(UF4E7Km+l9 z9V2TU4)Ebp8>H$tCP_S~7$I3bsTwH3!)qq~I4ZZ0N>UKw@WPP0e$R1RpHeIs_nQ60r`GaKjx5dRs1{HVM2uO$)HaHmeTKD-WbsS) zPP{zyD7z zI}^80@@n>jSsE6tVQd*AC^D)89%&CJS5F`dXmDAT`1(aeNL((4obh;!$j@`cRl{&F zZeM1D3d;-M2Vk_+1`%+HCw~KRsqHl!Gyn1R?dK`PwiCg+@qvT^n>~GL_CWVBpM{wHe zGl)99H$*z!ixst8inh=_ea(9KjCWRu5_qw{-FR;DAAOD>Pynt4qeuiYXV#+^N zw2lPHC~Ct8sXGW*8YiSE#|l3YfFUP!-t}emJ^}(F9LBW=#bzjT25FB}j6-RSYY{w159BPD{PsnQy{akkiz{si?he`=x{&4Y2lZufZ>|j zn|4MZgLNYFm`P+4V2hGNMuqE^~8qiq$z2!gVEvPJX%(e>iX*E z(E>)1Ui-M#c=4ot{?W7~8zLBMeEW17aot(~F6|-bPv>I|{)xAle<(3jZjH3tTtBG+ zfwR6DUOaFDth<57dlxWExdDtH#XeiTH+;MT-%kOcO-Gw~vLJNwDI(_(a0244xqMdE zCt3&)vjGTTPjJf6v5R|`?{DNG&?`hl5;pcE-R!u3;;p~Rn>Xl&0h7|>g{41^5hKLs zqy?zxj&&u%z~U(_ zaFxH}q*j4s<1yd#Gw7dk=_MiRkF#aP57>m<8aJ*hZGx-(3>dfV!tE=|#|zaxuKj&FCroh-n zfxmigR`KiRu_tx%8?bqeG@s4aWEOxrW+`T7H#*=;`Bj-honU71onMEUOREk`Ehoia zKb?@<7q}>beDuj7oLy19;$gmFEjyRbkqVI|wCrrJHrJM5ER(Aa4d;Lgpy2IctF^mr zBL=K);;4B*6#|r%^qXbPG9M0hJqw3t@^2q53b{IadUhU;AMP!iwnyr1NEts)e7(qk z@Wclb1@VHJ#~~n_SsUat9=TVKV&kVj)~KF5lYIRju(Bw%#DC$y()m%BJ0lT7T=FJ& znu86dda56=OLz>^hu^qq_Tb^n%qNp#lM&7s`i?`JzZDhtCVK^HrDnMEjn^=nsu#Og z2k{Yr*eI-|5}0+{w2V8sX=m8tVn6ech)-<=RY}d!6KBPw-?u-}%hvX$td7_464QtR z9lkJ1Yq+FQFIjE5?;D*v>Z<=D3EQ~_K7a_n1U9Onpk-FuxZ%2AU{pAuALZyzxAypz znEJ&c+Q#N=#a;1x)A3@@u4BcCB^T1I7uL)k1S3o@&;$3>Qr`WGqS@FRZy|3gO`6>- zBti03EZ}0C>#!AKD-u&ad^ECMKI-GT?04(3MUcG`OegRq4PIIExZpMS zxuT#hfhZIlm+w0hra*)0@Ud^nhRk~!vXpw%%mHzrYV!qR=wE6NlM^sPJ`MJ=B|BL_ zwjMYabL>9c9R-&eXuJj40W}QuG*vcmaKbW*rP)B@#CK#!FgOG>-=(1%IhWN@#ufTm zm9IZw7N83<3vfdYb6bkL+8s-!Am#bJSeoQk^!SN8W>$woWq6D8;1y8I68FKC+8oUB z0#lGwlPQ%Toq=5MRG1qTGloPEOQ-~c-b5B={^v5s=_)_&m<%Qtqc(qXNv zMg0eBRUIq-sA7M(%x4A=o=iL1I2=}%7@7$l=c-Tn1t>ml(@e5gjF+)tH1pr_dE60GN1gm#3Yxty?*Fy_F__|o%S2<b_nrL#~S-<7gUJR>pw(Wu0LSo6w95*6Xu||M2g&~)78x$u*-gD z6yje3^5^tigKfX|FTy>TSnIDpM1F;@`rY3Ez#}_s-?JFNd<`oCOrQQNYNxN+@&q`I z1LWz9{^VSTkJ(UimsxjwRxlJ-&bRYATyI4MJzbTsvs|crrCTkSMP|~e)%&OoGWQ79 zk84*mb>vB*?#y~Kw6!j0hNd=XFKg>xY-L*2rqbz@D02FKo|yBv8FY>ZA0w(|tJ@-@ z(NlV^!L%cwQT2M|Y@lrPlo?M;3irFKA^lL9e4s&=HCpT^)W}GWa}Bg&b;o8f(I%{$ z)V!YseO(Xp%xIW^004ND2*j-dmF+ei6n)E*<#c@K$VAuSxc0Y&LzZ08hnE2-(_)|` z#fpZ`e&17JwjyODeMIEx%z2{yHblPE9u~>FX!)|}aTrZcrIya7)t??@wU0T@%hEp| z1S-#Fj@KBxTd($qBk{{;h+I~S@K}@fYWsOudddOaTF={05-P(=Q$H1zYdqkYM1T_! z)o2nT`whMrXy55m_bM-lakSy~qoudx=(~Z|2|mUMJ}@v14j_C)wsyycPt^_ShJGOV zbk%t=!H&?JIh6QAVs|A$(qSWHqA%9~&EYs;6D+#;X7HB`GxI%OPXnj@ZO5(i8uOh8 z+##9xHo#|_mR|aH0s9@dzpeaiz(#NQ`n?}#<__PVqm7xWJ92pd3Nn^BXblb?`M5+1 zGjGXT15CE7(0@QjDNEh!4USvpZ~H zphz8}-hvt_d<=+i{SM*waq|lnM0PZHrSo)?b1%Jw4QML5UyOR&^Q{^npqzLtSpR!x zuY#S0X?p3(Xzy>ik5L054zUt9Ow90>3#jnw5oV=gM9hN32Uv0VlDdl8In?TRD-Bbi zH|Ld}lvj}%`=D{;aQw;c@`4Ly_AWO22){r?eejgtXU&FEy<`d(Wz3%&0a)vN0=&BY0Nau!P zUK3|z>S+z55#g7yji_yqe=mo&0*nK=$Bgkv0ZOnuyrTpp)pWl5qrwbt)nk^w!?fSS-5B4d&>~(wyw59YPH?`w@@=to<@Q_y=?JV8#n}AZ|7V zzwMCB3vU+{D#V!7XyvMFjJp*Cuq%IgoS$PRDOr)91HVleGc2h~BGha*f(yGu$DjY{R8IsMXd*Z;LO>6fJ`cV76+$TVcq1f*BM2JNz zPYtP>U`Zfm_VS2Wfm!Fs2vL6nGg$0WnKr%%+{i;H(!34(D>6|JHN1pRl694r@EZsN zB#dHU(C{+ZoU1z7&v1V=A!aLAR4&NV1I03c!-8l2gTo5;&tm4ib?FI%r@Qq;Tw$p6 zg;ainz8q7#ii+jFR@$E1rTMXX%duKz(<87>8G)twlwO6slVQ6LT@Q3WSG?X@{~&^j zfA>i{2E?0+81#gYKThz^{esky5iaDYTqHqCZO7D3&_}c&oe4O6@S=T&B31yj@x!Ya zF$3jcMAFAlNT)w!`InclYwO~Il;|-2%%1T~_lN1@Rl6szUp%|zL(e%m+x!O1gZ%}) zzBp6}qLoFQ#TpP}m_x#ff04@!ouEDFBf%xEuiFN0Y_E8Jj@l&G3quft7sf64yk(lw@9tB8)e)c)|C+~vcK2h zee@RvwQZTP{2v$;!Zr?_BY4Emj{)mFaRtBP(Y5u0gL{W4}2*v*H z!d95Kys0?44T-@2ayZuL}NF#$4j4hu(H2VhQnuS>eK#f}qj;hWzw^Nc8fm zg^#_l54Cn&a<2u>#dA2M0?6=8s%E*SViO`sC;+3wMuOO=W8lN!*dXl&-r4 ziPHu50kH;AcQuRbI7HHgk9nuw9lx!nAPZQdXF`x$!8 zTkatK9*-=Evm0M418N!2iOY7qP?6xoT20WXE`S$~-jv&SA=hadJIBj6vl2^)hk;kC zur?iCs}1hOmGc`2L+3irQdEnRkB+?JsraMC)NNRlgg3qVgcYNNbRIBE5%hL)uhEn7 z_)t9XIr~F`)8>%%+Jn~EWj#8W6RY6XJn%FTaprdtKpde;(sxf&1*9SA#?F$X1Q$j> zm+&7Cp>gK8f0}W(_Pcl2(wO&-^g8559?TbY*K!g08lqRl{za|i6Opg+^5si`PZ>w= zXIg#m*D*qMqP;-lP&fHiOQm?YK!XWQ_lA8Uqdm3e;Awu}<_U=(m za*l_nBXc#~>WTpfK2GmP_p9$_%^LNn@yq-C|B+D2xIymbUS&LS$Lx?%Xe7!@Ptj{U z?pl!8>{7aM)`j8o24__!>?fK!b$MD@DFso(nAv6I&<%2mF%S_87+2k#?@WOATMgu| zisd_I_l%c+43di4bQ(Vl{kZoidb3GfV!GMNch+(1S3wWL*$eAbxms>Dmvup8v#(Cf z?opo7GnBW7hwPt|{6pk^!pGdMT+d|dsm~P|`0_+suj>6}&Hu2gOmU^Ri=Vd|=D0=H zfnaPUg;B&>VK=6B^eMqd>fz&1NdHU7aaAM0Kqgkg{;@I)NYbE0ZUCgZ;ely{Z}Tcx zws?|jp4W6X*K{67?iK(kw3|H=_7k=I(!*l6XJLRPZZ$w1^;0oiVnxywR~j$rs01{0 zxVVn)2#}D|{}E7nMG8^-o$~RAT;h0R_eW33mHRw<;bQl$*tZRh6xnUl3z{v3da6+! z{RfXk1aog;Xc%kX#0hEZF7zeUp(1bl#w*3|EPpiFRmq^hQ!UwUn&t+2@XTY71ig#f zVFL6qj!w-X{iG-&GBM2rB{6_`IRPLx!caXJVLza+U=NO1!4O{WN-qTDi9XEe+9K3` zc`%oU#cz%8#dm^+ zEmj&+^_#H0MiSwu`z_7O$LFEB^u+Zw|0FL%9xi0Q78-_*y(J4}}TmuX2v?6rh z&v@gb^ud&EBmW2m)-OTAV9kGWX>4cVfLW9zR^_ z9o4HIfOE*-*Vb)G5-LZ?H1t-kIgNYQ6`U+s2xiTpgok*!+yS}+o|6lD=9pg*bw>bh zrYRIHRg(mqm{C!G`oh*95B7!1jRf4 z`7D8mKG3b}OwZ-=K?jVIbU3k=z33k(dlAG!2K?IX0O;)TE5dhyxFQ2WZkW%Yug&DES>p;#@FO0C{^`JT}ut~ ztx%TY*^x5yiEXyOxSpBC{yOI9+{t#oO^YP74Kdf+96jNiKWL@lbQ%Uumnh76U#g~} z)_h`=Bxh^8>03hD<8Jlz1sp$)(0$GN4vgQ>mtk7FvC zc$#6+xb=s})mz(ld{tcP#a|xR#`Jj@5nR+&bw2dWIhxqnPSS0=47irml5kTV(D-TH zE#YkIArb0uR(l&Tx(ka0z#QnonR7G5c&Nr``X%%z%BMP6Gk@T&U6$EZ*VO}QXDcQ646ERB4#*FWl4kCAE;ccTINO0>6>4quQXyq8%)r1b5;`{2to!=5w+ z9shL&s+H)noZ6S5onHIiZ^_p4@yUXggJel>K6aD>D-l<*g&i2STuMKyl-1-S+lsSM zbwn*$nwU0*Bg`ivLjH5GNs+H_e`+@XvL2pTYg|XK{d~+-M5EPK);JUWJG#lC~{}X?E#Sazq7e*1W{!6PmC4PiL=ahr5 z=G(2Y{MDCucVm%Ys^!lRR#8Vi8*(=eAlZ99sq`+3V*G={Cqm)26C0mnpDiJm2CEc7 z4d=zUg3kl(PCKiy)aY*`>E{LFCE46J>)6xU>Ucxa&k9D1%#>>Braqo9@MbJgec zxA*Y(>6b8P*&hTvx_HsXT5r3~S`U?9m1Dj7+=yb3uBf0YuqK!I2anRl3xE|q?n%M% zo+kXrT}`S%`AbYYyK8vpevOp5xt%oLu~P--K3B1d8ARkT`||74X@}?+*@TV0A~f2e zGw)@D%TRkbpwq)ikxC}&@fGEefmav7@QwK$0&7=9$OL$EQ`Z+>`iK zznJ9i={M2ZO$=`HY;P^Qeo(H|cy7*orcZ*08T(uwyvqN$yYPt#;x~>g)htf#^uE7m z%Jux_l{yud<@T~TNpqJlYdaS9EX(bNWdTp+MhKTCDaq) z_z90zuhN2U9EGUS9sBZ9X<@dR!AWZUXN#Zw53k3G+MUf^@i|zXUDcVO**Ta9nFw=* zLC$w!+Irsmy&KVn0qmLo3vUi)Sr3>|d{^?WW2)sQ{OyJ3zX!ZzE9_d~Xn$#jFD#EM z9&B=BHowk0+wxe}=ah1GBLl1L$5!Ak0Ec-Q8j;#>fC;8iB}GiFiau1 zR}GOXSJlr@ub*{h_1{8}%i9 z+E<23aus6DNG#k$Z4k69Dz*!m3dw^4%@K;{kI z5T-HN8V^q!7*yDZ_UAP%i4ndgel_w}M(ni3+0@Ht1Um(Ou&TZFHf`K1q)21N_Eyw) zJLJ;UYD8uEf@*jAi=bII>1N(lFaG{)^ewt7`4~$MGE8>8dV^+1)nb!mn#R0cxOz?@ z7Z#ae}$vWLEUSeIr{dX4G zwn5L;2r?4jOv^HC<`vs^q zR~V(IZYtp&+MfyHQT)PdM&NRX8lJm#=heK6OfQ#O=s8($`_l@a8O2`3aX{=tVya%% zB5|u+ay%s%s>U&6#UwItJ+@-3-7J*@HU(B{jhK?9CGC>rB%R@aTd2J0nW@wA1r26G z*@am~G@}$&YXq?9d>8*SFz5(q8=O=cKmHn=b-OmXA?=K%>+G5P&P|=E@%TGxnjH4M zra+^ZdAvG_(tWwTBW$;>Gkg|GPqM0>j90+P!g_j`9(jA$0&J7vTzf1_<}e-RJ);EH z_0pmakuG43$|&?}7`)o_Pf&J~ih5MhE$P>3A0n zs?|V_gATd0vsV00r}SiVc`@x-`Zb>F97m2b2gEsgbzWTw$78BL0ril6#qcdw4Pg(l zhbA{jdFF$RL4)+b{Oa2`^x)bcAJ1GpHU>L!O0|9!4229j&wcCYteXf>Bw-0?+fb^{ zDc)kozxoQ4cqD##1mTX)%jgV19>jO7uJUHk2T@0DzPHb-p%o*_7;1QNv5DP5;Z$eNqvT=6aY)e z$E1a+j&m}5#@v67asTE< zDOo$>OL7=FjI8}>+BYE4^A!As#I3zg+Q+XJSpax-!Q4qeEwIK6BNLNUO#goa|Y}$k2{&8=dlZVmw}@4 zH8mZQ=FUTtu0-kC+>%3fm001=S)MutFpdWQItUmi7G!zUvor&cDFr<@9r!@5SO_Fz z&@vR`#HnS+JR%ZS4@Rh6T~ngjgb1BHSs?$J5v8SL#I`(KRw7+yIZYb#oX1HeNybR{ zXIZ1>N)JcB=0?w&4#1S8R%fkg)!mb;_Wu5kWaD7-C~_N%9_sqE^PBi44;CDNz|UF= zz#+)uB=AAUz6iT2co87nbaicUuqeXNb!=O`!cKZ9zD800_0G2-MiC`)@{JUnIS>rN zOw`rIznY5)Pt-Opw;kc>lG-di*u%zWHb*(7FaZdS5>Lx3@ZEPa!HYbmmiaf!Kzuq_ z2K9Styl$42*z%E;(3u%iFx0CU%t~@BcAW35^vE{vh;^8a(t+Yv{Gl*dqSW3(!?|shhsM@960S)GtG29;2N|C2zu)+14t<~ULz*x8+xX2I4{JKMV zgH~&>#hg+uYJ&u&svhFCux#4`{j`o;ZFt(F?~NbLZ9b zpI*~rlf)zDHakdEZ$C?fr64J+|Am^05+`^EFoiU8QpB|7v1Lzc7V=;taHD~GLSZ>f zJ5Qw^TRQpwvHR6ki>7j)`kM0{JB8xr}F@(jG z2LIyor|4f2$780QcS8gif=Diu$qsq%&xw{to-9aB<=N_Bfc zF%|eXQo$JP>!BevYd->K-qWf^USyMr43XKpwd2I$y-NH(8d`^I;8_=dN)_*WU+QCQ z2+{1OT>{?+i1~to5_;d&$&f3R)2!iP-FhFWyfo9*l3+F!k?fQGX;6B^?%aqeZYgGC zt$~`(^RuqYOMsKo;nQCtLccD7z07fA!~Kiv^U>(P4OdB|hA0mkUb0`0un!+q9LX=nVHYg;%+VBoUIDOe*-(P^+j zk5_;vX{(`lajbd0_Bab5{mdS{-PM`X5FW^UB1cMH)kT&59Y4-i?Xt|{^7QsYlcEPp zM2`_!4UT}r>M6$K-G?U6NiZcDY`S9jA&Sq8q(E|I$KTY{3I0uvH44mP<1!6(0#n!Q zYIj9rq&?H64%Xxn4I3y=K+<32PJI35B$-@biw=LdY5E%}o>*FxoRGTuW9Dd_UK974j9V-=;YV z{E}Qb*PbudS2v&5TDH+4KcKejo=U9Z+_SMX#ojq}F%hG3+g5m)wGK+nL?L#)DlJ)T zViSjWMT5QaaVr-miDS=#)yTImGaU|9++M{t2Cv{NjiIkRp0$V{d&}Pj@DX!GX$m*O zdWc0EgGD^|#Ouv6KAf$A*@l|QOxirlh`oUs?01u*Wm5mMquu-JR{g;-i+vhCteds4r3LR0+O>`Q z5st@)S9EIis}mF!=5E3dO>+Jo-2NE5%5_rin=K*3BN$7JL)X{u=1J^`)!OgH?wjeE z`&=AaVHt_9l}a6Y##|@3p>V$7DxX}Yu@jkRPZo?5f}`qSF1{kWTMb7oKC<3oOSV6& zj0b(Cbun5me)^`fZ(TxWSwMOT&xyr1SUhT=Y z{mMW>LQ?FBR?T|G(?J3u=2hRQM_G{B>UH=JMNBC9bu# z-xM>oyYXAHfOJ^I!SH!HhSKnB3lrXRw7{n&@Z}$G^nW(anNFv?k6?o( ztv^4}vaK+!l8ON_&qjfHtrzS#UU*j`8Q7nJEPR_np-ukYs5L9JrcZb%yhicEsB0jf z0rF)X1%6>nEx!t5m!+Lo#b;1_cLlk=y1%T!pu@hW=e13+XGiFZ=-sl1k9v;upZw9` z`8=uf_RGiI~kt-i6D zqSmiFI+zIpH$xx7=boDV-^EYApF-frJp&}!^Ox;Tu-};6-lk_uRai|)^YT~jR=STs zNSb1j-8Yt_Sy3Ohv8R^%xamE&7A@p>5+qzpu=E{CY*=(&(W=khx@U~AcPY34aX9AL z$Ro*Smi-2?B-8<-WOhraD;l0RqB!PZ8D7n%U>+NwIuWO&ATB;~dimqFO7eX+f4oGS z=5vW*<%Xe0**XQ+N6O7n@)}{5?bJsRew%aeg$ov>^L5LKCg$$2YkOo9nTSZUU6^0f zT3r$nQtcv7#aM3DJHGWq)^a?#EH&oDv+{FXo%_z|F)W+X+_v?+{57?hlIb)pYTuIiNa$?wC_Avuy4(GL2B$2OV#j@11GihGj5cIvDH@dYQ6JZAO$)&RA zgznoVfeDFE@JYglWbWoIlOO%5kek;nE%!Xp`9=;XEuSI#x=9zzroN#M=3GGRrDdTS zR_2f@zAr$UYH#cGe(gdCu(Y#3parxE0WJ+y{TnMx4FN09n=D>WE2>>sy@SBPzvIMv zO#DYZp8xIG5TB)_pSO=xDS>GchU(pJBeqnkhn`yP&Kg12Mh3Q?rW7(7I zCuuYZ_-8imUV{;WuSPTLt8~ZRm>Iiobxh<}ww?*3qW0VcGf+|UY~%2YtF@O0Szd=U zOnB?^rd ze=wC&k#@A6@u5^DxY&HSh{wxD)j?RYi-lRd*~puU;! zkB3vVBN`Ahv&&&&#$GqA zF6WM)q`%ULSI zq6cN51rxtWKj4f({u>=$_6~{);?| zgyv5|#{#^7kI0Pkm@|4r2^Oc)^5UmIYg^`%6y=uddy$_d9_k$(5@v&hx+0xum3!KZ zK&`^*{tu&JRk0IDFw_xYaU`e*+eOnByKE~FZjO24qM-Rmy~VV&kuJ#L<`YSyB*Ihg zg;FBqmvQ%Dfg_MRPRV3eE!Z+2S#DXiD<)kU)h^5kk4fq9{=5uA zZtp#+s%@ox88|EKgS@IN7UF z8)_jQA&gTVvwq*+W7v0O0Uay=5cUeUbdzU{AF zxEEom0Rqam&g+1+$!%JxIJ0zA zU)q9nN8;^=;PtYCSoIv$V#xt&3KEgxuV2uN|hq z%oYvv%IUlHU5-*|%zc{U?R-<2bWaX$^HWA5-5}DggNIi40M-P$@-pDs*{ZCcTE56;k=a{{+ zh27%~`?bgS&KTDEzlm->30XEy$Y0OS$q#c`9v)g5FMZ{!93$}%q`d;f$^pMY`QUa| z7T`oGYG8WO0-aU|j26XSyg);A3-2cS93~~IpLu|za%m^s9hVStNh|V{f@00cW!*5#`W99Jb^N^ zP0k95DQkY(o4rR)4A0Yl#XU>!aSZ%WDI65lU*>3tPw+3-A(uJz&IsWGP9z?8nz;0%u9QZW-Wdbg_RE8|Lu zY}XV-m5l@(ek`MQiQ_S?F!Fpdx%TId(-k1Jm8&Pit!*Xe+T(es$Gl9ws;sEIe2fhY z84q)v*r^!NT*4X))arZV_k}nx71_2PcWbjqE4-I^^n{OeV(xfr4qAK_CZwUy;)41t z7&Bi_O{@-E+~tLjIXzr(%C$(qi|y9Q(&4%*jJ-|MRlvjv+vpx*J8>$Xep%0X|4d!& z-k}(7$nbA;_*Nwj-$#Xn1d0)Jz@yM;zuV~lbL>m}*EWqmDUhj?U_@PvPt3WqZiwLJ zp^}Vv=Yb@fkEpyrT=wsR-whMdpJ=({M>-;G|JeW7J1b=FxT5d-Wkp(XIESNY$ndtl z*}_mWPNiGN&`iL!cnU{BmB0tPqqBn8b#Q&rV*S!>Mv|7#o&TmTO|eNBwScg?sk1U` zASp6H^3mz1cuGP=D%zesPBcFnd*od%&A!7DsOr4X={~BMfii~FwR#_HM7Yi_qYup{ zCSL9n9NY@LIZu@8urR+a$*L0WXQtWMYezM7I8!uyC?ZAXBiuu`7CnPzmWS9*7f5xL zy34hQkNJP=I%-yC8*115Le8qsB(wo#z%8ZN;R!I4W#6%M#sQA`#7lQ%2J^sp0Jn~U z8ne(Xsf{b$+;_^zN4B_SNro>Sq^s-)<5Eb!1$b`pYi2TV}7UHW|; zAoY=Yui-40%Z_p=ZUm*!ucsYCCgT1&Ys3i=$eC#Z^O-8u}imv!Y|on_BO^&7u*r*N32u zihb&N!=0m7YG&rDDdf~AUV}Vuy{Dv{5>MrRZ@6@oeJD<>t&Bd2;e|!F7-&-j_<*(wjKsYM~Rm zq#Zz!zhutaCvC~o$DtEJ;;2HGJA&8x-m@89?o|{_TLTv;lF9M&3iX^Qt?u+s@~(zP3KaY(~4bmvm0FX4jyQJHESa{6NzR zokcHdNMq+?G=HBh2M!4v$=|moZVourg<0dm_1;wUYdveIEQ@%q4k}CA4F2<1b!Svk z-{`Po8>+S=4OSSQchOv3^XO5IMi;JsFLu~{jv!S1zz7B!ws|8D%lC;H;qt!jX_(r< zKC@+CrDA2TpHW6s?IA9McBwqH@bUY#C`m=6*JN zr7or~P|WC6qP1#Fjnyw~Ct0HC^&i^iJP(At(k*>elk{Q_dzzZ3FhB_1+Ab<3M6%KQ zAUZ1>pOTf2ucw75p$3-C{Ig13dS~YYv<)d>|AVr(0BURN-iKSH0tMP)#VHiG7Ap=F zN^!RU0g47M5VTmaTcl95I7Na>aR^Rv*WgkJ7F>&eC*1eR7Ta>u7VP`aBx z(2ZoL=In>r(ttvsw9OWN^~QN~qx_)zNdIvHs)8Fa$^iU;D1kWJrm(3ruobs&#m<^A zGP-!AsKpGVU)HNL+gjD9F!zo2BJnecSvRC$CCiT6tYmCAix=|)L&^BG7qd8EXYqsl z7yS`Q!VbuxeFc2oyfRxMXF=T|3f__|GM>G>>@4`s5NgR!6(_6ZlgGF!x~w4!IhExi zQA~jXRa>v=D@OyF5k>Lyum^5`1anl%bLGxl6GblP#g8n#AXC>#c)31l@xN%(n2K?) z>Qh(>CU_DLtCn1iCSw2QB&LnlUKzkC-=tiH<+zOYsHp;x^y*@xIQG+4c~~acBHrwFQQqBI zj=C_RJ}~N{5**bpHvn55IvP;0NBH)C&*9CRkVh|(^__`u{e|ijuRTvP@l$wORz(V& zdRAxoN{A;z|MMA#ig#BMJ37xThs-H&QSEV^y-@kHUD5O=(;=4HiKYkxtU2Qnd;blU zZ9l+B&;-tvfSu)WYAvP|1WpK!_KQlrzA4XLzAWY#O7L+Od#2}3bO%e%oNcJSN!3Pd zcR<{DJ>w(ehQ{9I5bD>kSxrOUcxFFRQQVWOJ>^_VkAq9(&^v_Uu)u@n9AH8PI|GgU zaK=_d|HWQM63}&!#O4wvVS9~TRDYou&Sq0JTww-m1ENW<1fOjQ~)~xgmX1+0&9yaaL?i-<& z8I-RBm!bBWchWBZpxse!TW9u{F&Sp%FCexDsZ>sj{?af3m0DC!JGb+dSffas$NLl}ZQIw=xICBS z20K5o)tq8gtr^Pm)_kY&vKl&I1T5<%R+GgF)LyIjJpRb$M(AN^-d^Um_@92+y|tan zg91Ie(DuvrEAXY~A%{~+bT?`Dz?p3%9tv^cG*TZ6gca>ew+TFzf|_buo>{Jo0(%`` zmh@9ArmS6>U7b7@yvWBrC`gL=sj(^KBs4_Pdl0e^1LUjMl?h$0;+t6$5~;O73m0gK zo&kY9d8ut==dyQ?_a(0sXae8dO8|a`yf=; zezcc+-cNP2d?h|tUi^ypohSdM)nHBCf$;L%wb|05`xL|)n)|HtnWXTQ1+VxVBH<~N zjaKEmcbD5dae~$nNjNH)j#NDGaqBIqe1MI1_0^pwHlzi=G7#vup;3Q!sv0M16vS&j zuEkwi)BSDvoKMwaVpIRq!PnZewua5KdCy=XP^oY{&F+zpu!6qtwy4>eMx1eNrKxSq z*rt#S?0&YO?F=H%J2n~Rq)NuVU)g0qzBw6Do=D0!`vC-xq3Vg<2oHCrtk2r0-Iaagj+H zlGX2c6#&pE==G#JY6LW(c&bGH#9b=x#j7m8oSj)>sB z-QJo2ifuBV6!v`w48JHuX{;X3x$Hv7P7cj%qKRHo!yUI7NaNOZ$>rE>2Ipfn)PV(b zQs3>X%W01ukHBh7N`oeKE$TF!)xt*n7!-fxdXisr^!MJ3U!c-pmc9D8A`dfxe>;cD zMW4j>{4%hXJ*4{1jYd^UMgtQ9^nd^Wl^1}!xgAm&G|TvIo&XsTEY5TbS!{F`eOzCm z+6qBtm<2q*naB#riHDAcI?H7B%{(|e{r55MbTK&O+FB+WdUd@n*J)Kcz zQRTuon9cex8l-;~^#j2o&-VaZ@qcK5IkXjEYBJvE#yBl2;IsGZnXq7mFV1IBuc_@n zX>0&i!3k7oUErra!bQOy( zbkSsGy!WS;RD9ZCQiE%-hAB>mWkyoY60xqbbe^`yZYO*w1LB~nx53-l-ya*?Co)Dw zGJH6?lZeX|%dW~%VD4g#is^;1PJO?C^**T2Qk?bD3uxH4=-~4e|21{DseSzn4ZM~1 z!LI~tqtakpn0`ng}1Gejb?2^>-`VgOQ9&hd;Y zvEd7-;8wyF+6mQgo2-D!{u(BoDKc+FiK<@6Vm_ymE6;xyn$Q8H%f^#S_aF7I@B^^& zBv%Nsg5kG%i@09cDw_~?<{kV0@Dw%ENXrEQW=PsX3Di=fE0Ii9v~KI$McB*RX?OUU zD@>90aXgl8sTP`P+XYqol{W6#ytWf>CL_09gZg za;(}7t=zwE7e(Oj*#Uo(gBJnd+Q$W030m3OF8{^$cMu>7ypT+%qJg4DgZUN4uk~7# zUSXqW+Gi(RKwsykI}ss717u`mYC9#qU%X?@`iYp(U+Pk8MANQ`5`u3APLQ-{DE+>R z^^8Rz6~IPtIjsVk;L*FNKaQuCVM?1L#1k9mmOg9L)F`B*KpT@u5 z2;5MvUWbdnX*Aaa=DTiYF&P)T_}-r}T8uA;y-wHj7+9naQdaX$!q9`0eGg;zlDg=g zH4N`xSotUJp9^NpWku7oYR@A zk6|#_caK+07?Rqd=Rqz z<4MRp3Vti*a=B5?7!M3#Ildx13jTAFz1%Lx&@*!vK+4X9dHz^@$>e=6THETMz0}A4 z5!y+yYSRE|F8QkNjM!%!9HCu$kEj(3en%%ISub12aSy9&gcg(Lq1BImUEla`V?m&W z;XmIttA6=#YS1P(c#_FtYZ@t)Q$&aFDpWY8Vf7zkusg# z-8`y%Dy^tnD53aZiOh$89k|!3OjEw}xzR;wX@LdpySJtv4jB971m>byUof3XT&qQg zYmUuTuoNAo*6LTA`*!vl2XMy{7{E;hirmgfeEiRbL3^?i+V{V+kkez;P9KEaeF>rC z0}x{+--^hIcqQ8!=2|MB0B0n{G$j)RDZ?y2&UT-9<* z8tuN@00!mD^{o8WX>WSd^Gc+CxQCvVz^Q|WJFL%#@kxl5WGyUmGcq&PLk2;wbiO4e z0pNhuH-P>Z@yjuWxGdJ31S47#9VOXp`|ZtczSkdUi!#m=v&@_1Iun0q1$TCK4&`g} zB*!viuxS=X)z*p-Zsl6M21_d+855!dXx()HcUVJKty%@4wJa=B)`3(t6fG z^X<2lr*APccf3^PTb|0fTOLFjU5g|2MPqB|3a3R+Jw%aM9G_;3>^2swx5USWb~Xt@ z2)c9Z4FHe?%k>mDeHTFV-3zOBeKc4gM7KlM`MrWd48RAG4a!+o@2xFTX{Bj`eIm4< zii~BdhFNGTD12RtJFa;acg8er!tw|3Cgd};;gG-jZtezny&fDl%MCs;32K{HHqWx; z9j%q?%$*;-^st2$j2Of!=y#&UBBQdU_K5>M7STe(LR;P4gMZ6zYmKc1m)Rfa+E~yFBvv zcKG~C@G!bKcAs?q*roYP_07ResqjBRXfc0Yy)Zo*=xYpoX#-em#Fx%|{zY{t+xYqd zI6y|kIzivNN$c%BhmL{Mwimq@H&u$gudWBUnbiflIi{x|w)PA%3@e~g4<_M=;%YdR zfypPS{CF2PcUQuH{Q)_eyBa0oJ-5gpvH0)?i$9c@zjYm9?&r)ykF>oahOf2>337&@{YiOlm^jmt(vsK^$=k1T-G0D>8a;o%`3|{Nr#-z<4{DbxyN^gvFYVljbp^P^dXg^-Z?EWlscIigc25{aY z>uQds*=g#3$A_Owg(&!~h< z$A|kapcS7^Mm5jm%ilM4%R>A7fl>Pdut~i-E)a{;FK&v+f8^0&j49)@<_@jfesASw zJ1(byxC?Y%RF(G*vkQ8D(kfwG2eI2^fj33>TNrnvu2U8CDzabmIhF#u6}z@<2+^2e z69X)%WG_Bcg;4W!QM)-dT-vvhnMvE*mxx^c8n|Hfs@{)18r{ZBE%T&ApU;S@1SVED z{BD)lO^<*cV6=^jS;+M&i2*F>qE8H^Xn%Tj(S*ig*O+L!@3zblXs;meHW1w6;t(W7 zKNB_J*jxnA!kcy0qLR>$RQM2}E7%k)LHDGYq~Es5s>qkd4R>Nrc^uztLTXy)@ zFxuT*;Km6?lGA5y_7f|#V^;yWw61fj%5L{2s?{>>js$Qxih++$-eR1_^xNWX#bay0zNeVL56Zlo?+(N_0 zh=_0ga)XNiU{2c2YoZSR^RjL_ZX(IM_1{zzQU z;{_bz9ihXKVPv91A8}Ih?m{39Yvi~2!&~Mvu%t3;#B7Bgo32Shu3jhXv!>g{sZS#U zCQo598I^*0o4v@UOuO_=hDRWNiOr@^oG2=`5yDei^FESM-elqPNr}tg=f=~BTIshE znbvSXKsTYH#KElaeyDsTRkiT5Ijs4|k3O??ifWD++2v)65?1Sdaq*&qO=W^YD1<>y8yzg_Ms=5>;M_L5=l}Sq*M{(3 zx%S7`a)aOFV_2n*QCz_BmzZZvOx=r$527KeSuV2^3ks{qTL4WffD(G}0yxV-#4k5m zwfk!5q`0s`CHhX>SfL(Op>%Rl-YS6p*CV@QI;ZvHVqT2h_SVT)AvSC10#JrISJAJl z96~1Mh4;-Bl6eR3@V9iLc%wz#4kCcv_C{H`c!I=tjhF1bzmeO!LuI~3H>TXcMui@o zbC-XP<-DJg_F`=7>>x4>>ASGqUgMr~yl;Pt($S8vllwMj!Mk*INHYgnT%h!@X)iE` zh`G&<9;lAy)r{om^lRizM$`!|J;Z~L%F36b9LafJBGaaFJTLCRRw9f65-88%hh%fR zG^b6W63Z2Z!F9tehrBWCx5s+r_L=$Gr808yugik81~YSWcr_4Zl3DWIGe6%{*v!<- zMSYdTWL3{&l#P!A@nmWQS0lQ==%XbA|AJWyIHyc1d9`&wWj#v?O&K+exW)Vw-e=j@P+gxywiC z{eef#wS73a95D*6kWHaT;w*j_8jl8lCMv8gJH9*i>-xkst8Md5rw!|`kHA3c3TMN4 zW@Tmlii7n-D*}@OxX!j;Kv`Qe_~Ol9QB=#v?Mu?)orQWoqHD_(9a*)hT2A2~)|aG@ zoHZd+OXyLp@L&8FqgqRf-cp)qG_ipYkiR|*rupw7HT9#lk(>x>uDcSEuwI5z2aOT$ zSa_lPsGV9^a-H=plab@O06(gDeoIcWIBh3Hj;Tz0D8(4O#VR~canAE-|NG$Fl#=G) z&R=Jg0?ezu9ky3ym})lBTY0LN>NzT{1tr!)EL5Z%(=Q9sg;#)0iB)Qz{FGD0hdAN) zz9tQF2^N^9HhLKdd@3GfI0;9y4YjyU$dc6@=aw6=b1YWXv-nGa6faW#iTGH3kxo(a zM{&9JksM2LI1Qj+93$vp8ppzhs8T=cGsAEK%2z|@;U0+o{yDZ``6<5VS+Anq4plJQ zAyr$5iBjXyTw)*SmV9tbL8jiBlJJaI>mCvadx_z8->6lAGo)+dEW-i1(}D-ky!-T! zd6TgFM3OqS_QRHCR-4O+T6?^j*wJx5O6L`kUR&IW`G4&EG_l zI}JHmc=vHkFbW77ovIP?vpy(*G#qVsWXyY~ z(E{LZ4S=VG9coQ&06w5q)am(8;rBnm+2p!P*3CW-ZNgrO)hlZI$iQ{iTO(@?arMOg zFjF?RBMp1s%B0Y|caT=5;j(>F2236TsXbj&n6b9m=bf8J$;F6UA9L z`Mus5F<_xFDsS+nsK^ix&z9F}Wc-fh=c$bLw;*yF$Ks3x8Cl7xtTQg|CT=|QY81qu z8!ycKiPSbdLXAboVCyLZgQOdcYgEo;v=v(-9`$kS@u^BmpP>8G)7tV6(9!A96U$`XnQEQrVq-JxP@d( zmjlPy%o}XyDu4r2ZvurlUw)TZ0Q!SqF8;EFKd&Tl_F5Ozh4VIME-GzHrdSp{&NLL# z8;h$yH<_%5=$}ze^lRh}@BB{l-`^D53j8Wvz@6FuC4dP^>2?v)c6R8a zAaPaQcZDb^rXW(}J7i<2LDk(MKvOw`7QI$1vPB3y7T7;kbDrI_uSBPWq3HC3vy_GW z0_X_-)ZIMr0c5Zwld29R{~l8e{M+Sb_TN^u_iATbZh*n0;B-& zynw>8+-RMe1RPaz@O}L3s#Mv*a3xa>QuKLNcHQUtWptW5X~X0eeDrm*MX<@yAY?a2 z0s&-DMaZ$Ic#~TA^scaV3Orz|%y^eh`?;5m!PR__QKTn1&3=^c;3Vm%x>i`%)N8_c zTrjBI#*$45a?fn&*Dik|vf@}Etr9O6+Z`*#cDBgDc%p>C>DaWBmjwitdN97E{Q&{?pSk0<@ zeA%XjKa7k4rZ48%lrP;mb7+FbPoXr;l;VrR9};+^7V1TD4RTzGW5Z=lvhaJA&vuWp zl9{UXn)-chhI1VYrpiVux!p!O8hH~6Y07?2|Dib+)vVE%BK%}&^Vyc%F2NMg82f$5 zle-dfc*4>tFuWhTlGadJb1cxTP@2;KcO1;oKO`s&fY&B#450yv(xPhq8?y{0lI!Y% zckF%2)wEI5T9D%;T%!OKe8+dX#Mw64N~-}J!>Mh>HePjjI$8DeJ|=XN5i|(d_)fC{ z8yVrHXdI+f>WzwraVyK~$eYLJP-l*2oYFYd;?1A)E=WCh+Z(^7PKh zRI;pFmK{~2kXz$V#pBnt7f1@8!4P8}pGirTh68nz9KSe;A->Lg+O0U;rr8uP@Pq|V zd7YGGnhLc{*dQA7@)}7#$qDmBr+&pN$bbQ)MoG3Hh{;baQs)c1raJTEoR#gw(a{6< z$iFVOU_K+eSxtg^X-UK73>w1j&G*EAul3IZl<4x|kWQM{Z5bLaD9g|8HRcRCR;niQ zvE-(wl6VJ@;@zy>WioE{1;@euLQrhL5dec(Biw=Mw|_1$<Df5E(pRz~j;33p^98f9sS3OqB^6U)d|FnJ_D z*xQ#k?x(9ZLo%OMV%@E1OJLOl?ZV`zj+PsooKCBNdi`~h)t4VvVvn>JCjNl137pEo z;4?;&kT!l{njg(m)Ymb|T0IEgN|e-};p30b!OM!55s{27oN*st!{@`wY=UW#kQ#g; zQDYTq1y}7`2uNjVj96$1iKg5^l&OpY3QndLt%FAo5uQn&AKeC`JZc8j-9e>pniFcUOq-ADJ2Brs<_>$Tr>UAa@fc}kty5mKbV!Vf7NraVi)KU!k8>FE1P~e# zIs7-1r5eB#p(RxDQE{W?w2$=8mJ@8JhEIVyrd@zE;|4T5XDHJ!rR=~F-rYlHx(*-B z!+?|Gy*pfmz)0m}0jhKxAP&RPxjr0+z9)anYV*Yr z&sn$1J7|hzjSqAd1P23K4hDLj?qra!icseK(dLw~l)_h7&e8xr6(OM0Vj%~l?_V9= z870bEG(OV7rxX^chMH}gQ@1RTlV&I>nc>%N_;%B{hp`od;HA zbIV<-kzX2%lhr($ZC@{+7Rv%hsxtMjjI4^y`ZnS!N|fvva;T-g2Z0$MWJEUznL%Ip zBs3Rm+C5}e8DIcC%yv#m&rq1D;kI1nf_)z8l5nT11B_qk^?w?_e-o$-UJX5}2zH9O9ey=}XOrnTs6#A>1qr ziIfjF-d~n4Bs&_F&wD~S{$=da<&6wTP>xNZK)*o&rkF%&Z+&4m&?GNE6=4-!J_E;P z`;>{WrCl>+mBt%}m=w(;{{nkF1FB)ohpIcCTXiUeKkjmZ5lPkP5#OZ8I)33?=}TLF z;uuCh$~>Cs>T-(_HC1crSo4(-L|^jro-miQ(kiF5BlFuur!euF<5dW2@n(b-VUN}H zAKLwpjqSDg_-wP0B=PBe)rgPFeVQ>v{2UP91eP&KI-z27^XO!Mxoe0a__YnNlsfrr3eBWyC=5Z!p*g^A@?d@D zWwBRPkj^&@0nSh9(XC}dYIf0iljW%IEHq~m`<(jqa?3!vb1+H1HRL_=lmj%`Z}iT~ z_RaHeg$v{)oTzP`g5jUx#;`9B>bVeLygzG13D^zttw5ECai)gGFsnOpx7$%0ZW=AB zSVoii5qIm@L^ihT+|>cY+IAv0bnOiPXsAh*_#F!OW!vYxzUm5iYLZ50{27Y9QfMP@ z|4X^};j_WX%&BzjTE{bGDS~1j8IPii9HB+9o=#{xwqdO zPy0=Y$3VfC)L}@sYt@t+hEAyhovCX558d3qGpgi}>p0I<@K%J}cjjR=s8E&kaHGfO zbhYZ<(Z)~10H8cGdB{I)#EKxo;~Ocke68z&^G27vjTNMv2gEY@!$R_-szLEjX3hF% zF!~WfDV&;&_*)~781H2UgHASLL;tv5<<_=-9J>*uV^|21}yx zw#-c^Dpz^!WC6wtUfQjNJg$ff#F}ZktYtt;ck+uFHP7Y8- z%o}0HsB+WOHnQQY04tjhUo9f8xgfXNl;-n%g^8P99Yio4to5QN|4#bXzeE+;?Km-N~pmW=5qdnR<)(huc~$FTlK$AonNo9jz4u2_RR zjiT533m+%RCy`PIysG-~T`I#_@{f|l%2yxj_F5g~lP%Y463s9yl`{34`&GPi_xw#} zMozxrv83#z3(2hFm`KmqPnO#vMdB&hD~Y?y*z)@adDe3zkxrY>Ft9HhLYZ`>B$(2(Y!dPmC1T%RQG;){%I+293f|KwEZYnA-Klb7VJ9f^b_$Fny8+W zMvRGjM4`D`$W`%**x)Vz*B9N=lOX(O^dI=t$L|{CV|8J8J|8{st-JG)L?fZkmZ+P| z#VMXK^m~_evaWaJGhH+kM~L5pee(tFulXHnJ9P8vePOh*QmGr*j=9ZmKxJjBSp4P# z18T}s^gu0uZ`f#y{jANdRRv(e5xC~u7QB7)rn?EvEdVrmF~G#~X(Zrn|8?Cn0!k1DN@7Fl)u(;wXf zVs55=&Z57*@VB021i0Rp-R-rL{;;Oh%{t!qg4A1$HAcs&Bx zT&ynYu$4G>fOJ3uj59$s0X$LXMrKUPHJJhrIHM)b>N2`NF|gtU>=k^vo}&3D(dnes zxHkj-CFq>VH0T|xi=?N}INE0@Z=sFhdCT#U{LNhyWv=;Gn74~aIHriAWFmZT+^qbc zY#$Ngj;?j9{@AyT-Kv@jH#c4UZx#^+qJ6m2)w3>xU8Le*k8$I3{+DFbDC`pwq7ab* zXpy=GcE#NoEB=rB<-+2=-eS?uBmEgy{+UhifB#g3XaLy307{Avqg8MAu>Vdy@I64o z7FV+GUl1+-*Uz3w0NZQ~B|(N8L)HI&g?8Tm79jHa<6j7f{ns2mSb!L*%q`Zeo4w?} zMy>@kWs&}LfbjsTShfniJroDqwJjlh}V9=pWzR&Go)h z8*!iykU&0T9x|H0#JHzM?E{piWM1_OMKm}Bs^!r|j8sKujM&n}F`Y}RtY=Eq4NezK zaHA5ApE*a~cPr4LgYQe`j>&yvh1+MyMCU4pnb7~M0r~TWc7iBg@Mzp9QxVu{yY8DF z!8G%=SQgvEqQB8g$$+uh*dwn=Dm1sbyh0SW9{b>M6|-^aD>S%&-*`@3?Mb;?Lpl93 zp={IPgYG8y`K6^ck8?bw$5^XMfg9e*#*aLP%$gjGwwu=nw2kUX-YXVyVcwmk18ATR zP{odGDz4|d?dZLxVP$N)49uMUZ)(RQ?7ibra((8NXQRyily*xb(*XKWd%$ zuXFx?zLP)_53q`wC3zICItQsTUaEreZ$zcya6tGN5^(Oi%li>1oiZm)|O@- zDNr8+0Ya>dDPBh(Q$qp%SG`&e`5e16kf%jYl$y!dQD88I?6l#+(Ya|$NzHqZTMYpG z%Q|h0KLwPnB6C!;I!a7r>2%{pJ&6Z)1zmP7_@~k0v#!T=&L&5R+A;L$s<1@&zG@W! zEF26+%r`k}ewP8O?d+lcLe@XZZp3guB6(j>p@%%^wvC-qFy|`I-9DqiFV(P(TzSXE z`?RQ;;`x=ZT;b-Nh7gtROFJn+_;DBgRRU8AfxDVLseJSjt7)MW2^Q;L68p=6X!TR$ zi&H3Zh9vJlw#Cb?#Td=gjI}JR8=Rfbrg_)3)EW5!IGev1By51}BHo*YU;Wom$4jaT z(F%+s5p}MmwR>H~5)`&oyCkY_>Fc+(+e640A{iCJ=lQV|o-D{iHa)%8ucYr1?%-4s z5iNDUoI6)E?fXt`!-M+7YS(<9smq@f3}`!8M+tA&zNxUCqoz~NQlN6(X$s5)Kz_8! zXTpmEXvfjsX)5u5Cfh)S0CJSB5LGRaz`vQHxh)ovl9CcG&gunU;?B`d52)Qe&5MX6 z6xtDOAXE7M+y`egEEFUixOn-@S>Gk7_Ub%+?_?#Vn?6j0E-TSKsP2l?OP5YH#%$_X z6a?#L@WAP2^xSPFwQr|#?to+^F`9ut=861iTiHV$w=h6vBK)d9{tn_A`0<8m&C`Wo zqTC@Xt}30W2h=szX1yXF4!P4yc>9Gb zy|(><_3&Zwz*}|!BL9y>KD%z)HFGs{>{4d64l8gTBkV`YR_iP!yo4!JbaDk z7vcBJFC5$e91Ly|V_JE(lDL#eIp3g{cu@}s+gv%hmX4hryH1C&yGXYGQcB?erlzd? z>g;&4;AP)_Gic1@snhV8fuhrN`+_vRv3Q9;aXGydzO1bA4@1L|%Ay@|B#H_87*K5d zC?pG({~4}9Q0src#-yA|xI($jf1hNmwlt{jd@m)(VMPm6<9L4)fM4zH0Lj73lYP>G zIG!wj;v(^Q_Qln=RpySoyCg2)Fh4M_=efsF!3?VCqF};(XXD&|$k<3@nb^&FLinL8 zAN|5ts`MNOtNe$ssKLIZsraABQ+dH*k(zghsfIjPz9a|xS$==|N=h$I4+$+!^^u2R zOeK(+A0We?7LTdH?|+JGxbG5BMH zUt`pacRX&2v=|$6%k`9P9Rs?sGzXT7OvlV#PlAk*M{&nAN!Jl+>6d;Zm zo&0WOn6xiB5_vMkmk2wAunkxDpo$te<^FO?2imp_Q8XlG`BI2yG#ecew`*gKf58>B zPb$Z{WA@m^-`{^Y{6|Z6MwOrEi3x6WY%JgX&LlBs`Om&xw6`#Bc+uWlO(VHiyUz7x zN`1a{i=Oo25_{p@P-uknR_YAgd5mH@qf?cIpZ{w~X{q^WSJ*nT()cxC)`>}553cE6 zjG|~ZO<6x4vp(~OnVCp(s|+$8Dx0R@R=uB*8sQ0n4eBk~tZb>n6hN0_6XNp8X24*( zs)^E+#+YNgC?tY^C)Z`mi~bhEA@<(XDTe$+Yc zu5yx#Iy|a7mvG*LY%=bL(TFPy4i1*BOT;)Xx*VMKGhb=0?0iAxPUOJj|QZ!lyCs@_eokgNwS8r=OG7)|Te!mJA79(dOZumnQ2i zM1;d}+}xZ4@m!bMTyqnT*~`OCEgKH&ZuyW7ZZhxKKi$<2OZKp^(!&}X2`1mA!+sm~ z<8yc5YI8lYnsOAv0P37#u>RbR^Q3a~4Wi!~7Ghn*t2HYyJUkpZSsoVQX)rT0;}5CN z8(Kk?TP~-dkVwhRNlE3mZz=W;4pJ%n{iB@dq6_u=U)q3Y1N{P2vJ_qnP0u}DunCqw zhi;5~nXIs8nxO;NJ4*jSiZFP<gkgGke9G3+a_S`7!Ur_xt(9~|rFdC& zM>lyo7AcNmC*g|Xah`O1l3E_D5s0r3U3PszDwMzSC)DFAD@oPWG*m9jEu)e>zvAE& z%HCP_#K6GFsnen{Tv$+3*Jg-@Lm)XBTCveF@dwfQMQn-$1gupb-xNMl?N_z_DfnI% zarca489G((;l6NI9(-V!m{|J;-?zOD)d~K=u%aBwV&3Qx^?d7*Yr+#MxkY%OYO%AW zP=cyl3Qg7fS=W`-Jk6^}Cn}jAtygDrj-rM*@~AnV53fHlS7wLQ3nxpu4_V5yP@gT} z)>K^Sj5pCsP#p>Cx?_ev- zL(BiX;Q|Cg#31KSeBE{CNKXZArU_(cpZ0pZ8+RiC343C?RNek(-$8$R_u+sf$3vIV zyPm?hwJ^CPMl9W*QC!m-9yRNPtZZxr6tpN&YFEcQKNXCxF6+wVT@W9S41ycG<88-J z!3I8v9976jxur7>9&Ti!y}dp2p^Hpp-9y0$2RpmxqDSKo){tyURqADoJ2les@|pc& zI`XcrhkS3@ILZ!8dU+C5#uhlq7iqL*x4=)MN(>)GlOjPQ$75noM~wD#)RZG+A^LKq z+4!VE!6+G{wplh0v-RlQ*1$7B9dfWR;WL>imsmYTC^b(7n2KbjcxR=Zrk-bKstX$J zotvK@;zB4FFCzI@!Stc&T32*8cfZ!H5yldZP>PqYg5VEW|4NXJ!(s`WcH zS(P3OT-0#%G7fg-;_i;?zy3O|?Bk-FkVme@_W>=@x=m~}C zRJ}>WI-}oeXwCZIiGWs(xUpd(H2@gAZ&y_@->6$`#Z3*F1@8qU%j^CA4cQp~csO>i zC=Xa}2m9aEyAyj^jbZ6ey|f>E zS)Jvupu*~t;g^LT*%1#`lt(S`eMraR(jcxIe|e-G!>+tv@mgs`5Y?=&k#d>d!?iO* zdUDV9pU$2m+KN`2zC`+GBUFnxCDRi4JvjWE?vVY4v25dBP$JF@*Mu_!`|s)Wzt(B9 z?Rj{7L(~PrvVko|O*S@0(P^2jnGY$2LmcnP)05D!Rw1b{N*G16fULRslf(6yEY6FR zJWXY3>5msp!rDQ67+gB_hA8)icAAECv1V^2Ev>5C{(F1&lhsBPR77o|iK4|-C@!xP zwv*FSzMMRN|Cg%-UVn<*=!!`7&(p1rqctz5GmaASN?P=I8GB|~&pho82{l50Y=p5Zj>==33%%ojyV~!_#4BD0Q2^GyH(P8Xe>ry0- zvgeUV`Gz>bg!A)r6Zh(B!Kl~-*+{bVSgqp(LzH&ZLvi`X70E25QF#Xr7 z0v-2(9&Lwpt=(6V9PCGSLNu>M!YIe`PeQmk6JrtUW>pUr@gCE$;+G$mWP^J2UEcZ$ zEYkNx~cBURogDj!2Ntu(6 zc*spS9}TRFH!1)+_K<4W_3I?l`dUjsSZb4RV26(CS#@@{QnKta7MT4G2l3eHCl3## ztgyb8%K^c?)bMa6*ROW7r-%AO#2*Xu21btkJ-_Ca)-m*5`%-(+pQm?jjz3b5fcR5^ zQ~PHM->drtaaVV@`Gl~noJsln`0~Z_N}!eIMp~NCW1YPZvU+Vkd{3+lo-(cEevDC_ z)nVN!Ii#ql=hxb4i;w=WK*o7y5i_D)ob`;~^p`^g6xHvz)99JClp)0Db%{aFZOlw1 z_USK;e3umRy``-6)fcE2fLfYVo&OU%M4>ULW&{wun^lDBG403ziA~S9i#lGR*YmBM z>8Aa0OxTJdKDCCWrKL;XU7Jc$)HUo&b}U=Zy8YQ&URT?#hzM%7ot&JM8Mc7Bh?iFc zs;a98FOC(XViNvb-ZgAReSa93lPcD?FUoaU#GjuoXZSN1^Vp;-3PR*MthX3+94o#1 za0R+O7|AGCmBO`_cW8;i68R+VsP&kE5uezGDldcO6-h$Q%8rO&9yZsO@Lj3DeDC0q zzix?q*ReuH@>)R5U_>@r(v>IqyJTTu;gIAMLfn+)}iroUEDK@!Vx z0(*qJ-EX35v8sH|dxqU&4#`VUB)y)wCwxu+w|6!avx9TAO|dHMgVEwILrsnqxdK5x z+v#LJly5f^J{e;{$S%1DkQpW}4b1=L%F9P9iv{*f-dfsPmO;pN<>XGDPmHRe15*we zcgpgrNAv3*?b4MXaRHF5a^ZCU?*}W5XRc}E{To|RzV#_5;JJiPg^b(NPxFOmA1gX- zC)2W@ghqP(%D`naK#dhFSoH4I5A=VmqxmXAZzYO*LLjO$7yFpj^M-i(&Vy`$31_Tk2E`WO01FE=ErG@7HDP98;U-WhA|i2A8Yd=AVBKU3bJG zY<@;OUgf*h8r-mN{g50#lR*iY_@Y8>-URj1%ENl+Pk*AI?~{Jq z2^@OJ(ZBNfAg(#wr6~4HV*%BK=nqT&6meYY?u)^7xoFa&i8{#L6N3C=CTE_m-m8XN zAf;5^j!~kQF54WQ=CRUZmc^pGPwxMVRm%)mwOTcR1&dM;dK%T4T#~xFml@2s5272K z+?~{!H^GA&w)m|i{{r=k!p1L7QDVOZml_w1)4B2&419(zFWfVO-|;6mLon~)r%^Yr z;#+c|GqV}ykerI7r@bmZq{pK%Kw31(%*pu}qtMwuwg$)dhx6*d7wY88Y`Lj=Yc_y$ z+D=mESE%9lI=Be1xe&9)~Z5<=Kw|bX7F!%)GE=9=`FEs)=bq{QR&)a48 zCU`v)YZNFZ{wYOWpl43XnK3*o>i#xm*d#fJ=8#hFNouSEiBD|$FTK<8L(65VM}zNb zrk1`JIP5lMG?xX^WPYU*9;|jSGry?eQZIRR-sl_2B37U0L+i)!v(@oyChx~TUg_Fc z!)&uxjn97O)JVsMZ;(g$#=oquF!iuIi6L?+9}y{;e?j~7%c;Tz2fewyK&_`BGHc`E z-6WmJsUeC+p<&2$jnjdctNEnk`Up$F(6GOML3uezh0P)CD5zkswY8OE!>n)cm@ycx zwPZr+LL+hkH$$FWq!-V2{O(R|8nkUMJ-q8$#3eL_UyN?HsmEp z%g2G$1D0IZ4yX^Gx>Vlx>AQS~CA3cAT)zW8Y`WV`VKu9AJ7V^(G(3id?q{I4ZUl#W9!6@5m>S(@hBUkx#B}tLFNaf z){pLl$obFpB+?hSCOsq>=JzNaRC|>5UI*gSh-xLhVm>?VV)NpkGLxNrp)>J{%%&Nx z{ppiP`D5yPdTz&5O6gd#N1y8H*)W*ZKWHmJ_DC zQ+Kp}75{0vS(58LE_WMABDMSZ%Mpz#TeTml^EGzcE|QcoYbx(E65y(Iw}7EvN2e!6 zF%PjN+Z|z5oV&kZ`xxh#9kNv>M#P0UZ5Tya$!_r&zMogUcSzyTZd3IhS`CePM_h2J zKZQWWWgAAu(2$Dn-g>~y@K0IA3uM-EXtx$z3?wr@`gp(N(|2pN)VmjFiGh&3?dM(2 zyGY}NH%h&D*BhJpKMZnibw1i?3!#z%@BrdF`h~K) zF*%;4l_^;%$y}wLK>q{Gt|Ba?~f2M!(#(B zSA3drF{X{b>#C|ampDJf)?eHmWp0Q++V~FaH~K~3NuFUMUPa||Y6e-7naWzZUmY5Y2d!29S>G6PE#4jM& zbrAchMd)fjx3iwE+S~3Jj&Bp8y%eO}m13aR^T<`#5wbh(RRj7d?upaC>a}V%d0oR? zCnfT;Vy!pg5w8Z9k!1$Pq`BGoX;)`Q7F}$%`5G6W@=H(U$Ynkrh$;75u5M5ZFn^1P zct^frM(sP9@abZi;_5ldS?5c~_$gg*0Ea7#ZyR@%Kxg);ydZtN8wvlf>FGald>Hq< zZ{6?`h`8kys9(G@w?w~v$A^@_ajVvhnU>bO5ZnukPWfa`^3sdKb1%pBb>93dmiDhh z$8)yaIx#%##IzG#wM~H(CM6oQKy}F8!C`eVOydc1Y<90IS*Q5D8wzO1$h0XlYgm$4 z`V7>C7z2WO?fK3{B_OE(DDq8%^EB4_MCnW9l5VD=*#Fhsbwx$7HEYF)NDv8%AOezx zB;t^R5(Okm9AFU1K^Vf25s4~;WF$w40}MG142TRlOOzajAUWsZHs|~gXWf6T>v_E0 zZ@u>F?%iEgyXyO@cHtXL?wh~VccUh(bzQG%YQFVDU2+=yrZ+4;B7z*<;{*KTQZose zv^1lr2u70B4I1$e10OW$oa?c+Rj;mTNhl{B7j?dk@#dtR?TrfEDY?A$!%C!r3@G~Z zn6c%A#G~g#E0E1u1PK2(FU3CoRMK@LynQ=8dqKQw^zY#GcSfz&9t}BZtFO|bC81jH zh)2uoLa3KXVWECC=T(=*rCOMMTtXz1KW%2z<8ez83S01(YtZ(@>8&VZ_2=eRBgW0+ zighQud}RJPV25oJnzb?Xm_~Wcvt)ty;jkkA`qG=Vkhc$4Qa>ZQ8KAoP)M{;hRvcAWaAC~Vro@$s zW1qrluuV^IhOB zi|F$SkH-UdU6qng$>1Stj0>1Bah)v`Mc;Dtkqo~_x9BYr68_kgj}POOlhTbdWXgLa z3=6a^H*45ezOfIv(X2*&?)(}r=ZDhJ3PW2{x;+j~!@OR&Z!+p0dD?d#wu1ep0cG;+ ztEtwTxIGjHZ>6nM$-3G1E|_eJ-^p3xc;v3S=vY`o$A}k-2Cm0YT4<|MAr}6tR@Nf6!|{@dbkbP*Z4gMO@+Tb+OI>#u;{GYU*>dmA(8sfpOMj;mbC( z3p2~1;q~?Po~r=ku(UZN6%`%F&UHyfw&HHH`gJu|=?8Hs;r2d5o?AV#Xp6s$`N&dF zFsqrovGA&qb>Wl#h_B9)_j=efQd1xOW)H>|tv7acDOp_~nZ9Bzl_;e1AHCmnQNiOa zX=8_Lr^Kc5=><9UJ#B59u-W!ra+8I%h^tUM{{6rOM3}C&^e`~ADtiH_Z*(@NJ8y+J z9NbEaB1YuYwyLI@tj`p9N#?Z7SLUQYj_Jq5nxS+IgwY}cZP>`CC z(&y}5;RMVPb&{aHejy`OA?X&&*7i0PNJi>Kcme%lWQ43*O9&l1he%%X;1d@Y7bBK! zH%pLeHTiAQ&_@+jjYd7m6OCu{JlpZ!BZEvQ&F_A)sAmbOPwxSwi{v2%7xcRJ(uCy=WJv2(4e88a#Eh{{C|V^?x?o=Jze=h8jB%?rGZR5_8egCoY;9mgOQc!ATKL~!5i zlW{ThD*xJ@EL5P)#P8RtpoNMAz+Ls%uT3xoD}EfTEF|C3egqQTfn2NGTd=;~W4)dL zh}G-4&2|3ZW0iL-KEo%4s+!IPBATyztT>5R@_8i#j{rl#S!24z_0bM9$%eO31TT^4 z$tH5+U2&-!<``{{$imUthY8uH0rd}ARPOlpb~koq9~y7`ApNRnWZ_uPqak5aGHv?( z{&(-3fKL*zLVZjIsnVfE#Tutg`ysLLhX?;BhW-~y0lReBV4#0w?mZ>J6Dmjh-jxYk z0Kt(!)E=I|VX&K1@x;R@ocxN`(b1O`8DI?&3Zi?^76+TUqTZBwy>$xcvxK;X!{N&I zJ9<9X`3iXy{l{?RqEO^hauUd$S6L&w8xmo%Av9ce^%J}Br1cj#k=M2T1U|zE9=w|K z5rA*mRIGe0Gp;D{d+Hlt!Ta=S1QOKIX4+YI*Xn5i3}ec{rpN~j`grD5SKo_>M%t#GojnY zESVFmJDuHR+f2ZN>QI12dmnAfv{!|_7z7W#l`6{wY*((VKKdq+UCkr^XrxLP4vv${ z%w#SzZgHOZc=*Yar4kI#SC%t~F_p<`Kj)3fwiq}gxn9$QT4?sGTuN|B{AraAQ)XtS zB>25S#YCb67dVuqg={n+unX8f9uzCU{A4HP98X)0Dw_mHrT1%QmVI+HP+ zjiz^~QZhZAcXYcNIr&xE7eGQwCvh8tqg}(ahv%;jms>VIVY^Sc?^L!4 zuH8%6@Jc&23gv6mPSghIrtn#l{j@Gj+1{HIU5l~9J@Yx5KL;(eFFw?>a_R5-%7p%^ zv?DFXeDH&Y5{GOaq>phGy`b2qrQ#CR+;ZJ*m>LazD8yKAU5amrNUcpSZk|obM09D{ zKNi_<1ixu`9u)N3;?XKHhb{YOwz66YOvO!1V#>xaiT#JVPYkfs!F{Mh6Y5UA&d*qC zVB!WhX~g^oODCfqW5R1{YSb!voAM!h#e6fl!!ZlwW?*fRJ>ijH!gq{}Y>yvH=i@{j z+@`;`fvKPRw_;n}<@v-__;KrWvVSpZas}+q6~_wy=G4?>wlopQA~wW?ikrK8`?lw! zt&v?Rgi>3vyb$FtLZd+whAcI>PH`(7QjQc`I-EO6oJ)LG3T!LE=!vISn+28Be4= zmW<87mA(jA@H8CR34ZxYN9RufByW9!3GBh z2Q#`oNP*^=pjxLvGOS=9YJjPkR_d+uAb@{HFd5QIe6J36a6kbd(MiT$S$N}GLh&R2 zm6Cv>rlz!h2({j}nh*AFZf=WZ%f8|5g-&w(!qAP%E{xykuLlw_C!TY%m+LA|>GnoM z_?fhTzTIL~g5JuZpw6hbw?}v+>u~ z{Y#gKRpg~#XykX&gYuWQ91ZlXlu#wD5$8Mz-<9D^ORYIz1Mj>^Jxo-yitF>Lt~Ct- zeN>MYx$f;w?}2+a^d_l27mDI^sL1NKjwMVY_eGfwLxD|J78N@DPL*ehff0ZC;iop^ zet!ze{uass@}dDrnwSdQg9=;SwGMC!5!3yoT9l9uz=&B8cVt`xz1Rub1Rz#$}S^Y5_78FZAlo<1BVBqWT4kI;Ryt;RkyF!LeL zlOLVEO%wsdd^AZPi;7^D%%CX(!>awIQoi!#4f;n0+*&t@prg9FO3swIB;B*=jF5`X zT^6$r0nr<_l5Oq3&64@3Vn#WNOsgLi%c2lR+}s#b`BrF;^|G^pzP~H#9qnGq)6iN1 z8Y*9!gYuH}V3PNzQ%-aJLRa#9t*vq8(?EEf z%jP+qzHTMV`8xgC#{qH)s$LU5+k3!|_}KWv`b(F7jZ^XWjlAyWCxU{p`0bc_g&td_ z6_@%_ODzf0^R!@}P1%FWDkm$94oB%&x?DG7Nyu!=FOAob#oPrYn6 zb>vekRnwYX))b~Z>(oAd54vqtdhc!X-O`McW&mw2ldUq7f{FUXBOT(;do3V%YwiHq zgVflj;(_*wZ+#&qwBxexWA^)MGi-Nfw|jC^8_WBI_dzgpAzwux*4CPfm}AmVOJ&;B za^fqS`31~$X3=Ioxo%y?JUTP_XYBW{ToNwD4>HhDF@8T_WtR2vd7%Xl{KB4@mDO*a zQsAs$PfZ&5MY`N>N||Q23Z$RcOhgKA^c|i94-SHznE4`6L@rvZwnUe&u1gcFhC2Tq z_=xL8nVJ9Gr>pNh+I4j3DwRPQ{fJ=8a?J0X;_BRFX0@xo%PV*m%jgN|JMZ+?-*@Z_ z+Q{jhNU0_G(I!>J@@}wQbx9MNs1l&fqvrOWyPC?ZZwkO!8VSyp=L#!(hoW}i7+*Re zi+n!0{)#nS7jy%W^*{yO5ArYPd%@G%)Nwp{62{2rubd9I{5eBPwbX zsx0^kps46)i}=UF@A>`Si#uplHP(U!h{gP|x$nFtmaFAhdgacK&uO*1;7`pJ+k-<5aG3$s7~9$S2Ht1@D6 zcfEwUYh-(EkYZ?Q4Q#l?_2&Tg!VESfDSa^D3k(cY4TFg+&y2=LxY%R^DMIR!k_6Sk zG+-pl>niirK{P!jCH38tcuuye%PTT2`|%A+SAB*Wqms6XLO?oKL#YzfyKU--{wXBqZb&4dHm4I4{r7%}KF_WZyK>CIu?B;-A6hfQGQX z@n~+M0j=mL?z4Le9v@GY%}1*U*p8EN=lgf?UH$L7 z{);OKH@-FpsAhR*+9P+*n`kW7hI@jBj3oB8qaE}}jI z$E}uJ;8}gTtl~``UqHjYIU73xP8Rdf(x_3cbKko|{zN;jMH0w5U}V?@rI(aE)!8la zv{fblbExvavASt)=7zTgLj`(~g@uKHBq~j=hV%^vi28?dFyq*OByQ!UGIuqgH)ZCf zU}CsE9hF~kat96_Mf3keBbWE?6eDt_a(x2L#28WJ_Z&8^+I{veDbq2_eXuHwSnMw_N7_T zOT@;gfw8RY^(0Yvkg)U8b2U2QaI|WqJ(;Gd{%h8=h)TFbVvieW;r1DXa$u~lP!j_M zHqAigBeUC)I(Bl=YL>Kl7^HQGrs}(#*q=x7SDNi0*leBLSl#7e&z={HIflavLwKY+ zh#!?5qdAPs57MNYJDT+*i9P>Shtzq=Cg4pWMd?`5t;Cau($uBQ6P~uKGIR<#E}zYD zN-<(iCq&CI@NKv>+us3vK{YNz69PD@km= z+|z;|9`=RM)8@gyy^U_>9iqqM=izT?2Ow&^iz~xO(QNyMBflLvLn13LSpLwLi+c!q z!|hG`i&1Y@V98uwY&X_ z;Cx2o7t}=Ps!LPaw-EZEvu#{QR9u|=^7671kg{*o#}U!k*w{MUlOif6)}|DD#nF)x z|FGKLvLX*tr6?Xv&xYrNQZ!rsPBtb%iXO;;es-3nwg2AJG#Cv#RC5C^&pm_p@ZK1_ zo=l3@@h<0)EN7j+en;XM+IJ9|>+mIWd9U~!hR@ma-JxFO={8KP|9zG^DMmYY=D1>~ ziIu}PCl0tF`@eMLdV~n&YzunZ<7ZE?M|s^h;O}AiDU={XY%^}aE&U%OF1`ow)&3uh z82`K&igwCo+Yi%OKMifsfj|_nG66vQO;k70gl4vKQU(?UaNO#zUcE|EMi}rqs1BiZ ie&D#r1spmp&*}Hm(eedE2F{m&LtaK%8YTJ0_kRE#d$u9~ diff --git a/test/integration/consul-container/test/util/test_debug_configuration.png b/test/integration/consul-container/test/util/test_debug_configuration.png deleted file mode 100644 index 8fa19ba9399855fe8a9b76c203cb0c2ef09c3f0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 294046 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

h?A^(vY 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 F{{U`(riTCk diff --git a/test/integration/consul-container/test/util/test_debug_info.png b/test/integration/consul-container/test/util/test_debug_info.png deleted file mode 100644 index a177999c0d95a407064d4c3953a823fd136a3d35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 622325 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⁡LG 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

ef zDHXESgq)f;6V>{BF*{bi(8LTH$Nq@{eE3jeAx1rDbGz0P_; zspmQ29Ylc1b6aCQfX~7gEh-H7B0$xD%H7N5aPH0Hyz!Z=+~(yNL@opTY&5+RFs!-X zaqHQq1p$x0W_~0I*iZn?lL;H>_5M6x2Xrpj-|N9?Y}jt7w3d!xQFjmOOvtPUy7XrG zqPZptM#kW1<`V_h_`}y@rG|`FBumdDGfCW_%qqv_g9SDo@*cwHq>8U1+9x28dz5?< zrQ$vE`cjV~Eb8eC!xU~FC$j|Fc;37&i)>5yU5UlJaBJf{l;F(R9Le%Kt%@wjyNAwR zXB|_J30SU9M$fo0wZk){;;8SqjUfO>Gk?heFWpNm<4;+{S|3KuctZ1L%Q21vP6jHY ztoi~{REYeyc%n-TteC1qB^UbtAwMY0lpJ*xMu{ zpfl;UO91GVjIN**>!+FLvop(wTX=-)U(hzkjRZcoY0^Go;*jxvuqE=+LwR1M?$XhS z-H!q8!IP(Bo>}(S!ueYse6>?T8BXR}^<_2_PGG?bcDS)aB8`xBoF*xR2Un;#HVmTv^7iIcODzc5VZq>RTr zdEVZF&l;>Zm@|xmtaRGGr^R`1f$QCr6Y67nDu~PoWEokiDHb~o$Q^CtNCi_HXFCAvKn+)pizm88~J=n3a| z)axD-_UNTA0+H+ke*-CkR;KT_;MQUUQAsaBj`SD|P|cT9nKl1ZLqO?MM_g#rWwan? zo2yh%i!%Hy(P~9PL!#o7haOb-dPx=055hyMgA+my?Kz;i&e9LcFMi-CYuZ~J#+AUX z!-30n9Kn$P zhvW@Q^!DDoq8Lg^eW%|=f{bjtz}Wor^5V?!FgFV8faiFdhyvzduY-`Am=bfuZ7;#a zM1Bh{%xU3aNK4}`CMAf<;`9!d*E9B8;xlnv`rIuRJM{=;{Ii{B356PK*3KAVnH+5g zNDq_SX0wJ1RP|?_%*SaTaQ7 ziG3ztTFqMOj?jqkxulDXgy`yXT&#FBuWF64;@35+AX3 z#V;T**LU98BdIW*u*$$-@IdzTO4fJoGEH+OhwU(oFjmGi64$XzIZhT9 zv_9k8+{6QU>C?HwW?^C_C8ftqi^dM;$EZM9!lEdk+Zp*8>SJW@@r^dSQG08#J5B(! z>K}ONBdMyf7X8dvH`5@kh#LW2<$SpA>aP`R5f!h)V+nUVJ?U5;o?0JTu2DJ+3Oe^H}%yNj<^_9mmf;fmP(fY#^<-SONs0#q$FpE{$MB*F-`~`T1|EJ03%k1dXp(KsFd;(0U>-R zi#AXFjHu|x?l;%l%&!~G0EFE6cj8FGzv}^LT)2Z4L}y^85BVKf*w(@iV9&_4RNHRF zYn8sr&3TMTt^5gUMhEZ`#f~z|Ihm0sXyaTAj!12th7Fz%uByzdbPkZFeJtw`XYJPZdjcfh{X;B3n zf20Am>HcOW?D>VbXo0P0QSHvpmfj*AkvT2}5R?GMU3;jMJ57+kf2w?j6e=RRPKcAU zv(SrW#!#Lbx+0l(SC<#N4`a#?6}_4wfinH+ViRE_VEUtaRZ96bYEX{434?YJE1<;) z08Dy`aX2Z4yclBr{<{2YLG4gc5p*N=fn_7-1XGr7umKM~!1P8vnr{`NPT*M)6NNR1xh3WsnWo5N)ScH_P)L#!h?HB z_``Xa$={rXt%7*2-Iy%klSXE;ZKN}S$SEBLu4=S6lKf_cKq27IA3j2;Q48wRWW<|` zbk&6_0!1S#k*ySLz(O}K0dnDoQ*(nHTSBBl_H~n5z-*O(n63K%o!R;sVz#ypHI3Z> znML3YgIs4nY%1Y`#=03T0*TINAa&9)PqF>={XowQpcAjSE+xR^^Z`uHt^0r~{_l&v z`IQagnc$9AD&H_r*&v!|Kv@AWFuOby(nB|ZaZfD&%`pB87F0n1=TTdK?wXDl9pn1hEY2 zEx5fn*MGHZy;)i)bQ2*>~HECd|-!)cyz$Js>Rr@R6@+ZQn#8w4K+Go!!#-vSWdd!uKrVz25q#^1-U> zv+S+0P2_`LOFBY!YvCxzxf`z}kPh(9B>?ZdmJ@#C_sRGlFV;VQ*p0<>!7dkB)9(It z1v3-Z-*yRo8`V4?u*;5r>{1>D+AH;)Sbl)L?GF2dy8JHVe|+ZeU!Oz*OF%MFqrR>x zgSVeRYMtiCU+s!sTYPv5s($*^hQGJBlpxsNWQ^r+vcNvk`r!6Peg@+YM&RGe_-ip| zA&cK8ZHBp7UF~a&H$-hexpWp)uF(EJ-+&;&o!hDpG||ibebph*RgYmN#a^STNxytZ z1~E8T*waRVZYN~&`*-#uUd7)T@gKnnSk!JvN}ylHHFWd$Luts$-@*q01;yj4h97_P z%Rk6Nx)6#kAWkqY5r|xlJ;TqriGuz#LGW51GP;sicxyL*KZDG&h{e4HwCE0))c)m+ zzEMEy6#B-Cey3~{^!)C=2zvQHd$|uK(08lQ1XMDnE zM0e3XLhv@nR){TWf_{8xo&HAeP$&)4zNK^)%l!sd69zoMR#yQhTa>Xs`N4nM{0Pyl z1$L@ST9crmhS-~jSaJOjFF>XVOy|#=m_e42GPJRiaC!^mOmUW1I)l(w{iFa}T~m`~ z5%#66r6uBUYg`=kE0NAlVnF&&_o56f*GuYulHJ1F*FZV3y9MY2H-hW=%SvM*;S~5L zcy!Ge-1^3mjVnNmmunBr(p>XMei>4NUMM(VjxT1>LrMlMT79T`xZ!AJZQ#) z?5mv)f=%5$?rD$SaR76FEuI!vF@Q!aq=)La+C$lyY8+02>l@FuCPquFF3;JkRK=ah zK&#Tf!ss+LSX_?jgHI1O^w77y9OuLRrV&(g#}Oa3#(HDa4Lpbu@9Xnzkhg~w?4_UVy0%lA|pe&La= zJ<#S8G*asaB^<-Cfwr;PWUip@_Y=#2<7@>Kp|8p;?ttj>S^N9gif_{JT7VfED|YX* zDL~__$Rnp+Z=aFWZEu^YtGw21Y`Gj`CobhadPZr+ywLhte#2(YedqO6tW1IV>nE;9 zerahFE9xsJeoD;xN9sTC^4~;$e;cTlKJavHw4-B^}Qd1|y_2%sRypgvZV=uS0?LlGFF6 zsMC4@E@9F}MZxI-&JQ?#`YvN$s%oJ?oU<|;_*k45iJD#h3Z#yY9nQ~5$~5eozJ31j z@3VUZ8?4txhejmLjm>?-0j5=}t=;&@9rA8P1+n?kE?05`1)5jN1!qeMF3Eu2(Ok(x zc}@1OK`nf#{W|{Kqm3%gwvYv}k?G*+Pi@aUIWazbyKL`Kp#sLGdo3j-R;rJ~t1SoS2=M1h1n z3FK+Ap7$T=P60~q${K@f(FTjgfl=KV@9A#Go8k?S0~vyu^1T5utk%wPytd)-JkHr2 z;(>@n>)80(QLpO&Cc9QmU0G2f3#gK55Bl|A(4j&SUl@@92_!WZ&Nps%x8#3H^L*Z` zvRukPrY_^hgdIjXy9#MekbB(2Tzn27_rCbas{6ot*9+n#_{XW7({}cWZCPy_JX+iB z*rGvn;2rnxV`B(%hjEA&zueB`-4> z^#v(7Ni}JHI=+h+va+5Vmm2m#SA&W&jBJh7qZvJsLWUlhf!xkTOBJCM@_iud zGPta+U|=nGeVpKYNivuvFVan%<>7;jCn$4ds&0h=ytD^ggDenY6Y<0FX2f$>$_om* z=S#iTa5@~tR>&|_A6-D^r4FfYY+RpSu0=DdJBIJT&`y4Kw&T#B(et!E3Xv{!rFwps z%pYF_pkB<6Jtp_3YeeWC)kl$W>Fp9j6G==r4_50$0GTAr9%97nP1E&;ku3^A8=N<3 zqs)1hYXz)lVnEu@qjD_t{A{ay3wEQStw=H-eSA_}HhMFW#dFS@U=^C9Ub+*I7 zlG)HaC%;;%Uibp<~|F{;2C=(@~zb{jKV{C6)KQ41w-{fw<^{nViBjS=&ZwEHr z>)1C=<4q$)xJqCQlP;H;_j`0~I@ym7M=X;m=ev77`-&%DT6^da)$42|C&VB47w=$e zGN*tHzW)Lac^MEA5MeHX`zx~t`g1XdZ45)Sg9jcJSI`sEtS{Lc-6FQ${p0654#X%~gMj%w7L?(Tl$g)?ZG z9uFh*(@|TxI>FWq)_lWTmQZcKCwgnv00YPJrWXLW=@`{oSP0pDR>Q3ps|an0 zTyF^jcK^K0XgK@;Ds-x{ybE4BmjknYvla6ytEYCyvBaVX??BzvpyCWIEv=QjT`m{- z&;{^PnQwFB%pRI9h6-&>@BR!vko#{l#OGws{{r0tr_y`9>H{RF!NK-`*0UV~^; z*dNjT{55MGgv7Dv6a-4hnlJG&*`n>XERGkYaK}~rd(N^oUHW^1QbdsYk7VJ|f0kUK z8(q1VFEuIVy$Wa#bL@CM8EbxVYQ6Hj&uDf{VoLSAschSE_8LLnD+%6z6~m-Y>uYD0 zknfXF$NN@UTD!is7t}*3< zsv=K)B~Q+p`s8f3SZC|Sbq^Bn8_M7$6%-_>DOS-}oquP7V zbHZ2c;?usco!B?Z-TKTLp%U#f)J7vPwLvLid5i)(A$&Jj=kjQVJ&*H}uT3#%v@b0g z**E5W%X;8&V!j6|%MdrWiZNcj9Ue+`Fgj_`UME33i5r{#6op zwL^z0QvK5&KWmhkZ*o!;GxF>BP6~_E0s%ooU|t^Q@9dulzSMMF!@bZVB~2X5$Ln!8 z@?HOj{nb5Nb*$X6YvW&n>^~2#0l-GKKRv+*j$zJ6kXp{}SbdgZA=C-p4zyKJE`3@o zqWv1si?eiEq=LoG%uw=Fh~Co^fIxSIQX% zNQ5tns%l;$^FuADBi!4u9`Hygy9RXl$8&IfLcSu5kCkn`0OaRzbr4N?DEiW6D2ofY zV{ZZ+wj&u3K7O>Jw+tFF+#6S>AE*@&QMs~3ePv&spNi#0-%@V9iSnFCR$BNzUSgdc}o7wM9` z8I=dCQFNjjC7EU~n3GNOQzu0URR#Ci4B;twF2>-3v{R`+ho`AD6DXHe0O zWWeOS1e&qT=y_vgP`cY&jiFBild52++Ff6rIca=T9a$&JXDo+e$jP2t@b z&33~eU|}L`Aq^XD#*VfTO8Mu|e`Z(6lyL}Iq=I6#e?Xw%GmSW!`h$S`L~AjU<|I=#Ve8(laeJ{SN=!^jW$!+_ z^v^=n*^fDN3q8nblQzQ4PaZ01s{-PG*3}1Bxlfj=b{T8q84=~2_TBLvoOgm{PZ z)iL=~o>y|b(*A5uuAi@bP06Y8GTHNj*E8N^pmn)~X`D44{O3EE% z&SoG*O&`r-UCgDVQE9VAP`wu>ORHn8`*|e*N84x;%4q;sDAo2=w=Swe=C)~6bAy}3 zVtblz7^we1{r<5CQ|2*98CefYGl=Qv=q#+QKSxl9GE3{bAALXBtLxWm(dEsbD1K>t zvOvhgdK8(7Nm`4d;S8$&qJRp46~9VIVLU_~N~L6KN(vhJi7)r?mQzIRw(cz*#d~>G zRoB{X)$UKUt<99LUj&AL+HtMo{braxFd;j0wmzr&0?GN{C1<|ylWYg8nHO)g%Bx-8|6@_$g~$o2+nwu4y6qoHKZDjcu^cv(oOZARK{^DGz&$x;+lOu za-2O{nM*^g-=tOeYKCg9sfIblBXS@A&CVs&tI~%DtCJ#_4VPrq%%0vy+4|AU3d-=p zVHXV-s_3MQSFUb%bCQLp$V}>#_&>$JJU0PMKyKDBQ1pCf2vq6qX-%?cdl87BOgUv^ zFD0BB80MVyVVgda_%M7qo+GVVH!0Enbg7-_mAMQZEg)Sb+>`cOe`{WcLNCl^FKX|k zo|QQrQ+Ln*ipU=+%3ew$lb*qHOo2H$AOFN5a%#z|K&Y=GM!L1(8Oh7eC{M<;XBS*L z=5w)=wp|hK|Ate&F+pyl<8d$SH=t$m2@1d;3q4qPQW_0_PJp$5%1Xe~nU$z;4tP4p z_bSDtF>DMx^^IQ(XW*I=oOXS-(d0rw#!tf4*6Clw?(V}t$bSa_IJfVOR00C|P%(Kg zQGjToVu8dRWbRDE@E3-R=Mi-B32fxx8`GY zF1%fVb37tc)L^<5nq&e?Sbc-!mMW6?c#e`LYBsamdP_7tRnmrDOMzx-eI(!@svP{t z%gp_E zy?4Smr2u{fa6VlgO+^UtT$~*Y+UKti)nu$bkYq|TkOrdbSK6cCxH0H!+%a;Tx_$dD z5^2xyTpvXU8B_)twBQky(oQxdoO}K6taYe*WYt>YQ0K0jGTZSO)$Fj2a6ib;25LJ! ze15hBq+QdwBze#H?NV~63RJe6<{00u4zPb{k6`ti#k$7Lu17~(I)hMSH~Tozz=Re~0 z^2K8}Dy2+xJU_mNi!xW{26vUz;Du}`T>L)z)5W_f9gsh45CN}Jn=TbYP!rVr5@e_o z?0~xBYveNJ2*kEB8@$%-x`+in>M)f)GJOm4Kc1x9Z^p7`+Z74kb6M>ziJ;^tC6zFl zIF>g8fTua|X}(<3)rRt=Nm(lMTz0MW)^w4M%LCRX--PO- z9|^I|Gw&ath#S@HiscH^gJEwMD~~;ds%6Gm$fLuf!KkW$RYB;m8ysTW2%t z$c;cUE6M3qSM#Ea1f6;p5M;>%&hzs1um1yxZvA2PRSU zORqIG#DB@k+&1|9OqFFejXb#9kKVrS^3-qpO$zdG`bI3i0w5R4dlqz1;+^thxG~X#?baPT}(#}H0=OJu)Ii`qB@PxfIAt;FT*&Gz5qZh$;!$gvSz8k!-Le71D!_!xF>q;4u08n*r6FHDY#$;~v=I6MvX}QKo2t~- zk2rg`dGOru_usUBdd@XbCj^J|fT`~rI-f^bYq~L>Uj>^L)$x|x} zf~||R>Jmo`uXftpeL@zt#1Cy+li7?#si;dyV|x+4l$%UZb9K`UTZjBO9P6GVk~r6l ztK6@E*Xdk|gtz7tLSGHvYYxPbj$%3!EgGMBe%q>^k2Xkj1S^DIc1Pi4=JGZH|GM6+ zY_Vb<;QsC{a)oY}e+|7vIT943)JTTa>-;2JL3|aQHc(gtq!6J;R3HxtaVCsC1d_Ia zb=&DYfze`pbi6)|UOK`~pvgFu$rv-MGj=E6!zSn+Aca&V_Pe22w6O)WU6K=Gsx`ceEEK)4;5@pkrV>O*x+B7--!@52%3yI7^dSKJ` zjbK>AVNAh-K6V;DkC8{-^XEARfbLn=#O!qZ0(74U!XP@_8t$397_Su|+p*6NHqnuU z&SWrhNzN&JB6BT)S2|66iDnOv%Z^VvUhslFkP5&$sR#>HKe|*|R{&3~vev)$MJ9dk ztFLc%oF7G>KUZv@Ti`#!t4j>bDOe5vETjE8;qjwPH6-au+>_YK3p+`86zfSpM%z{S z1`H#I`UKYHnXu)PHPxR8|0;$^fKaVb>Zan0QV1!d9~-j|>bx$5Ux;-?`Csh4RaBK> z`}J#~gwi1)2uOD~C@I}tQqqldh;)N=mvnc7EI=Bh8>Abg8@_v4@B80-d?$NNqw59oNJ*QY-KrU%bh@l7$TcI;RN4FYBkoV3^uieO?n zob3Bp;Gb349G*5ixdyuuIv$<`Kv<-$9R%1z!L{OH%+&0or0(Yf+$u7YHI{svt%B+U z`2J8KoqWy~kGIu}YH5+hi^z`XwE%+a+l%#7W>rTd{s;G62%%OgL^qW*D>$(TMwq(V zT7Tq>>~Pm>-X^=-r#!*6mKYygXH<9l?lXb;hK&K{+iZVA%@?3I>xLg`-)|!pLF_&H zSUjhgj_XIiCi87g6b18ee@f~FSMGd$6d)Z}dfa&)4kxU4cvmZbThwy}kVuO?Irg>H z=y85mD9C(kC^HrhGMkvjSWHB{jGTJ_lx=!zW}6W|hXI3!oPRfgtl0sVsFBlV`rvGV z^B~D-?!0iJ5$VYEHbXSATDyBk5|>R*=DV0C2AD}(mH*Cg-%oNT|#Qd>m znSOc*{Ns(D-cLv!gx z1Nuzl1K1iwB5U&6R{q!TQozkw)JZD{RdvVVqzA*9{M%qMSIy7IkxEM1HG3ind>*`G zAY5n*mX6$G)d`rCZ*=iNHp;bpeBc?zFHgL(;*)fdy(rOjeQSqD4UF;pYA#67$F02&=bF zGE;6Sh|dQsYUN2hwLcRyG$m6s9sA(WzKtv_dA588)h|j_s^yAUP3J27^;dl8rZtqLqqdkuro4B3xK8Y{$>Ff|yzDJQHu{1+!-;9hDk#iTKS7k; z|Dn?+@|La-w6ier(;9M@Aka2Kj$}fYFMyU+T4!#aHCK}fsXWKN@PANmH;UP9i@49> z+&6JJo3LK(T|I<w6zLd)z$Fq{^hcK-=RcTIos2=k*uuv1pV^g|7wy!Q`d4=S)>w z_YrhVKy8hX5j+=(Mw>ClYa`H@Q;>u|WCmMTyzsJ@niTS(0Q4%^G!;g*KF zHJw1;GvpHx0qI?oMQP?#fn_Xmx*35-%XAI{414TVEW&J#eq^vs;j4-U-q2|^zRr9o zLNT?)Af3|KzAr7sFx67=)A=&yr+faZTet4T?z6qQOnp@zQvJI`hpzeV3m$m|?~h$n zjUiNLch_}>8{u#2t8CQ`ZUV~g&?u=Tj9h$#z)B$tmpFyHs=PbhTU^w1mo1S@%O|bX z;+{O2S>QD6tWiZOu_80u<~*m@ z*Nhy@Glqm6BRkxDNrr_Psn-( zP~GSb1u+AOJp_{qfx62zd7(y(>en9gH;wkS&NbEqNnQp*gM9?D_tn% z!P_EAO0zb2&DOTi-hFtpQmzmT1ubH#I zf-LOYb77fQ`~`b47ZE6is+<%UbjR?VZF{0NA>zg+DB0(%<};@aY7FLTbl`A%wsNv4 z;HU4eQuXshl;6h(&b%a9+SSKtN7T6#)~A;!zqFJdhdnLz`Vi7CDxdYvuW9vUb50(^ z%%oF-S|_7=Fn2%?HM_&`W(T8O=twDwSKu<&SMjI_E)x%2%^$Rb4r;#XDqWEV2L8%< zufR~&BrIB{X$kBRssK2*+&_u~9r7H8C2<~xEbpDWjmtIU18vtK3FqTw=ke39^4pC| z*&f~LJ2(tX(#j@AX%|$|!=&Dz@4a}8oNmtA25|MuEq7Yk{fVqYDLmPOhV}fo_4HzK z&*xClwisklNQK#a&1k;S>9A2YGc3=1ruy*OAG!4zKBEdS zbOIE6j4u)ap+JpwZe8e$1xH$w`9>HPVDlVTFVlr)`!Q->Im|oxQ7RV`b$o_44}Cv{ zg8Eg5KhT?3{q!F$P^Q}q@q3cYVj8n$9?{`PtwF7x{nY%z9O35n3ir*U36K$;gUsI- zuA|xC^wz{DU~PM~8ZXeP9adgN@HAsGUBKmorp5rp+uCe{l5jk&dc#3{#{C;mIr+fV zWsAvWLvD1`Zi@&D8?Hs!FBG!&!TQ;QYW}Z4MN3Ottnfw9IN&Gfv~AorHIzZH7wpTn zW(O#N!=Ldv7)!N^^X`7lmpzQ$xlZPYa5D|c4o7AOF7{DB%@WidKUQmp1vKVD4M?q@ zU{){Lcc||cn?Z!w;iaWDU8&K~11F2y&nghXQ#s5?!*V7=sgXq^NFlhyLM@WQ!A})@ z^vsrl(S2iYadHL#0ZHjx$Gr_gi6nx1^pfkE`b*43<8q%h4IJrPug-E*=*=o?ur*($ z&Irc>v7_9eR+9mS>5{lmT-AJYr{PznClonJ zC{UKKU)OlQE_)l15k(S|`m;S%)s^>9CeR@63Pi3BL+}3F>Re@pI!h-{2936-o(vK3 zV4Ql>&O2e6zd--jpo8j2KC*!Gu3F|N?tj7F3aSeGYmm#geV1$5kk=erhtGxM+L9~$hnyRB((0)w57)_P0*);@`veu#MTp!)S!OrHR}Pg-y%UHD@CXt5Y{ zCoz49O|G7h{rQ;n19QXq7A6e<2q8yZn2t~6vLy&T!ff_7 zzDC#`ED34C2*sVBAE0f`cB9)Us1qs|&+=cthX;Xw0v6QLN&Iw{rWAqiCqghYcQ zZF9+i7<9Dz4b2zM5>cO$;=BV~ONQkfjn1N133_=MV0xhV`uL8^NtSsewqOqX`YnLE zd*jN!66Q5bD2~N}5cv`BQpKI^N*9HX+3W;RqpX5y7+Zpojz5?sZ8;MAG0M5;5>4-} zv-7rx`#kRZshD<;^Az!IcDn!U*vfHvAQcwf z4zOHm7hPJ^MuA6a5r;-744Z+Wm<}Kmy@z0+Zg3+5oj@Fb&cEuN4C(>%E-U9Nxc`iR zR(|0rHgt?{4?EM%0#HeRGFPWA_i4TyNJ~1nN1gbTY;AX!czt_O=Ww!B3kl>Zr-K|? zvSGK%rF_0mGYn}OPFbDriak%sfl8P4~dRMv=)iK43rchvc$Dp3?toB5BoH$a|6 zZ_c2YuMj`&K<{KVe;bQjZ3J1h0k^mb#B7Y}e$X+ht(nTB2|Z2nVMimCika_ZFSInl z!a^CC^5MU|QSP%=i89AQ3$?R!ZTcE>K6p466)Pi^P2Y{?LG z6f(nb(OfdtD&-t^=F1HtJD!XA+TU7N5uBm?o)l}CV+`rQ^M*zWzi$`+#j4aW%mTCR zmn$N`#YGC#&a#0+Nqw~YGYi!-9A*XI7wcD7@l4tBB#SUjARf7V4@jnr$7`5qrj41v z41vavYc|9;<{qy5UmUHOG$;(_NF+O)3hX z01!M+>Txg?Fha+7Ct*7Nh-w5mHH-1P)#A{2FI7=rP!PTB<`=t7#?hh%Q3>b6cDMu( z5hkZ^+qnV+(k0OmVus=ZgIbLlN>l=yS@ESU_N~mviXFk9$3}PAj4ZqKUetWObXR!k zg{xVA<^A|3<8Cgm;CU~CyL3H*EKd%gtN@LN5w&^-&VSwa{&Fi<#S?PdEm$Qi8y7iOK%KEwpAt52;=p9+XE_(&IbP;)1m~uaZu_QlzZ1yOkE6V&mC7R*5Fu#`?kW+tr6FyrS;1&jjT^+ z^xH5UQcxNU9*fS4G48&jsS4dpVS;$WWt>N5p&x-MQd2`HcWo()q##^;eN*fF#fzG! z@z><)p|gzp?I?sAt{40%oi)kDwq$is`G=8J>Fm#)Xvb@B(P82xl0`TM8Am~8X@JAX zh{$|k!0JMf!fpJiI8aHY)_jIl?eqp!)9DPqDOZ6avUW1zoCYXhyjYBW^0Hu_p(WYF z4~`;W_Kje6I?flWBIGMJR2R>OL3)pTpKX6|nhx6VHV3e*i~-GhG0$aC`pXkvN1V<+ zY;^OJ;%`(Hb$*}3;D+-8FjJNN*4wq7aF|b@Qx&O`@xBy}sDw0wBPZW=DT>>9#OAF* z<^~tLQMAw?=m}(lq1f$e3K2B8)zE1|E-J=aQY0yx3^_yeSoB77N#SV=XlJ`-mrP-f2qoZq&*1AMYHgS(Pss7S3Y zPE2e-A3D@(1YoK%WDs{;V^r|mdA`czasKBS`Ou-ebyIZITkdZMlM0IwpnH)15dholA0S`YtU7X)c#tzo_*Q7>kTC!69)}bk-L@Dl#_lmGZt+dQhC+ zg=?1}cxJc{5JdlkN-Qq5PX}L2XK!k63UC}^U4U+eC@pQC!8oY88G**67(?hk2_*O+ z1@$G6vGT_J)y3OGQG0sN0A%D`fR$|3cM2FD=HC9Yl(TRo{IZmHKWV_jlz`(f>$l&b ziD)9VQG12YU#v>3QIe1asE{%NsJD#AST5Hi*+BIOuk%Utb=QS30vaHch~B?{Ki}aA z{t?)q4(~wqgo2qlial5r9Qi5oyaV7(G4T@o3Rf=T$q@NwO0>0)%rv|{_M?;v=@1F% z{<4<)z!JOsv6kD&hu2s-Q;4lt4MZRjZ$PFZIkOMUbGF;zplDlcY&>cAmhQfWO>Vz+io zu_;uNhWzL-maP`)J=Yu9mVqP=;?B}ja0(?tAagn1A!%?X8ovZ;rSGjCh;I+xmFaeD z@(>;?@W$DYfQfdRi}}4O@hNU!`qw*D-7jclp$PkK#(BVe83k;3Q+Lr+>CC_z?}R@l z&c8b$;aya8!f9si=vaF!b+OWo_MsNwEY)E7Fs@W*W=z_Qq);g(3MmD1ie@UKiMd@) zlTLT$g<|iTBxv(Ab6tH7hjB@;<}v3Vi-bO>Y)UiE$;7Y)Z&2RXE7a8p9;;wCaiTMQ z(sI5r-MpA9Z18r%c_+x<@vX<*4VGrJov44NMy}%lszSOh3^r!m6SYRi2;_pBJX|J* zKl9IZ+GF}l-my)|ZjQ;=){<>VBKrD4Y+vPO;JL<8jj#sJ$ZZfs6w}$C-e1WJVIDr$ z4diHAd0{QkdA5h!5WZezkZSZmghM*QqSFdDrF_NRb~Fe}KtQ0{tkWiaysXwc7+o&Y z$ZSOJy%-`1u^L$BnJBTeM4)RFyJ_cTMI~w`&2lrS!BcZu&w_Qn-U&fyTb>|LhrI(& zrf)kj;lZ{c$?e0<5iC06-60n{iQwhUm`^zHt-9T2_%^(T7Tnn=>eLG^Bo%eTU)8c@ z25X2@M-IIlHv2+yqUM<}F#1=-QUg!EV7j#+LpqxIG&8r6jv>M{0;iv+n{RLru72C{ zvlm3Co!S4|YoHe(E8Yh^wo2+Z4W&n_kEs570+9V_pnW}YO81kfbw1ctGt#&~0;x(d z+6UcWda!T-4jkxu9^O9_I4CVM9wC)Yr~)n5;}qD2F5_Isd#-P}!vkrffeF+fX&cQ? z%^oAAmmN^MWuD#WSJGQgmM)s))`4Te_dz~OWTX(J?QCxIX}g1WtRA1?(8yrNg?u_+ zAbOrm8A^VzZH0lIWV)|@^DwFb`Cx@cWprt=8FC4gNFB^lIFmvOOyyl?jIXSGp)P!- z$4`3a=F{~I^Hs_+sN;zF@AiU-jx9k=NWr@I+*)t55_y0EROib(D*-iVZMWzS;w5J} zGhPItI+9zJ;{h{sdT2XRD*0h9P(rOuZJj7Fgb@_>3FM`nyz4w89?6lE4J^dR(1{p> zOvHP@F^r=U_5@P0fO_Cqfi_>hZoFkbZkCf*Ej(JCTg@I%9+3Cc7f-q*FSP<3)QG|t z|L)9G0G44hn_HvGSF6e|M%slz;0D6f!Wp({n_VaVomdL__c)ApwK(-kGjyryi7mP< zE1;IrSh+;s%qmT-qCtPh6?A3@f&=oj?>yxmbwb9bDw?xAyh{}lD^Ga{xl^PVj~w%h zde^Pz?lwmZ(|~G19$YW`8iqAN`z&$IjZGvrN8{D_ZCKb%G{;W{-re8Kx9mab>E;Yh zL!><>LkamHy=jj!a1b_3bvyMrr&dmJ9l7c`qYV;NU2)zXr@7oY8eDY*3=KTrCXvB; zKm-&{j;unv9iEIE^5i!&x_ppV#YsI}sC~y%<$t!4=J~KawjVOeO)Sl=DgXW4SCzsI zC$jVPQCZBdt4*R{gP1BP?9WO^4sYhl!bLjDZz{XEf@SL2lw)%7Tn#N{p>}&@LQC`; z*B4}4=yvC{H;&hDMll3M3zW=r)lRm`5rby0PIpO~k<(f%L#rSDk2^m*H5kn=#w%5x z|2YD(|H4kNFd(4G`+Gpa6Tb~AYX$S)Le0^ds334)pCTpo5p53uJ!@2_@=#KVotYXs zK7dt7dZEn}?BU5j?tm$y~}x zL-1&^blOs&UG;8WVIXL|lOjL7XD6ghjeH$k)`O6BRad<#fRa<~xE~vwe>8kE#3{o9 zZZ1zE@q-hx6#GccuCn*@>yWnm>CRMuk2FvHlkb@#<83M? zJUT_%WRR2MJK0?c6ii-pNIQt?8^+Rhr{Lx`RPLQZBXBWSYp}0M$l(z+axvF-9a!|@ zGZ}pwi00+0j&z1m#iOyAeKGfyi{6W!b~RD3}xzuKJcCIy!6{J<(Kl zN{;NzNP`7M1xX%17ex+(aNONhzxWA~+<_|H@jAhbH`}*3fecV410yh2M>EJf} z@6Pt_wqW<|=JUy;cw`uB##-Mf3A{Tap!bJID6vnnhm+1a@^KvEHULl-UqsyW^3t^` znHkbzP}XvGaT$3+MD0kjNI2Hkra6;*Er;Uwa-m+4AVW=ARO8jR+jZV$6OSXO_Ntqj ziZ!*usYdDD6M$@39TX*@%f3-=<`-HTG)gMm)y^VV?W%rD(`Y{5>?ZzxEKgn9A2Sok zQL`ZYj(sU?9FHoN78N(c&R+V(uBTqD%^OB@_C)w3|pN-|EgdnIH?c(8@jOE!X_YmVh^}TUO zUK@y)L=u7>_#y?S+=`6aFYJS?ib~wm8n7Z8ycmz6Q6I`lb*DUHx0^tg>}q7tYbNzT zSqmbdce^=x&S~}IV=;}Ng9Q<{rWF{oG&CBuuTyMcTj!f3k-m6b0oEd`d4AtSbLl(A z=D$P;A@=U~(-x~vzlji~De`h~Xuba7hQz|bQH6jpMcKx@(BL3F@W$x^*qU=gV4FG@ zQ{q?I7F>(a7hxZ;ihtF*z1N|WtR3L7hL5WE0QXm`YyVfP3l{O)j{d(kR+LvM7A>NI z>-woVVJ;_`kF#t@%J);*6WmnSl%tIyz4raPQQbX$1}Tq2FKfG|1WO7UztvmFJc}w)mY4=%+AdkZGIN&CIVPG0HTeUXh-UewsOHs zFaZTeo(`4ila*amG7lSxjsc5oQuu#O#lyt_5AT-y26l6v)1a( zxTrsUndyXuLJcsU3_^u#HLzUYj(TG02mpjh-BCMFkU~B?YE_g(Vx?83OEq7Cf@4qe z;N70`;_m831Tj&cI%#VG`WR3#IleszU;WF#v~B$Okp`_4ODBVdsj{;Ux?1C~Kd*2p zfI zRs8rUJ*v825n$UxzBW1`bZNrwg6AoSH$LgVvb9ACV-`lhmjQ@%-`EAs9=XnTLsiSq zi$^OR_VG7KWH;IMz6CS8PFnR)3A)IVXi*`ox}WRB3q{x2wnS=~QNuH1CkpwuVG~`a zvWDPbyao1+vG=m!u*x+G-cf7li64Y8dg=rNP)DI$jAQ|}uiFTxZ@ci>++1BF`}ByA zfDP$=nS-y)?e#^GqbkpSbM``(XteZs$m zJ7~6w+8#_X<@()}EngT+R$w<-=ozj=v|qmKeN=j9KE*jS7$QJUr5(4FkSCv&(dX{I z72B{k|19Ut!z%>o?DIxc9?>gm^D9Lc=d0bC)s^+W6d`czs2cQnH~!zZU|*;=2)S_M zpAGpX+^?sr?Y;_W70#H!kGDxy2IT&&3@G-=@G{|>VcgcC?Ozdb%Yl$){je}C%TrP~Tl z)wvhbkw8xzVAU^~YqLtZvbmW@Lv#v%ezo7Cj=@~t(9kQ>4?L&^yNDJ(7`S(L zGvyz2Q)U`35cHpGo3aq_27e&|!8V{iS%g76cpvsrU@knKFc0+(ALxR%JS>D2|EF*Q zAKpTPY)MHak754Kf$(4ap%_+fQb6I@LA3ome{&-)+u|;Iz#P^F#H-k;rt`yK z^Ck%SgRzn6@9*D^M>Ov?mMbfNxFjypQPu4zdG$yP*J@6{6I}WzYj&LIS%* z8>@LU5udg8fuJKIIOXdmJrOm!Vn=!|t zFYsX<8oPBgh4=3QDDn%j5ksw27>D=LXw1e*klawuDbwKzsZ6sgjLGp(XOz5SI}?$Q zulM(`?QwY7AH2l%B2bzB%kW(2%A$~DKY|TBEApORb7ra%|K`D8Kk*-#%}W$8E#hF2 zhhY8|XJ3~?r;ZAg3l#>y&-8yx{y(6v%TBBU4g8%AUS76)9)~CIVDKsw<$5a5U!~c8xzTo=o zoyz}oEC1`Mu|pFmlgAEK{<3~1p-HMCRfK;Q5`q2S-(3nClbOQ|zFrByGGzQe8L)rM zy8q{h4E(=Q&;REhW7|?k;1JaTo#Plhhs-Zb7B<%x^OIs&vMAj5GYK!={|$RR6@}tF zQ!6?Pm&NaW;zr}J^4~|~=lai!`tQXW&}v`(X3*>oImi8_TCqbjEkmmK5YRYaiqvSs zkV(a!I{wWKM1Bi<|N1^9;qgul4Ok&&JiTuAbozcJnEVs;{pZ8WJus|-xtJ>d{i~(V zehrH!n&gIO*MKcn);RPxxse?P`ojO;VM|o7dN}0uez%nV9&$Or%C~`M&#FxVzA({` zcg;*ze<2@#M*qJF@}mnnFZ8!{&Hwz)kI7&2qIrjb!RMSzfWsvQjOPEtAfbYzIC5Y9 z-^>1=_XIN4z-;n~r@;j1BRDvA6|-mmVTXPED1h=4B%eHf#+L?sw&7vY&NkN8=|6rb zRxa=FB34OJKmM!Yx%Ws{9Bg}&pZR(IjR1A%7F32g_lK;K~$6xOt8<}*zg$|C2tq-c2{`-4)&_9gGl~{rb z20Mxs{Q`EjsmI-CV0wQa1bKqAC;!$6*5~FdRVY3J`w#VV6&X;bhwrAikj@hZ*h2Y~ zP(OFQdi6<#u#BxLPcw6)MWLVwN62`0x?)U8y;4YAz2KC(N;$8ItxO0x;ti(gPmk0y z&IyjXv-h(rpI2_R2+kT^To-KjdDzw+Qh>V96CD@VlwSY#8XvIxIJ{g*mUpI@Ko(}{ zXXdMoRYiYSH}T$6U~kL9Wh+kHDRA|HSE%$4`w<@o4k7%lt!EpcKW&G#gcsR2T=0=b zAKYPr4g-!L!YZB4KY!eZA`NJ@8sFK$lErebsDB$V!Zy^ZxAMdH?Tn*lQ~Y^Lc9JW+ z`?;K*@{l0}zdUMbIVB-qio}(tYph>(R1}&28!qW~mV;;3cxBNv?F>*THj}Emib-bj)I980q)SyFCWmFzvLVoJQi3R*cQYmaeH{feLl{qki|D7N2J;3(;Xp;&6 zNCWihp922v4_}~0FN#M7?^%AK)Q?8rF#Q?h^pf{HJ~H-`QpLUw&zaG*qIZu8!)5b? z$D+_}lv(lh_WqtNiEDgToJ_j?#jq8)I6$bnrCY3g%T>%kDqoH?RYdjfwERrsMUq)px?L#&FpAF` zRcAxHy+eE_XJ=V{{s)q&rvlCnsXAAt-%C-dEEih8@{a@C$_8+{9AC}W@snSwFx`FY z@0GoB$TvM44Nx7a9B zaxCxEWzOJ4&opKztI2mk4;)vAZ(mTZXt$=#JUXbew!b3fY|*QL{>P(C=Y2J}5r#&* z9j9yFg{scwM75|U8-D(X<0Sf*1t4s@b}PkUv-0Zpnt;vz>0ER2<=}xtxq<}Re-h68v|{I=UXXRAf>JELxT-4!EB z*^EbJ(YabYA9V4=Lt{}cPiZt0n$LAhxwRd6sfBfPa8miiCM(vp6VBEN#N_ZJvDVB% z^2dhmkm?VtraA?}gC* z1tva?o?U7Zy=?qySyk`mFn(`C8I5cKt)j(9gw5pS@SOO%@tGx46opY}H$0k0qLc$& z%0wjtSws>&L*jX`#py-t3T3eX;HLA2mIn=fpp}Ole4yG`YMF`tA`}{O_4HL3YBL0) zk4J-h8n3GN<@d`L_PEY-*?;o*@$e)=CS!LYgXG`0cpteG+9ROp#rli31CD@DFq32S zdU>v{E{1FmkRa`iPBeghXJ`!aWfjxX1^lucLjXft5@7Hpt=$x$2m#MN;g^~4XhE1~ zBqEFBba`JP?I3xVRM7{7;tG?9$6|a6pXHB36S==GEgm8EIixTR`4jgXsh8J5q$Ub! z`OHe{dx^;Ca)UwP3m>lDtufPZkEwFTunv1Pvf#|Lw9%ld;4m{zwy-9isi|pD7R~Jz z+i~aAb}vHM0=L7o>8cMFg4)saWyy~BvL$D#ZBo+Hbt>(;we5B$WtUhgO~w+yRh3gJ9%xoe_o z!BWYcS|8CmJ~sZ8@+H#NVv%2!%D?15m?D4V^?J3-IP;N@6Kgex4?QDU8P)m77jBr zazk2NXVe#2gW`BP$^%Xs8q8C?il*{;Yli4Hd0(g&3(YzKQ2)+|FlJk+K|yC&G$&q)#nhCe0VB8m1Rg&#b93^a z<1{#2_IARF_-lU;sbKRi@d59=1cvMJzk>DKC*aJJ{jmL2{l^Xv3@WvB{90BFE*PK3 z7vM7_fr2XI1($@nKgh0l3i8;}tu7)3R3tS-L1j;B6FILK&_kS@wQC>tMUsV8ey;^x zQiU_m$7^W!JdUQ)4aQ%F159# zynB$>)!0`pwntNK}p? z1ji?!tp$&w_)J_hIAG2_47CLY_#Ycl5zLBal(W|?6+fShfON(FlxA9R zYU5}QJ;6=%t8)VHIXD0|vkI-5`L%M6x-_LmdSKte-2{Q%vdVN(7tYhqQrN5Bu%#L! z7s9L)@GrT~Vxgc+BRp2mBO?++lLXUKg*F{V|B_-e(l{9-jiBV5m zz9m(-xR|yb3H~Yewa|Nw2W!95rGKBfHi68f-A*JB@t+e_3k5o(5pbZ_C>j@ERndLh zwQDJRh{cR{Vru;zJ3k~WVruZ$lWW|g;@v+vG5kng+_yY^yL{F z`n@>NoF$RIcO7ZyjiZ|QS{Q>AC)0weFbm`C1TEtrseK%^1jNh?rtq>TDXvYy)_7)J z_jC^)MEO6Lw2y*8c-b{#PRah9uMVup<*Rklyqko$M_%~gU8QaM(~NU)aUh6)L^6`i zVEly>03viBGg}1})N9Lqe90?NS(S~ZRAg}yTLRt%NWuv!N&F524Wym(!}D1X1Z zuJ8nz;^}#SPOdz}%f}NKjBbVnq7Tfn%JDAF(X%GOJagH{zp2pSfq6VXT)8Z`PP-rB z_go#0m$$?FL{-F?;&dmTNv!(Tk&E14saPdjx`5c-{Z^snjR3`l6>^4^j$KGbW~R?r zk5!#v08H#wwOA5gNrOMf1>DhHV+zmRUbY)1y6$1E$>MrcNek*;3mwG>G&fePI>{P9 zQeM$m*}Smzc8V^zkRdr(P^onwOS)Bcfv80AN&~ZKuz$LBTdaI$_G+$~kfrtfYPJYC zdPu!{Za#1I86uE*Vje7ncQieeNYf+V%3r*)w?|$mz?=2`iR@AXQ=Gj8k2u^xb_-wh zZJ(+~=KxFl!$+s+IEVh@#q9ZZS$voW);XlQT6m!Z&BA1%^Wg{WbV5Pvnf1?l!V4N6 za&S%u9MRzl3Gro@hLcaXoP92hbEUIJbKc&ijB5ERZra-+<`^Dni*J3)mm}Z#tP@T* zX1fZalO=z4?UcvAN~BO3$K`}!lNmQjhVIA{Rjm0eThFh!n>V_COV8Lt+Bvg%pl5A> z#?bpilbJ%g915lCw@5Ra)wHWtq>lQM5!oR>l21!LQ&IF~GE?vh`^&sG8@4lSLwO<7 zgC#xYT(bCvSb?Z98q&8F-`)il&--+j$lAtx9JQmsa~JWXHuWlJ5JlTTw%bF9_vX_p z)Y)DQu*ORT(GNAa3Q?+Mk*;E-`t5w;U|eao(==ZXk2P@^tE=Lxevhp=UEoGudh*jc zL-I{vi0fO^Z-^{$iPIR&M;zdol`VCFX)bv60G;aA{e$j}7@-aNek1b zCgPId9pOzAE!r_zFOq7ptUQYecyjUO&`Kurc{pm9+UQAddi+VY{}n0;H0=po zCed-P;x11&qjS+k|LaU31=fDG_2%EuNN8;n16swO()5O==JclMC=Fjhe1cZR{GMVb zWnd@+lHC3w4aqa2c7h*tpz#P?t(a__ZF0ljyw^X8w4 zUA-t%H;^9>m~1*E<8kh3WwV?X1pKQpi4~8#ZHfMbZEw1S2N7V8LJYw%HiDtH<{>dJ zra$nqAVAR;DSa;X;{0gk=VF^e#e2zkbBVa~z+ zWXsbcZfRE}mxD#WyZ(@KZqZ;U^9@_k1U*wK+4Qp)G7}C0(jH$%9h1ZNU3JkrEe69I zz2+_Q4o~iHwTo&)G=n}u&OE%PL^&se)612cmIAGcz14lCa-Y{1ip>p;$53}K_^k9z zDV46X=qDzp$DFVRp9~GkvlUe6H(JTEZH=|$p|jwi2L_{wlnkX-IN)NCjT`?E-*=Z0 zVV$WyKxZ*glH!($m`h9ax`X+i!FP(YlEVT{{6q*7TkezUh_;R$MD;eWx%|epLjjNj z9`^pE+oj8)k=G_VrMea@?p4pVeB!uhM0~xRs?K8g+zVWUMgFL2<1IlwA>pGw3{oYN zk%*pAtaX))K}*bYO`ggyvC(|0P9^}FU^_MKSzZxabm-7%VM;Q+Ma{|;O?^{-bCImR zvEnoS{hFVJ*RvqfqG zJ?F_C1fxJ^tY(1((;5e%Rhc&6;*PdG7U@}FA`+fxu@Ahsj^Xz@CWVaby{5F{E{ktx zw+uo2#oCI7+sg)t)fqPZ-n~15S2-mwiLmbGq&g?C-J5f_$q#^c^m9qcK;T{uAYp=& zRWuRazit2ZR}*MIxk^3E=MRwfbv6`nYfuyJ6EM}@vf67`pKo@%O37QZ6OR3hN2@_^ zSU9D_8t?NOXipl8L8QBUBCBOYQPBae%eQfS3=E1wM)!Ck>x|^&WRPhn6c3DKJ-B<{ zE+x#hY^?=av|9%CD}ZJgu1vqD2qDY9Fj$R`BVVQsk4fj+TxYXIlYeP&*tpRN_aH&mN8-f2e>AecGlLIN(dD#s5-jfa*|t8 z>nkUSVwS}~PanQ>v_hy|2Dl=&TkA1V^bs>5%)nf&5^#xhu5lU>MK6o(eYTijMV7!L zf=H=Yj=owpNE{S*Wpwa5Xd3?f-s1ZPP>0CMD`j4P3+|Wt2|gJCZCOEBAdYQ;d8#8Q zHjU0l$a1aUlZJ1;{)4>QF6G9ikcCC@bDTWCXiJO@o=6e2_Ga(i9ZDExjXJL^-X zo)(Z0mLvPEWz~{dGaK|M+bw_lP~poY5;yTf(!=Dt3Kgjx1}4JP)_W800O?fT$i_(< zB6SYn3gNnlIY7O#q?$mrN$;{-k=0wjIc)=bHK zXkT9Cxup88XijRT4s0i>d)!vYFk06-()!2H&X#nq9b7##A*2r3a=+4Sel>r`M&Q5j zsjjOeiLI`7y7!V=>e_9MR#IIm7mOu8v%JGk&&fzBrBq7nvNL!uPR!TtsuM%;m}v)w zmBkDMQNG2O$Emb*8m^E~PnNy4-1T03yi^Xpr}&uh+pKN2;lAnl4ox*0R}6??*yrZa z+8V2gEB?`M58CJtE)4W6rBj-3qljboj>5@|V(7~pMNNj4&%*WOAc8RW_62^9-LvLh zPkYd8(8U_&MeU4k6UOS!^+xaFDg?P!8&gY8?eKkTwA1Yi(O&%iE@+3c?W3xl+dWKy$au6 zx}q|qJ*1|=r*|H*j4M5@UF|Gcamw9m&r2h#!edrTp-UQ!p%Sp1M^5z_>=JUlW3O#; zz1z7q=bRINwWn~F)lMdP8^|rBj>yBiX(6lA$VmEM%JT3bIPx=9rnUtiCQk7_q`wuJ zA7fD8et9F%igf(mksCN5?W1Wr+w5jH;Q(jLUYh!T;F^P_f27JnOwehQ^WEc}r%xGw zWWN)`4t*_r_YfVyOC>6fD@+R3N?>+2#1%c_l}Pi&_O^10O<>}nG=3+%LzrP!EpfN7 zk`nBj6pOaj*7JZ8ShOk1g;bAQS}FsqeIbX%lrj)wu_9j>*Vo{B!RU4~_R33Ym{Njy zLq=aB@ix*f{hE@R6cL|Mq8@+E36I_C^QZoc{K)Cg`9P4zgM=aBBuy&u3BmB^ zS#K9TL|gZHS`GAtDC^bL8|f|CkZBTw!}AE!%AaRE&Ig1I9D7`)@kaaPy;yxWv55OE z8O$u~3BP7vVs-v&b54b^!MiY3wS$EQf=0r2k1T_W?3OUHO`L|i?=cGbc5ljVA6;hD zj5Fr7>T2tka&5dXqUsr4J0UY_OIW_lKSiu&ey1XSi2gv7qWndzH$G4BSgh@{l z2UMreSfz=IfJ*_vn9TxywR@ZBkwr{RoJxs{_9k!qy0z0CK4?xA1y z7HM=U&h764_BQW=s;i^brmOQMWT`etnb73>5!0qtLgx&p9z4(6SC>i%Xj8jKEgpTN zH8ofk@rj7fGb~$nb1a_~l3ucy2xF+X(8TIVT&q+GU{Rh3yQ#W6A6@EedbuE^ujdZw z`IK^z`S^)^2f|x@^~Qh2>5m_)pltT(!Fz>&E!B*G^^Zo=;D8L(K}<3A@i)bi%gXWY zx^w)H%NHhB?NR3C@c_kdg(~sl@+_YK?&ipf3M&ToK#0!=@7vT9aSJg8AagQV&^qfp z0}fqv`R9voHZ%mzr8 z-pYS`0E~n3(9|HKA)=KfA`NYy3i0iuVK=asg!uTUCzu`ev&kQuqm|H6Qi>Ia(a^7= zU+Efx6{!@)FJFEam9ER+F8c1M0)oj z5QA+l1V(z1e?YR9aK%b-7Ci)ocA0&0dX<#xAXT%Bl*}UPS@}-{aAxm^p4sb&B$&1G zdwJ|Okc%|RG-^%V-^tKaAfUCR9MU*BI{I%HkTKhJyQCyEJVh^=qF=>S^llCxoCy||9&fUv({ zvc8tSzJ9p{!x5}F2vk$d34cOpx3{AzsU7pSaW0*h#dui3b$*)~;qW;$oyiAbEz6l5 zT*kjWW&q0BUGEQe+rFnfN-Y5dAGYMg5i8tJWT(sDxVS$hSddZ^cE!UL(etH6Tky0_ zpr|sEk5H=`aVxoPSmrJ|-~O1bkxXxRV~jysy{!959F%N)U-7}nES z<+JYEfwU{Nefu2gN7fPaM1DM&Kp0Ls#VAIlNq(XdJYt^?K|M&r5~RvH#9=B02V>MPIeT&}@h3rn!PH$w(6kQHYXEl_Y%{=XzXwc}iCT&XlgZ!eG+V}5Q z_vCsr8eHdkIlfhZ103=QB!yD)2%2I#?dsra%Y}UO<$p<@_Z}!gqhAW<-Kp{aY>SLg zEE`RO8@0qrsqPf2lQ)%Nz&tGB7ac2(ZtJ1wR=n?Lb^|JUzwu&C zs%;l%XSoGlw>*BK2jCl913O|E(S6krs((FhKYyXOOt|!biBU>g>LX{n;0*xuhd5G*P0Fu|ZyBDqLNt z!e6_!jEs*%1QX0isKpKMEPMMv3u2>!r^)Ri*InI145qI6lPAkL9%9}BY(AzPJ`lA9 zko@(Ovm1=6_zL&PjOv$!x$l&_0|W}jEoGk&x-Y*I4GN(Ca$e~`_fXtpN6IVz?wRAVI$*^_}Zy5{C)X0vnHo1JsD5STqz zo~xOXip`&k0_BBqj=9Wj=IYGBIb5NKd9h{QcVdzJFoJ-_MwI&DzwVH%xp zO-$4N)fo{@e927+%Sr56w^Xh5`?LOqVD+2?AKIRbX0;D)21KvU(>*(cK0LG?PgT-c z!aZ@zv#sH@!7S4P_ZU!?s7P?lX6HVi8w3aEgTh)79ycSuWjhm>@8t8__scXzka-JR0i-T%J4 z)%$+lZ{C0An{UQ(7-lZc>)dZXjZVuAQak>%? z0#^Y^lnCy}#b(dbD$+gNpj12|Q-9voN@h^VHX@d4np$J>1c0%Ii=4kclph`=FFMc6hq zHmovlq1y(r8yqRn`eO%Qtgd5hX^G9g(Zs9Uc}r)@&cZyoeGLZ>A0?l=zkrZgrY8>n zenrzoNx%<`bw$M1UuMP+*V-6uic2D%zC>6!U^s5^4%*1;LSD7mOa8&zwV*+yrT1l* z5_zw<4`~f!S@Rn;&5;zj%jKn(`yM+S>&Qk|t#@#M(#o~#_!AwYIR8TE*$hDEnTqY+ zAKLZLCAntPEvE6!OyZk^O%t}gUkU==rt1NIt=m3s0-K9}e-fyL+s#%20rT%Pl;Pyw#2ez!Q-v1diy@GmUfxFK)9*&?l$kCmWvm{IBJ1( zf??ByTH$yo=r3n97>;s3R}r7AtCpG>svX$h7DO2S(&qMhREky|h{CYAe!Jw@C|IoB z=dY}Hu)pNdtv$*H(}noh!?7i-57TOSQc72I<~v+;BWW~K6SUP0S#;>9SXRcE{NbFq zLzecDgTC%d54M$A?=LyH#IQ=I3rTH}H$H0Jq@(&^{EjoZl8sh5_C z4Ytp}QbnIDAb3(`+t=H_Dc-;23ql(9dnBM?|6NOKKFTe*oZRvxQ5||zt0leFm!u#n z(g7SxydtG}`@2;=lAC2~a0_`7G`*FM?il|FVDRZxv7JE1nkmcmmUEdHa7zhQUydl# z1wUTWy*j~YEsU-Ky7ZMJ0T@(fre&CGL7Z1Y)tHUu%oT6V-0EZA`{jq>*Xg_>GH2`ZP3MiZS*wepgyi#W0f+V0X7mnYECoF2- zRNq2Pg~v}4#`Vy%`1_rZk5C;fjR8JO4roR{MOu2{@Vo;fvo)(5t`}*I#AHkmC@l?V zOXfU1y~y|Nz0ljWm_9l8jq;?@a$T+8aNBRfoyB5%9d6NnYIJUpXRhh8wnCA%D*Q>= z!&eyl16Cg@A>o*wau15XFAb7rx$W2f(%f2!CV{?eEu)0C4gg0PZ1l7mYlGHYnh5Xc ziU4dmnPLlKqs5DScPO7ZOYX9+(8mIUVFwt=#l`xLhI0YXYzp|W7N zood+TEk|+3cW-U)oImgFaYI6^jKPLBRNYAZ$j6}83Oxw=|@24zYC z5SN{aq4>Bn;62lO_t2GGA@sShTXzg&5xzH;V?psT1Swk zg`p6Uy2QRDgn>0;1XM#4)x7f4#TUWrk~Pu<)1<9I!2c`wtqje~s654U4W(3{DzIsC zWrcsH8vPQ+5DA3elj_yTV8FEQ&2l)R_BZ;a?h>GeKySOlyoq;ES1X#dj@0x}WWu%1kTBN^3sx3ZR-tXH7OxjlvE4vEJVqnB6La(DPi{F+ z?h-&MBAfjANlo24I$DK>a*2PCMDl)P0uN})kMDq%M*z}%ZLfkkQts2v;2a#6u+G|-9hQz-QWx2*&FgI>M;EDKoiJGeNc)oFK^>p z)#)W+=d-_z$b!n~4wiW+Vc8p%Wb7&Ugn&ITD6Ma#G1J>_pIC`72${$wPtiNLzoNXjX3C#&kq2GMfc#3WZ^~6-zS)X*_rA&7| zD2kYd$4CH(OO6C~0-_n{%${^$H*J?>@P#uOPnv5f^zZQ02nI=P03n;Jv#m~0X3qKe zJS0r@acwUJR)egl}}Snc-WYkfI6fn>J@{)}3t7%Z}qF|)~Z&=q5jZ?U-r zpww$EOmn!ycAXSkU?+GsipNtyZE#BKa)Ti=g7t<^EhR(bvriOVcctDf7hb=~t9?E_aU9=@}NOX*!p z0&cj04@5Ujx|tR}_;)WZBGK#rd_bV$mM>G4SZ?2o5yxbb3ivR#dPMm%#qNEN;CeRg z_GVM0@ShiajxjtpT|dt@7|ATP9|y3#l>=NExzkHOvUPy89D$A?_>|EcCl)8Q-mj)Z zOQO&Z5QitL=DZ4#a=G#&Dmyb3R$0Zh>>8WOZ&B|cxE;=zKPju5x(o`4ESqZnsuyZR5*<6G zQb?9P>@J06&w1xs6x&q~U(+LE?6!*mK{7Ssn{UND%yQ?!aV3tv$K4EW{@n~?O6zl{ zGuE|6&7MWI2}^#=D_3&UXCqZxco+ZF=RgC}`nkd82Is#B#1BlwL6VRdBq$t=X z!-4vb=NE!_{#k2sj6a_L=`YV8Vh#~Q*BvNU7V$~^w9zXDK4)Rf_oZWS6}k; zbB0?0XnZ290N__1(R}zMEz7&QGMd}d9|dXQOS>A&4BSxj=)T)Kr)&15l+ThtuOm4V zzk&_$b#gKki;v#zzG#(?V$fQ=7;gjv-iQ$hha)1Sypt?SWEB~NiI9$wD$yd?;^HQ%W}$j38pAp!Ss&U> zIZ{vyh!BzGk(|!=QZ}m`{3F35?nl-Gv6&(#32da_Q}o6ikJz%>EPaw56N`*l?v7!@ zyqe&dzKk&h-FdLl`*h*FWkK=a*GQO#@uml4h|o3OV^k z5?56Hwle=Kz3vFBvv`)A+ex#|@%b-!*w7D zCc{Y^GOl;6K$W}J*1jpTp#%cOJHI)E2hgr*#q-#DTWuROgtQjyr<$umVi-i-49Hp? zpIA%MXf(CTs04!J?2u>)$jKqN(Eapl4&(fW=A;f~I#c2{&SAAQ%UJg;4JE?^-~I%1 z%jVj47Z|^W1A@vI)yC0(KGdL#&f8+>F4Nnl^#{Vo@EWiUQnq4qnU2O-rnA|J@1x{l}cQ$ZA<%;-1@^(zXNQTKyOs9??I#KP`yPF;nO(`oG)pjVX@ z6XbAmAuS-aS_Aoy!Q3>%m8B_{YctB#rEtpSzvGn?DOXK}r z+JajW{_=+gfWeG(_CpPmTkB8Yy*|IqDl*0AOd=GGC#T@C%mgL`qGXvi;Ru~L)Sjpj za4m1lSn(kZSlnb`jBK|0F25Oj;>o4AgMx;NPEeZ7{PXyWY|2;h_y)sOVL*&@dR6I* z4@5BWxwyDuZd=Y}!mL&D%Wo}Pi8V=PWLy_+uC~cp-PDaxRZI?#dN)UwG$ZySGGPSK zN?eKGEnjWeIOV*9e2a)O*ol#MZI$ZkL$ z0YLZjs_dC{XJ6O4h+JdcgX;Rq<|6mj+t`i@BGHnd)`oasXB{=d_h%Lqxy5?6*lG z+DkM$@ePAb-S2zNKEB|$!TcC5t5F?E4-4RZoy8P0ZtG;X0=cF$2->w z?ST!W+w)Oymr+stDte+RPn!LTSa2C`w$C>N)pe~AQ1|Y)?P@J{ia&JB=R>Iojz) z_KH^V8ppHb3QR2h1)>>23W^LnwBvtj{z?#C>Bu<+MaUFmsoo^no*IR?vm9V51i8X= z;N5N&i}b7SUt7RLxdD7&`eX)3(Rp>c@|DUm7;tQ5CL69h1Pr%J31Q(MclSAf>JcD+ zOb2MR5CCv-4Y+RBdU}rl51;YAYQ@q9Fzzb_o7Eyh$?*7(vlS3JDt@t0GE zc-~x|WGw)=_CA`};3q)?EO9EIt<}!T%Da0ahIXKa<9mM`cnXRt7*f%l+gkoU#u$e= zh>9?e=aV}Hk?<7q=h`CJ;ZZ{h6SY&*HVnUCrc>*8|1Py762g%pu55}wHy^C$KY`_c zg$^Kkw)^A0AU$BOlcpquc6tnl7H*RSn{r~j`1W#R2>+_`ji$fjE$24XLKb=Gor2F$ zKdgwxix)3OlixoY60}gdKilPgP3IV%NkPO4n`cYjDDMp_sQyL|RY*+PtT&QteN6q0 zzJS81{!uuefhLAy=b+}%53ei<k*+}sbaWC~KWJM6M`^W;kdFp7is zwj#)+pUtoIF?DrhMK?A8=K~>%6AVhU6ji@><3V)b_o3R|@mMWWu1J5(yNB~`rBU%- z|4~&aoLgZ_!1?YB5GPFxPFk(-SS{~f`hoJo!s3wLVHnzi!dfIVu)*4;36lXZ?x6AW z@eOW{WVPB$oXAndb4d{KFKi7~X}Db;z^{9P2_m3=)Mm3JS3{KHfx3INN)}vJR%Tr4 zdbOy9l_J<#fAsB}g9%emSUGI}Q#0>HDwQH-0G(V7Qp@HT(0A{u4*tE{5b5-I0n+r*}!}| zD<0IMn@c5i6uOdC8WN54{+vA%;~BJzFmAoMea$f94_EUQ)M2CCSaJu@Zd;@4?>@WK z`F4CfZ*Mai4MBTWvzr#|R1UBfmg@2HUz?LgdZQml7*7QiEx6>4;U$qW=*m@oy%?}V zCf@oYZ=ZM4(&1My4L{M=rz>ymaRKfK=(ar0CU+{0=BDA~1D=O?sUd<}g zPL9(YWtpbC?7{1Di>-IUl6~Gpv7kj#K#7eM)PgHb-Dq(`%u#J4R=;lPV>J*}PbQ1! zq{pP>s&z|h@y#saFkSsqUm|a1C8M>7&zp`wtT0)*@PC!$KaW9*!G@Ku;eXF}d?Ei; z3^vVaqPE6$W*YX>685tiSNae7dv!WHA*Hp zqN7^Zdo%ml0T<@JetxNT3oe_};wnA%!WKilrpX}eC-D5*ZU|TxMU+`rXn}{-ZV$)+ zz`~xw%e5mwmfH6GBrG;1Qz8l1lo4G*L363<>vNS?T0K_x*9&a1hoioLS3AhVvgOddVcXo5+hR;!p$ z5af1pNF-ZT*uNFYDTAu1P&bl!%Z*ND$WNoHTZxD?`4s8BaEk?Q{PktlCSji2bQZQ; zUS`>6-TdKiSZo_b{O~9I#;754G;yV*F5=Zx^7%&?$b^=HU4dPAU4T~%qU(0LOp4^` zCTbl}?yCyPwEU zzpRoPz6tJJ`GD*>c@Pq+YpxSw02*Ycm(KG67napuoD5w&=>=wIXAMrGEqM60^~;IS zS_<#4&8`3{3go#&ZLO`tOfrqa(zBPphEh!uUiBzu%`hgW+K_4NEuWWhBH~4>w&%X? zV{_af?Yp+AY6QjZcDTjG5f8nUpBG1qZ(InFG=I!;8C9f8XWX=?gZ||6ga?XUBF?G} zCy2YVj*J$S?^!Fh*I%$UD2VvcJZE(ZIb8X`-gjY(KUaVEJ=rg+3f_gWI-|>m?D^My zfkC^lyUdP~L*d9DLtQLP&#@;G-yE+o5-&fi6zGyCLH0&7A(hIrjX>5j8g8G}xAKHI z7^8E>3WFJWE=qW0Zv;$Ha#}{z(Pm~D8%1h6+Zh2?d{8ujmz!?jZ9ILANfzn=yY$-l zno5SG*N6BjfrO4Y%f9$s#$x+nOS#+7K4IR3eHA8Zk@}1d3p|2^iE18|UY-vHOb{Ls zf`m&VYcm=Od_)0GSpY0@4NeWsRNrY~4VP50Fk((X%7NQUWCG7Xhj`U+yuP7m27a-} zAs=ZBj^E>xRHex*;l(hn!Le{$vH{n77rKkIJ{rpOklyTshj*)72O3)DT| zGKX2{Z8Bf{ib73_%848q42I(f!vOR*Rm1g8iDVdiYI-sGz59t4F*v|hYrUv@(D1?* zW8T=dBj*L*ZcZn(3^*u3#V+&JXwkxFuV+I_UsQo`L?6)hvh8zFZP#op&TJ`s75KQV z6c3($!L_a-Un^I_#;Mv;euSHy1!`EXq}aI=Eq78`%MeOMES#y>Gn)p8(!z+*9bqR= zKGuIoWmalujuI(t*)+*1C|Z36 znBi-H8CFYvy8JS#G@6qACZ+tOir@LX?6e`B=Xi}G+reM{b;v9Dk;13j?mZsKhk$uc zAnu;_SfM*%rWzas_m$bWqjkZ$v)$Fx0Du2Dl=PhIsajqCFW-mfIIvv?cX=;^c>sZ+ z?&-n7(^{O_*JazAra)@#IMg!Z2J{|sy5htbQn}G$7wR3{BdJtA$%c0&klv(uQise{ z+B)oWXf95ReCwc+@W{5B8K)?BJQa3Pmj-m@a<%ToP@5F_K?G>TM~|@c6fn+~Rch%= zFpX`0^hV~6ektHCjcBtmns}|4Bs;Op439s>P+nFRhSGJc-j{ePvShd!ODWSXp*ZL4 z?T2BS7n@+&Pu$I^dDPA2`eVZB+%2pR_3^hG}!I3d6+e2mUYPlscZ zq=_;F6%?3W=D67a7WgJOkuco$F@n&oB)>?nlS(~3W zsK7M}lzRN+@;;nV?m@7~F3I%FWxDRbWcq2SnEr}B9`1O zZ%4*iFDArOmwYtfGMu#fyfZL)Q}ewdnCY@~+5i6i`(ZIU|LD;a(26@b?3nZ19Ywx#cRHiwqjw+2)ACY;b?p0Kmy-EAl==K*%~@*w5V; z@jclXatB(JL}9+3z9gC-h50&7;fTcJiKmL|wg64tAfWFG*IX@$LnMa`f3{1&iTI|e zSEtdBW!2Jv$l|pR5kGfHWT&ZEL%lkjOsHX4b-=;``MWMc(6X|T!lEsumg11G-R{jy zlhMYNntN*j_<@hC*}uPcQdcBxOJ%*gS=#m_Qz()QC>DrUg7W|2;)jYZKcyuG2OFm1 zU+U`WvzV*MrIIU7O5Ds>xdx#|R*EQi<%mLzGdtu3r@5l56|#}{lpOK=?2Hh=J{{Xr z-z-jF0vu@0+oYnr3uVedA5R960(>`D1eWs-o~PD(#z&D4DHwuIHYVB`iBPFxl2Y-K zB!7w(Z2w%jva{{OpDo&M)!kuaJ(4;?YY*L~V^}ri>D`nX^j-3RUsciCa~3t|j3M)8 z-cRtTrl~@y^zv*)5Xb|w!|ASFfj;RJ1 z>;>2m5&5U_Ti;{`zpMMyU~#Z-+Q}X`V-W?9#7UJw5~@Xwh4H9OUY&zLsKo~z_xe=z0+8bE`_~+s}%+MN9P6$ zZcdx^_LC1D{%$Y;?wfqb1vy^5t@wvfM+d@rqil<#I=`65^G(&gYnnDDwW+ zdjo*TmfsCdgicseMNH>#6fh{Zij_%jeyR*Ew*IbNmP|7N--8CQZe!ZT+pUkDoFS{g zlgQ`40_knE;dnkt{`XCC&39;onI7+@@tOh9NT$sXb=7hTYcG-_&NFWp=DiH6(%YgJo;c^0vo-9(0?J-|2KdM`EN+IuwxS4x}D}CRTW}LAYvi=GI^;X zCMKp<$-;6+$!MD3xlRW)ffijv(H=F6#SBo}%mJPAEy8lu>UZims>o!xZg)3dJBUF# zULC4?(wX|bM7zVs#-JeI`LGS0r+!k1>V+&*BSpS&v0MU(V7iP!v;r6vGk_q4hzQ44 zV+1oic3N7Rhd(zuZvC?i(>YE_zZDu5m=6}Vc6M1M+U;;6AKK_$a*>_imV7)eYC_vA z3)_;(37?%OIW>oV*cNE@aB+B6-nlUvInn3%WPYyhUAQmIUOdp>^44E7djy6e5Psku zC-o>9~#SOHqXaqtGKp#0q`_3AgUq8`I%~c zANOV&6mx_Zu_jbV@0c6)L&Se(_GJ3sBi@1aYtmhcC9^H`?f@f!ErMIAE z4TKeaV;d(q76h?f-th;JAILnZEVt!WRJvJRPa2zwW%kE*=u1pYJPNu&;Ew~tP{1Fz zjRJkqr3!ONc;vBdnIe^uLw~-_Vcl$vCf8vsjc;#QPUI$`W^?7p`0r1%b-F^WfspW` z?G?TYi(sgB@GQGx^;CtCf&nh5vr8>7)qT-|4 z6s8lzGx8=OIF?mZtH*jpoToPsA~W)=neX|Fybll-8AJ2pSQ$zA4l&;i za2sU{etG)Kl>dU6lmpzVR8Ug-kPm95&}B64kekW zS@;x8vGf%mx3&U91OLjQbIb3sSsYN(FNlH+_LIsgJca&d29Tr54FgdxgqeCO`sj~G z#2EuP2vLSoS%!o2lxTl%k{I&cCAJXI@eIsXdsv>nB+V> zm;8bje9utGHVivU8oq^GpR?b8)E_@7_~#Y=pa0VmfkY?Ia)H6B5UT7iGk>wbFRwkJ z6y2$LS=x34bTwK(qXXuV3I5L%=r1rC;{m$`2`z2tT3?(X09cPpWZ54sjh5+ALAnnP zpk+{Z=_5}-~K!T@b&nReI;X+c2BhDBvAH0R(x{V!DHF9F%FA7bLbfsS#yr*`@s z3l)F*^;OOnyDWJU<7;(H!P7qN-L~xf#;tsh z{S|i2dH)W(em(wkSQzr@_C(Mmhb<_+1fH3TR9C9kTEp&6m38Q|K-zZyZ};FSGTnNk z=D+N&eBjbNBmd|RW=XlKE&JmpO4A`+aooAE#WQO_AS0yCiL-Pd%zJ5R8StkEP^!Tt z0|l-0S}uCPHfIl50b8TU5ktU_j|Jz;~KnyV! zDfQ8xu=a}r-_Mb&Kn8rZMmLE}Bf0$iE(w#R?_JBKAG&TH(~Ifd*70UWY!is3puYPE z2^h$j`%3tJefmo)WE(}HH&1XLyifdw$DH0V<-z&?wC8_*Lks_KRlsS*|GF?ncRrfv zkCXa*3cmm0*dCBU1FVkIbT88WIlnqjA-nEl(rFn6$!;^o`+rPNB(2U*DkA>*=>M9@ zJ6^EDIuBA_{aI9;7H~fwj+s9G|M!>0{y+WYKh#fUmr;2as_pqJ{4^wms?;i7r6r>O zEHD{l0y!e-0h%%=v;k}JueUHusY0*)%QN$riV*U{muDi}H3PY`c74UjZLR+YrZV9AT$ z)>8Zy%8z=eCl7IIwUW+gF-RL*Msm;uU^oWdAsji3mdZHr|5#-n#Deqo54M%C!F%uh zdhdJ3d6!qHf41j;pQertJdy^sQ@~$lmtaPysWMo9-)5cEvNHIZn!1=Vr44sUKcA;r z>&=Qwbgncn!?y|W`IT7VAw(}_C$Qhz{xO|bkTtiU>=eU%_;lF%CO^TwqKM06AFuqc zFa6&&?-k^(8G7OG8)LRlt^MasZK248bu6^L0muX3N0v^HeodIq3+N4DIK+g4Q~8i< z`J@Y@q(|)Jv*95)J*7qV_SgUHmo((4%R=#LJpk~#VGp5XW2{-38m zMC{~&4#(UD#-1Y9CjEQMzxzEU-iudLRqYz&@p8JtR)nwmi@hPghw(SCK7n5*l)QNR>fzhDoYKX zod1`n<0Jp`^bk8(tG~Tip>Lnn^?JlpQAi&~yLj+o&5FZ-?t}KfZbOI)YG*v=v7a$JP0sf-B&Fc!fD}F#bnyP1Ey8%k(NFz- z^Z5?(y`)1_M&|QhXYBg(%hdK?&X^7j7HU&CnL7tcw#kWOYJH4%Vq;?~jdp%B?^`&BpsgRAf2v#Kl>T_M`dy;z zx;ty>Zit-V=JcY`r_(Uiv>lc*nKpUU9G%^lSGfa8oLQ^*@*5+Wc#*12IW!^vCHOxu zge7L0#uat0n5Frve8|0qo2*Kun~0G$AbMIDA4NrE=@14kZ|uU2$I!IT{u|{IuA?Ah zia~^3#_|+m^4+1pt(4FIUD?z3F+6G}yThB%*%fVGm+)I`zIB(Cs;9ku2!1=xh^l;((wd`_WI}{)JM;gnYJ4!)k8rt#eZNZRgnK_|Dy!IA4XobYZ^|!5qvTQdDh0eG#LBzIgfM)BHZzK@eP)%;(B?s4K%eD;pSyecXPvgD5K(& zmb|8GlIb!OqxFBB#yx%>_-}OZ0D3s#pVhDy^#7L!trQ3aIgN_yRYdurQs$NIov#|JVM% zhwMLCo38fu_K(QBzyo&i6Tt!Ce!QuAU4D*Cb}<3~f29!xVaw=ua)`x*`k+%vVe@;C ze8^+x3C^6c{pItSPS+GXd_zK{=#$+v#2AQ(h+fm#Le*3=kBnr&p0uq$A_nu?GDIB6 zV6g%T|1OsKsci<+HA9F<)5ShNYsF!CKo#bkmoe53@r^jMNkU^EIejD=AtUx=Ks>uO z!kH?IeT29%Gf6(tcskFWItdztjquZZUi?2t9};I-6aDh3G;>3#ynlZGg`5ZC67YIH z9MaOGA^SVSYHIm)rQki)fr9$QAZJ?x(TqnyM~_+w0Q^Z3kZ}qixG)k*;5PJ&K@Qs! zxZ9XGNcSmlH@2Vv3qlmPwDTXLxG~vNO6h=jwKhx`p_~<>gRXr_l8AzG>KcTqf>Iu*RQ|KPq%mJgExb9Wdq)S+|RiI+Slw4t39a z)iu}wBz!w z1b^X1DdB2uTf!%Hg1Ds40wG}7?ydr{mK551Ac=!%`kSY(L;TTT34`F~S{Jv{dLY8Q zPy{s%$GDlbW#{kdvR|OBPU_$HW;DeQzQ5;__7&tDx{LKJjU1w%<0bmLk)^k_E`oG2 zo*Ab2H59hZ{s-I2%JPqQNhnw*EdER%9s@%vv<-$x-+X^g!C;UBDYLqqOoM# z>|w;WtqC)3EY?Qe7tNj(C5W$I3pd@e#!+f8Qa(5b>OvCN&V=Lp`uQvgtTukGcLrWk z7OAoKK)=g_y2R@}_Rc4#ezUU8lTDe}(vzjA$V(=(`LFXx6Ps@)Upl(OJWsE%>f_^I z0-R*@PUBR*Wel5{VsZY**=3yjzj?yaW=|pzA(al~hip$&4B2W6cHAjmz&w4A>-{N- ziNMy^`Fsg$`Z&wtJ?q4=+ep$4<~7ERydKTs>TOhxY=X3EpeQUdd?cmN7@I6XU44yi zLn~Df&)cDShkL2fM=ecivIZKSPQ6jXZuQMU zB|ORmt?Pv8atD87lfZ>y>PibKsgP#UeA8AUTh(VqEt_=v2v5i?a@|lUw`3;LLv;h z7Kr2ZCc185oCd|3Em&1m&1039>h@+IuE#TsP>j0xMzP)=cFBe~wLMRv$metcZ6d#N z_z1hMW$pV?>*k1Su*Io=bJFpo+F6T_p!M#RTz3o|`sGz*=4{Qb&MA&2h2`ud&1OGU z!Lb5hQ|Vrj(cC2eIn3|(%@=8$2wrlrng66mt@tD7?tFzzlK2~k-*l-iXUFRUs}(m5 zb#|u?J|J38r~0zPQYw>G#M&)Bw)DfR0aMyF$=P~a76(hw`TIt)>AdM^wHf~Hx{kdh zGe#~i^Ssf!RRqVTnp1@HrpMc43Vf5(0G9d z^W9mQEL+Oaz&oJ9#CO$I*=ph~eAboH+GA(UQ`ZvU*=YK%o!3K8~qN57W}9wX=(j>0rL*ok^oST-y29^ z6I_tEmFEhNQowzEw<>g46E3)Rd(m)*cZ>sa7i;#6K9k*^bU>B9)rC5 zSUme;!QbE%-#;e*jPjlvnt!vw7YeTpDwUX@wNs;3I3hE7*okgb@)0hq$Af!^vi=gM z8WBo`(7Kt01DYzf(>^=fmY+9!4J0z0SsU5JjRc^}x$ppEK6anTjgusCg0Ekp3&XW= z+KfW<&HW}3%s{A#x|2JQqazi227j&KM;6gAoL+;XOb z2cr8~ByzDpUTamo)>#!EQ=@>Np<9WaD1pm7@r57aK&A99laWk{Uu^Zw>1sR=0MLuZRb_{}<3w zfVX+3^%{zVLj0thIs~0oMCj>r40aDwxDxTAb4Nl0lS{;!FHd+Vyg z{-@ijSZ?4ZZKl)WthJ+xgn6+cf`lYMW1lx}lI?J;ml4x+f5+y+wXM?7MQ=WcNUBtt zju;{choptQxX3szIbVG!Gg_&}7Q_h!1>!aYUxaJ^Te-9;3TNzjFFd%F0eQ>6kB z%`3>$4y?vp8>kOKTLtm$RMT+WI}U?yNe3~LR9-@6vHPbxro>f^AChn%jpa*)6~aAS zPjRnolN>iO2We(7EwpU)`s9Y<)j|i^=Hl%W7~b4^NtPdy{Sv3nex>jOJ|#3I<(9Lg zes$=2`q;`;;koP@N^4m2_8u?txjqtC*(?W856N@=7v+w4fDN^kjMdC{uO!n8+5`WT zgT6OFkGgg>G&s7M1#u8kx_9vHYfvg~_(Mxe$49?u=2H)YMW#m}+nsJ$Ja}2s5pOrY zNyz_YJaB1gZv-?$H{;AcDWZ2>D_0mw0Uu#fxjJa;c6*8*h<%^){^MlwdtM8lIfcq3 zCNoN);v0^_tBmmdYa59Sp@;-)Zf`_oZV-eGl4!FF$#Hj2%9 z<)W`-GhhG80$mkeA-sey4PLrFVK+HDiDj)5lb84#)TI|g-b%>8j=F!_(d|EWbao|o zdE@CXp0E&EwLM;#(dLhyn`)l~%x1|(D44pCMYbb#hfj}UW z8l%;5X5z&<(s-fl=)rDvMIZQ6;mHR9v;T_xl05sZKFXbNrBgwsCIB3nc2QCa*!@$`cHOJs{m zCw1>cOW}x_#%ulw_8h!1IGKX+ij^B<2T@}do^lCvzO(794{=^_3S-Sb7HS;5niak#jei)2Mt1tc# z47@&Ha2qMsmBAnKzTd2ZRJe_OZ5k0h&PEW360nlH3d>46ntlq)O zaV;h@_5K8pUek4I4(wQlpm3umLLi8&E8oJL6XJig)l5CL)a#A+ghQni&lyQany=p* z_Qijq!z?LRBy=c=v_!|ZmcZ&d`BRQY<3}^75}7JR^z`m9Abq9Z^`&8ZQZ}G*J70V! z+sq8oYJ(9NndNq|l_)YGa){SD7SvGn3DIpI9d(IaJP~o+qNy-|%jHTGP8gF9G!9aM z2!Ms%2jN@}CsB5{Md$j;9O;ZopCe-j6wv^;1XhXR8MWGOSB@V8a@VKLtw3>aWV+(; z+_FHWNuZ72$5ebIQ{0PMD)c)7;(-ekRgm$AFF(G}-W*5nSGLDV-dSE|n_kz_E<}RS z)w4rZYn(^Td{1yv;Qq7C0sm~X4t&t&-?}HWDA?vVray^Lu|eFXz4XAt@+{1zjlMpZ zTi6G=K`xrvW{ZAv%qz+O- zv+GyQTbKEWIU|^z7wh)VP;diybc{=zS=<{)T`yPBfyN7}(tNoA-J)lS z|C^|W6ql1BZ?q!c!t&MrEYTQYuz6AHVhayLT zMxOa0!E3T*^Y*&^AO(X~Csiv&S7*%XJ~7h=b3&GG#08X2C~BryqFwIJ)NfinEI>gi zMSZCUJ)Y5IRtV7dGg`})ND~+?6h6}JDReMkKvABv=TThWx)6?D&jon*Tt>47rD*+; zk9ndhXKZ+)UKi_Bl)y~1?kL9;)e&MDil7YO&d5l4;$&fWP# zKmZXw|MvbuJL;(f^R)C992LOhy|U1Bhb(*wGz^T?=23+1kESdM!0pVmtWX+(&t4Ik zrzqyg)!=;iM(uf%PF^I*5hzthPVKzu<#cnRsv`r)iWu4v5Sx-1$?x`{Gnoktf@|QJ zQw%8iNCm!TSUK23BdpbSwu41Bo2~v(XLoOaP}a+3yF)xoE?3w&8| zeD%YJG7z=}*`C0zzvlk=^T12VC!qCnwezys{7-oQ5CK{8ng9V|*=DYcI%H&t;7xZ8 zHanr?9NZ6_COp6jG4%Q2qa4$@+TrcVY$<#LFoMrG!AwstyJnTWs#0azWi)m+lqLum zI9>t8+o-)Z(kOqF%wYl$36e?(R*U zwZV9Q=iD=M|G0O?d1sHl1N(W_`mXhjPb_%Ap)27#mNiaY71ZT%?2ssZ{LvQ`8k8KS zhkem1x&Uz%bX+F(?E_R4^`JnwqSRCcpzapvRAWY$x|34hCk*F*9jRy5D$Ye0%_2p_ zvVSflPF;$!2YXz5eWIsj1mO8%F!<06_?D%9s8ig`WV?kR>mOzh=X$%F23?G~fEP>XjhC zG*a#$-C897;u|=V1vTH})SA6Xqh5St(6uzAQ=TTWwEp@$N=YPo<4XsE;rE}HY}Yx+ zCq}+Zls|v@iv?_cz%58tDf6|{Eqm5Y^F`aQJ@m}T3RPCbGOP=BgX<1b)P(TkYO%oA zWt?s@iCjDEbUHO<*aQtHiv-UNzK#J)_H>~1GiEtnY)I|45T#~xGXEpF-x_jmf=;z6 z766mWRV!o?rVWkMpjRtM$7j#%u&8HY&9S7GNt85}ib)w6Q6H!BWH}{@ixWIz zSE***lH|hND3zIP6sP2**hAFySVTC!jWv-w4 z^$=7TZFFgUtbscl;P-)Z%(dO>wRRok%%DleNXKzoWXBV6N zkgA%T7cwm19H>3;#r}4j_hMmbnfuD7i(?+Ul2WXChLkEYDrz*9E%u#|rZ;!~tSDIT zu-!WY++TT|WnF_`-u!p^x!}PMI;O9D)*mS&*#Y2%U!H(GHX2+!nD`Z($XJk5E8KL2x#F@M(ApidcAaG34shBiMd`)^TNOeyE zhN!nKJk6+qU*AA!oGxMRfeEz_KRw`BLzQyJcpJe08%11uJ|gfi`O4hGPsP}pHs$z^qS^8TnOkIVM6x{H1M&4)nl{H;ojjQQxs8HqQx9^r|Y zpl^})`yxnsr&jf@Da`zYO~iHBxuzdWo=<3<+kI?+7T7`y`tO4MuRQ5?U<@p$%$kug zFrUR>&h`vO03R7T!Odya(@9zxnS`gYJnxxzfl;2n)pUcbR^{u!O5)e-n22xQIHQ{# zJ9)P2u!TM`+3RG)_F|hbP=A(tZN%P z-T@Ea^ON@Z7+3cfXJT1SkB(~m+b<{6BUxC1Y26doc0BBdvErJud3d^7_QJ&fcEX!C z7Iy}OK-Zki6WNA@l{+aSuu%MtnsqHU+|XqPl?6J zT0Ch0%}a$`j)_pq5#m{P^p^J2KNjdvAEN-~0ppvDuO_OB^GGl-NbA|BYMp!fF4|@q z@69Chwpfp3vzA+5Mib6moO6LG69Eygn~H}%C0bOWLK56yh_L@2dWw@scAY5lbt=Wn1j*`H7SkhAQU)aVd+w7U7gk`kc#{bWkj&*qryom*Po+%N zPnFMq4NeEX-|eBTHiKTy$XLnl7k6iL&Qv)Z4XDmxUXn+fljZX>w}9omJEHFp<8xKr zY_bP6c#ff{XKrCuXYM|?`tK@@wiwem2TtG`S|VZXMg5>}3OF$OTs4B=@On+L#%>ka zxHB#gIkH3ERd^5BKx zFV=L)xX54=lX1lz+_V}0R>BE>eHK=#<>-W zii!i7vKC+aS}TDZ>KD^wPdStOL_EN5YbhBUh*_ZTF_QCP+P=>j*0tChkwhpQNc=o= zS3lJ!Ojffi58CvS^cJ0F$p_r{(U!5+mZ`LUAc^LQ;iZ$@cjunc52b}b!41m8^fqFg zu0)V9y_mjEm>{OeHR_5+@D3!Tj=Vk-o^DTiVf{oB;BRg(cF`a zjb&jq?bd!`v~1HJ`Ge+(;`!LCt&kn}hT(+V7x}sV#V6GU&GP$umoG*bEGB{I^-x`P z7h6=d?VNZ#r*lP3xd+|FCh#L|41HkR3}0@oax0Op1VIb^MuTpl+Xz3S=tJv^G>~n9 z=33b7oe}z3_WGpEusYJGmPq4x;(l~E5ylljzg}T3YE>oAgf(G9HM72=3-%;~p_(J~ zL#~x@GQ_j^Z9(#0XHu0&fE=(ky3NfOJOElmS;kR-mfnur6uyk|Zt z{_T)?gn|y)Nzy`r1~9Wmr>Z%;lTxk&dSg;XjdhB#BbC;Aw3tSxUT3z%Kq~hQ^Mk-f zbb+IZJ+`f1-+iE8!*EySr=1QHN69|S7>MvXrq$hVK?Wil%$1R&fUu7pfE!N@P4_o+ z%CLkByafS%>#%bM zA@j9QC!PMliJor$)yfIgBpFigtcNtWzko*Er08;t!{dFyM}$Xw@zm-}R_}FHcO)%) zxyK0(zFn+{z}F_?dzU9m)?*DD&af{%0c`Grxlv^vqe`mHi>5%MWF<;XOZoddzgZ+~ z%W~)88%zWMQARv8g(pK5vx|4wmx1m`vS9Fb==K+nK)UJf5 znui~UHn6?jp-qoCEEJD6`Hk4M_9{1-bIw%UO*gz(b4-^%f)4TIHnGdb*kEo4g?CAj z9l-WuV@8Piw@lT$bIM-AIw+2O?tx_Rhs0w^7m2*F)JHhE>S5~HZM3^Eq8giRJ{@k) zs8#0yKC+AAV>F)AVaU@5^h)_GsxCEr89nje6}3XkUVkjM)R-!^*^G10r4v8m8~AIu>HAx-Z;aP|E-F?^C2O)Y4d3^-98PH!`2Ql z4hBNQ%xsur%YGrPlh8+qTc0l+c(31wFNT$C$9$DTu4KrVxBE>0Fy_}I+t+K zENcQ{VkQ{A7)bl0j8|K=tR24qO#YAYdZ_X&`V4FMC;C}owXqjDN`B%W9?~wk&p_|u zXPyk@YxPkbqyc9WP?wov)NBiYd2c|=$5VBjaIfy?3(cet1kV((Xn+<{> zxXF%!b?~)E|1(LT;1Dt9fn#3bD6hsBvsMY{(N=4FQOb~GryCl$fp)KMAa~fgsjXu; znIG*}L?IF)B3XU?OUwX6xq|tE9d2L8w`X_LN9&Snz0NfwGQ)rxF7g9L%5m)~7oqiP zX6hVIDYe6Ur>@DadyBF>&P)s$wl6)vO^tw*jw&UqVP~9DHFD~38f32*^gMy|J)21n zg~W$Cw*&*j*WR?PLZ2e?AEC@sdtOwZ8T10_db6f&eTNz7i4g(G?f;_3DP*pi-?1#z zk$-Ep*ccGmaUVfpiB1*25hq`9;

y^{ziNgS!+WkD*8=KS1CY_vVDVVWxPbe`W)s6mHw&Q9>dH$n63C}bts=+ z+6Nv13uL<8{;4MwX2YfoO+n1R#tGIIYJfD1eTn}r$-UZosEW64q@E z`8(5}Wa(`r6-bt7EhX$id!V9n(zuLa$v45=-;1J9X7{>qiZzOp^Q!9lbTDC)LYn=_VrDM8LAAkr#eI)Rj3y1MVr`35?6<0i~VGW{k<&Z*acmE%Vbt}zY3+%kk5Ts_RjG5aH4f>L7tqFMsuKY3d01hyEpcN9;1bHjmUDP?7@(J3 z7%4^Jop9}R`$9;T3D}h4Lsz$$e7)ZCA5qRunJ;_eIx9b@lOqu`z0YyZPnJkbTHaRw z=h25T6qfQERE~f-+S@qptWU9?+W*dq+yDp;~b^za7l$hu6pqIfjN6LTsbeY;0H#HpXMxV+x;v zR#cb{TLOr>wc6HlBskh0Dkkqw3$}>R)fN%N*X6kXN6|EsoJCVqw=EfR!!JND^X+X| zg4IPV%bx@72BHh^O~>xr`l*$L*z12UPDxsj-9#$QWerqq$G%tSraf5KpD=o?kRnXE zI?U{P5paIIlic_A_GttkJt`+KWVCE&X!;I_GY$ZOW1yc(9@y*!?}mY1Odse3nSl&% zw?DjsRwGNlQM_+40F9&%aJKGL-rlLB7%T0;(e31Z{P@iXJNce48{AL6tNtP>p8t;d zBaKpfmeVu-1Fsal-@BKE{VgV?RM30$@4M3_OWl5P_;(jk|J9GW&#xz9Q60C_{@(X> zZ{QQLx3oWA-GUzsRBN{bzDFcK16`sVLKL2J0V~@{OCVh}q{6hUMp3 zxbR;L>*@axcMUV;0*1w+0g5RGn2689GQYFIf4Cr0;r-mdN7?oN_xrzZ^w6(cQO$M+ zaD>hEAL7R#j)|AYzSbJ)8@xF#b?NmmH+@!(97W<<-fZ<$?y3h;g-=~`y|5r>1>d1f z_#`$CBnl`dSBXMseFe*(p!)m5u0Lo~ed*R1tp3_T^pB8m6MdTW{ra$h3r4Wfm3h6nZx+H^r^7EgIoJIj%W6?yg{xX{{~X`*?~QQG25%uPaB~^fQbz908bb{MGoYJAl;HQ? z+vbLc$3(=5?{~0$JB+TjuY6q|3+A7p=YRGth>!`%>!U_Id-*SA@>?N1;PqtN-~LeN zqhbOs+`{L-SbJ}pWdG3_6##&L(PTa0!o(Y3E z^Oqp8Z4O`g{!cbgm$cRC5$hhf5EwsQhsjO}RPt|#{f`ee zH2V7-4e;lf))TQ#ya}EI7?i+w z@W(Bx*Z-I2kpKN05p1x3&tVLIjt+a97AI+%rDo|sWYB56FH&|*Ot^6~8BR9sVT_Z1 zcpqe@GFO@DX;TL>`Cric|2VO}eY|cAS@{MP{QZZsAb71em`)h`0jzq&f~X&iJhJq5 zr^4OetLl*iLQw$XtIG|5o@K_@@lLNN_weq&TjlRI1s{li$NOU=hkxKWf1 z_%s}Y7z;r-cKMFTlmCC7q!aYGI^f$%_wRCe!C4d#b@9T4J775?u9w4+nd<)kWjVkU z13ubtd-&vUGKs#e0bh<%ESo-?U>4inTcaXZcM11sjQmq&0;5ua8v@m4ERU|<+c#qn zEHxj{iALbOjeE^k2^vA6znbYn_osl>0oRCIP02*OmHi9SF?D0Q4*~JuStO-2ZZ6~0 zcvx6o*=dj9GEg`F_9raI${M5-N(7wMA&5ApJ{mDNFdhhN{k3QKw>Td?VM6N9js zRuw8SFgRC$JC0p86J5srx10QKz@C|7{+FU+??9n7Nl;+mb9_SI$*gzQkkQOUEj zvu5q{&!2Bry6j*+acNVKuC>?Kf8udG=Pvy=fJwW28ozX3xT0x{M9?cy0H5<|@hckV zh&Q}L-UG|5Dqo%n1>Xfu_gO$WP-D|}rv8pDO+q-bDN1S;LZ}(6J7LO#hT(7S2tU5w zQd~zn6$WAM-$jh|hu3B%&`a4!zraLX=6Gg7jCKtJ_>7w57SI_;k7m@(eCLNe`dP(6 z20LG`G6amiOe#^~kh`;BcxS{F1v_A!Ch02E#!O2iQ-dyw01c8q-}*MrJ>9 z`rJdy0Ey+#^HbY>x#4saTCEBXKV6p{v5o=tu#?^Z&t*_{NAt<+R=t9-R|tV~ile8@ zwiU){eL+}%tb~G$j7)(W;RXBAn#77*U-S7HM4UTY>SEu4bCc9j+huCwJnb)({ptn> zIW`C*h9l|Mt58YX-eO(LUH*$;C(n4X1 zqjn4TP0qH@833t2m=qZ37L09u&~XEH40@i=6?=P~Y6Am9QrS(rM;ImETHKi^zgS^6 z`tqynJKRZh_`dL(5m4bZD4A_}`7aPaSLgaFjs5VG75h)*yphKMA)m}P_Mn9fKJl?~ z`S8=P67wOC!$Uv+=uF48ApnIZSdZ7pl)-mf%SVj_&G8uyTiWyee!E&n#W21*fGHsa zCjJpVz;7xNh}B2&-A;HJiHt+11l-enhwJwHq?dtIfh^0~vGNlj;*h{hv$dm*e&Qrd#=h0M*h>895 z+N7wp>BbI1N+P?d+|%WUh<74_zjek+0;5dv^M+K8| zK`4eI@ij=%*FC^tR()AFn$K|-kspxDZSQ{lno239EIxC>uzBIhguMD@V-r<8aq;9=|0QMBsvlF#aKE%sae1Hsh-J9%Uxvb^j81_7EUHc3)CdA$-S(TPs&AqeU>T~ zjI>o5H@`LQgMg~OJJ@`Jf@ii8A+|cStx@3N3fmU33@vvXq|4P!;{k)l045|a(3^TP zFgQ))1;iE7K(A{#c-|2%IH6Ixxa-!V=WaH>rN!ttVJ^5gXS+M!B|TbV66Jno0o;86 z0Klx#8lu@!)?lL=yS%!WwQg&2UTry;JDBZtey=1!&+FVzDR5*CkP9-vcm@06LrLHs zk^#AU1pIAsQW(J1S}&_{ae5@+9sqGzNzIV)R;;w*&(*E>?;L9|w40u6#y2IN&@4*%#HENQTEZLJw0$0?3yB#b*6bt zIYjb%K62aM#<1kIZ;dEq>YjL?anPDNkblOI#2=P~+C@{SMiheGBdAz@YbD$6!T~#y z>P@#qQ{Q1}Z`sj1OSGwcI^zgK-H;DyI0)nqJojW9I&)TN#*t zPVqxo3ckHSfLitpM*=BUCl+88Z-XsY>wz1?pdka=d-m8msRuj`%aVl+u-v>#=Plhw zfGLt{c~%UX4`aFa?%f0PA#XdbMdemhW$g*iTIp_LykKm!s0Dpf`QH2l#N_ONyP)UQ zcoit;yx~6`mHYzJT0dl*ouDWf%@gr>9EV|xYaEf_;K;H=;^a>KzWwC!5(6Us%)q}Y?H0XPSFf`I(lDN+_$csxz?3WwuY8NW{ih5QqQtaXSw`3->7T&?Q3fW4dkinPrO5aQ~W_`>N&Tntrg zP*s2^=ph-OS%=wc>9Xtc%B>?c07;y_@!HOx=f`_Jg66Pcy;ZySf04M5vt1NMY&~d6 zls}^N9>7M%h+$F7J@%A5z#tb_Oo95*YQ9JBN#vGY$P<2RPtKIUf9me@C46tP_`-6m zPEIy~V{UVn5|>*p+|;rS%Y zQ{a;G#2+RGr}k7lJc=ntK~OGq8{69QyPQZ@qw`aE{1q#|Z!E3StUF2TMYU+MKr%q% zr)Qv48m^=zgM^APf%?6_K$Jv9Lg^AuKL0ChaXXNWA+y5)T)tMIXcQ;K3ru0M~^Q z`80nnfZBOeR0@q9otmob(Q|tCT9)ECE|-nbJ$@uhU?3rUwi=7~P=W>l0YO@y%-!Nd z)n#I)QJb9#5sM>~zgeV1NpnZ0sks?Rah8-;uIz}f$c(p4<}NZOF>YEa*~NlblWek%vi6(gB+iU?uvwsE-(j*DE#l5gG) zKt%J?Y;&vs2qb+n88k}T@_c;*;r8THTSvw3k>x-0(AG76#&d5e>)VT4^=S@NrjqYN zBP~S1V-h|`xQ{ti*WZ4cz)8LgJ+Y7E(0VcB$_iNsW?iqg>5Nr`Vi|tOKqHRf=g0-n z1S(|YKEAMGg`Ye`SW~wl=Z6GquU!Ry56k)$+`!9ih>pRXdEa5`jduP=p7krtzv2D6ffugHqYba4h z_OjWGCwr*Tw*xNFB?r=!W7(7MlT%VMno2np1PmFxHck~uq~mH{_M|mRe2CPqXV$HI z?Ca&D5`Lxv6^+8ju$6W>;d`E=l$H52A|+Bl#7(0q^=HbgG_#xa!KV7MC z%!27q9_i(1LKREz;F1Iqmg`H?AwBD3i$cir9=^Q~lxyKOrL9v^%qTsf7qK;i-BOgk z0YXtDS_U@pD!b8s?}kjg}U{|io#$P@cz1Ld-J)L>G|?}lK)vYbXVk#bb?YK^@nmp*sSD&YWQgJ za!~)~WbKLt@2LjB0S~os8A6gsg3(Mt7O3HUXf!I~QZm0ilt_gnABKSTNJM*W9PE|% zo0A_&*b>I=vR45mXfK0w#m~H(&l|S$S;N~xe-`Kv`0iIo58EMS73o|F=~VD^2u&WG3bL-!tRsYsgVH*=JFf$DmMk;?O#=DBc0 z66f9dK#Fqdypk+nmhBZChCZWcggE)3N~nHnEiU%Cznwsn)nh2gk2Pgncz)3Hg^Be7 z#H;z%l(!jxaQfE_aZXeyriruVkyL)fO7bbtt(ICFE=&UhBMmjYBqiY->A2C%*bD(( z>NG&-rsi4%<07+;=&qerl>%)I!qiv#qa*Iq)83biYc3#yQ0lmS_psy#GQ+|cR8oY+ ze!TO${a=dA4ws#a0BTAb0#r!I+*q;-(DRTL8}Ahtv>Yj3GN=~@H*`iVHGShrb`hAH zr2#d^Ov;X0KvEB=gWHx$fqQ18fTtV4dggR3Q4_zXFaqgKtfmVWomO%D+mUOsjkrs1 z5J^MGS`3|h+FCzJQzm7x;&mki)THj_X%7_azFF! zd0&rcC%Jdz=ENB(crK&tc7DKVGuKh-VHE4>y$5q^)`^~82cFxGN&w3yAehS^y4DG^=k=8O!|e(Bxe|a%Jb-s{Uj7v- zsx=eed}L|X7wk$apZToD@#v zD8e|f@7txeytP;1*VFQ%>c2gjZO-d#!&^(E^IEG4bhp3hz}pWx=ON~? z#tw&0>zr9!FD}U5DfdB%2FZ=3?35_}TRs6Hk5L(qAj#1vXzzBKl`F=85e`K?#T|RV zy?ElZkEo@Z*e#8!Pe#D04;3{xtaTdGPbR-N3=l9=u2~7#cQuDYgKL?6z5bubKvw_A zK-qXOQ1isZKXH``BF#s5`F$39=B6M2_hn_)8T|zxG#I>|IT($$5coyNW%FhsiFx1f zH@FkY(P zhe;Llmb}(V19~Xy>B*jV88&qp6O7F?35z%#)V~AyTFwbQOCqGtKw4G0jl37vOx*A@ zw1Z6a@VF5otpYn7k1I21Mh2EY^1wD(841G`kd6Fe`QF^ReOt^$f-#-g9mZq7`w*Z( zEq^7ls}Z+IXp2K}p&tNzv2a>rI43+oF+Fp^%ww0?L| zJD-nAWPDLmZehMN>$kHy(r%*?%e4_)Nb7^B=DxUZ{)persII`J@QJ8P#$1^!B8sU7 z5()$cBUs4^6OlzDGPwV#!%}@ZYpI(y%rE=6TAv8whL^BHnkk`rJ{T2Q07qR*k z>Hf#@m-{Vk{_|~N@tNhF%$AzAEbnkPI5yMf@PqIFyKHXUgiu@$KlS7=KmDhNjtB3y zpy(VM^H`5#Wv$>gaO z5+7`yH*h7QMjwhxNJv}Ty%l;3{UqlV{1cppjKVL?_#PUCx=lQ#p^>ckh>_F*Wey1T z*}V_d(nTd@!rUYiokchHY5ra!*b|}%-Gus~D7SpTH~x%6@0Dr|@m!yj5HyiO#_|kw-dpTi!Jp~%ufMa{ zQ%Gc`Q|F@S)^F6dZmY2M*{(0WCxcUl$uRt(`-D+w3}8Z)@aZKAnsl1MK%G_{FLcMO zo(aZbzsOx|()G^pupv^{7o{5@Jr?i{e&?%!dzkBK7X|1lA7^3D2Bj3fQKxpn!{Rs-!UX7~@bNq8p{qZHQKt zZbsu!P%)M<)G7BI7`B*oE-MaoeR9~!E3z2b#^@V&lIhf$Svl1SuF7-WTgq02HyMAk ztN8V^%2-%gy?}-cWfBRs*4Y766xUcB*&0%z^m^U1IGG2pP!g#>(enbcRB-Ce3w$^I z)OwCr03k`oBFmVMD0#=5p@E1C>&j?(%n!ff5l~UcIg};Q z+aCf;`hlGO_w}nbW7YNuo`<8RxLf`Q&HDNv&CXy6zN=a9R!?0wq+Ry%C(4~sf=(`s zb_Gh*rH+{sVNn-zIYM!pUb2mEip*!TY_2bluQ^{0Q8SUX4l87>#)ZKop8F}y76x7M z9DWLldpDZ&-)bmijup2y^rp2cY)(`gON!t=AwFX!jPsJQxS2?(awdry8raa1F#6;- z<;ws_F(e@dWcg`E;$NPdF$xO+(4y{Caa$z64)_7eQ>DWhphw(cGoAQ7$wEAYkhB9+ z6VDT0O|IP@dhnZPh9?|=P^RB#{lsx~PGp5jHvawXosij+PC60ZP&m)*<}e?JMrf_~ zrN9j9K7j#RQj!!pRSPvi1S0|tL*BU+kCzJso5n8xK0do*aYTIZ3JRcje6$$bdN6o9 z7+*Rnp9ad86>hBEnui2xnuXsr&G`}NnUL?5Qhtz@dAJ}6$qiwLGNBTko-8T*#Y{XQ zli6|{tJ>il{CphooXQQn`-Sru=>0NcJD{8DwA1bC!0$M_>73Vn6= z>vd}}sXhb{eNwLiHyIUB$+ajL1F{k3@qcg&|L=e>>tgKBWgKGFt7|i70ahAM&m*wL zX|V2ukgG_~S8zx;X=Q0b%;ofoqBiu8qDD6FxYYf5;Xr_N`4OK{QA1qaB8x|(Uu7(S zLP}dRPu7?d%kD#&adAq1DUwWmBsf~>m+(EZAUi!-{aVP7bOOM2@|I&|;U_4#3|~mR z6R8UaL&43ev@zzG9wUCZ+xAXM4#ui16}uc<7x$SQggD7l%dro+FLHz-XE2oW!*Rp6 zH;)vHUJ8*i#8NfxmwYQUmG7!m5nfAWmR_~rg`zMA6-{hy{{+O=7x;48Q_EgO^>6|l z@$m&9z@e9iL}$QkxtolECo@A&ctN!mGpWpnP<9p;NjLHN2ygl1FXNR~?NX!m^Qj(p zgC)^|0uDEdU6cln!U|vNw#^T?@dHb7_b11djmo)zZ$n2N!*IS_fTx?5DHcdRk@~fDyqyuT zTon;e9|==RM@O!mF5vaQzm!loJ+%IDI^BG+ak>ThG(02-rV^It`L6LNQ!##lF=Si) z{&V3-Ow-}p?hde)^E+!_(EkIL_$GJ_!#KD1Wc>#&7)AnD=oN*3#fif`QOi)I9@F41By=xwH_IEYQ7q)Z3!(pTpI*-2Q zwVI#?mC#*{7K10a87qEzL;4P?)a$fa5@@n@6&@#cvkF#;uLiP7n?pRhQZ@il(ZV3q zDUk9!b`z7TM6C@_(J8t1fjkYvA+1S6Qv&tUdlpt9#MCgq;7`=@DL~Z|rAKl&TLfX_ zCwGctZw%!D_sX>Q4O^O}Q?fhuF-+DStd^r(_KTH~oYuN0+GCi~CEx5y5Q~>rjKuZH z0*qdej*ouLaGWi%i^}a-w>OnnY?4LI0G1-&Lha%7h3ez#JZ=hmcC;uCf_97D(yqHW z*s09{4mO1w(-t+WUhYU>h0A`g@VnD^mK_U>cJ6${1&{R+TiE`m;t;uhC3&R&?j(MZ zw2M81*R(RTexSi3_jxL_W_HV5&eqm;_Nd(Ur%KMPc|0vH=g#GD2iU&3h@ZT`=V#S+ z3nld0d0K@H`$L@{F;Ox$KAZ<#LJahH?a~*2Xj#Af5s@P7kmYF}06AkZgbl+C`U33a zo`(i@7eH!(IUNB<1tP{MyHm}tmvmYMiD!M^t3q4*ete?7KQZtTlL{cWL){#P8;mmA zk4qI&pid0uY2qmPt=u(eOx2P})c8$SHR8^BD18Hy`9KRbAU$K7_h{uDCuWvW$gfW5 zN%nK%I6>1MM@{!9?FtgEG83LmK~$E#hpqm|fUo)ATutZ-i1WVn4}=TcTd(0j?eUC@ zgbpYeika@Dp4dgeF|HLnsXNm@_Bsddjpm`f@h-G#@9Ea`ZNsgnsJpP0qUkKn`{hpp zh(iAxRWLr|6#<6rC*b8^QEAy4@_9K*O*edjVcQ@jM%N}2k7$)QN4K5_aE+Br^0liY zOgdw&XfG~KNoYWuXE#aAi&{P@G9?KZ%1HyIm!g4wz2#O1&|F+PAG0W23kY=Pzk-CT zqv+?y7FYGhxKOLcs)GVQSG}0b)@%d7D3ziaNbTx@Z7B7LHpJ`ml$$ilY2weC<&Fqg zqD(ATczYxhxrp1=xT#*1X08ftJ44;xa!&cJbjOM}U*(k`iz7Fj=H3uaxFJ0y^5a{+=KaKrt938^T+*V6FN#RIlXkWKen?87a{?DWk>>;ji$ zpzC(`HtZ;kUJd%dG07$MsiUXF-avz62X1jpf-%kTG*{^buu^y1jWoBDciov4d&I`o zfaj(fDyZY>HE`;q(CwDnt&;^bvb^UARk-!sYA%0aII6pZ5Nn?6L8vJE`^U@e+K^Gi5?Zh}I)2e{BvW9GfckKcZl=E_ryOI5P{ zv2h=lR*7P&iqmQWJ)j5j-gfa(`@R9YyCEQaqonG6ydB)D9@+9kcO0-66xW6<@6V}E z+hnic(3dqjGla+rNb3_ebxD;Ba_%pCzL+UdX@4Q#B|is9a!{v@z&$2kbqy<{g1guLPaH zEOATr&Cn{NtK&N?R zX{9KDRj)3$<~;@4zi9>D9nUUxw((l2Z<{+%t`s1 zf9gk5&p}C2*U!_VaTnhCO>(dKS?UK=fMc~&MTsW>$z$4sy?@p+3+OQ5iic=tSFGct zTMRQfB@|VP9>%w=0L6n|kXEiEpYMMj!Ae|N1M|@&IJ_PJ3&Mz{_Km&Ib^^GThkQRK zZoMC200Xykmk@1wll95A7#ASc0DOcn4%SD(ukdjNGj_2HX8>@a^)lX)2E3e%d5{zj zF>sZkUYc3tb4A)fygZG=$$NtG1+;&#r?G^)7E6fYJ`zCJ=VMOfrRSrTct3Fi08SFH zDebtHma};sR*&^>Peo*ODBINRD}`Zst?*6Od3_{CoH2my;|JCQIc45}xFsjn-j;1= z|B$n@d!Sx;`x_w^uZByUs{TF=(>=_Dm5}=IP3{X+G9eVsnQfJ0*K~9aLcq9_fa)E`hdlLJKPVj)# zVQV@R%YKS#j08td{fEc`ePotFb5I8}zRf80T+7cmcGLSC2VjfTi-D~et$~4oQ3fxE zZtf&yw1+naJb?ZX|Cpcv064}cRHSqX7L;_#52)qNv|S)w;uUpJ)dFolw}xTqpr72> z`?#c;V37XUxHC5V(bLy78%ti@$$}EVxKmMQ>`W&2eBwDjDQtb@`8Y3onhvk?&r$Cl zrI+!~aurMc_ZQm^;L~YxiThEyZO6Kl^(?l4jns6C;~sdVOyG4osIb1ex3mhYRgR4n z^uCGj6ql?fSA1lU<9!*L&MDQH?#St;PbN4wUTK}>DV#{~`0zowUu9G7EQ(y>2>H?o zYg&`Q6Pe*Lmz7RfC8nN?)F*K)yPT=jL5s(S-_0|sLK~ge`dxP@i>4iCRp99kn4gT> z_dp)kjYD4jm_5qZn?{>+Wi40PE)9+rZW^w!d%;bQnqPO`NmS#0S&Y)?6SLWZbx} z;%anpu*?;Ic_ho@L>XOTEGcVjcTbU?HTg;E7J>ou#L-f)18pD8>jCFu(G8y2>D?{$ z5?qE@dB{b{lwIh5hAua5PE%gP+b21E7yjNyN$^`IiKzM1%~YQ(i!vCuP2Sfo`r-EN zI}`G6ngbKTP;c|1dt-n3nguI~#>omuLs8ofF_GzG;$mWofEAd{ueIU6zbw=fWaE+O zALKLReR0xC8vX^;T<0#J>qsd;v4H+l2#Q6J_4YP`rm!N1+0Qosp+vnmTG|cRhYRHw zz@7K=vM~lMw10h65Z!%cZk{P6-eA$9jtGMaZn*(BE^^%%D+j1KOl))i}kFHQDJ>_k(#t|GR$Gv?dt{M2^d;VR4mmce2~tMB_EW4V01{P9kJuczjN2o7Yb2)% zwQ8ernRU%*-LtgNfXrTWUGl|&+Wu0qw|e_N9_XdWM}1WZ*O(JL_YFaw$q;Z{->*PN z9O^g4FVOh)6yPmfHtt6?$trEAZA@>B2D?CBF&DqwskMd_a|?nwgsyv(_t~*6DJs!d ztA#AyBtf;I>CaHnq_8QU$6F*>awiikdTRufGV|L#M}90E($Sqms`KY94+wnm4!ECo zsARIQU5gccJ$Dy5`1ErLOsHh_WD*RrXWRGYLJrhgirPwmF4|x|HaprQuE)AAuchw_ z*0!NzKbuSLksj?M@XLG^Z-1zrRW9)na;bwuWjCEqZ<-msATq$RBVf2Gm`-ZJ+}k`} zA?DX5ZTiJ&ur#=EZ$v)$XevD!ReY@Qu@pELL=T!FpSX+L>H)B2$M?7dUGQ(e3ViSg zxmGY*iblQn7lKNG1s@k?&eWMabdm9G6)kjqsQ>;H$t8`Y*m}A_$)UA$A*>Mv*DTlU zd|kwE`14YdyRL~XO}(D?pz!(1cy|(eLNtSJp0!E!i=?%Y{-1Ep?@0(E1QU}AmqA^@ z?fFEteU>qyV{g4Xntmab@BB|6c9YI9F}~2}pUOn!aJxU^vukn`dxYTgx7gj-MAA=9 zieugxLcs!Bd-8irmuC8zOeWoD(YuRX(g0M3g`jPn^SW^)(E1-x3c(4s9zrv?Sy8#beMhSOg>gqz%}auhlcw*|qi;0n!nYBX?}K2Kg{`YvD3`CV_QFblwH{C?-gZZMq~zmd%;b1g65=P_qgC`-Cr zW+hR+I6Lu+`Nri2ah4AXEGD|Ay7gnjn_jeP@$%g0;U{bL$HRFi_RtHNXtu*IV5<9E zlVXH&ex8eGlOZW7-q$1*s^J4P)Ff3_20ps)?|s+W zHyzQ5GCs1OZ|hYl3R`4!`ORu}TKlg_>$7i_*Q{nwi^-Rae~`A%b^+2hW1gUwSNvTo zFzcwFd+v)vO!^BP-arH*(55wQLFg$;J226~XI{_W-ECD^1UB7#Qw$Lv`<9K3jm9JM zVCLPWl9|>n8+#nn!f%DI_5w@Bqhez<(;yfuU!Ed9|OEF z7Z?Y!%whWR){`}qt!jdrWoAO3MIVZzCb#wUR@sttkVz!T4+hi2?FEw&mh$~+ zjqQ02x^L2U4#&3tQo!YB=;^U9RF}GjCHoil+s^MdBYBk{HzP9#;#svSPJpBaizf98 z9x_toN9a~l?`QXr4L|lk<|7%{nf=Kou$X@%exF1fk10`p>{s?*b_*ysf0h4+9@mPp z-2cetSc=r#jJoOEEzf9{jP!2ZN4%9p4mOZz5+li-7XZs3cLtEw zWhPy(Fy1+nMA6~ULHkuJeUInDswQilKOwvbifCX&*#K&B)WRHF86GFQa8|{YjF$U- z5==B=z7b5R9*mh7e*M`5>xztFJ#U?O8&HFf)wyDAj1>C-%!d#h+dSsDs=$LW6;;3R z;UQ}xmqWZ17L`mon{j*Fcw3ufuNAMD=tP92Mq4zUDxK;e$Tc>#dphx4O1l`GV)@-e zupRA|tqzkMbO;FnY5x-#2sEoM*B`klf^b?mND&DTjol}*(*a=t#B(`QsFPfvP)=Zu z^cpc(onAGU!m`HgfG%I7*8gy8oSLt39=k`1lC%oczLV+y;eHdj3K)xVUI5nIN0#0w zKR^U~gnYH17@2)z^om+Xa2d7Q!*c6L0zcNv`yf2n=6?Gn#?aqYSMnK&)JXWx4!*lu zP*LW@M>4l=7E*niTHtk9r?8y&hQMd2YU3z#|Gfw!#II@cPptl}=u2XNDl|&Mw_q2e zF?Er7GR|(Dd(xeFLUb49`vefVXwtXOlUO9i#-?aiclML`#-zi;`vlBHxP6bl&8Vm# zwyjg5KIb%Salpv5%ufj-w{$IFfX)7FrsF0%E1{N|7cl8O7I$k_JRgN=Geb$_5}pn! zr~sDm40oa6-FvTyDfj*OByhO}4hH(!P6J51fLeM?n}x*s;8E1ia`Mi)kDNWG1KGW} z;kohC1{gKgA&7HbIbc%^KrU~z$8&t8d+Jf52F=a}b(r>$(N1ie&r*Aobe*+GHZWDY zr1l!=kBzlwk z4*TW#L+pJQ?-IL(p8ft^<7ghBo8V2ky;CJmBcD{aD=n5L9`dEA$Q$c39hkh43ExGR zjC{6KS=;wXUVwIu8&jCS7xjO5n|%9vecaZ+(s+6Q&vE+(4^C`gW~0@R5uyRsw4WA) z8Xwb&yj=dNPu8Ssu32ftXgN~!om~8hd7m$6P|E?4*r=2!A|l_r+8g8Lc*K}r!w;BW zqAs;Up|S~2$JRr}0iyqfn`CDs?WYXX;I)x7Qj}q*jWOdNOThrM@En6c&)&=o72|&~ z_7zZ7Zqe3K(w!m=(jW*(ONWAVcM1y9-5>`f6r@oE1PN)8?vzFl1?leYKK%QDqW6vW z#`y1W+yNZ;V#nGm=A7&Kd*G)mbj2$MTG>1XBDWtfZrvk!TWnD?>2umc75GEbvM&|x z^H3}3qx8u3HRzMwrBP@gRcM*o-0ymW3J;a^6V|G~5ToSJP|Z^Kt~FkF z?}IyF`s0wt`1_e6N{6+h9`6#Tg2W}aov3dc=?9`evjZCY_0e9LWhubC^j-oG$!*%0tG=xCRH5r=(}#pqO{xC?r%;!g$18mE4Alvt`RsUVf}}| zz7c1YccS}zBM-D!h+)&!Frgj+n85ig+UM`{L7jmjN9jWv*>3N9##8FGH3?WlzBfToo2onZOM30@@oWPWNbk%^F9OQc!KIT8fz zMO_9!?9OTqTk`aMA3Idlz6|0!gpQV_+?Y;N2!5Y`k1XYC5jD0h|-il+1nO;F#+Pg?AK+Y^4(Hwo7(?Qa235`)y?={{q^PlM`4I9 zmroZ9mn13ZsgvoGtG9K52}2NLqUl`{G{0RwJFx*Z_ceC%pNoKzOZiP}?U;Yje?43s zu)2SgF=HVq{N+^TAme?#nnyZp!1a#~{xU4>54<7!%hRjpV8XQS`fva9#bpkm<;y>b z>oQmsa9!o12Lf|B&kvXX&>q)dnkVd}1QnvN&7OR@YT0YVE&u5*^zWq~{1$wO?m|w# z93Pp`*Y93}vC@nAgRN*&oxA57(l)C+jxOF;*&OW-3!6Xo&sL;ZUwi#GgbsCzpc z8*%@!J)-w;fFo{3(wQ5?s9DA;jOQE2szbGo#;EyWhqkb|ulZ~CB>)e5RthFS5B?cE z0+8vu`XrRR=pbf;yNuZmw}(g;u0!7IZ3p{8GzvA_QNwxT?HpF$KdbjF3C58==AL~V z@rRj7Egu6*=UhGW8B8J&I!Z{r~=MR2jdelb#`Qu>W~Czj9bb z&bEAD{D3-!OPs&@G*R65>Lox^$|gxlEjmhWAf5cY|BBq-s7Xx!zrTc^+?6lNZY=p% zXhQ^MoqdF)-l7{Oy;Zx)ha7%D=tZ{+V3BT#dP6 z3(0>XY^b}i>zZ)|*U>f#e1sOtK!@I>;c@GJ%HMD22Kuh!*Sb9Q8sPw_*ZHf- z&oVS2`M34gKZ{@CYGDb$VgI4+-$0ZX1NV^U)E=k1WF$F9Ah2HzZ?`xYo-cV$JH7Y; z+^@a_T+IObF)hCaG`1*6m_4``%SAN8s60 z$?uJ1Y(H%V;}dsfCsKSujD`Np+;ywF%P;t@imgkCLf7PW91bLqR=L+|<{TXe>+Lr_ z>nC^hFke7d%YIgt_cgnLRF7w$!>E$JJ9W+^*X@q~S%hGzsU%i$CY}^z3 zQ2+OlI>G_UI-nxx-R_j|kMZgdhuKtfj=Q8E^@fZ0WY7FLI31td)gelN|4sTy1{B#e zi{rPYu3$06UO}jbCN9R@ca(tiw+aw?F-56d<=IWAVwt@$Ev2A=P4_zF>=00 z>9q3WA%lk){ujK4UDLtXwwnKJ(uN0DD0**c#_Jk72QO^;ZUebYNk)q=!n+A~FJH(H z^w*=IKv2X1eKOOZUD4=WbN~Nn^h0~PfHcXh^N|GBIBEuQ5j5l)_?#{Sz!Tp*UcE}b z|IsrdSuI@}lV4s#Rd#hxy#8nbfd0YaS78ppv+Qd&wGllm%*o{6)uWaVgf*7A-f*a&>}<7|z&@cfc2HB$Gzz;(!@8M%=A?a5DB!QA6zVSM#;M-GpR zb$wlgn?h*stDQc(Y7vUKZHZ7XuBfXgmAllPLS;}eF>za?Np=!_&&GAt-Sfs|C{J(4 z+@(YYgroqV0M$M3U~1acOdBDD*5SOWGvCoui@;Q&HzAeK1+`mR7PalK(C3^5``9?$PLk9RtmNA#>A^I~S#3R}X z*-cG?{|q1pe&p^Q$3U_BvI$x!7mpK##P%wbR2#**f?%k7ArqUV=6P$Oj1n1Z<>OKcD^N z+!P$;d+A+kEv;f>+(R^fq*QW8-y=eMLb~+h72=OGyvyo2Eq58ykFf3oS07lr;3-261H-M z;epEZ2NNk2X1!mv-R_@kCo2&cUQ-eS3?p9by`xox?3Z|NEXh0Piq(cEOj>DE&D2U> z0-H)hCLHtRK^_5pvY;bcKJ^3#W%TVkH0h~sfe(L07uyn#ar@m?8g`v$K>se!9p2lx zbgpTD|GF&2ciONIP_f>$jM_Mnm(t=yJjK;GpR@vjJ<~&{!`#BUK=RS@PgMm@r2y(< zozOv4t?sqA!3YVVmBt9>%2Hfqi`uoK1EbZiMQHIw%nuTBKh=%^wh902NKt<(D&mpz z{YpE3zwY;cKY)Mhmvk4&iGiCt84?0=mmJo7==gmyQ*D&KK}AJr9M68pRxG!SKLwyp zk4Pe&zD5eM?&0T!4 zoA$KfV6vqW_M@@VR=1*0L#aZEEN$5{iz6~b7OtHnuCT&NcWV&JAV ze%}#7FJYdgr!QG=Ef={9x~>P#cdgZPizl+EWuv?z{P1rayOKkPrPoW z17V5JZ8%pYs(On<8^@Y4zBg~ES!p`GPtLx{P)Y#){#0kIwcFG7`k3Gr7m$RU1~lW= z0{{`6I^Bd?#Rk!2pM&%=;bcliT3Uov`N%%F^`o^kVPI)>GA(2uji! zll3eOYdr|_i3|dHay1))G&yL4RaUxSJAUG0`6K(Yx;ueAT74J5hFR_=gnO-h_E!Qx zj0&%Lv~bEp5L`Y}Q%Xp+SOtr;i1F&Jw!QPJXb+{}6z$@Y)qESEm7P0pGuI(quh z?V4xvXj;`SudLJBL_Fz;f-9mL7aUewh#*T_Gv|>u~U^HX-XmmjDZA9hz!LxO(V4YMYPQ)^S3(p>}pYz7nfPejRuoh z(#YmhcJ2hET0}h!FA#PhbV;fDBxF7DnpKBnTq#(r=lchxJM;v_g_A))c6q7x*D!zi z?A$yrnfh~ZUG5npBY1}oKz0EA_K}nQP~zo@2K#^#2iRpwweU^d(vnjwxKdidI4r zVsVW@sbBTJBJyv!;fUS2^xKV-=m5Id9~5fEijoAJ(d1JejPrpqVh+lf6lWVqb^DFE zN=pk6Ln`q%E8-Y>&)sREsW6f$8GM^{yW zL61M>#i8(;xc>+9$R?pKw|OYQycms9*0ZFmjRI|yKw{`IO^hgz2Pkq}R5)5#EnEx5 zA1!%`?tQv1BWA#QY zIC(>Bs7W3zxUXy}y*n4i7cb9mCo26;WV7wy(6J8+q%vqOD3v}wIrU5x>9qia!x=k; z>Syzhj@HW!yPcVN_vSQp0@dOkj?z8zHvNIpW%(1j)W0e2mGLO@1x*VO9!kttWXA9R zJh{yqq@u(Su}Vn4LVocBD}Od(CyFHYNR=vV69{k;YK%(-&P1>&uX25RfX${;g7XQe ztji9F+#J=O+Akw8AmLrS)1||MgOBjLAPw)xyF$E7%k}(@k$*JF3gFzvMWm%< zMCWA8DIwIzH1wyuuV-eT#>Pk1_S^e{t<@Jek?8CGJD~eO7Nol4`hz1}IDW&ObozNY z)n6twy7Jxe{$FE{u;Fy%6|(hi^wtGv z+>$BcQ|3IYa$1Iefn3jM0xC1XGmqN_?FqEqzxd%+gwa3VNc-7BBNdw3cSk{W^Ijj# zPoUzd6hmTmrx+y=S;>qu>)9(w6ijsdb6FX=U^;~o42ZImHusoW#)6JQSy5kxJU(&C zjf}Lemq+K-<+F>zR$-k^(!ZXFyE=plfqH`Me6)I#oOb+l-?URr1hPcW z+fpS-a{8Q1&)uc+$zr_Wng=tOB?lG`+J)ApZ)n8Ci)8Fy2ZjJ}$cuObpP#JE@`@ra z2e%cb##q&~C}=+jBH=Ok9JgAS=pJXOWFV42Ph?Bpk~62>HRuiq$8V!XV?&O+OKAb6 z;D^vu9!_`?vvC@5S!8*1sH9_nyfY4-NwKKQbilqGBNOsLGiX|;NKc%ik{~+>Co_yo zpL0)ZP3fFgy3TmP3mg;1$FE0lDGeWbrKk{jo-_E+O1~CIZ-z*9m{o57`ka2G?}cpg z`J%r+qnpR)aNXA!ppO>3NBZ8?gUE-m+bWBhiy1UQY9lvJW2ItQ#nY)2LV>&pNR{3v z#W7&jBcoAXcxM}4TpYT=WK5%;W`4GM%U3N+CBf}>KJ#RqH?oQRLEvJ$AaLO9$b z8RNBIlg6z(=9%PYa)W%q^$*0u?eQkDyw}xtIV;8D6elUp6()|`ML%SBcw`B&LqZ%T z$)U*=K6|ezYlk8T=v6LClYBc~J)m^ov+et&%HT-Q6SB;kUIcIRdVlQeE?ZhEsSZhu zf8L!SLe6nySw_oSWyuvc@ykE8LLM2LuDK5v7H`l?)M7SP&hlysgCjk%K#z1S=!#-9{Uo!kN#xR2Td9gMWP< zKQWYc$bqOEyLF^$)418SGjtXXe4bICbBPjBTKnFu>~v z3wiEQ*(?I~OQ$%E$+W(VZNT1#c$(rJV^H2F06@2_oJUOZpf62u(HdiGFx}eio$oA7 zwVdXphi#OMQF>{eg=4q)R~~0;B4aOST)F3XqT+SdRRr0O|Ph-v$S~Ptg~wF zfY{LI)!<#Z3UkgkI~4p5B%>FQrxbpt^CqU#KQ)8Xa_ytHeySwMxW}Aj$|qv*78qt( z=GsBe+yM$AUcE*oA=CVfWp(Htlob*}dA=wSYyJ%`LMUjELom!GdMc)+v2zP7Zwb(m zNRmJsX}rj|c84RfdLEgABV@ik<2ZbIK&>sdNs{d>7V@;xC+2v*OmJ4F!?0^V{qU^o z{s05&2btRKIBhfejVZvU$2Z3-w86F_ez6hRJbjWc$YJ>%HGZX-fFA3;H(syVq$h5s z?)nTz(VK^3H5c7HZmyqCpt+g}vK!fyR+h}ZXM^$y)fdT&5Duq1=TEZkDP^cJjy0ZM zaH%SYDzKkAxh%Ih(EJne5pV#KNmU9KusWl!|!hmdT5S3cficNQdfk;zATpZ$A z2q3G|@W(2$4OW=JlR#e(e|AqfaR&!|`|vTcWPV3!>q6}>q=N%4q4b zN2Nwkq4>8mIUH~DkU(LPd~;J%Dex#KR;uP;U9hR4jgr_Iy4|Lw^?H}y+->t5TM0*v z!e*=jmDYgr8Bu8mH})ar4gKl|jIaV0W<7K#TF7kwlayA5W&$Hb`3Lk3ZBS!t*t1-t zT8~42gIbTUvfd<4goW;7)t?*w2q}ICg$%Yt&vwE0f^sFkT%q#50VDT{3qp6B(n}AcN!a*Wr`yc0OuWb{&f7GbV$sqai_P z%=u`AJ*`gig~m_G;-<6ywv?GOAw0J4iw$8f43)@zQ&lb8_WIi-$7~3iylsFiz?KN5 zSmHf%$gen74;?hm{T??5G!sFcRJI zkY47@Y-^F!3=YmcJDDZ4FdjwSKbL#|_VAxXP6HwuGhAig#^yH&IbTHd873-bu_#Me8pdtSK*E4C48`A-NRVZinT>cHcbCF{yj>DsIS7_)Qy78Fpfo2 zK{`=nGgYnufHzX-BNTh=!LiFNw5MdaTQ`3bmE`Mda+b9HlCEOCi9=s_&_fp2hVEgK ztOovjZ3Q~HkiAK|N37vD@gEl~v3jm-VyCvpJ}G_ctfZxl67b?h&v~j3`GW*_%`bO# zT{;$g_H~@8@)&h$D}6A(ALQnn4tFax&}v6M5onZNG}?n!dn8&B(oaYlj{$bGsXC~w zKcDW%x*2kWw7b|0YU_F5e}w|MwxfOCNij~RA_jw~D86MHW znciHe4b=c=Q4S*LB}x3$qUSBD$hp(ElZZGWHKoJX|m zF6~b=Z>U2E$RS%>GfJgT(qtWWT9hm7dd>WQC?^N_go8{em-S_)GH(6D1!hPS>) z`f9673?^S}cYmRoxD5us{sLEATq3Zw1>f>#?>z!`GBYCc;bKOHT}pu%tj$;ML-(q6 zPjv#-LE{}2EpzQkwxNRFk(5ZKTN56hC5)XK7p5kUX187K3@q`ml$*M{!}x*)kwNDQ zf8nJ%x7{cEXDS47hhQn1Ydh#3q$~v5hTjW8o9FCOWD4)m{3WN4Mx04LNx&Sf zJH_@nX07jqOe%8~N!HfBreStq2m!BU-{gn=^TPr9-s;81l26gC2aZR@%3q%Jv;unA zS$NZgItT@1?)sW*>l9F$`&6#?9@&4L9KP}*PMfoU-5j#&ZLFdl%B%Wbs==A9+Pn8| zKkO&55YUt`7e!(u)zi|Fmlt$x&e@>yQhXRn^IY4hq_Y9{Ix7duDj-Gq=~-fzEH)wS znAv6hHL&$`AW`l!%y;*GC>wn-M}JszSQr)}d>szM2>=|6RAGC~gfO%)(XP@P`Wz$W z8P*%DMI)tTr9cHstcDcUq6rgRCvLHoEh_@>*>rxnJW)XVPp%L+04`^F9ZmR^({$nm zi00AagKcZ~>DRbFg2Sth^70u+CcZesf=uSMME#Ts9G%uSh&DZH*i*dhog<0t7xr_>_ydh~T1;loH- zA|i5#sMifbZRVTI8aXsou~oM5v9}+0K{Z|$Vkq}#K>X}4Hr6!;(^&^@8>fIp`Q^`| z^hia+*I!OyGfw6*j$)bbou)=8GsopdwhNF_8xuVP*y2DA5K#t z!Fc-IA=X+k!BQ}bNu#h;l1bi4Em-JlljOqyk-rHfdLtoNW(g++{r0A{eZ=1n3}Kli z!yoHi0>dUW==k3J&d46%NnZl`s3VYKVecyvL(nR5!v#uslFly78hJ0_8ww#^ zL$orlQ!6%;GtxlX7XBs%3DtMSBtG1)5tLb-qdDp2U4-QvraorH#W#}788WMuHAD+zj)l)^DLA;MXF>db^!fuP8 zD1Kzxf&y~7y;Z++x~Klk@^mb|uUSu(FH}{q8nDoLTYCc^7C59kUCnQ&Ky$y&7Vo4N zOIpnx`HxKx^YV=j1f+OLJCsRCRE)ZEU0TMnT5TOq`9m?XkGdWUaTD?v|DEC9+|E>dE1&u*A*HY6@c za_raNGAq$CV!E z|N72PE7r6K%7?*uVZ^M_35V&*vMO~Z0l!3I$|wt-2pW9kv0$CL4fDl~e*5Cx2#*tv z$g3Q%q%?b(m_BW#U{AW1zFTloNdWy?jNLSi-A9rdUSYB|F*C`>#I3OArdLh??}R!H z^x8AOh?qfV-mKXzGj}0)_tOuTRwl&FgL5u;v;NB?Qx+P=Y?MAZR&1vgx-n{1Qja(D z<%YhWW5<{k6n$I+%~eQTK}VybMRfZ3>CUe$ZJGi7n>8$HNtF%<8Lg7}v)}NE@KF^; zUDkWVC1=#QSuyaUqXPHmv7zU6`eHc-&`!ty_!|aci7;)GS#-A128(0%mJ3I*sF(5P0bE3j&w^gR$+?ELo>2!=u(jx|v zuVG=$^N`%ys5`VDfFV^X$?kaD1G?Hwbuc`(NinZ8^gVz4@xwVtbxx(th{?*yNw9(qNGB^?9`Xe9r0`%PR&e>TTMQjS*OBvNTb4(S^)zU74r7se#>?eZS`X0`Ssi zxx4i=Gei0M=pyHPBI<7=9zYRC4M%K%U_?Ep5Gd!ov6yaxaJYX*RQItE1QlC9>bte9 zQR}1C#1D?=Xf3qW+DhkKWwhua_G-(k&B2YJnXuYEuk8eUviF8NZuzr2Xe_>}=q%pP zIh8k$c4Ii+1b(FS-MJ+x9T%9C%dbSoM>5Wj+zh}4#(PWUYVxsy9>*+Q-yO~wce|du zevOz|4TglA=<#FQQX=ek1xswKS8x6JIBVB7<2;A;vw51b$E4-cxyeuMUv6tvLOnB% z@xqtCOb;n{n-rrB-3E>)Kj zATh|}Q_FwD`2Bq+-_6Bu$wZ@P!AMUXFi7+hEcT#X_ET$IeSsn09vs4R+fL|dxts#> zi*eiQ^&ECAvLnQjXWsQMbvb+~y5I6hIC}vStWvHE8!oT$nVVLz*_)N4RoV$ZQXYAB zo5k)#OfCy~O>)hRn)^EKPH$-3H{ z*_MsvtPA!Tm(39*z-9lmQZaFs)3oCPd<7;500pzX09Ptt-pPnJgm~=B&p?+4G8+wj zdz8r!OF5L?p`eDQh>DMjrq8l2=%lor$ZvYHJ8?IQS)npLzP^~1Z7AYi{g{iz8RM~4 zrH>GkJO&7nXl7uAXLBzKNpYR7(>H7Byblbm$uZej2=S$`Q#|orn~yu_yfV=2jo@WQ z#U5m5S~;E!+ATUWdR?i&&4{(>!ikE_v@@@L%Tile7&-2EbF3EKwp$PaFXjBsb11|w z`C;Zx+w-14^U$3h!ujWYT|S0h$C!x7#JHR~`3X94U8ny!#_AYgmErBmqRnMH^uMPV z{S9!6Nt-qj;e#&ouo8L??G%eLjrwLpQwuP4=}vs1UwnCZuiQM?SC)*3}|H#)l*N$caqTFx$Y5#d$ z_~rxff-D>F8mvV*&*!>rzA+X+n{5{;zUQWrkj@%E!eiDhN7ETMC7-FTgIMEmjMi<) zfvtkIMy!FDJCqH#7a#+mAVp;7+cK1CU5f;X>R!zHzZMoI#KXQ@aa_Q8O{bClcvye{ zq}K`W2K9Z$7IDMIqI{4COSc{!MfU+^JlxpWSR_DUmXv$R+x-wwJuL1dSr6t_7A()2k2FSex+NB`+6-3<3p)q>;VMd5|=xS@d7k+PDYWieKn?P!o=r4ysdN0c9; zazmg6f&`1lo0$qWv^9z!WoOQxb`8!_6>GQ*h*2-N@b9+$AFVOl-X31`Kw~q{<%UW}qJ=*GlYyHsJ zL{ATC`rvH=F&b}w=;GFNA*xkUjslAd@T7r`Bdmxfvk42TSWYMNJ+YTY%TxGQKoyk1%2fcYkjfmV!QUzQm(+t9LDL=nB19?^wE8RflJ^UFUx z9mt$vwf$8Dm%r5Ah_p_g^94E|Z#bRis2&Uw@i&V*CBhQGu92ozd&$Rb(t;9Pkdrij ze3TyX;l2(EO}u7=&^=M@_j02fDEP5R0#@<&*lfArXr>CWQ=9tE9p+a`^ILB1_GCu8@r*<{zVN2;jy?zx4Gs^>J77;SeYwz4}$zwCih_ z6laPA4-M7H_djyTXcws@RFJVvpBo#aDkhe}qG`Y~?PSb-E;A#Yp)Q^q?v4v$=fGj# z-eOm+7SIFWCSXTCfBBNphHE_Fc-Ocy=AlMgGU(n+<)2n-M=Zq?Elc-B>v@lIre-LD zdD2caVwgxe`VvT-F{iiQM+G&6`HNJo&vv<{ohW$owHFg46+m+6o(>A-{@evn$DyYC z!A+@7Xl-F}8;zm<_(X13nJJw1u(^_P4a7%*#|aLm!{0M3?|9|idt}W53DH1iqft>+ zRZcpoV;;nxHT-t8`;p^~KxPS*Y(0P7$&RDCFPkeYNtFd~G=e_aKEgv0488ScqBLCv z`jj!%;_|`{Evp(E9X+T*HOj0XalC#A6Fq{wW4)Ivp*+ zeJVTmz-cL0L)95?I4~K@* zBn9BW5pr$CyV4L=GmHH_`8&;R6{n z`k4;+UTl#ws4>50j3*a7j$}51JemFVNI$1v1%tyIovsuJ!5XSNO;lLA7M=Z3xfL2&Z$9!b; z=};Yl5QubUw$dQz#^8AlqC$_7LAE}gzy14%k|Swkz_~+WiM#uSWhELCRa%Tpv1Deh zeX_T#x-~RbX&GYsN`7T4I#26xeaKMjeF*`hz>4n>asTJ?i%k_wGRwl`nm;_diC`j8=)htmRot*JAp8iKqK+BB4dHFkn+BYlPppJvA z?d^QVUoeD^FHYC7l}aoVdK{ih*-X^jsyjWny-N+&W>^%##jieeM_0ozBh?4a{IH9-34YH59~jh~%yBT(%8s!tq7}oQoO^lkOH6YT>-v=mtQV z`i%2{R~y6k-t{U4{stl+tXS~v8w7!jlQ-o$ltQtCcc>$n8n>%HW|cQHP8)p@#D#d@ z9|kO;n-br+rFV8deY&Y;gRq-x0akR(AP!95JZu*sUrA`Uo2w6uaYccSIypq7a*n!;~!O#v71CYw8>FX%{Pw729Mh(kq7D^c;Z&gmgr z_{w-Suh6T4n;lXVr9crF`dC|viZ|@y(D#C&j2M)|KzdDT0(T&I(B%`_G&#K=BK$lY zL8WtD*u|Q*>|FFR1@JNw-ELh16DHJWPk%gW`~_g8h@dyH%O_=!6AlLbX+ukHF>vMS zQ3|qrw61heg3}*S;d7Wn=`HLP?3(GHE%tGc^E%q1ri$;|Ky;|qqZn13qzuL)4*&up zl}YarclKyx)zk>a#EgHqJFR;GiTe1izIT)JLCkoMjP(?Hc}UI*7h7?Q;UAK5-PIEn zd-AqxU6Ww-%VT%wC%9u_X!ZsGEEv|1y$LC(H}qU5%pyZ0^#%4#Rg0aT>Tr2)bh837 zYES$H*{K-M7?Nr&$uTC$5^^ivwlQCD!*a99(7i2d8I_ zoCh#qXZoa1R{_pw20TCRKT%DBpCRsV{7K=Iz3E@iQUaFfl5o=K@1Wa5d9=E%%AiQ_ z84?w>T74j?tSn1q+lgANj4Vo(B4|^6AN~at${Gj>YWg+lyC1^%MrR%PpTve_@W7=Z zQUa}E(SeZq3*gL%#WJg>3hUrKo2cO@VAs zaWW0Bo`=h{dT+mzEiUxvk?`#7dl94DM7x__J`l&zyCh$7 zV7UC~SMsV=S8-zf9oz|QNqDp4i%(*TVVMKA8;T;wj5yVe&!1f58NkRENr)DF*>N-$ z^y7Pby|*}o0M6$gDGDCFO2WP2xzAyc5b4`+V}|ro2=E|Z#1;5K$rh+2R-pI{u&|+^ zqT<5Wfw61^DW&nJVF-jCM0zxpg*XR}W5CJ^Dt?!1Sj|NRyD zY4yv25q5R|8dEp;vm2cW5+KcxxodM-h!8P2KP-P5cGt*>llRpa%0Lo5U5nXvC>E?` z{FB}U8-?cE@}dv@Aoh<)Ps%RN8-tY!^zz)EE|0rPH-9#jc~8`S_MT=25l(b!^TLg2 zqk8i}zlx?_0BPlDb9z&#EN=#mk4d<}V++%y$U}tR#nIWlQgLD1v2`OM~Ts0gvv+B z54=fBY`jI(K(QJqEQS?CA$K&-d;vV%Fy2S z_6F!iS#eaheBqc)e;N`2GoX`K(V%j~irH4jm~WSDqii8C&c1hC;r!1?+~&1`2U$jI zo00KqzsXZ=JFG>1Q1A=_(7<;Q+c)uxq^3X`0M6V#*%N`y-uGabp)ATS2^|p##h`!| zK*UT#1=^T^HsC}}JSC^xJ$Xkdsl5;t5C+JF83IEl-vg5M?rNFC>|Y}XoVPJpV0~O! zbh^fee7(YqFu;Ll7CtetdPiHHHSpqBtYZk?VfGdg_zeSwe~1v9u~n}r1#fa$^!Nc` zJ@*VR_873U+hFr-`T%L45xk$pAZ(^D0zAAO>;H4-f4(t_0J){b#ij!kd!fG%;RJgK zZY*ogH*EBz&$}IcujY`75)5Cqm)}~jdJ$ERlgcGT{jgas`d!Pvlm9PJwh#~4_%pp< zxe1ka*A6R{AFRZB!&OXm;Ifv%gGtu==L!wDa6UKYUn(>Te+8~zB@fK?tDiEM9^<yY@*g>zcOCwHpmA_l>zpod$3DVOnBE-F} zdwSH@(~d(0j2n~a+ttrc=7TVVwcy?Z#{iVO_@q5L+$EgTdsSr!BM3Mv(^Mq|npcKJ4j2AQ8zKcmBQJ5NoLLB-`#lnND zh|4bm6_^*wlpB=lAa22TyNsH>osR8G|C#N-g7a@ z@TZWK{Jo(iWywfS=^ZXtnN_V1ALaiwIq<)?j=#sv%D=Q6zjD~im9K7>?_9>DzPF>t zD6XE8@dhwoYH)lZq*bu21NY_l@#qO8LH9=bADQ?6 z**_fxNk})L&DZn1MBRX$y4Qz3Rs*YL30~d_;Sg=%p9IZ+=S=kW)l8Lc&+1)&BHG9R z;%lV(tQCslR=_37rogTFlb~-vfZ1YXs+&f*uv=Wc48qp;dHTO*1{+&LU;e6_+aibV!`SD)C$Vqo^ z#NTrjL-q$)?gjwic8ZyLp9eul7E^jd1>@QY654&bevNB_1ig{vZ>!)zVz>Br;UUAO zOe_lC{iQztm(~_|{-R3NtG}Mog;|C2GjDZ4u(ancZw*6x1mXXo@{Dj`vC}q?i;I7f;O^!>bj#lNg3U`a)wS>+yv?PJV=~a6B z|1uHrGpL z19nG&60_S=m^YvGdv_GC@>(J~uMFZ3^FG(Y{={@T&iu&Mr<{4VhS1T5^XSc3-aBH2gDuBvGPbr_jaYdg@?K*SDxgJXb5}{Dj;7AE$#7wz(hY9pLS=zW*9*?t7PyKU)2Otd$tJP#z+C9H2)vnayM!(mh)MyKMM*d%BE1DqvAK zNIA)C9Wl1lA}M(`PGr&*&s+Y2)sfwR4;z5iOkbma#3VgzrKO>wNkdG2L8U&R_=L>$ zS0R0mj%bfgsZ_GnP(fq&(`fQcO+pGkL60`Y8!n0Ox)BpZ{csp{N*E>EVsP_o6Wl2Z z3`&Jvx71yapvx>f6Q9bdye~XGp_}iy8Zt;jMCF&i;}8*H!7zdvqpyCr(jKa_mz)kb z8hiAr0PqJRAvpr?_HZNU>NN!q{npb{>Y1~|`=q0tvAS&@PSYnPKJ@D%rSf62uU=;r z%HlRe`hIvUgS}#a`cl(rOMEII@ZxRj*AD+BOQ!VesYE`of)})PB2=fLcOh+@&Hqp*A}ly zLH8-6g5r6cc~nNr0l6TmG7ah}j2nwf@ zS`n?X=@z3XJV~<4C8<4rufBk4OcPQm=)9bX_u>ttF*TLO&6CZ{rYUIOYTD>osJo$! ztg+u%`M&$j))1CBwz8+kqPFLqCri-DT20%MBP|t4+tDhde7X%4`t75#wR!_%8Xi_g zMwBX-)sQ%j$3#>bg?ex@5!q57DK`C((J`=4{V8fsrViaXt1|@f>FL!9&>p`l_nVqB z;2YI;{?Oopt-Q1joer_^RACOO5Ap-5jBI?Md<2eTP2tw;qo=+c zjI6yANO$l(@)yT?1I15chk;uuN|-bR*d;Nj?apm)_P7a{43wpB+q?q~f$CMpq?*_V zB{Yx1;|Ld4+pD_U9i%;wHR5eLp)u^SJIXw8@AVj;>S@deg>ermHp-}kdu>hoGwM#W zNx611`nA$*mO(@tjFFILXDiM0(=^8>B->YSOH++!>6=cdv=x#dM98fA+H%G>Dg|}6 zhOCvbP=B=FQF&kG{K0JEoPV|jRjbbF4PU`odN}}amOf(;o6YQz{Bg@ktk!JWtGqX{ zm{qgf{6d%-6h=D8)rd>PAJWJb4{|t?a$;ln3u`A?4)mJohkeCio9m;AxTn{|`Q+P9 zpuCJXHX5_FYCH45(QH;6L|rk0($Jy*yRTu{P_d0+`Q*^P?hZDlv1y-_JHX8AiI{&fuJuTT z!r2qnAPtOJ7WE*yl9wbw6y%J3w#FVr=@{Tp4?e*p4b7gHBi22ihoV)5E z_e!y~&O}Iv0fmX45PlIojL0H}sh4C>Wb}Yl|JkI#L!dZ3-NBH8r=bsQ0to+mi`cs* zIKh8?+_wJwNc!6uSy^FG(c8##fTQ!8NV^F#{}t%SCt3kWw{ReY5E4erWqj_j%DdW) z>iztQgm2?LYW3{iMr05F(~a_6r;@tyW{Utd>)LCV?TO99^vR$<-P3simagR zHomwpL0~%}9T)obR1G&ZSoze&_C@v4(;vWLA4t3^)Qqpz3xw{x<>5s=IM|p#8ZCcr zpNj%>&g9=z7|&)#CaB4@oQ3R`uxPTgyw&a$r*+|aN(E6eC zd07IY3K=+2hE0HUO`<~xQi@;U!Ua-F-o*h2SRz^pOZBrI@7SWz*MXHdGdfH@x@Ul4 zW?|^h|K$l<{7k10i=oSCiLvm<%r#Alpg9lBRD<)IG#lR%k7{Ub$+ctK8x;- zZu1t*a=o}^H+$l&zCy}lg^ms-s5Bpt22F|9Rdj59)Xi)D1}H~_uoaOjJuhK;=?m-{ zC)g9pi#~=??}-BHK(|mG?PldH#OyF4yPH^KFX<1^{~v2#9Tim<^^FKhNJuInp>&IM zm!u-yASK;hGlGmX0#ec;(%t1Kf^>IFOG`5_%zSt7(dT);^?v_-Yq?l=E#aPf&e?JH zKEM6j-`c}gP~|)9@4YRc&r<8S-G9DNn*ey$m(CW!#IpbjG$@hdnOUGr$cSlI4Bh$# zK=d2Bey;rGbE}`})GyO@ZvYFXf;Ia}*)T zNE#&4Ts}S|%X--CMX7dNsE9u|CMN4vy`feZ?m0eiE@7IwK9_iLxv|{K@vpXeUJt8l z&3$~b?xk6mYYx=xH=pc8P2ed9iba5xOxxC@C~4Qeh-;lxWu6|g(d^6;@o$xy@H5_- z=RDa(7C0m06Fly&BZM>_xSro9)}VkS)yky=_<7wVLnCGTE(2@8v5tC-1=KwM=vtDo z?q6!?ckR29?~Sj1rGlv+6a7y0OOjPM{ixmfmHUI!ED@VtOoCL%np`4_2AQzOF5_u* zc7szw#9n0gi57LuYvW3F22+-!FNgqbX?6LNEwRMV2@VSW$JoT=14!I~bg`A1uBk(p z7x(7{W^s<=h7kd_%H2Kg?TzReY&h-%9WV{XFAlz&fn{NB=cy2OzBmzX*V>)17~OnM zSyp!bq=+bpbIq|-+tkC55+i4;SH>0kQ;*+ercu$-xllznH{g&C*ZSIwo_`g66!{6l zE1zvW>>OGg3j1Xl^)uO81$=WLQw(VCwFJlNEaPQMi0-NL>Lb2NvfOq6cXuhcP|M54 ze}U07z5HgkbWyv_-1iy%_9(tCc3GjZYMsgHw{%t22~}+)+vR}Bxi7>wtLl93XBMUl z`?M9Kn^x&+pl?4^Zt?Tn9TNrB)-1k<&j~s8)MRV{V2yGCiTRLX&C*-3-qgcK)K&J) z;6-D9ev(@bvtA@dr!@)-#2Z{O`)(}QCrFoDLa$-6A*(U5VgU}$0=^h?4A&><{Yo>mg zgz6mBq8TX0%GQsfSgyYp5TcRQ*gHL%54jidy*f9`1Kv!p@^Mk#Ju}OBwTn*hgG-y5 zhN1YnB1r#xW-p#cOpGx-+gtPV$Dh#}I^PzX9Nvowh7vPViKj&$Ro+R>v$+rM37TsK z1EHc9#J@+FqkjJCN^z6M56*IsdS&tS7P~>!P?Z96_*3SKoDCeDO&gmE(7dfyO4A9Y zG!Xg8QC%TCH!Nijn~u5`ACNC#{}e!^Xt8Npj^a1EKlnAZLNCt2N6KGjV*WfA@E5cw z?ffT;1CK-1s9LVHOfg@BN4W60IA>_C2?hwsC~(Zd$nhT808s7OI|;_nqPO?~{dugE ze6|=jZ;8@_RGQ)f$?lx(FA@NU&DVW>DmqoK0qR=~RlFe3)kWB2fG_igQwvXz;R9Ua zer5mwsC)O<>P_b2HnDqBW->$!BTS7IDyq{V(m{q=c9rUVXeezWd1D^l$f(oT^Eh`nMM|f}R?-xRRNBPK4;u_$*D|TF8`M#W4y{SW zLQ0;;bt&CHp5W>YXECBMqCF#QJ|(+vp})q|*veQOMdE2c3p7lfB*!JCmp%xQ1sU)= zyl7A6w?uX?e;fW5((jlZk6oVq(;imEApNl*vcCRV1l<))9{FpWr8F3NU+PhQ>&K#V zCG3Q3k5tcfL0jUm`4&2*T&16w=&p?nGPM+Z{S$nXrFtAC_j=6_-?zW*IURdmax*IB zNkWJga2U;$Is4(J>C%&)^K-eFQon`v;0~tiJOHs|u_SWWSimV-3F3l$JAXVnGtQ>f zd9vfaGe)Wq`O}sbH_k#){r>8C_V&iq@IwFynR8e%#VD}3ns`MYjcJe#aAgf;Ygmbr zcQ{bLJ$`fB^d{#|md06?pRYbLU8rhpIY>m&RgEc5MzmJ=ZQxHenx}46Gk6U#_ zhL7WtfDYFgf?&j##qmlruJnn^BzDz7*d#B~W@1?!?pVr_Qt5sm-JFxkzblNU_c`aK zO@hJT8I+k2+1{ZQ3^ZE`2|9MZpLg*nb~ijvc}JgM@|&ub+Cp^m5m@YG`#utQ_n2kr z+5XdWgFMd+k241Yfp4G1&dp+?hCZ8Hl{|b-l}#S~^FtNWn~Ci~;xn$T+gDF*r?)`N z+HrD}V)qvMTOQ;@8 z>Gw59p53czu(}WMh(V&e-nAw6Te}c+AQGjv&)=^BfdZh~s^a7mhnLl=iwLv1(Oxqk z|3Shv)&&~QKfE;Eh~5Pj*K^I(ePs@7Yqc>bL&)KAS+0>5wO5S{l=2eKTji0uMz z6ec)qWJ)h(H&erM46rSbGe$J^#gHk=M^P-r2@Yp)tHB9nP3aqLj3NnapJ%i%2?9r% z-uxh9ikR0-G?G5JG)9wJc8{c)#kq5CYi+Xl?Q(uniU=bgNC(Jqq6HMaTWC^{1cgmj0=hZXSqK5%2%e#KENfqC5Or* z0p(T4uplzioND+h)12=YmS+i^nF=o(tj?bMbS>q(nj-M^5p=zefRh+8*+$m|J_kil zh5x1*TW^@FY4Txg%)<>^et^?NsZWhfvxK(YFCH0`j_9u9knj^5Q`HsEmHV=(!KnA3 zuCcsER{^^~Y}C23liDtdAGeNpnyTZ)cu}e>*fUO7PBs0BaYe%IBJJX6GC7sWlt{K{ zvZ*c#2(Kx9o(|_*qwko8`hu51I|tBA`zd0Yt3 zI=cl&r9$k>N>$v1#HIFw6-nG*J+z$!9cs;m1o=b03QJkE3X<72_rkeY(j>g_$p$j* z7&zG<+`R$tu<=HWbRA;3;C@ef+~vv`7R?eP=mKOk%w{#fqQl_U-F$fK#W8P0k-`rj zATRb6VDY6;VrJLZ*FQLxy*#Nnmc4rPeRH9hV8KdSPNVFV6>h9hYm3Gw`};05IX4#s zk(y;|=Xn>3R8+w$NhKe8Jf|t4zBBvSpt0LxQcg%Q9>j?u(gHi;f>ti( zB?aA8q!sLxZpl5n%>3-ueD)KM&gTruX5AS1oy#S!vXpA__{zq{=lTALd_c{eJveB{ z0J?VWwSm|UJIdccJc|er^E)Hm=$e?KEwkX+%?90+r4TO1U7rT4bsUN|RF!XB9JOCX ztb08g$k|uMnLJ=1@x32ye8HkoSK~uIMIiu^m=qV6Rk-Ni3JYF>Ud$* zqNJiOU2$!8UjRT39p*gOdrX(!EE2M~ z+I@gpOP}%XWx%Bbz3e`~tDt{4TN3&3PvVvP1{4Lc1C3_++hSd-u&PW{@c}uy#nN)) zh6$Rl4xkt!aHT|cmJ%vdkDSg)vD@?WEt<%!eAKyw0D!^x+#UYJV zcOLpz0gg8Dx1&AL&%b;@V~B;@iOEwnrj)~NKv27zkS_pjbv23-0P5uDUc`;x#Q`$s zA-VGS&B1-Hrl5h653IeyweRDy@9LZ9I^V)ntr0A^(*rRjf|MG5Zf6G|YM}HNPZ()z zr(7*d*_9jTmjXEn4L-Nr^Lx((&la`tN+lEWJNE5jzjasxk?ajOsIkY>D%Pow^lWfq zQK?DL)gN}2OICpG1G!#SokG^|xI``mtl?HGE(;U&_V*o9s*PF1m^0_2Wim|e-wdT% zGx$!F@WS_N{rdm@s>fRX-c~=;yRx_kShg?79jmx?cPiCo^t5xKU(-A>p zYRRg6mFTt1zyK-A_ET@>r^?8aI_RrXS?iIK#-D*4E|G_z29G1gkg~79`BvtqERX({ z(?|*CSo`7xiGqK_UC8khrcaWI?h47u%a}NBYBi}4GG(#*@hfNT2j&&F9jUk( zLSQ9Cpf_^N4>{t8IOzjhmnm~44!QNE3OI%)(XvCp3B{V<_N_)+?8)^@=PgZZCtU9g zeHK|nZe7ajFI)|-o+e^&5V-G|W!x;$ts?=Ny5SZdA6DB#0SDT8!qy3GJ~L5Gli&lN zLBXq{NrEGDDeF@`l6xS^^?oOQ2VJf?3buFK^AmnoEI`%}Nv|`9;;8S?)%PVQ`>N*7 zX7W5c$+2s>;c)@1Spq?gO}u$Va#fZS^OkF4c&;r~3Rl7dIZp%jz0B1~F7N_a1;Aa4 zA2a+pOV-Y;?)nE71#~`VZsTi3Q`n{JT|Z9E(>9AETpw{Fr|`Qys$Tj$$rYq(Ov9XM zNqaWH_RGtMESx0aYa(|nh_^#WiI6jUt+fl_tPz1FI4n8*y~Fx~MCHtowSCPTN=hoh z&F4;At6@1g(u&veRQR^Nv)y6D>++7U1u{mWPM`qv*Y^T}A7VeQcJfBi z?S>B}0f3SLFf~Eyc{z}AGFQqf^UmkV0)t{+(TQt^;>5ogZosa#die#5QWx&2mdq+7 ztP1N#2)pcX8_L+pCuTb@(biyT-d~L5V8AzOamEKAwYMyLI>PD)ot7x8p`MYN7f9;+w1t7m#cIknIi$zVP-&^B=x}KR)wJN#X8lcWM)*_1xqh2G)YKsp&Otw z^d`G_$M=dDueyVZ1U*>4_1MN*jsu`_W+w%O0>YsfwD91&s|cYRknoW_A6q3H{pDYK zIjprZy=_IV@Tn%_gtESg68#%B-lca?pkwqRZ&RbhxUJxyG`@vir9Czd@7P3M zg5~D?#0cOgbvS`?%*8iAt{66Sq8tGsaUI5~CkdF@Do#9|WtF!}OT1V+@0R4%cc9;6#1XmPdmrOG8qe4C@eiq86(>}BmQ-dgoblW7pE6krsh z!L6|7lb@Js=Ou4~El2a8KaSX9h<*Aj#iu`^xz3~iZtekX6?Mf zQtjF1_vs0^LWUpE;%X6T)O13acvsO`;$~-gO&vpTv6cung@6O2r-NSYNU!R|Ly7rx zA)xHI>OKlP^I+#3DclRfNdkV zqmv1(KUdM;siHK zeh&#lzlk(O2U2HT9bqsam&cF4XXN z;hKA51lJTOMHG{;bExZSeGDC9Rna7g-A`50F-~-Jo41J+X~WQS1d>mZi2}@qUm==R z$trF*MC);R_no+k)LWa#w09#j8w5#|yq;j^)!Q#%-9FvTE9%QOLCQnq(g9#=+eim) z-+^nc?!j^!I_d8IbSo|pu+kIwz%{PDmbx_Q(q5FXOxXhgryj5-oc+WdC~C@)-7BnEgY4T(As=J%H}q& zmNDahd}(tKg~2ou#j97HBH>l196AR>>?40l`t#7q&Rse*!t(fslyOLY-tXGfVA29g z%2c)P?KOxXCk;?x^@M&*l~ z>_qDPsen6}YC#J-M7|e%7U+ETjoiO!tx-OoJb_53IjW z1Mnr$WZ=F}jxEX1=}fX_zlj|?S!Rq4-1QqgAi9i7`Xngnvk zG88y?n=@K(0dCnBJU2$OYUO-i`%*$ezgmlhNv}hyor&i8_14wa1={#g5%8k zhF*C8T#|3U3Z6surSOa=*sni9-AavAer=Q8ZENQ%)?QxrZ6XbDWg(?BFm5l`uk8E8 zJ)F^@kP;CGaD&#d6NTO6M^tcEHt61A*bXUs`>EeR8n^@M>)vbzAGE=oPa|iSPGt#hZ!v)Wp2u^*M45IM=JWQAq=UdiRYaO>{4Ad!{9Dk`1R+G7)^ zOT~EUz21noA*rbfZDS=R>ZP%3=yj;vM;xy6$+?geEH_F6{v2C7+eRoEtOk!HRodd?{VuA1;x4KgX!R1-$fz#=o|T9&%cl_w@VAM=%; z3P9Nz)tQ24-`yVt=m9I&#l?Wan<1cSkLe7OqG{C+wwBb9L&{(cq%2xaCT8g!aGC-x z2f^a)0^2GP{%gY=3&}kDQb5r$gfg~%!Iv0dku>K_5=fS$B}83zazxTAcVsoMv(npb zeKwNLV(ty&G$QNK;pS+tG7=@Y&n*2YX*Zs!%q*xPQI;SHC|~p15>`*tBa}c&0%vmu>u+` zo+fc>km)Z>;*gI%amlZ&P#}?6=0Y;$Q?lgtLuK&w9o$J^<$eJ*9XwzRxb_iC00{1c?&a!OVqAf)j&5*!$gjFQoI@Wk?3V z*mhY#xN6kbf(Fi>eMz(-cKi#CS^o)DtEELmQoA*k&%>XMi1^*%!z&qWI)nK|GNsj4 z!E*LN*V)uI+1@7WOm9^ga>o($^wK98k)v&c#4D<*G(g~8=qR?Ldb*e(&b)5|SmDV* z$lCrK&cMYn5|UXG6W+oMZ|{Ip_giT~d7$^=7#x}71x7kl5&?&TX(Db)$|sog1SrtW@Ne77 zxn4H!EA6flsT%_Wknjg}Eo?C0>H%gcFLLT&2u;teJcN9|_xy z=ghWN^JL`Qx-I>ymb+3fLi;Cv$=my+93`Ck+=G@8KI@SbC}S#2DN%+)+^zJ|*0$(d zVy0LCPFLQi`k+KaFGQ<#m#KJqZK#Mv??o7^7LHP4B!<3se4w%R!=#1PnOWnZ5s;sy zP1vM5bTwc8UQS-=<9GSr%b8}%A(=ZN6RN5wCfnyp8zxR5KX??q%2Xa&1nN@C;n(c4hQ2t}0!X#cyS|Ot6T>ToAQ=NZ>HrdPXD6 zi2?R*v%bk;AGeCsKzMBj#9~Iv-{yLq_?Kll1 z?p&I6g1#|2=Z?Hd%*>484@2vDAmhuH@jy_mA!-7j<0iFo(WI^{jYM3uqcCUaZo$uy z7j&PirWT-nBKivbwS71VMVg)UL%G4q(QjB7CndGR?ht+jZrK(2ugf8)^B$l;jVC)C zaj}rn4qPJ>g*+7?zigLT+*yl5oR>$`>uWaDp`LWRIl|h&u{Dh&@_R@2%Zgk@?gpRH zTM9rwYkG82r9^cAzlT= z8WZ@!3sw&dy8_nBpY+ZUd{La@;2+?es&c@$p3wBvr#LE;Bb*sZSRFcJco zb#WP^d42BDD|?9fo(2xJkc+geJ)Nx*+dIsKXHb9>9b7yzGwu)7s&ci!h0Ig5_mPdsg^BUh&O`|>VEKI-IqSVJPo0NrB2Pi+smzYoPI=5D85-Q*f_^H{EL-jzBdbS z=OGgRCN+^Lb}_`X@P4h5B@a&tD~Xa)**4KY*P;?v|cmO=? zHBe^vVH7B?!IDKkyd2M*d2pW;kCeD5oN;%)R;$5GyN>J8BTe0>9~*#j;1|x$id38$ zWuoy>rL^slm)x19FZlWKd*UOA393)`JqHCmmc3H>oCM)AHrAL^&VvI1_wyh~ur9AbDb;A>0ci&|Tc z0=-!a8%Dl0H2aw!S3)ho*+K|Z10W;-yfP0@9vyKx8_~;)$JU$B`dJfJ;ad-O7BpVE zFzQZ>fK(4B)WK)Q0kn@F<5X3bXEl!%YWJ&!)6_Xm-?=>7t5eEllHNZ*u>cYuqoZCu z#s4HJ4?EB<0u;1!IAqM!A3w35la-ylK-8<0TbcC2j`+Z0R~`)I)qiy6@&!}lgE6Nm zg`F~kY8*(|0ig+tlt0a2vaq5h=JWN+v(0GkO8N4T;0_7DGYKM3kDp_5nsRQw%G*x9 zux@ed>%_9!IA)(`kaM)_SBI9XVA#2tMyZN#V9K&kp{+G*gS zKs*#$?=XMo^0Z(Bs_vfbvW&rQ(xmW;7fgmn5b~Kog8tNNNq?w}ddsRC2(sAzcj%uw zHnH-VxoJ+4kK2LDm-1`U9yFX3?%4L=@|MG@dACc1-@Z)i#YqRj^ydJY$N9?7%OZll zZ_v`weWhX&c+AUdI-DcN?KnsCI9%d`B!CTG1Mq=aT_dWckKS9aO)b4~W?|Dvc+%vq z$83@v7dqQa42ke^jM!bi%aH9_n__nPVg}R@9#PdJNzhn4Ui7969v=R<&_4GTiiWM_ znuaa93@L4`hq|(U_l(I$-FU4hy{S5s1ft%vtIe05hSdRkH6tM`=9~~#gynccyn}XT?7SsNvoEjk;bu2w7^GRg{ zGb;^s*pp4>9CeJ?1sPS^_}~~q+8UD*V@BS=&rSwK z>RQ!VEi$^oi}Z7dgHQYhyry<({_rYSAqFPuGnH>niMGb?-_?ZJ}a4Wyr=k9TTbQdR&D8xNNR@}#T$f+PA6Q&KhG;4lGXEj#cpEv%9ll(cug$c z2a#2zH8|H^l|_Sfj_RSsZ=Au#YIXi=hk5RYvQ=T|Na~Knu_<~InhbzKZWIjZU&QF` zCf0#M4R^sh8xlp+U)$E$adBWTlPch?z1p94^nx^C_5thi$<~Og%JoST*FLX4D3U)k ziTE@kiKLG}2j-$z)`v7|g%+=vR65ro`(Vu%mmwRhcuqDSiyldcU8S#V9a$Mq!$IKj z5-oY%NIRB@spH98Gu0ybR_`VpW;HZx>TbPKPPQIc{BYo;n%tG3E-fWKSX}G%e0wL> z1msV1blNP8NGq)O1qtn6cz{O&1N@$K{MuIqiNiYR#HVuT4YZ#~7*d0`5U_M)ag?W5 z8Sci}zN)d4k8UU;StI4#z-DtWqP=%rr~ja9@u9s|{OD8_j!%+zAeVGYS7*ox9P+IX ziKsgfcp2i?5n76UBG67-UCdOGftUCF18|F7v^&s|Bmcte zVY%yC&j??QPY@m@|4>)#!@f7p_~^z`U(#`3?Abe~Pu()R`7ox;s8va^6JO)I&w}o0 zE@9>U?>Vxboyi__?}^T?w$aB1%dtAz1>#)NxP&&DEkEWfO5sG@Wy3nlW;b44IggcT zQ%cH9e){y@>TL`geR))6+wA^NmyIZz1+?Wir9~AT?Qp8H^})ebS7kd++v?i8X6X{r zy77$~y75a8@B#^d54jCMz=FcbaI^Glw_h;u5G=14>Qh{`Sc}gS=13gLI7Gg(vKp00 z73eNNixqgnt`gpHewq4iw{7N&Hk;i|s=ckN#ycL#1~5T3b~7%cDrWfrE&Y?tt?w%$!`xePF7bY&P)a!$ske$(aTvUeQe<$*9?K==tS$glMz2@v#n z^fg>uF3w?cgOR<?A`7pwD>LKMF8zca~DcA-KdnrSD9{--uCra^eGHU{>c$XGo< zH4*3YrTw?3rS(B3M7&O_#z2=rMBjew;yxEBEZpSN@*AZ16sK{K5a(P+l{d$uCz`q` z(2nCay!=WA6?YG~2odA0+qWZ<{DgZKF-5_KpWQ2y4L&(*iMp;P(de|LuMB>8S}FGp zU)sM5ym7cVI9u*2OG$ML *X7@Fu~`l%B@zRewyT^BOzPkK0)1{DEyG43G6ph#51) z{1P*KJ~huv@!E_Ckleqo*x9k}0+8zNep(5A8bzT7kaiRTLE<5S7Cxn*Gp)no=O|T| z*RLlDoj1_qMJW5F+iYvMu#5HO9LRd5(d)v!<=E#^Xn_4wuW{xrBCG6Q856=KdLP`u zY^=$*bwes;;s}-NIu-Fn^p~oa5TkMf>bT+$!k6gWZgGyH`?KH%_bDfGSGB$oXdzc&7W*V8A z5a&EwFs$`}w;piOQOuaK^^kmr-t@_h6BvheDL>G7<E3fQ2i+^u#A|#}4^)@D#@9!^>tzXd6Eo@_gz`?0 z3q@GiQ^V5>`Om~SRNOxykH0LE)wjHDT)FH`_^nLOw_&$&JwPOs6zts9UJZwrCJ8=v zN3$KuPg2I6NMBubbEXmOELu^smm4j0Vm1gPz19$W_mDW@yjPt*^CwsRmLCkhxUDnr za6Xg>5y_D7kg)m;?c2yNqB1UD-nSHw#>qCTxfv0b_C4WXUm>~6GPRlh74C6_*e}+y4&KA{8`{xod!CsNT+a$)GHj7L`N}&>mhi6O% zwhp6pt@E&upeBu-#tH`i?OH?7^K%gyJyNaBeu>5h&@z3~1L;(smd3p2N6sDtT*Oti zE+CeHi6vW*fhGN&e_HWMX8po0fT=G{etc<1NJ%Us&@O>R4DdYb9yU;7kq`y8kukVd z2Ruveasaw|QC+dlHR;j-Tsj|b+`QEzm+8<})t@DG^O<5!PR_@Kc2s!RHrCBn-lCKa z^q5G(g~%m_5i=Dr`v<+&xfb_kN~(MJ9+gtv!mW=$AW|d`igf#W`$Sclg85{{>pd`V z)XXh9m`$k*9>Eq#_z&C0^CI-j?rz>m7u#*DZ*~}$e`iYg(WVtu#P0-cwc=%FR%jsJ zV#OSQe?kOhuFojj^3ILJ`EfnyDok@3+sQW0&o?{u+NAp+q6yz8YNuvW8wXOc?&L14YHf{Yr(^}x8@3FUYr3E_CQ`GHsm@jLsdHMB3 z!gsZzW}<6i%$|C9SZg!7Zr387LuaDyFgc{~w7SCngo};kx%~?*!o-=W1a2C391HTM zu-o=d;cgTQhJ~!Mr!EHvn!=Cb--K>ATMP&J>j|zziIIKy^@_YcU@=3i=Ab<7NYCdc z0i2th@$l)~2i`<_DT8|dor8Sl7rNx#+m&8}jzSNFS{rF!PDbyJ=x2Ed+54ywxK-C^;a zo#=F27M@e=;AbK}=ULSZL8%?akr~KK!>tNioE?aNuie8i zU%Mr(_^SVlQ+ANw)4R`v+-u2mAzr>HeuL?v*oKBa2rc2LEqVgqj6O(O z+$X3V-W%{RwL&6R$qy;`8WUJG3uujd*c?*c7`FP#m8^VHWDAR4r?xk$jP_>X;;$3O z3_qdr__g>2{&?UM-u9YrFit(-EmfZ_QPY2xk~yG0-&eL|R}f`GytPy%+~H|k0JPh0 zjh^bSb~|5d_e9Q*ef)?pGrC9ufMq&}#`q)qSn0!OKjmEHG3wj1+P$bQEgcj|!?$%aJR;(KgcOZGcR0Vp zh#^r?-_Am#a#Go0+>x^}7445_7;}wiYu%nl%Vf}OQwKVpdOtGaJ(=lr90T1|OcpAN z8(1S>00vR7bMW?4bH_;_haI^H|X^|IB#P$0PW3EiRp{+JZ19D975$~Zn7H-A8~Qn9#W>$%_SY&JO1=7;o>q3W};Zh z)3-XoiC68_Ue_R(P$H|55?RMK7-l5j#UaI-nef)%KS&P6m)uwcrzjme5o>hgs{& z8O?9RmEWRza0f&K_XXw{8GcI)I7AcDpWwfYvO|d)O+PcMta?(5`zI%I7(8umfBPf? zf3_a_z6kp+GmU&SRkm@fal!_C1)wwh1hBtK8#6I6jc$!YM*zOt!dLw%BwQs^K&5a{ zIPSJR{MKrP>HaX#VdR;Q3p)COW z#_6;pGqv2`Zs5Q}Ln_)ja_^z-9*$?PM5;|^9mgIU6+<8zRx(yWlxGQUYRnIeKl+4* z!H!h`i<8T`!AXm10gd*J>e(1&pyK<_d9-v*l%n1-o%}M>T7(7+7HphizAZ6qK@(;& zjQ}Ou!l8)HaL~B?op+E7$P`~E<3wTYd@fEeg`zuY(;K~ z!{#L@`JcY&$BJl2;Iq@-R)CtDJt`@IE9~lc#op#%s?|%<1`rGtNrxJ9qkAhi{#_G$ zV&I%STltx?r%hJk!0EJPvnm!;>4Jy1_U^?qRH?JSmvyeCFXOMhW|>0I-KH9V7+k;B zHbK5<24KJ48p_Tk#M{e`eJH=``wrmZRYM|fS~LN)-NW%L8mo;y=K#@{_10M7r>alS z)1PLWy-%9w2IxL1d=InA39g4Fpi%~UV+B_#MC6th=7LVD>m0h3cpO&_;m-2sg5Mx zvSFN@boP|K^4`Lr0`k2Z=zmoMr5*HNw6~`(9?^6wDjxUtSY|Yl_F&%lM*QNkM3DKOYPjMn03r+Qnhl@@;MYV0Rol5a?E`wh{8+Q^8N`cVj=NhI5ZcTQKPG z;k^&na$f*{*a^txTJpQ{@6s`!PD-x7<@1GquF-#&?B8dAfNI9Nv#CN%8teAoVTDn{ zQrsqEJmj&OxC6u186dg|`m3f5(!gxXhK?3mfa6~PD&6k{Jrn<0AoQPk{%6jD^4CH- zB?Rii{IhRAE>RnCW?(xlt*a8;A=`U5knNv2JKwy)F4=e^hnx%*UD;emSAI*m5v*_i z^UlBD^7^$h#@JJl35Zc!Xy4yiiK|HVC;2yo@u%L32qR>ip}L3lXH9jmUf$>-^<79M z4|-C%kK*asJzHS9$M<*gf8x#GpR@7X?1*#{H2&2~|IF7ZTriL_hrvBc;)gc@Ks%?z zQqOc8LD}D5Nuzy@$;^}mlO)3$sd@ecxG=0=y#2uP$$#|p@9zQ+hjQ0TBxo`fbMKEP zf00Bjk>s<)XAm|kT@<~%yr0yyX~21nMwW$xR)z0`S|OI}725taESvD(SN{9_CHMCV ziG|;X{9QwD9$%}4?on#ZQgHI71Y1=pZEV~tUBy#=Q6wg2Bkp%`~%ErZfs~& zST^PIVwxVW#pspU3dI695eAF^Btizf)1pOkjMP+T(h|-8%)P@BgzhFQtI#kO|&#Lv8r@ z_3J6u1LbA@F3bNI=Lh4B+Tmyq(>vJzP6psO>rb-pyl`YT6p~5)*_=zsar1hj%umpD zU$Z_rhWMIejXZ&0zngqZCN%Z0sQjyIfC5U=5ngXMC&qaL!ykPI;z?k!$_q*;*|1T2 z-sB>f&HT^ULnwVqes}}WwnbEB#IC^l=sWHI_2mHF*R?5%mA^5A|7W9qgaVr^q_h&@ zLPkd1DvbOe^3BY=M5B@6^fpEev=$asF*mHf9a{N|o zuMF#&{~SvGyBCK~e=D|AOAOB6jrK;3V9ila$Qb_pn_15AQ?wb}e};d6vKs`FCqeYU znL@Z51#tX8XO<^=5LWf0amF7G?Yj6agT(y~>?=Lgad13f-to zax#;>0>P0K+JLZ2{?2;_vsUefdd)Nzf)ag0?f$gMfF~?wuB?tQCz6n?bmD0Ur7IKcL-po=DrQjDg^>V@LZdd z*4;+Afd9u3TIjZ!q}y#}ak8MlLzpn2hL{oe+YMr~0svo8c)|aO=Ic?E8+{^NK7a-2 zT)?$nY@Es0((7*7bC>NfsPey;qxF7~qZ z4e4ddCs|cXYp$A07g5{ptPBt$V&cuiHD#gYUCdPv_*CyZ=fB_o?}IbbZ&C14m(%+z z3ZJh%C`WZ|>?OF~c}7w2+5C#} zdZze}T1;ub^=!YEMLJFN{Dqb8udg9}Z`cQ*7l*h2u`C{$={kAYx&T)(_h1MfrPQ!i z(F>q$`qq50Rdmr@fa+~u_yLo}`8$b$><$U8$9eZJ7PyP_Yg0CbxtOZ026OV1$$CGc zCjIoYL^uG&wLhDfEHlbAYW5s1`M}F8B-HIF9Njf|?xIUb-x~Mjiie?4=>uAm@9wRD zTF!p9+1E<{mnAuW@Ov2+w+(8r{%V{UO5?=xd{kK~Q0Kk{UVSx1uj{Zc%pd=jZxoJkmKrNE?Fe)>X29m%c z|20oZy*rLhvwbnMiqm2Q(s$&}$&pZXWV*>Jza&nC@&vKJ#b(WAZw_|12^n}>MX}td zS!uuJiVUC$No^ZbbZl$mf^fU!;p zd99n=03O7Tc*3p}S*HD7DI{1gxEPm=lzI*tB3K?v07%XPig~17f@|@{e#_`PGc$9J zI1qB)B9$|II>4pzaE)W6&U!dbzs8#Gn=3I{Q_AAf*%mUbTeVX^EVFPxpKG)1CYG*KI+ZvU(~l-UmbhqNXjI#({x>B-BQbnK}n~%eLOG zUjWnZNY~wO&umImfrTnLTAsPYmQ4P66%b1HKRnlKE+W8l`5KX*%B@=y|8WSfz3u|8 zYrm*=yB2~9ttaL0Dxn4X6M3J_XKOZl8tFH=W0&gJ_BieV-H?WP2St?;ZLE6IZSRgp zRk1xs>CrJHB~37no6xk1+?g>kFjila8di}&f+4-Xjy7%FSAT#|%XSBQ9OL1}U>DwIz33ldftb4-%m-X%YwZ)I%A`l@*b+)T$p-{Oz-OUBI zre{B<)^2h{;639^x9NTOIkD>Syw@VfO*djj{q?ajAjB+I0b1?QtJG-KKM*tiv@Xz* zP7~>yiBDAlU#L&$6lI6P61aIDK74PyKib>E>|^{%rNMba%rJCAxf`&a5+8x<(lv$7 z8)eZnsSx@hJ1k%k`HUdpLI3rcud`9-;np%-$|Bw&-9J|3#=mzn7eK?_$XG}nBXp|a zt$?Vv#5`#!BZ@7vX`4{9ix7kH*@d=#>3vaeLQ5+v5qmd(e^IfkEBs29$HvRsyB^jr8(YK&McqQMdLq zp=uTuMK`h8&Cizr)<^&G6&xlpoGlZw3ZpKaeUWQG0W{yT0s>@~$C2RkChpkT^W)L^ zLZi!5eA_cD$){^$e1n{>vXlUX+uZd`~ztR>}@!@C=NA zh3Mg&Wh~HW#IZt1cuDmosstfP%u17Gi&+x*mMLxH-PvRI`gLbPP4St0Z4tvpwaPt5 za?OtmLTS`idO8YC^Oi|ojJ=D_?ENG`U^Sfhv6l=s)?tpP)a{qi*PwLdX;JWU)T(0y zaV%NF{}dtWA6S=JaV21EeL&xa=Rr8mLas30drN&i&#q>_&vM3V>+#il{|}D$Z25YE z37G!+GStHlVvI5IVu4cJOAPNPfa?7|RDZEUot!5%r=F2oUSACk(iJ@>Y?Bpmk>dgW z3LgvTWi)CD@GtEPDx5fJu6&Oww43aN2&(O5tt|;Mm3-J;Xf?3^`8;$0nd?jQOC{<`pKRLY_MMU733>zb?2!cl_pScx95us3(? z0*#RL+XI4!Si~Y8O_>jTj@72u6WFwefYuw&c6FEld31}20!Z{p+S(1YVm}Syl2^$h z1LS7w9QYsyitmzq)sNQuEvF9GdTl;=>vc`=$m+_K8@IlVq!97EvpduHW^Np5_|u`D zkKFuBku^Z$k&V%9GG@?0N4`5Z&oF&Y!i52e`_b}Vvq-3~sA;&8s%pO10;qQ#{w2N( z^8V{?@7;*IN51yLo`K)5UTvnd_$1J7jVckl4#1hB9@r2nb?ByBd$3Qxf3CrwX8<7z z@HWBtKeWAdRF_*5HVg<-f;6IZgOo@&N_TfF-Q5i;ARy98NlSN^2%>a@q?B|w65sv- za*oe)&inlFz3*Bs7y47U@4aWw%$~WfYlL6kR_H&ra5EN^**233gmOFVMq-|hk~TK| zMkuLIE-DnWlO^aZET>MAQ|5RY6DNo{k|mg6f{fby_Y7U22^r$jtkrQ3VA8WmZ{k8Y zBrXt{s}ytvVKW|2UuV(H1_lLR-vF~~QieIkrrbGm@jvl}-^glesvrfR&1MY>W&H}Fxt5NiUiHHr1eQ0U!n%h=-ttN{kXpV< zA7@r*l`Pf3P(S)3sdl|xpws428vy3T0zM!Tc3OIo$>Ojy+rT{%G;ooMy}U^Etg91o zm>>W-{}2Wv?Q}2|UEyWep#qrfV^{$O7mby1nP_L0Ha}4gdwl#*HH@^teS220ByMkS zx8F`jK;ThuSiuwFKu2}H3ad#8BH4S4JwxGzlwMC0tooV*quy+#-63Q@e};sN9K8sn z)l*H`^T}vG&4Q_JCbM8dFX($GJ@tS&##Ay^qW zJ)S9g(A-I+$<6E9{1_+Fo$YSgyXNK;u2BsGxjxdJw}F1cZPRUx{ja-XW}n#W&tmJF zM#VZnUq>=^lIrUo?>a&%~&*VmZY%dZlH38=U+jLWj0H-b`%X2%X&V&>__yib_1 z?@~Xh6p2o;qhJkrLnm`;rv1(_(&pygcvVgK0S9U=wd{Gw?$9zy=r;}u9yEU5-ev33 zkCei}B#|1NK;=vi6a(S263s>=E-v}O%YXm`bG~ql+Att{pI?-)qn=cxpiY&8#ghr52eQ`9vmE8e}m_*rN#?9VK9(`5+`)K*mh3jg!%3+j=laM zn8QM%{gbPv&@tihv94=5JF8_*^|ImiOu9HG&8nXfc0L&3v$v94DF3lPV?KWrV?K;v zT)OfM@QTu3Az`=FStOQyRV{fg{%J<>xW3)*i{*GlUqJYmZ+p+$q*Is;n@v8Q9vr|8atnI})5 zQZq2Z}6C$x_F=``VP zO_ig|uVPX6QnG`2&C9JLCcn&OyC*ZRd$1!4kBV6CE9_na)WYVb?4#{adTQ;OIAJh| z7(=C#yBi7%!W?db353g0;&NN^X*a8q1s4v6%L~VJpZ~O4 zmBq%80MYTCHB9G48ji>*?^+Wf(YI8+LY^iB)lUG!X zk?GLdrAe6*6&~+C!T|-0|1^O} zhD3DgF+T-@Bx?)|xBI%qR2>EH=&^qL*RLt^WG}x<{#0@iM8K>zc=p94MzY3nfK7f~ z`QUglIqM~nSBnnI_RlrYjFQ?01DHP~@#=m+YTgOox79}AR4vq@&&xDX@y?seMV5RF z*g-g8>|z&}gwC$WW|Qx&c~`Gh!%_iQKLHZ--d`|E=p@4h>RAnFmcQhS4O#<`#kwd+ zYoGBr=rL-49n{g%^GK-B(IPu`U65cS;H;V^*P&BrNv0K6&FC$%5$6&|c%ay$p@B!6 z&OjYC4z3&e*GBpI(4o>e8x%2^zqMiVVOWJ%e%+latd{{*mA8v)FtOS*TwDq0IPYQ? zrOtaAIK}CM>EPgRN)aAn*(2!(F@zw>+IWouP zld6Qrtk|;*=Sl1PD;>=lOtp6i$#?5_4>WORAM2u1zDpV9)W`j9fwFb9{ftwgirFiQ z>5(P^nft+7M4E*YNmoJov0BaZpty_fGO^F8eSOcq1U1q~{6r)A!j9&7@nZOJc=%2= zn)6}qfjt?EcuAteb@nS1^2;7@5-cO=^&p=&gJEjZ#2W? zEecHKC;qJ3a)MLC;SzTQzLjqf$A}d{r-+D@R4-6xc^ID0X6G4FTeL|Vy)re!q zy5sTdZN^jT8VQsgTn1rA-3Fmw&el{oG&yO{KlUq?ix80LVNnLQd>Y1v)Q1FH{WA<1 zQJ)>Ax;t5*9~bOqkU)woR=>@Qf3IF&soadU#%23$(b9yZSGdgyc)7l3+BIME?2URd zDJ0L!Q!H|Mi~|CHE^tI%kQ#iK`}t=6}nYky6(Y(Cq3D2qR!l_#U%GnEiT)$t$T9`>da>yvw?}4*7ed!vPq}(XWPH-yB2s=rCn6h z;fPk4k0gpa z0%BvbV=j}e-AKDqof^97BioDR4$h5r-2kanF-;r-`{x3`t?ar`!mRyd+TBAmH7U+;5U!DQ#P=mFV6^ML} zD@wCncB^wh|MvqJEr&qzi52wMDLi++QDu^^k5}S8sOUkA?bTOEVX+u>Z{{sELJYzL z^TA&OnMm2p>00MPEQXQ=Vm?}xJTWrS23d4;bb|pt&2;xzrwIq-*jTr3Pe7gBL8$2g zZpxF6sElmdA&OSd+6r;sRL=f>5`85G(zm1KrCbbv7vn3~y0GwV{+R>ULO?L{JQe7M zRbGPAtv6?k!E|cRy`Z9g4W+7TUdhJOlK!Z&=id|@K)ttpmHy(C>?ba!lx>B~rK_5g z@=^^5D&Aim7`HZO$az`MuJnqjR$`?4S=;MO?#-I_V1Ag`wA9JF)YM!t=jMu*aEZ9M zXvYY*!xhshd{?hSUVqb+Ii5w?j6JWU6p;eDU{1$VLT5U2A zIO!gq-UvmaX;y3&678}bGDyXs-G)V+nH3Js(ePI*a#2RlN{%$kB)6h@8gOHvq?L zIZ~EC7RN~4$7TBLP_f!>A+Tvn+3hGobcumPMyt%^Ls5Wg1OS!N(J>U@;@~#26qbB5 zNUcQ1Tvw+nGsz1@R&5LC4hYi9_w|1v2kN2EQTQ*`6lVjYHk#Whh#EtVw?Tsau&2wr zYV0B-U}#qVv#5faS~guwas&v23Pwhm%WQzJ`vI&+yE#zK33JFi&wRf$-|{{%h>E$O zH^&nXReVFHS_)pVkVDEJay9z7$z5#gMr zET8pk7S>+j%nCHYBaC7ajUgWjMb<0FjW%9D0kQWrziQEN+`#g*$86hD@Ag6+9yuRv z>60j|8A^P9pRqaVVC!;v^yp+Zgwb@oB0tl`oeJbEWd1h1n7wl_She~L3PMLnSn!&> z<$N3r6@r*}9&0wFiIUvri7m4=&p)E&sFa4?;r5zG%g9Koc*Q;o2ezs3dYit3q#1YF z=~4I(f9=Nit|77d!of%JTAv&F?W%0zJ>*`DpUk{2>aD{!-tnf<;)Dm37NF5>bY#;7 zQ|1~EX4m1Q7Jg#>8dGGmHX5E@UJJLos0c3m63$&`Ck?`uf#y11u5*CqiDA%MqLi=U z_zsMe?Mgn3blrY|OIgF^H9;X|F;I~x{^|%wQ7dkz5C;c^V$U7lK3nvccK~zTLcA1l z3-&HR3A4AfhmR@*0C)t_rY;U!iIlx`wB+qIj8_Xc(q8s7qfwq8HX!6++!v#XS6vEq zrLxm|6>=vb;{cm}3>H4Wdf*yoxr))QJCh4j_Z-M*0V^{7LfbAiLcrDz6 z`>(R8e}Cp93&AZVTcwA7`D8#!M>%#62Vut%W|&mSYSTZFD5lG4{^xgXtvcm64x=@- z9M#Gshw@Gply%4?#1H+=Zk^TkrhA|$uSxz33>9q6bmzqT5;KH~&mr*Za1&Prqp}yE z-01srkP$Gk5k1^6p?Mhu0$&75BERgkU94zau8HP&L`?i8gJ4tVAC)Z@Yc{qNsZm-hMU?W;mIU973x)`}UJ zfANsCYZAA(9-!LmlV}oa)gH*Yi(9_n2HGTX#Yzg`1{s2mgy!N%N32~XJld2NSd~n6h0j5`L~lrCOtdfNa6&4IC~L!-W^ELI{}k)`O{EtVr}2WR&1=0;nT47xJ51fM1mY@exV2AlX8_*naUPU4Lt9 ztE6);Nc+nX7DEOHl{CP_Tj|6T{tyn}aBY47hr478oulSsGlZX8ZN}%e1eK92S)PKY z!{A4&Qb79I$qKu4~OwqUB z6a{c7s0o$v0o1+e5keQn1jxipPOBabi%X3pa!tyH^PFVYo$rS8FO6GM#n0~8%}Skn zo!wTLbaOP^R=hamKUs*4#;H_jevF#HbF6tXcgTvf&Dd~+QEu{G;ngb!xo>Yj?LpE{ z=g3C%)C#DRwOz&_Z5DeD%|g##`Rvs6^j)Nl5rIJ)_xLw3DDAR%&K#W0MjGmcFHWQ0 z2q5EjS0X%aw8^+2@+f-Dd-R4aOQ+=dqpo<~jye-pKD{4$BzF1qJwRxX)A#XyEZp=d zI^YBdSM9G1MaJ-toE|*L*Q%c22@>tmHOH2r&w=f5-_wnf67A9M+V|?pg_TcMSum{m zoqVx|yZTv$K3$q}BVk@z-8Wtuxuu?IvR!aHbSVY#F6UOLt9Wxs>H@yRLL&p6IjXwH z69g>!)l<1M1<)H%IUj6PT*fWkk!G)PZ7%pk1?p9x3aIn~pU>l!$Q>f1#5*JZVL5OR z{Nt*vc9oC(52wFA(~AU_^ZoVSOw(xGz3%|L$l{L!BE#pz&`e(+R%m-$13_>-K%JtM z0>e?oK{a1^x&3>DyKrl~cI(0Fh^n@RhtuX%;>t*PT6^?E$<^SW5kRjH%`Xr=lNbS0 zn%ZVo7}D}<#XQqm*MH++xGo2_{H} zoz`jBCu_ssz75MYIR@ZWzLW9xl@y5|Qs*l98!3xP-hw!`3+>7pjaKvoe0Fic*z_V` zBxVN4Jlm^EjTKFgikvgBA3O4&*Ik^$f8722F3_qW>9H{zz540nbFnKnI}$PUYimYrAm%c{0kH!eLLPHPtNxzhu)$Z11y`5ckNYA`1u;3>$iVumQ;1j z>g1|kNW8z8BF_ukOpA+Ct5HR89C{F&K+Ue7`got+S~BZb0Mik=^u5lR)4GGzUrwkG zvwylyxK4qAqctpdB85xL7x?cQ_Gdi2c*ithJF9>?lMM2CGksyx=WSx(y0lnYsGSvH zxm>0_LB-JJ@y;i=iueMb5 zXXE;wWhcqmm(~`w5pBME8S|4~JWV7t`{~QDK~PFHWqoCjg3r-A|MpIEOP#F{ttUF9 z-!3O-3v`nSi>rEvBN9F1Q8%WgRZB`Og*%EQ13=|limi9fA(JN)n^^uaiNBwWa}*KT>&0jt$SfZP7LstuSW?=n{5 zm`j&?;UlP&B}3ra&5$_F?k@OrvJ(tLLadNyWvJ4>$|&bhYa2 z5?|193VvI(3_;=^M#;322L7A)ApE;#|56qK-T~&TIOAl`qz#ivjm&Qx$%3B08ic>2 z{4;iHmfUv2)X5e$Fk-#NRR4LBRkD?7^iC`Ihr zbtam<7FI!)=XI_u-siFv!IAo>XZv!C-3kf!aB!^b%yXFObSqvPbq{vV<}&Td8t*!< zjRtMhty&?Wpgam{E;5veNrv~3@uK&je4In85&2_ zYN9Hl;bg~tmzEE{S@%>s-)0v6SUV~omLDHbJLC{k*r2KQ#WI_oRAFj+Q+ zr-ofZK+SME#rti^(y!3PC5sqK`PBC5Oc6vg-C8VVMC25M<|nCK7>bMoegw;VBYl#z zUpE%FX2@u0xir390F2aLBhB=3 zLZG8;Hb}J&w<(i}h25i-vKX%*s6VTy_)u-oiga@H%yJj#GYhLRfqQqAgJx`06!|1e zR#p}W634wy@AmCBcgn;Ls1cP zRCKhkXgJ{q`^D~s)$@%U{@OShNy#*zDe-glyx~oi!y6*uC|Z&4%@PLv$GHysZs!`x zoypW(N|Pwo;1z@&#U zj`}?j0^k0Y8oY<324VY?asYSE)aNY9u92w;;|5xObn0)tj`We>Zr|>Q)Bm*C!+()d zYEbG3T18QDan!CQRYijSw|7p#F)wrZX0ZICNUPee<$WaRaAnN4hIAZN+b{MzPfN4y ze^!*`m6qk%4yconk;xp&_09mm9fhuUtin?+W>cwf*tk|k--COv={1I9b%PxamR zg5vt9MS1UgRO`Y<_F^YzZC#gb3bXGe8FXxn3@wwM-cj(sv8`7nWxeDpG_j}1s~a2~ z6Wb-R0S;NU8(sEkoJkq9&w-zSKH48>FANnG9@{eO=_D{+TnsdCF1awrID&$LgFs#p zw6((g{QV6ZfSw()vm=?bVL)JDpM4K672InuvnkVtPhZt;H6XCHhyPb6sg|} z`Nos3_mxc1g|nkDb0DQO1;f>8zwX7yy2WG6!NNK~fbm>Q0Z+1FU`_8kTq0SKXZk+V z3#K$76a{XvPkBgAF#^bFDD!(VTr~=A=iiLcVvQ zME=NRd~@gX?oa7w6CoVI_*PZj9xT-T zWI-N!MTZ%pu>d2^srdQ%4OU++FE6uoKt$T2X)r12zmQW<1i4%G=u`Bmd_lsdmDAFy z>wF*YDp(UdRcc(BpU&C5qfm$+j|K$;Ck0*-?v55!r9Xh{B3z;WcQ{h-6aPSmSs$Mk z@3N|wjyYQ-Y8-gS+UPpZmqa@_zPd@nFr{GC^{zZ%;f(mW@_X?!(fW+B>^}>7ph<8E z90#PY(3?)E4Wx6x88MVw8b?Pdp+74Cu8=kC@~&uGq%dHneOmWjUMcy$KEjXt#c86; zS+0m>wsX3KG(>?Q+vA`FFzhxD4^|xD_KYvl7KcNN57uG+s7l>9ZTBmJ#X9)(cnZOJX9>HSe`{=Rflb}|MIzPtfGz#zA#MI|ksyu$sE>~FMa4@n z%l#JA`fn#93$VjcRM{(yQXui*V}?{jbT4FS%@F=Ph`*nAg8~G+Vum%H0&0|-+PX6Y zy0uwGZA~9^&9wM#ulMMY_1C}f^2F=_O5Ps&#`?=suvWR3Yt?Y(RN zLX&%#%>w>5IY{0up;E4yDa1bz!Oz%%RX&SF1h8GvOW5w}g}5-vzhKGhuXcR013Tj; z?i`^)+MS6w3;7h3s@y2o`f{;Y7-t-8!%|mxGg>=tc8e`m=zgPy$#Ai!bkOTt^`xU|7rsg_weGvi7+-?%AKF z4c+|LKfVC^s+ar(5dvrv_TPIZUIsiJ#r;Cw z{$Ccy_w<^-$j?20vt&%SA@Nqk{KC@kii$!kMW=nDOUrS^Jp%vECI~n}t>(q@c#^LJ zHK_P?P6%nU|MnU(SFy|qhOp$urvGXXgVtP?9oqv`j^F<25VAz>9B!I4X!EALw^66q z?BsR-<|pT!mc}lNyCmm zew07G2X2G^{LMimx(rX4TW{cg+i?>bgpz<3%4$vy!A878fls)uGWfVd7*o9X_4!x` zJ7t8o;K#`h_t~dXSB7#10`sIKB)LT&u;pd3Hs)6(-uoNn?r+--)=%dtsEj?+9yPDI zgZ+Cw(5UqwNncYX{oZ&n)79y&$qTtW9)UW!FnK=jh#xpYVG)~6T%BeJ1#wgL7Au}K zHZ1Yiffvvmqh9#nHuVHFBuZXQlo%p=?re+V=vUor_tm}PRnzo+F8h0c|F*fpK8W*s!Bc*KNTcv+Ql7}!?~+6RT4?YJLEMyuaL)j` zy(fI>#fLl6i(DeW648907Ca5CarBM>JcEar=f`bCd+U{vc0B=D|7M&ube-DaonF%zw+&u1CjzEKb zE!3omlX4m`^jX7k75Rg{ZH*np`-Al{5rA#(=~GT9(8#aB!q=h|#fR5w^a=&IXi@bi z=_d2Hz!M*WC(cT-nsgg1ynu?g0T-`5fYtk-OI~lNtrm+WPjhqjk|}{h=9?6I5b6)< z8(7{!hV}J%gjn}$LoP?VmVsWoCIDbP3~`^-yX`N<8z)hCdwc7%Zi}8QXTjE*PNMe} zXmcZBq<$V31w z`@j=DVh}^K{GM+3*8+b0;9N$mVe>UG+x~x9+yCL!LqdZhK9m|u#{!Woi(43eV2fW1 z>h-5vXF%C({SbVj7qwp0x4pd$X_-YP>!QDV^z1&p&S~lAy#gVbWIlh1SO)1@rwy#( zjFW1GsJ30y`z&z~`p%~PmLBQ;@<1CH#)Psb4#6_Rz`%TTl1lIh`|i0L;s0yB`E`&r zdCOPfjQ7T?4iM$6q5I{AI$`$nNMjo)9^???Bm-LwJ^5j-elSB)HJ*t?pMhSZiuh1U z>`!93GO6PCvG+vk@tv7g17Y7%6ey_59wlcPFOJcTDn%G3UH&M+pR`1T< zmB5*(ps1K{u&(PC$+Z35I5|y}$Ww{Us3V4+<@r~=Unoys%VKW5fXmKdU6K3PPtxB! z0}8WC!32VKeFm-BI%k^Cy$QIAUNS%KURZ-P$1}Nxo^h+}rQ8ID3+wDxD)DVCEnFz9yJ?V1&#blhbp@0ULG(7O*&97J9dwmQJ)?mobjNkFD=~P|7 z#AA~G=nVf(;Cy@-AcXAtLgZBpLfRXwp&kO*?&q(*ykqTu{sc?+^x^3ncyR;<1c>$NOxEn1OxBd|wc;i((A2UcV(tzSlQY9Y^D+tm z8mFwI!E6vci4K^Mez5snklkvcXq@q9a|pZ>mi zNgRjy3kxnS&IgvT;8K!81`|jxvscCxA^$SqMgN;mPpQ|nX!l+7os*U{kukvlA3_86 z{+XE>hqEzO34rPXfRYR{QG88P^Qk&cP!oOI9)ptQ<0Am+GY@3R4lp+6rPjM2a^(Rf z5vSCX{bwJg;%#WbIQnAE6`&y2KikT$IiIUt%jURoT69OV(Tn%Gc#V#OBa%N}_5oxc ziqD^?7rk-y4I|=bXg__)W;vGrc4i<1amf`r$6&z(iBVOsUwWeQJs?AV-EB&l#Ueik zk~oRX-N}#pDk-Gs2rxuiVPKZDR@7-Sb5t;!g>K&#Ok%TW`m}e%!Q)!4Y7GiU#i#Xe zZTX&_Th+NKV^U>iX7=MIFG@FUZc)Cvx!B+281Cu=bHB9!uKse11Jbowbkq-j+Jy2~ zcx!?NX{gsoqo#17vqq$aiZ4LwZ6l>lf5QsD$JMQ}gwj4LkDt#Nc`mOXpM zASER&nFe%p-XZjjlgMH@7Nz4=O{JWj zg7{g9!yB+SgkKTF_KxVvvfTYrjf(+k2yJ70QYw|nBY)>~z(T<9_Em_Tv;-r%P)?i& z^Lv?b8;)WX7+zq~mzv3}(36y!p7s*4SqKFe*7b*;o6U|*v%#TGy?e;?qapirK1bTX z+k2a_Wcbj3In_Ti#*<4EtpOMtgTG;H`XDCSH-@6xz1Y*i#}0H4#(YHG>-`1vgE03Q zq@L&cefspN1oOKAiDo3yT}H_@(sy^Agt@)Xc}{-5x1KLQdE|8}+7ff;SWnW%A|8|v zC9wzy=<`0q#WzoTdy}8-kLd1boE@zV^klC{%abDCixir=MpV+Om!wOv0Yqh{`%g+K z3ouTi{`}-Y<}ah55`ZyR)*5OI51&Dy@|h)eQ5Z41W_VA}q9FOW(87Bp(Lx9RaO+zfOw z5ruTLp50F>9s~UfflO+padDIZN4lQJt{ZUw>a7GmK%{1Bv~U?5xUz427!(59N3e8i zP0^1bwVz#+!dNuwJGQA)fk6|FYqQKC=t;*jw+=>5);MN~61oPA29JZ`m&>8-Qz_}` zbIc7uz-zGH-PtuMK3<&2o5y!JUz4ivd*aS+Pon^+I!A+%nB^U8596u+3G zX*82yU~Vnv6|H>1!O?#tPlhN+$Pve{7}h;rW=ZA6&r24$Hdg+g4+yhAp50m_A#PWc#+;V>g&Y+%4}dwgH|75M`4kx9(ub?-Ar2^j z(IW?592k_S_n72@@ql{oEA-FcpGmWY$XjJ8Dk!9z%f1gn%XWux)AC`)rR0M7ii38z zHfkWDQ0Ib}qh8riH&tt&TZDn6pNbeZgcuNXAI+xd{yjDZB1{}lZl}S3AVsgEB$dMR zArV^Gn<~!Db?)j5ms=3m-sY%p{o^IqO+)^O4^rwmi_xe6d{2Py5rr)f5TJrZ(un%n zHC)@;lAccPc5K)+o04yJqNK)`M>#>RiF`+S3hlf)EX|7DEdmvL#0FcORfJ0{f z29&Or*u8ixnB^?w=?!W#)k_GX2@n;<;?A$r=TVqd`U4cRN2?*bxD; zs9jy(px8$s=fSvulhSO%WRxQbnP?Uuu>g)Bu>_}W0`UC>$adgr{{b46lQ04wnt;n8 zok5!@b_NmA9>Un=?4QT6>7Wm#26~#59i5%z6<Hf{IEoF-3cgUcp8KUW%T%+~&~@K7neXv>aMi_`wa=xu4pjn&~` zPh5h}YcTaSvA%rquyjZ;{Nd&YI4A9Lc-#qY=G{d9Vj;)h;cjIuq>f&_05t=e0!m&*dr047lK3o5dgoROU7ke4Fg9G z=^Ozy5V}c;T$}R=0KE^z=X`RT6NA$0Y@ggT{}E{6)NeH-{}lc)0r-N`g;RrNuf9qs zH9Vns-`vu!oTI1~UsA$J^){>@3_V$TQADbdDkKij!HF;dKh`jL z=)p)JaxnVFt=|<~Jqt)G&VocIHUA7K%Ji{0TpGiG|MQ$W~uiuTfNi>Uz+Yz4csR!zn2K>JP_cS`&>=Y%f1wszs&9p#IQ^_ zezfBiB!sg4?9)laptg`Feb!gY6tT)-HNkNL@|~l>S(EQ26etjHnqFZ!F5-V1C2CtD z&jk=J+z!4Q)9qx30QagWCiY5N-#|$zs_bo*)g)K+#NIKO?`YB7xpTTu0=Z5 zbhA63)1;K+QHcUpAW}z=#2XiFHR;ZpH-cF*lmIh`$GLNl9tzyl+rUjd;-a&(C*F(7 z;{2EO$y%wbUC;9vgQKkopqoPf6d14S$#m3amx1ly>id7hGdZvem^*-Przs&O_GYpDzJZ3ueaF>MLp&QZ~{x?mBch^Ao9Uzz!c3=O`;^tnt9rBI>=KBpakceyDi?S_x&tUf)Qun(`B zsrUWp48Dp+7zB~Z-|gzgeJ zmz{$dH_$}FeS9{jzEFs;Bp(8M&3yuTKjG?NM;xAo)Ymx)!ogw}BWJT<=V4*LA*B^g z$Mnng@k>?6CngY#pzI33ff4t)=x*WNXx6q9FIbyAi|KhkKAsq#c-;NuAki}+0=~v+ zKsbBalI%sJDNY*|3<9wa)Stik5W#lhuD?e91)VHOdi9}z076`kB(%KxU6r?ZnDLML z{3|hqNzg`NFsZzV(M3|UFU}e7m8KZFWIUpfh(cqNxqad;=&l?uFtntHK8;JOFUtH{u8TqNh>8guIOqI&#T5#CQkSeRS8-L*O3 zFx_k@=RlodOjYo0ny4}3r}**LLA1{Tk+7d{rF>EtM|kZ}{t@p!mDD{(5RdGl1LmNK zo1m1S9NyyQhzaPh(V})+7wCi^#JKIx?rjoayEHg;nW zsma%$oS^_r&ZrXu7wn(WMviNv@?4HJUl5ol%;?NdOEgE~*w&u~1qb&_(s&%NWA_- zK$Rt3v$Ei)>6tnp=sm0c$(?RF?u3Ddw`{YqHS@W|VOaspM>egP1GM*Q)Bq*;!TyAS zOl=Nh${eMSZzo0;_@2FJiFvylTlfyeZmQ082RQHeZ^w7!pl_$Zl+7WjTf*#=K-*H! zhenAWkbGII1u&;b0GRo@+q2(6#+rpL00j+;_UCVP^m<|Yj~Ui1P1{AUKJ^vAW=f8Q zDL;qHXZH<)rNr5rA|Zkiq$Z#X!$S}=>r{xy`3(zFCU4#js%t7 z=kLa-Rf42@#Y)=)y51>BCpSgG!Z$y~bCc81TsFHtHKfbm&W((nQxQEg4kV;IPG zE3+I|>ACF+Ziv7sgy>|B8QzwGje@!*2R)=sm`exk`aO!nWi7@|Lk`r(L-E4M_BI=M z-JQ6lKMVfn%Rt_38ZnM>3=j7pkyG`_^$Rs&Kwc<_&js z`YMU4xUN4}Q*H9lDX~JSSA2{emtDbGYP8ftiWt<@y;_fUtj|aMas>sAbW-Z^<&JpJ z>79G+ZyQ!8B*P(m?bv|AKlLE9bN#26OGb*@R0l6d!;Sm&`sJW5UoN|y@T1uikGcf* zbF?_M%-5m>TO;&8+z0q$K#tFGYNG9oT>UK*_Um_; zr_keLT!>~E?SA}>RFV^ZoLAcY(s<~=fsKOW`gB*Bn3(Ya0X+YNhZe?v85WvAlQqoG z5T`GJXTxw>_pU#uV*uY&z3v@hAt7Wd+)gu71+HEc@|5oXf1VOEPE60BXmX$o9`duA zU|{YDsHb3_%E5s{(Pz8$xvP!hpANt&rCx)HvDT=yc2nT>=S{OPKX>1@<}Poqd~9kV z{gV8>G;_5igq)m>dviNitx8}Qnp4Rd3fUP&`EnOPe{}cI9E#mH2Uh^RfdvablFjZL zxPMp@Vm-Ld!@SqX@D{iVw$~fHRpN78H^0!KR^S2y@zi$g6xf%Ri{Jq{*NtGnC=ARF zQmP2yKUoAUjAoNZUw4&_-XU4}^$CXFggCmXT0d4vN~VY=A@iyDK_tl25U0R_WnS8N zXtMy^9}@xIKP?Cvf*SO$F!x+D^mw2W{`E`L(Sdz)J!X!1r~^ltW7(aDM;g6>9%EOb zg)2{T^;|HrKG4}stB+*|%R4IY;R?xPlKCn;a8x*sIL+g8aumtpwnV_&o&s2NIFyqwZICrkY z&!49bt?KG<+^W3$k@I?`Tp(U!XG1wpwdS)zx5z$%RGAKuJlXZ~%7EqdS!E7a0?QlD zr0`Ec4+;kQdU;c7Lfd~Y?_D^syhJ+v7_kO4i*s#`q5&%?dO@{sBrX#P*hJuJ1xGTh zSYI^>RmO=0{P~>Mp;Hd=(($0?SYE}Mk|mT(hsFr;$jv~Qb?*^_Mz^yVPzB?{+wayyZPW6U_YIQeJ$t>rml^tCVQzU~zDd{ndswmmKkcPY z;dQ*yNLu}!8Kpq7MPCJ7*`dgc1h8p?^+KFi+dK;PvP3>$5Y;!R+SxfvW<;z@qdXl* zh5`}LXOcW;bK!=|{frjV+UrVTq0xlAZW5NyhK23N0c*VOU`0+`R+jzlcF;dQhwSxp zL?wp&eh#S13{A-}TxlP4ZNDgV%c~+ua=HgZU!P9|OJE02N-q$l92%!BLAJdfiQ;& zPSJtDecS_~TAEwGouUoIk=U_&7NwWMQFb#MNwKgQN!^J_${;`>eq-(1(vsOv^(F#cVz-RXGre<|~JR5Cxr0DjY0!_9B#mCp8_FVWQz!mD716VW5CkgGDN5D39JS zt(`OB!g5uFGtsMkMlIV5@*YXnkfeA0FrmB1sLRaNy4mIM@kL~b>3~uHui`ceIyx!l z?&n{de9sm@iR_r+<(>b&!TbmOa20O@~Lrx-uAv zLD9T_-1+*k!fCQ63?}0n^f;GKq=oh1TZo4z-CceT1PT-~Ws_r6ak3VHP#r_8u5BP6 zJ3oy$4ujSY76SO+ukd?QE*-#DjL&frtK65s`UQdN-^<|h5aLOPj`etx(1;ipL;3AN z7?dhHc(e}8k{ymx=2U?6wfX>Hya_Th+v&!XgMnfF)%M0T3hCLMaofcn=f}oYI)Trp z&`hS!C6))M+{Fhu?SFoaqKT}x#cS_;DL{Nj;3M(psw1JZLpA#8)5XokY76}*11bt- zCi0x#=XGn-zp~PkB_iEWFdW>#%NAX~tjvhkL+1(GESZ=n7Fj;+BXJ$|gd|nL?|1q8 zC6mW%9CPcAznIGm*rNUMlD}P@H6#_krLQ%rc{?iPw+oo31a592hVov|$0nijt|V4% z?~Kdj*i3~5Ej%M|gT4^_eUA9|HbjA~u z7M_ss-ZRMol9j?n-3bgdG&EKVBoXc~u#`26^BqdQOi;?XR=29trPS*kb`R(qC5#xL zzlFXpXX{Rm;J+CC5NpYxPW!e=h>9J{H%LZK3%_O(L89&pf{fC*5?P$v@lK(3dgqyq zgG1RJqV1S-ZHKKN(5~mzUe(4w=>E}}5JG|td~;RN%l9(2H#@5d$s{#{{Hf6;IZLDL z(I&fDDBi#kF7L+;=4fl85*|rXz9w3X{n2uIo04`Dw6MQ|b{p}`48`P6e%GCVM-S(A zVX129W1OGBVD7T*I3nfV6^IU{rD8Q38K8qdSdaPq5_MhzOEdok{zPLBf&owN0D9a~ zLP(R)B13oBl+!qY-MZt*vSKow8u7Pp;@xkn9W7eEI)l5rgiMlDWE)XO5^rDrYw~OV z_vbb?-GYSZ+;C*~l#f_f$qnS3iUH?BEB6zsyG5ZJmh$%2y5x|*I5Bfc8PDDp8HOU~ zu=S@PI7F#VS)wRKnmJ>lx zXeg^uv{WPjGPKt?HhvA~KaVq4r?m#GG)RQxvW`JNwL9w7S1);942Vz5sdcutwssx# zl`C_)9>qeSnne+-?NrTTHYf(E!?%T|Y=Ay$`|0uS0$}yvF0kL#a$k4sud?+6tTCNn z9C}(aP9UZ++_9MKZA4k@Ii_n5a5Fny>>ZYiorz#z&bJ{|=YHMB(;ehvAWpU4zz%~+ zP?y^xp`sFl&f+cr+9s0W?^vy;w9Yp#3WnF^GQWNMW@Jymr>wX7^e*pdk6k{z;m*7` z>f%uB>A|iroXeI^G<-_Vy;7o>LN)bDr^N$$JKFVtsk`CSH0WP0fGiyqRTxp1vOh34 z9ZVgZV%h=fwoC7ntrAxL*gNlSMch=O!C z(%oGOqO^2}bR(S$&Rhz<+xPQ2=f`*c?CTQP&wAD!GsYZq%&*vAC1yu2&yU_JOiW1l z)@L((QG<~Fg)eAFh13Yhf4_Z_t^9Y-ej*dm;l_#2YG-0!ocw|a6YL{}kM;wba3q$+ zFl%CP>slYm;U)16LD-`x&Du8$;`1F-1jU@`usj_1o}4)|J(QQn=*?FxxHjT|Z64h* zN>{ld1vqRn#=YjSvBm!UwN44%20$`?U}-!joMkm0c+`KPoTbO@h@?rm%Km+xcZ z35prXrplD2Y3u5K>+xPN`Wm&=7xGb8g$sPMVxBLjkjAq^h&zmV2g-|AO?9H)GZJuE zK8;@J-HxAV#lQ-k6??69ave_0GcxL}x(cRD*-E8P9z*3|?n0vFTnC4- z`I@8M5n|hTcQJdet)?z=gj_t*x7GtwI919|DpiV9xx9LRnbU5K(E}Y_fXwljAL9^S`N}Htfw}mcVrjv)f(=#7$3hn*y*n4?Mu}~$jGC4c zFQTH!XQ@zRS8k;(sX#4#N>U5A{hpScexcJwyG$6fVem*X=2gHRGv2M-5`70J=5dUC z6UFvyJHNVoOW6(-ruuZBAVIz>DQpVK@Pr7A5vFxn29#S!{a+}I`1|?Ap@MeLP)g^3 zdS{HA=Sl^W2-N)y(K4cfz=JoYNPe_LfIu^7s6y@Ga{lwmg7x=w7%ag_tYD-{>u2{h+q|m+h`gq(tm&;ZAe^5@WAP^k2(=E!AnSQnSC_2M* z!rEgs088(1`av89R*(-B1P3fVe8z z)zF(yS*e3A)0|d6N3O&`zgmxH>L1OW|MEMF(N4F*;m+=R6L*4o#unCL%K#o8(-E$) z`*Zx2F5nSFK(uM|(4N>f>&W%+#*{Ji8DAneh=*3bhLK7KFV|oXt6Td-oH#NmCHkjazoF)S~O&TvXyhCYai;tzCOIsx-m~^%NH3zJSZwUQL<(2 z`B_ES4|O+B)}a?4uWW==2Cfy4I;V$}Sf^C13ZBu~VhL8GdDdK2Y`t`g_`CUA@n`Bs z2jQuTB)m|%;%1uq^zxh$LRYOEx@FCKRc#isK`k})N&;Ie7wPg=et3UJNCeKg*hYCT zKgwJJ?!6loCdWJtHxhF4(irwf zjaP_A{bpzHY4v=WSnCS#nPO{_Ke7LRB|a5YNM}A?l4GMRK6hfhTpf^cmP6`G@}LW1 zGK0_(zoF;%s!o?(t#e`G!G7)Uto}J?@S8KQPq}&C1^m7OV-hlf$lS>p(KWaw97}^G zC2USAG=&+#sIn1Z+u()Q8mXY&I-GgWwv`a>OBo3n*?euK11}|n`;5V7tEBce=05sN zspR!FXQLQE@k++!iHL|lChq~?O0mhX(mBpFI?6t?#XhsOh3tjR(jn)*U+a(9<0dzt z&?`K!^dZ1(gvn-+a(3f&+oUWka>^7;h5fx?lqjpib);HYQdzpy)8(^!_UFGse`_Li z{MrZCL%XVo^AW;kklkj#Klsxl&gm6-Leo_1fb zPGbHqRzURPWuA{uCJ{{ym%Cl3B%t@lGuo<9U0QKbaEqvRvT5jwHX#_ z2&1I!?qo0t?{0|(-?&IM?H?;OMR`@V3aSa^*BbZH+&t~@!YI1@x47+f>F}#9=Rz2{ zzvgZ0mR0Z&F0T3_3&iC62l;JYE;saMf?ltm-1fiL)K&&y1CuXinm#OnpHD2d8_ESF zY|u=Q(~k~7B7=sh8YMv_%HahOnQ*yFVvZ}7o*+em!wvzi<;n=RdX&lZaJ5VI#$tc1 zjvBLad^oeDaR8aqJ!#&$FF>kRnP{^qL*jnS`-mdzil!v3*L2J3J~x9s3%IT zRFJZ2T1SD)HfETz0%hhK#8%^Sz8Y!| ztl8;6;`*YbXh<4qtZ3l9I0@dPgY`Vk+HCu3r~R#tWC``kYK;eZVv%eNdRIE2&qZsi zW>F_OSuBj&Kv%G^6#JU3q^3B=C8i2I+!4y1m8|k*OaITCcWmZ;Llj{KZ3TR0yt@~W z0gRhJuqlH?JgsKEmsEcumE6=UCDcCr0fY686Kq13@)~QDf{qvXkZfqQa-`P9H)NvX}bFI8L+qkeV}#%)-3E&Cdo;MJ=U zue+}CPNSLw&h^Qfzcac9=cmonc>nxo8qZ+FljZlQw9&8ij4@2QDz`1K-nc;yp14xv zF3_z4VSOL249-L`TD@y#a36{^p7wIU#l;o+K1#zOtod>gC}LT9!YWWj6%28l^ivaZ z%16C(gZ4mxOe{3EGsW8L_HOWqe7?tJe2&TZ3Vx4ELAosw3lk&gVvB>t*(zp&4yuPa znzfS=rorkm=d7T7+LNc#bls!>;zdJUwdY+alJ%E7t)}{Nwep^Qu_>y8!LKFM>W774 z&0BLOyn~E8&%YiZ=07&sO)?r#%!KwC`1_d&6&Wk7JkP!|1505xp0Xqf3_eRxdqYZUsAg{X*_#L(2Xv3Deo|m9UaZ9hPaX-K&jBM z=@Y6;!>iQ^FH#Epkn~MK{*0TUeF?(STBQ?r?CUFtAAOj`T{ov?Flr4=_JZl72F-b_ zq89x#+_pbs)mZExw%v=|ojBYl^aW?8>Y}RG9LQD^${=a{`h1?lRFFI=1A}DS&25mc zM?wcFP4`_=rlM9#h#goy15b4KXDw#4bUkB-@KpkWEWNk4xt{xiFm=E6GBT_@N9g$d z`t51&n!0JB?-O9p6Dqft29rbd8q~Xo9}YHqod+4LPpt1>InB?+U!`SD^)w5b z)6{3z}I#Ts0_!{M0_2bQ=BD2NxW{=I;*a}j^ zC367SDqW&oG+jX&WAu*S-u9F+YlxY+n9*HiC8#y~@bWOEW@3!)<&ZBJot*l=T<4DH zuhMZ&wY}@YNwKgSY3$Q`J3BX}A@Ydev`M<}5=ZOi8GSa13k?hXwwot5FTMLGkz1$j z>28Xa>e?ob1A*wfn`yE{vZxQi@Nk*X3D>7w96w|(KQGUV)bDFkyx{xW9VG$sg|cV* zQWN7_GIJhSW0O^oLs-ZB-eRv*yWuJ>_kh`42jJ_s@~>?LfQF5F;G;rG8l8ifqXYSv z2*6fWn+!jU*d$loz?mI)y>Mx9)WsFLAbSPhE!M(n`$K}#09`Mer)}oHpF}@(AN$t4@2GI*Xbe`U!eCxOr-koPY^=^o% zKg!!j!gs`nTN5q$=x$T6GX*3MIh;+j|1>y zGwHabKj2d%&^9jxloGVS|AT^523l803X%|v^h*nov);Z-sjyr{yN%04QWO|jozu0} zOquf&5F&G>$i_ja1#t6^lZL1~6a9#S=<<3aoh*VMpnK)zp(VNLgHD+&6~(TOkMrT=5=prE4od|zH=^Xj3`#*A#;{S{1wm?H z{rSM?Xxl};X~Jg)zgaIhH8}5Z^vHy{n!{1ePUoDe3$w)!73e#VpIp3Z>c&>Il-~YzMUQhXKJni~1a_UB4=2CZz6c?1+%#lb*%4ee(F|JS z>&>Az4G!(9^N)XbNAc$P1IK^bEra zO8Z-bCKgK9&s`(~8s4WN6z&^to^B&Ay9ocX;>RT&FwVc&Rjt+d?8h5JbRXCoiQk_u zy_O3XWp4}P*J`_GDic>ngy2i^huIH%W#_w0nMyEeDg(KH= zLqsEfs{HMRe`jE3zgLnVIq{fygoS<;>5d+UPgpZG<6`T<^knat6bfW07G=X}gGF+m z(3gMnEV?^w!uek>a{U^;OSMvtflR}DC^y+(35ow_sV^r5N_|0Qn(wW#x=+e0)yO?_ z&VK7drO_J72BWM!GvwWC1PJ#n*nj&*cPU_b#4h%5;R$Lyixwa`DW&}dg%HjD<~E*F z?d>2s{>@KcB-bpz47BR&T<16_f7>8eDmnT*=z>%v=0hvfbH zt&@JcYr`$f!jrc?LcaB3wx_9~Ms;9*8KawL)#i-B?@d8VMAAq4GwoR3)zoo$KK?8A zJ@Gnx-+z<$t+qA6Kk@!YjEZfUJ2v9^q@P^#a=3*)@dd@UJ(erUWjW zAZLA3Hx#RyYOeX5+|Iwik~6=V4$3(eDOZobiNZs8VxEAGqr!P)R<-eCsXp=7jd}>Q z!<46U`d_WDhR)7@V*P99Pmr*O4}O!r?rpFb3;h1!UzKu5d3{&Z=YQD>4N2fkP!BMu zWnFjkR6Cnw`_Cs*-}}YO>T{3c4?4ctHCK_K8Y$&Otq4io*CxA(HYBbl`yReUt z`kkgYubiU%we47eDAOywu|~JO%_;aa;ze(X|92JstPEDc?*)EY^j`nw@p4>~LN2g2 z!|4!JB)<$=IQC$RT52$lU-q6C9EjKL7l$ff^-V@4Pe@*W-;WEFzrI9CtosQ~%uNI7 zcik(a*ayE#wNg(-u1Ak?{{GC@KrBo9{_3uKV|SWVz8yo1@7cD0MvJe6r4~oj~DiM7a^}kvbM{q zggB1BB|0i$X!W9~nKHl8OM&r*g@oftV&q>;NUyAUF*5x=?r_SV0Roc?bk z7ag1kLEEo2LcflDw8FrI2`3o2fSI;{5H&~O2HO01>~Xv^SzsT`jj@~cAQPG%Ni;sW zy?-_ixyfudeup+g9v@GB4~FNO!BwQ+t@rZGzJxFG|N9FAQ6O+VJ-Z4Fd-;om69!-} zT;|fE^V3XlBrH}sSpIpgBY%4l>*ZR>li$NhyTE*Yzow3L#P%fsl;x+N)BQdYBUl=z z8u8M4=-})vY+qqMzFL1DjGE5h#5HajQM=4$^9glT8&z`o;MN#^Dz}7-?OnIg2BOkY5guUn1lzS z9|%RQ27Xa-UW)`J8p*Jqhl1<;epu(6`C6SByQM}&4g=nV_YXA)27D#Q ze1k6DVR4CvXb**no}P`Bd7%l+AgfqSUEMcEqX+4c5CX?%UARa^W;Fqga#wCdNuO)g z)oEy5ikNB+>lAPEXncTz&7YX8|F5P6WK;&{-;I&hF>ZSCk0q``67(D`m={#OL?Y{q zj5-;eR9$d^4(|SMx=#i_NElBd)9aiZdaa(i6T%N4k<1wsol|Mg#4=>Eq*QG>vqp=X zJhdK0Su1XaTal!xoN=O^TH!apKV^#Kz65%{3w{^$Y;$!(T0gHAUHrZ{8x8R_3@GMY zs1(CHzVv^u?+c{kIoDW{qqVgA%dsGDhOIgrthK|S468Ft^sB_RN`t3P@t6w>Jdg>P zB!OC#T<=pnG_0S6HFchZk6-0-8A1!jV<91-tPsrW{Befy{r zl6Dz>#Xmo1TD}%u$+SmQI;GPSI8i;UL}+2x)5* zx&h_5+}_7W(opcDVYHaG6c!dXqw=Z7E;JogBXHiiGF;DYq1#kpw|<~Xnng$ioHKd0v>cWks3a-!!FS9Za_Z z@H4&Q+Ml5KzYfQh6j`Hiqo*|z=A(RlY{ecRS(ay<_$}@~JwtY#;jmdEoVfPQWny{; z4@~tdd^L|yd^YUG47#&u&S4&qV%Phui@tc~jEao|5{<@_fQ z*A-oSu`4xTV;K=@G6=H|ykZ-1O^O3v#nEVNo=(Y=oJtT{vM&q3SRADBz{G#iuSx0^ zJ16BAGQ0lOE0(|TRX#$OFtlX5jhBRZDhDy=J3vm)kWdy;|4*|Xi*y)rgg27P|7YWn zgvrCQs_HC5!q6QuCbGSByb?%C1%!fwJ-otppHY6@qhZU1V)O1?DWG+Y&^|>5wHJSA zr)mJCZY^M#P9MULiw;j!y8gk&S!-f{d3n9_{MLgH%B-2Jx@ufN;CT=fTvHc2FMjLa z{8HdNy|`AVJ49nEV*;k<$kJ%3 z@o-2{p*OVaBgNW|R^@s(lFbo>B-~{xF_UtXMJ6PrCC0HXOa(zB;XOd7dZsE@>lehE zfHjj@0MyUar*Rd5_pZ=F_iq5y`~#-x;K86;#Z?K6;7(*mua zYoAKaksP!%EWcrc3dB-&h17gk7ICiZGg2z5CUiz_B6a88M4;|8+%bkyz|_&QtptWQpA zd*n6KQI>4Pc@Xr7DpS302p|tj-k1S&jvQ1E9z(}>B4}sC2d}6Vn^Yn>eHe2Of4oN$ zaAeZ&Oi{`84Ch$vUuO@pez@WRr2zB^7m(Nu!2aq}*8RkQV!O<2RVq&=L2X=-X7hF< zo||Xf(0&2_-@faY83Xf(JVyjKFuJSahL2sC#$}{uxK+5SN+Y8YKQP@EK};;}h!jHuDOE-It`m1J!!nhrR#iBU6 ztxJ$)z8r=LovFtDPijTj^&c**!N81CuiNaOtrc2su^aW#Ey8dE=7HX6+N^n7CdgRx~WZRiI@t5YIp zuzC!AW1-)ihuXpBNK?zlGm|oiQa%WHz5QioQA@TaoVh~2TCZK)Z*MOSP(1QZjOGVO zkRi|^ril12JN$d)f3@BWr%im08=xz|JKnAgVz5$*$wF1Bp6puB)(%P;9d}-!U^~^e z%0d?h>uHxW3v=%*-&d%M3Bw5A&0N4j zMU|9bHS&qV^G~IX)j$=iL#_ve;l09cVhU3bpUQy0EwYD(IGbm@5fiV@ugvAiIxLqh zh^uDpPQcKcV270@Bj@gXjx>FzrD9L)(GWnDBzw!Dm}ZoGp+hamuI{a02he#c6IS5A zf-RGw77j?}4ek}Zg<2%@#vnNRq$N+&In1aGB`$B6VRaz=v_X&k+S%G*!B$xV# z%aKzh;RRl5_ES2|CJNbZ4CR^)kJ%kqM2n2~WL?4$exo%4`=pURxcRZmhgu$rGT)rR zwdbiy)c(u0KU6?g6C2EaU@b$3_p#6DLB=E*(!`@(b%5PHF!%S;t```MwZK8c`leh% z_{kGWiZX65K{mYewDU|`46E*$gNM*Fu7g@}xVNx*$yxVlJclM>s4b|PGy=|?+?jrg zk2!w~xH_9Qg&TPnY!|=By*xau#pL}aN>`b(-9i|}VdXzkN!Y2L{3L=5@M?OAex6Y~ zy}%Tmq_${oD)6aRDKSdV%7B_w@Bh8sUVr9>`fVd><4A7oVW5T(%d1)i(LQQP+Ub_R zp)26HJ9Vc6DsF?!)_6=0x8^tBE|p&>fH5YoFzi+I(6BIWvhl@Gi8-v4Ezr&lmAGHc>BXYg+``5#3YCIm#J7B_m^Lm#UVYl_bwZnud$LRD6I&CKODI^yxd~^lVR@ zS%Y86xmCwiT?xH8Z*ywtU#viMLC9yyp={2d%ln+^IH-Zv49K9>S}K%30^;H1wkvF5 zc}WP#`k1M75H<`l`PF8pkvS5}g3fkfhl8yh$_P=MHY~c>70R_4iup=!F!1N!YCGnu zt0_bkV2a6n@{m^_7FN1%N~?bJfj5$T@GU!7i~vft*XYz#fUc>7c86#F1rJno@k~nE z(Z4%9p4r_RG@XKS%ZqQ>RVfR|(QD^kWU7|eqj%xOcOvTzYeN=o3ka|)1EIO}4xWZq z8UqDB-Wv7y*zNCkU++pm!S2rRHgFho%Q7D{E}lbBNGE@b?9bnH)*MhSGE%gIQZ;ml zB1v$*%fsahj4gy)POEdt7j+JHR`+B=Xtx`pY;@ap*tF^|A)7~auOm_i`iqP?6|0>q zk+eJeA`uU?2YX+jjU{n9DElU{Y+84h>_Ej2J-^!$T*vGjJKCuXU6l;%-pA+ab+se? zq6S$-gBhgBBGBDDht8ZNddJt{*ltAwyw&{<>{c&c!AW~x2C_LyG1p`yBcL=eAE-F# z+JIs_F>VwB(*Aj@(0hy;HGI3h)rX0C#Ew5+&*%VMLHshgMD$%8N}2C7i>TO9WJR1Q zD7z!h`}mb48^De6a;@H9YJE3}6WW(OY7rl74glZw>}qTZBNRCEAUq-D-FqIM!T}|B zsQyf9Ms0S8(gi`ic@8nx$s6pjTq?f;ghW~0w&=v|QQL_p!jB(+&&S$=QvZ~d)w6O! zyF#0vV>c3!#L=%**_R4iXj3slMY;8KbQ%LBcv4Z>yUl{srlbdfhqZAjr24Q-%>{Fc zQ0}&C9$?{_ri@HX+6(oIVcZr;R96V@Y>tnU0;^N&`ggJZQsaCx!sv!DYVB%3xBlNv z&KIP~x&FuGTt|jW)H0+oGGB@U*AMK3j2Z{g$o2%H-a{iwG)fhQhzw5NI0ze7ZWciS zNFDm1Otl)O7fHjSepGJlE%^7bNyeDtgocLp354I*j}N&)3xIZGu($s^9IAJvmkRO? zVMW=Dc3$Xr<@jM>$uOam4cxl_oCt>EwKEZ=g`I18LgSVZ{7|lmkN0p#YYiyJ^NAn3 ztvWk96GcN>ixM+j4ptvYiatm;?#bx4*R6#?l1*TFbgs|*RP^0CoZ&rUaL34R%8xlM z)k4i~zww+xE~CV#zf5qCYd@p55Nc}~G~EvhBUb=rp9CHnldiA|lDuR77>`mtgYA@T zUrpV!`sVn}@v8~8Ko^ZhAc|?sIS?`_mZ{21&>TiX_CL|(e@`fu%&++K!^Lwr_q`wd zPTbsFfAusMoj#LM0uI%Djmz#mF80Ng#{e4qOmXFPzbcCg#ogy;D^gu69}zB1b?m;r zq2_D7beP#Tb4hIR`wz;>MKkc38|IB!7bqTUj6?nP9&jDA-c`(&ge$HFE1MMISFhGb zB*656z4FpaYn&@y{$*AR11P8Vw+S_C+y~eR>p**J5qoRC!8fKsZF_^*msW z{Dm|6CoR7J&6fD?A(0Z`H{NbUJRCgsjWrxd2++!4G9o;b2@*plvJV8z?{JR;k(waa zYFIfZSUFG!u$9c;#OJboT4u8{{qD&d3|z{VaMs?LB~yiEz9{^tD+E5rX9+mHi8>vV z4N@KGTQF5B>JlM?icF5yc`c!`$;n-z??3j&z zi4A%LEU1heWZ5OSHw&uX3=lFrd*uicA<%909Oz0PfO#WD;Fwc>C^KVW0+CD%v`S@V z$Yq8{-|09!Kz5LQ^9@__bK&08n9TQD-bpq9QvC`2*NUF;Ta^<$Zu5mlREech(snF!Mgiq-Sy%@20W!npN{ zxcU$eU_sYAz?k$`*yZO=S}Fnq;TQK{VYI^TB1i|NEe@8;6EKP`7Jn|14@%VKbp#Sa z0^}@j`VAn0FS>-sqVn0Re`^g}1UcUllefsD=x!N-7gwwUj>YabavSFp^GtmSH>yEf2=MttF~o z=^YGT3w2y?G51)X4gt{~h{lv7Tkogn;#N$2Sd6WQ#(^jEz1c49m%x8jkwVi)o?$O7 zzH6%c*$^6KGSf=tj*3@@)J6_1pXgs=CK{43!`_AOh}Bf^y_f&$h;Y<0HL@R`wu^RifIT^zX3-_dwGbR1r6tC zZ+h=XP?;4RWZ16}uwbc!!G~~-^J%kix{DTz$O zY1x<-@2QXKj;o~H5o1s*-C%5?3~h5R-<^&~1e#&}T1gm^t=njrU1{K=B!ky2)nFj> z&_cP;AhBX^{X75qh@p|O#1{@|U-M>}z+fpcnPq@=j{yv`af9M89LT`vq|wG?Wikxe(& z3jcQ@|I{Abp?HC8!GCH^=Y3K$!$cx#1otRo-_h%dMFNsP0up^lL~YTLuQ1j(i1`<& zc8`Rx|H{u$zTRbS($5NMHuHhP&gVsBF6Tbeh))YaWOy2QP9XCzk;YM}G#Lu5;Hr6h zPc57c`3hUJpdqjj`xO97G3st8C%)XB?@EQZzgzNfGuvg3^t~((tS|WLU<&D^dBc=b zl|fYUH|L}_u6_mFR;J%e$45N~#^25(kVwhQd!7*W-t68_{xHKn2axm2^g_LiTwVSmm#3j>vp*vl#tK74|xK~_6C@>Hhr??LyUrs@U z(W)r$)S1<#`mD~x^FYzlDA=kUFMi7a{4W^8EfxnTU5vE13sl8wk5755FA{_Y!Nih9 zs6|}#!o_|B9d|XGggDSSi+MpTa>tETG^rM_^Qv4%&{Y&c(Y05>+-U1pUy*d_}uYj<6_(0r~AaAO^jPk8d3Fr6?QaR`()s z0o#G1Df>A@o!~BwQbEp?Bxk-}TQInmS*;*SS;pqGkKyFucT66{qYy(7uU&w!Y?WSn zzA|F|B-wDo%u0=h(`hYXA|njwMnx@`N@36{F5~3X`^HrPhn9!x&;Z7b9lw|5exWbZR7E>eiq4>uLhuI#68b)X3J7a@5(Lu(?R5v@yOQ`IhNql-oY| z+?0bZ`z;D1c4b_9&rM5#f@Q@5W&lbDwL%?(=m+U)m1VW&4F(NUaKLWuX8G=IE;NBU zju&Z2xtitN+qdXIoB^kw6QIY3Y>Q z+z2gR4K-j}czVn1va4!~Ys!Yw|>4=s~Vk-2!4GN8Rm!Q@-7=V=3 zxIhDfI$fbS+3ImkX34IsqmKM6MhYw9QpFviO%#xQG(c84dEY0zKL?=a_+UM`2X6tV zK?vqwRKnvclKF&bH9~rWLGsqV=2P*T)GuK|6w^TIr#WiR);0Sz1}>QlKzoRwbB z8i5r&i!=W;cNxcuDF)p9PRDCdLy3$NW#=c-?T<^v2he}LHEaXWG7eWSMB#>iHP6da zmgsGpgvCUXAmxV#r-}`_MV8C^K82dn+ z`dnK(Rp*J#Xt$<~Y~;-BflQIveVV}k)hjfoMd-yq^3M8O^8T}yl}S=L_xw?PXjF5zf$n8S~F3>?<3@~<;1se5`P!M5t`%>d=Xum z6S&TW%W86)iR`Q%YbPc6acwt0;!%I-T2aRSaGU)u46^I~^bT?oDUell5~s;LfJC@) zYiZC}zu!!qj|Rb|`Pl&!P|cK+3JUJyvb{K!#BycZ25P>el%Z09iHTJTEC2UQ|EYN) z*;e4+{>iqIYHe7bX#nLK{>*)SD5Ije^MQ<0qRq-kd~g`8Tt;Xov^596jRv(%KqHF9 z+brl!-3Cp{RUytgt^5$@6o-BX33&IZBCW*|Iv`W*%Y6#;hyKF(Cj;*P3<4c~mtTk1 z@8TTC*slPJfD$x~JQK2_Lqd*BQ}COB8)S|8T@6WEJY8tCE-SA}3Lrz^H>pGtVkT)| ziE6`TU;A=H6eao2^-K`E@Ae*R>#;v8f)iK*6Ajs&_6h_I4G{(mr*sfJYeJXdD8Hf9 z`DbB9!}xc-y=R%+;3TR)MDo!N=_9SG7j=_i;q$ zIc;%@GG2Rb%$WEn;jj_&g#26b1G?PF_RdE)9e?$$wSPe5x)i*s`Kzm94g4SbX5+q{`4;BYT2 zff~A)iuq> z>jBe^AejLT=4eM4-?e|ARW4d!GJO?BjpswbMvae1Avr#cwhzYqrM^tnrHau7ius{m zQ;C(a4HXDP4+zA@Jwx{@^5ko{;=!wyxd~i7KKkg$^ME(!EWv_;4ZaWVC;yu1Y477B zRf`e_NmaSEap~TCx=wq%AQE@8SGZ6A?(Z|^I)kRvMMoFH>g{*+%e%&$Fg$K~deS>% zr`_H#H;HU7jBEF*lTUule5Ab;OiXYu=+5itvyXkh~hTP zPXlQzRst6aDukHJYz`O zSarn?Tye2qu977``MnA|N<>(w*rL~HD0^j7@3G2fXOvDKma4Phb5bO}^Ju`qX%h8l zoHFv_{1D@RSZxwwG1Ddr-Tae4(P!kL64BL70;!|)JiDgr$^%aaAob>~RAr!4xg|rl zkoVKr;X}iZk9sQ6Hdf<@;+qMIh{gTAt~qL4MxDyY))K523zX{gx3krkuBOWFUZqfH z8QO86UfXW(%cC|y1Qt;8^nWLVdc?Lfgk7_TX0Z9v1k7kRQ%pWHU>nab& zXM>XN^>HN==7heo*LVg(Xv>wm>obj$!T~@Y8*>Ot`~3$RxNdwG#i(znsqC?&(OA)W z1~%uzI~l#makxuC2X5%=`QMk)rk(2UIgLk}~E6R_u(6N>$ohA$u+WQ4m57 zM+$TPX(b3B{lPYwMRsalG`)=4aef?st;v*vwym6_eS2BJ6QLJO9;Bcq^Rpt1{4Fwx`b4iLSX1vh9SaC{ee|k4;&PBsH zR&ULSZi7;K^fHI@xfBl?N0&rMD5IV?ADdrkbztkG*3YDsb)on_=Y^6J%(|%?aNUzp zB3(vQRjP)RM8x%`xs*#5lo)Kx=t-9Hg%;3C7Cck^6b?FUYxL^u`nl{^N+wM>2C;VC!QYcO-h zd&qn}Q>s$va>yocP&Aq7b-G|^VWsVSf#UY`26{q`08ZeJLFZYiksX=AnSG3=gwbu0 z&|JrLE8r*WZ>c#NB&bj6TdF*WE%kBewW5yqk@%hcQJ*pOjaPSd zj*Sr?JyJQYGH~5}R~W3}#AWda(Cu>iL$zaa{NE~Ekc>F4H$9o33%lBKh+95v`@rU> zss3bc+Yz)m6Ha>G%OvX;uRj}lWqQCuJey7W!nM7`AvJ?VAxyY&y&p6#nKY`V3u5qEKXw-rSRxwrTTOAWt2m3=du$8L*FM0vJ~c1 z@8m3kk%>}`Go+@z{<)GjG^`TOY^bP6E+INIHpFHiYcgU@GSf~3lNYtaCkr=Lvu zh-><3YI?YQFrJrAba&Bs?@LAy%)oD52NBYYJ7YdIb%WtCfdX3R^$MS;NGfd+Sg8~# zv=G@!cP{EUR_|xNq8_%^)Ri+#k-R8zexs6H@|kzyi?%3UI<0AAq`PjCZ-;9TlzmZw z%Pf|+8cp}Z=Q-0z&Q!%=^zLSXCiA2 z04y>mFkgN7AuTi|1Y?D=t)k-B^j05T1ksTFW=Q}a{XkU+I&N{8b%pm8c#aO3L<>GC zl7i4$9BKxO=>Un-{-#y%D=m`?*Xq|^-`EocEryLC=Od?NuEU*)qVytDmqZXxdgKzr zr1xR zII`k-d3oA(KYvK^W>pQ@FB}ydv{fHa*Lqy;b$h=l8sg7Ar#HFLpMQM`XGI=Vwzj>R zaGQ9o@9QeRqmb`VxWK5=R$#eNhuiP;Gr@6p!kJyGSuLPf&iBTC2us?%C-Z`wGJ9pk{}r+4qE75McD@`}eEM7ZyL1dA0P^JG4WpOq&7! zrax27Q&Ntf+Z2i=2H7-~19OJdmAHmosx25@rUze|cp)&eANEJMd|+7-2`X)hI!AWB z0O4sBZ~WlYXa+Blpm(7r9-f=ORa&6mv-*xz7eY=NJnN)yX-_=x=QFE@x^q9MNTr1W z8Ci{I?^&|i=e>A=dbgf>>hPBNkj`Z1KJz*j;slPd)I+*Ogz{6~;d_{fr}+ZI=7N_! z)79j}qZaI)DwE*UFky|cD zk?PfQrDFQ3Ob$XBLDi4m<}&8qPm9!~_KehNwkJ2A)Ryco$u2SC@U5&!UYDvXnO4+) zN+F#ls3&aHZ(+_Mt!-)$x+qMOw0rzC7$Y;Rq`N1wo3BFoQqGZ){ca*5ZxDt)wP)KrErK;tD5~Y#NO7ky4jq4} zD{Y7l^Xxq@t1^kM-|MZ;s0; zgZ`6cbe3pri2Ti_a|E-L#lzMSWC}1S^U}@lqxC;1=^3`UmZpAq5Viw#nmu0!gwu=G zGIFqi+9F>c81iT$Pw!Ea{+2}}18&hSW&`70>NMF*%A>XsJ3e{IM6&~ls~s2P$l@NO zki?Oppv0ZK#+8wG&CG}Dt&Zx`PtH9kR4j5&<+Wvx@4WcNPhVc8*P;qKIWUppAcvdQ*FT-wv-9^Y$~_x!}&n zO=$?l*+vh9A3}+^s{G)G+Gxl75K)GO_aFC$Sq7Js&T8Cs`iAi{h(B~*f-O4Q=M0|I zTWlzn*Ijx^;Y&?b zVK4e#j8M+pU$f!5Z)zuq^X`0K=1Ld400wR|Uyx)Ym3i$NqN+sZxr0k-r7W({m&Omy zoYEEFvz^#mcn8ffwC~rIk??*TKmR7<^D8w$v@^FleT2gZcJ^|37e9I8hX-kCi&3B~ zP3rNP&G|T^2^$Qy)u>0*e^{{F^FJ4SFl*X*j%mr|=ZA*^MZSYSV+aox(E5xhlks)u zS(%(aYQ4i63`ds|X>wWn;`zSb!p@QIBFFs@)jOL`x4Wv)_~X6#D|K&_Xf4z3RuRiS zoAC+TZ4wM`_gTlBl?4`Nh?Rt7he~V|Gt+wB(c3u^e>$?X8#nZ+HvF^u{#YZy4@p zbMnut8;kZ{Q&*qRo8Hx%Mm*@m?LN!fsph~Y*Fj8Ped$O+id8$kkyh?C%EQxfu21>y z5naQ&aFdd#Mu15tt zBlz(CM&9b~5IZZHxaD;*?L_;{`PY8LE3ZRBv}o@{etkw!SD>G*!phcuN$l$qPO8vp zCMA0Z2T|zUDL+?aGVGp_L2dYHtEO&X4cT%Z%BYhjQxCP4^R|c%r4dujsqIr_RecO7 zl@VwAgA7f@d3ZR2Fc|Og+X|o^iqofNXJ0bZ*3lg=#ATYbFCyyeL-udJsNAj^?i0ADD z+!{^p+V9Dt7Eg#@9^i?zI(=~U{1NADyBK|sN+#?9hG$qQ=}&{%HyCIKxe-^$-(b%; z1;nR%uwJA0>rMYQ?X5{~?WtYNcc_s)YknsiZH10E$*qp0U1CKTQ9GvV6q6XY=M%qko>reax)~ zO}fko$KrjKC*$2WA@d0r%ry0E2ruDZ!E@N(=ee?58|0*k|OUt|-&PM{d zu3pR=Uy1NvmWE{Ym03}Cw?q$NN8j(o7xs`^L#O4Q_?C(h)7h7OAz)v5);>VM@#76)J)q=+(--tGc2@?>9pb<|AT}MN8klc)*-aIOAgOD`-Hs-5}L-YUcUv-2u$=X%Dq{ z?GD#+1sx82gY_LchqM9n|!u+5N;e_7Sue+G}5hfBnGC5a$ z?s~h=!=yIO6kh70zb+zMrt2x}s9-T|tP98+`0I*}U65^^`B}5vDO-pwP(i@QO z?v(EC{wC-A^qlwkuIG>Uy)OS)ZeXpw#vC=r9OJ&fb>0?NA6&n= zTQa_(A^Y5$<(s=fSuedfNEb_5e|Ux8+1K+V@Uu4yIfnJk3R?O4SINU0p(3fohTcRs zEpVG~dLCqI1Lv3YT9PDgFD@d|DjLx|bEv)O`5xLDt|aN(~T(qAH~dy(dW zKXn?m_=8R2rtp9yuqt^nP|yvgjkAb%BRI1VZ!q9|^H*g}-3@F1R|^T=fG6v>-=B^w zy_RC+RBXtuNGkmUcU!*claetujKE5?#UmTl67bmmD9>S$AND7V}^~?1ewV!Q}d{xYU{LNhFrIp%UN-0 zJdrH8PSf@A6%==FbZljMuooWhTT)5J!f(7jp}%|4lY<9&v>O^KlTUu&CtMX1rr`<| zcO;DuvwVQ#LrRt@=50(W%4iti@VHm2lDMTE6#4jX3u*OO(lnsF<^22&efIvh4*JH+ zIc08}0Xqfmw?5i01)NfK+em|f1^CJ$x%6Lr%RFJ{$*L8V^CygoztV-F7@ zOCAeNA57Y+BmVb?gAY+`iplOY|Al(JYuO{rpCckx4}UhHYW5vUJhM`PeQI4w*3I z%K^M!fI=b-4FWGzFw9pAd4}NS%b=l*j<>6TT~5P3V|&5pQF=y3S6)93m_2G8D|q^w z{{y$v)|-b;hobF!MtE>2`o8PsGQdE2`&KP(HWbpNC%DUB4PXn|y*9dh{HR72fNrHBBLd*l~AShWa%b+0$7G*`T00 zKs~k-A+8vpw>hx?i^=YtHiv6DoBS(t2UYsDR4$6-)#YW8<7$`}FJcZdxAisSoHwwP zpQuHnksS`E)V3^+E3EFHl|I6>B&v-g+7a*nGEbR-+C;z{{_4rt=6pjDV`kvZqUXXP z0quQ1zk2pv=k7+Jmy=F+EsOs2h!GDdFRdVATW=bu16mS{SJ&U^BpU7fu2dYNK`6Wt zf>X`^)hgG(U+jCt`30DWZj;UjFh_Ki zC?QD`R`+B2zL6P(ErBBx?HEbZ@`&bqGV8jm-s(IjU!q#{N~R-yb>1C$rOvdQQ~TS6 z<)SR#Q2CdcaJ1J(u`Js<-zAKd6gO~s%ue*YD%-_>T~Zn%{6n{h<+=%ieUR_GS-8F8 zP}8PAS;jxI^4K4q%#?$9vK4OOXL6)w`|u`4W9gPMn*Dc-)n$a|;L(ru^bG8JRH`WWVQ`A_}# z(ml+qsJT&1ZF8IRl;gg^=Z;j(udG)+maa19Cw)|(-Lb_e+g8JnCs+%py_%{gSk4W9 zA6@wFk_`F7N)p9crbk+)Fw%Q!iiDztor}EF+k~dE4DJt3F#dKndav5u`uiVgS8JYM zN3!UrPhDE73b5hUt(BspB%dn=h->~he*L5}Ns?x+vrJ9%=Vit-%!!@ergMpkbA!a^ z&v>-GykBBD%{j+I?+fs^y03#Z7!`IQ^`@aGoxhe>Jud;@8s!U#B zBX+bVx@HF#BRut{K%9NcdFcKzi1+zE^t^!;50m_6YEfZxu8xDy=cWW60imo*N$kTS z==?v}t1DLkfX$!ekwXUu*%LBQpZk^e)s#W%$0kl4%GvI$^mM9{d_bz~+H_LJ&WF{OhA1_t<1^{ROIMc* zcMtiCRZ`E37&^3pVxFCb7W0KeZ5W!7Q56jlt{I25pp1qE0a5Sq8@w=AnYPJE9~)be@NrMlv6BF%jt6Kz_Zq85;d_$ z{zZ#r($UvhyR9hf=O8^zjDo_aAD2bi^Zqh_mA_aKkN;U-SH;1rp0!ZWp7n-n;1$yO zXni7;KWmnJjS`$zW*-z*+-B4_vfJ$}c8IR~u;~@^M{ERLt!Qto=T*Iv1aR#EE{pa@* zVs}OD{slIWa;0mVj1!?oAW>ExpKT=pXV+QCPH0GvqYziTjS5IaZ}sTPY4#aRezjgq zqJ)Egujl-$y;;rf3rN=>Bs1Ut6~7e2^*XsK~Bh z{+Gd+r~!jvhE%7Ba8bPZegEjuqx<`Dk>ZR$O!Pa+aGqFV`0aWa!{n+Z%v18@ru1i*Bsfv z1q%<)Y4ZKf99`7_)V6Zin5I69Haa~cz14!xex*~mpj}a@sTQHSrbg-9)+54JR{+uH z<_nl4l`1P^+O#=2S}kZLxV^rQE_MK?MJgc+Wy?6?eM%*|d|NZ;9`=roSi5?SZhh5$ z-x3q?FE1|SE3KwPFTt^*`NklLrctrx&jkC@^J*|dI26d?dU^CzOjK09Set)kbCc?- z-s?IR{JwPK{asxe}*@V@1q2IQ17$?Tz$v6Sy-*8oT72zWNlRp&i`tqcN<1h2oghrE;lvrWos_eVXB zh|iy6tpmLMlZc|A0ku+nAts8F->YC|Fb#lpkcvzbh0r;Q^fAV@h_TtPT$FKE09^-k4a#D5%QF)f(VG@>l(>KJ6 z+Q>Pd)EtE}1Xi~(v9Dg=a+y+wPdRcSar}ik@*y>$MY{}@?a`Yp=ZNx)_4((0Vl%d8 zQ;bX7h%38`l;eEl7rbJPl4v5V#XAyomM_pQMb-&NvRlrTP>POcqi;D*uT;9_)?t3g zFAlCTbTRP^&6%E6toUs?#m26x^%6-G(bQw>R3^Ekm7`V&+;3rf$oM;u1+iQ9S1Wi% zZ4rLMd3!9;*d=bjpmJ`PzUbp~vEArOIA*!l%Lg~@JS3w_cXU>$b?IrhvK=W(*x$87 zc&3A?)={-pbFSx*F2bQRuae#ArNWo+bxk&1)MN{itV?C#l$y}uec7o?{|;*fN6y!( z&mWhi(le4&&opBS&cUp7`Gw@VTCLA)z&^fsRMobYr2cI7&S_?~Xv~lbVnZ5gH*`^E z0-UMk_)}z0NV!wQ8TcrOWLK2xd^%%Vg1pW25@wU85;uG{jiq_{!b37l zBW(eQ#M_Mh4CyI>pwzr`xwUGah;cdr?*;ZRh-DsO7k=;YI0q^`s4iVQKmVnn6+G%& zh54jY7WVNm4Dq8s|A=3sxt(#?#i}@&3khYlURBx5zXg+{&A`sTIQaPZ;IWv{ zUS3@(dV1EQ!RyvKz8mdJ;tB>Ny_8f`K>&eYqTHkpWA#Q3G`Hr0&i7suTZ4gIh1Z+2 zTw_njYtX{0pdS`_>C{UdpX8Foj)z2S9(Vtqn7+zOdT^vmh%gt>YMy zb9Fu$#c}7MK|yKpET)5p%N=6Sswxhr&Ec4bVZMI3RDKzOdtS*oH3X^4>1cRNGNS|z zTUp@Luybfs3%|2js!FLWT}+v#Dg>hBGx$0(4VxvQP*f62-{dJPN1UF zJ>9Z)KsI$)7KE6&_GH2Vg7MOl9&RN+^V;@z8YW21qBUT3?1w3wkRo&HBq8ZixKz8T z^{EZ@#i#hMX$Lt{l;;}^(DN0zt2kqV@ja@j#Kdm-Ah^k9S443ezc8&Ab6Ep!%)0Lq z-EXN^DXMsA*2oNE^P1_6{Hz12C6DnfUXN{JkYgW6X39~wE6P^6G&AOTbsM=OVk-4# zZEMHf)=s}O7PBXl-##ko3=X<;9X4)M^p-pipBXD0rOAJRHcgvep#ESbe7W5>CA=XBlg*-vlvY{JR>f;{gK+w6xWb|hZu?$w^3lU&d89_+v7 z?(tSPpp5_FgCQWYEa|lAbWa@0AaFNW%=+TJK<`IJ1=*)=f9bl(V2P!bg;BkL(*B$0 zo0-M8kY1Yh6;^A5kGE7JM{yt{6N}!4IzId)sc#52g=Plh;RC}%u}jghwirXAn-vmj_^3mXzlMg0Ua)9=k!G zvJBXYM$~>W0=U+BCViT%P&PvDld1#mi(ha=%q03Q3O*nTC-AyOi4%Db7rw+9JH?nM z1oRxgV8e_=@oQYekq|-W`RjIRu1Dvi)n-G6i;tOkZ^{xPM~gx8{s~aA;E~;#`}d@6 zHHt6n4oOlQ72Cd6nC=r!12PAo*N9k@O}Mv`C@3hxXj26fE?e$ow5ygq@CKykel_~P zgrOm$!IC*4bnuwl*K6tfFe>vsz5a_;XlD`JvjH6WXa~WNRnPJ1CtkjBcw@2|$B8zkhw)yPPB9Y%S+o zo88!4>}3R1-P$TCkjALg(1dhCdv87Ts!An(T<;z4IPSOc>^sO#EhrAuDp)MeOR=|~ z9_(P@pNHkdSu(3o=N>)Emztyq?F*OWB~LJH^tAE1ypeXDDyr;msVnA-IvW_h>?4sr zIhW4db5drX_l!!8O|_>`TYGnq(?0ax_B@ubp)|u^A~gJs0fIq#-c6>LLxoRIy>`2j zLaOLdU!-UaM1I`gZ95v{yqRnN3lCqY_qv8${&I(=H12#XLaQ6M=N*$ZucO||$WaHD zftF^wTzKX1byeQ}y?r7rne+<#hwz})c)>FD27>60nRt64#1Tn26;pagptsdCgllKM@)exN{*TV1F$O&H3u>1a#{Xjm zzJ+feHMbI%?aox%qywDXCL=>tPjvl0V*MguA8&wPW3)RYLe<~}gw)&sf46@(fzf~z zoC~Us+L0vBwtRn+9UN>#Vsd?=;2{!?+RFF5Kjk(N9@TSuT!tKehbA8k8B>df-}nU+ zuJ^{%)Z=zvXZNBKaDH*6G$s60qg8c31SWVC+0oaLaPDNiy}j|41Rm7;nQ1SixSWAu zC550yLL!9|ziXRBAg&qL0W}g#NI#itu&#&Wq1R4gG9pKENS2zs16(nOBw~uqiVc+^ zXyo>vYxHCGN#u$&^Zas_-aNUR{KPmE8sxUFOe0b(jwqwpa`u(4cgJlDqm5ZEO@mDc zINJ3rxRF_!fr_8hsO1438zpS3zZ!~%q|vkI3_n#*Nu$M$zkg?t-WZPb;#dvAhLATj zjVIjDDS_ee_mXdFoLN9{G|-pRL=i}5C}Fecml|l2I_^vrt6kgEd@M+?=4da&c=^3F z?yZ~l>Z$rVj1rdQwu}^|El3WsZWJLYi#buZ?b3xk%P~y1&wobxS)a$NRf%=*K4%-# z$Wfjo@ALVLFs;fcq@}4SKhJ5QC-y@83I$0Fsw_ciL63d?BcXf56gX&^vV|G8AVl|q zX63-L(l$9G$KdfdX@ocfeHT4SPa-kAJ&CifDPA7yKq6wVo*}f;sY+QE-An5(K+ZH6=#`ws{w7titit;B<(T51C;*d+GB~_Km_y2-lwYo4A zqJ#e^*pA+5ra-C}&*m*?Qs*Bod7b8hNPd% zS_;-_76zH5JeU(<9Vf@xFVbt2tv(u?XcYP!0N?`z6zI--JNXC!T1g2l>(3`($|}_R z>fM<51Sg0S8TPB)=%`Z3EIAx*?(RW9YpZh!yZL?Yk{YfgUoa<}tNlyEG053%W+DD- zcS5wUnniWg9u0L|dTj=i-qq5KsMl`E;##}ornKwE7jXFn1)MuvsJ(!=5K4UgYMf$@ zZ7HB$@~|^7OFwFLyzH0Kthf!Bf4qu%rnXljV_Lk8?YsTzcjMOz_>pH`8nV3AK3B|P z?F3-4#MNLN2Ne8(9&WOdKWW>na`>LZiB z$+Qv5SK=>G?+G(Pr7ZnU@uDa7bJSEgE_q4qTkZE|R+2q;G*IuDBNk_w&9S{6^2aMH z7yT`%paGZnOL_}V@3q@tjyKk-y(%f2>NT>-V(53o?yrgE9T5yZjnq7Y&B@+L9Uc&H zm=oxXSEf!0=4MAl6T`7>{NDC#k8AZd0`Bo2Pybj1ICNG~IH$kqyhi*VE3uju{PpYC z0R$4G_gtL^ULEPN)EA7)=^_P4XUmK0tE*u!7Mo`}Kb}~_SD=NyF)_MKJDrc22SzO0FK~0pT}A0WvrAK zX)ANp)MP6kjrWb6<l!lDDxO+NjE+k>kzZ?(@@A!M?8_%Wm8sO2cZ- znzxozQ1FSNsDS1On|E{pl6LlgcC)8B#rzp#*N#ZLCnyJcVw!&DuM(fhXJOPpaP-o} zd;$hn>loMqfI~-9K~hARLQU}!qvo>HBzPjTa~3;$J;dwY^)Qf45H~6Y<9cH z+P~^;R#x=ovi&Bd|FNKv$>;tQvMA1@DgH*QpZY-0qlQZlO3FeJn1CoXlY#Oj#sxiJN|bB9=lZeD4TO1yf$CZ|yS9S)I0#`O>RKF@S< zGF_#@$i^>NSV3hYul%mJuJMu zna?CdYLb#WF8Yf;fvn+g&d!8Nmdb}6IlB|eq`9eRm0e)^V`j>Y!yqt6<{bhbG_IOpmF4pX2EhGat5oP6YP4g*>FwnUpgS`7UiKm zdV0xVYuSDG?kv&${(bQ^+$DE|m11;$^a;9{`DrCB5!`=eSrM2IdyOam^@*zlaRCx$ zO-HNMP9t3+2YiR}lw@2{Q$v0q_d7(k&0qD-B)*T})l)uZi3WMDj#El&m+Ge-tl?l| zi!XSN$m~D+X+9EAJt3MBORFIb01@P?Vp<(}lk8IYsYw!R6=UO>{oS}}RlXV;8g7&i zO!rtQPst{8E5tJ!Q~BK8G>@d!{{oO@=Dm=i^tV6akx&41LsDz=JPPih-U-{A)^7t8 ztJi0@DFD2NR2G0>iNm4Xh?PUuJJNfPjjXI_opz_i3MDKC!cVt3^glJ|uI$|OYYlv( zko$5^gnpPr$m=Tj(*i01h;xR}c#j$+)$ueF8@RnzXR(d^gTUa;Yc`8f_-0WQ8M*GR zl+JJly-)Us6vyP5>vjmND>qJG^*ahvfOGPEI!gU5aGITx7LSaaY-F=wVAF&Wsi3R* zD3*4k4c26jG?TF8+NnjQmZKGSm4@RBdr)YAF&fFJYh=RrF5{^j+2`8>sIt({*t z{#xk6R9^Bl0>)JnCl{(vM;j80VDA_~-kU;Re?AWxiV}VmoH70Mma|Z0!dEqr?Ir;O zM;6)ydv{JIp)4M#+PE70{rnG#{YLBBcB^45ONbJrQ!L_VPoC&OWbYF)9E?_qTtCTK zeR}S&^(WQkKl1Bf8$Pw?-{m) zQK+V^+s+U+t*Q!b$DGRYJ_>t1=a!OeUrVNxSC61PNfC5go}&K6Hk~VQcGImeTU{=% zG&HczT2F<|=OoeUWWvd`wxe0ngS*jqsZtahkwX^#ym}q#7RX1*yOsQ*VE^ae%y`NWN7~#IktrVzb zX$}0aM4*V79FVY9qY99`F7QibvYXmywU$8iicg06)Em!JW9BOU5x>_ZxV7s%i z!`J7L+hKKI62Ox`^RMK=Qing58e4uY2h`GD@2Q;p3f?gs_*%Nn(JA0t52=z$aYXPK zLo#?-QyS)xn|#-i#R_$S99@#7HrngcZw*SXZidC#@;ipR!9S1VVDix21Qj-7P+_Z< zXrb@jE_+qC`A*ths)ND5eBjc|-l3Ah2EWl~X%oH9HopEU-IF_Ve>R;n2I&CXZEy34 zw2q^;W3Oyy3N;$$$nA^A6S+0I_?%I1T*K}=s@ofu_1htskkCWVw!J`d zCflCbL=Fu2kAF&Ulw^+#(iJ~#p#Di_BQy}+I~k;}Fxk-{t@ggM5`sW9N*oK3V68rW zBohlF2xmjY1O+i+At52*_Y)0XJkYvH(A{n^l%ACfYU{YS*ZXy7X;BdRtnYa^7aEq-vR@maiOyusojw@FOEKGPcr|fB*WtxzvWl>OZCZb*fPAcP^9s zS4-XvLmNW^mQMIghHpTYAQPR+ zY4_>w#sMEB*0LFMz47Ig#KeLnj6+zl0pr;vvU*$`nx>@x9w%3qyO3U0TgERdsON#k}yWO z2z-b{XLMImvnY`q#nwzEYfYWm*OE*wRL1a7t#JMb*|wpXmPq$11X6F-=)0P`B-Ndo ztn#3!(?lipCb0lynnom%0e?K+dUjNyB8GUQ`xxCu$%{>`II2~uOS=J6Of_v{!tB|E z5sDXvd7j=aOOdbQk~UX#tbOCT{H&dVq1obO$SmBREs(((0|&@&0PTgDE-~K?pf(#O2k- zfRqh)B4zvn0odHNi3Nm8L1!fBO_D1G;Etc=-5(p69mlQYUhk^nsV=+Tr8#rjkxeiV zX(Kew_A0$!Pbgc-UQdV&@#z+hVc^{ovSUswP^NfQ6WBoVsz;%pfckJVs7KCxSI;GL zOF2B-)4L1Kx}zRC{$7CkcTjM?1Os2ri)r=wd2P2WP`Th4cE4}F_HOsaRk#%>={+jT z^yI~iWw<%6l|_veyP4haDUysRC|?Y|(0EVKr|qKgA*Nl%jn(Ns+Vd{{_>Ke)Q{TR% zM|UsZgGA?CifSUn;cpI$#u)ohz=#s&`SX!)q4+~+B?}KqWG~A3oh3yg-D|<{s1OIX z(EnqWSWwbuU>?`!`*PYz?Meqf^ff#DTxz3MvKaaKQ~a6k)H8zKNU!)usR@NX+gX90 z&u0MEN2C%29D42VBqGlW60s=d1zq3qdf!ynN_U@Z41LqAR7N1JvYwGVULP=>M}?E0 zt34Hc7_}H&@F9v$up|H#4@pqs8#^#Fd;2A4NW+=ga-4RJgy|#c>(`r|kuAL`s_D)E zKIVbsTtiAl6+@rj<1FL>O0~#cx72=>`sn0jlty~RdboRdaQb9ylV<(6$3F<%)^MIc z?Z`0M{A_0d64$x!IG&}JR)m1b1xGkuljUP$p+n42lkJEU4KrHM`hNQ6Hhm<=00t~;?kG%g7u7}Hit5}UKGuF zwEMerbZh=2*(8oM591{g;!v4&8&Ua#;zZ59M3qz1`KMl;fo|?A>~Di+d`=8GUkxwU zP_Y4P{(U@l-PZcy8p7zngK35*$(w1{lW^I!&>U>M*8D}3#Q|f&JlLdxL-1V3A~#kv~)n`N*vb zRo|qjuh=;)rE}67@?19s)!weF*bTg(;C9yeYT3P?Tu3I*I=Y~I zeOcj&tWBVnB@e^JQ;H-Jo6<2oB(x@WBn+{+1272d920kTJoVa9xwb84i;GdI4hkFH zBZRyK9LP4ZgSD`&PLAvlGwJlhPBfMxzH9@*M65x+8pSVlLu* z)`|skZ$%#E71e}GF5HuO06Qf;U54SiTZX^9#l(qSFeXf|B7oWsjr@sUUop|aES6h}A0Fj!K zr-PRa#fT7d^&P!*z0)=}Ab-^Ua*@fd{SlCd4JZRB4uuLZg*IJnm(dxH&yms{OD7c+ z6vXO%!^!Qi7BVVB;O4pxU`K;__gk)23)K}uI-uAA0Rdkb`?Ogpx0pR zjS3M%{!a2|#F{$A{(Eg$u~v#dC`c z;Pu3lLVs32m&G1SwlxP?PfNd}X6jk~GSNFTi!TK+I7-r={aj04 zc6z$4sifH*t=l->RH976@HHg#HDTrKcoZBa`Bim3e_*rG4zhclRQOM>A875o&spRK z^rn00tZU+aE9g*vC3^a%ta@`~T$@?)ZH_IkQcq07eIj=Wn9i?rS-S6FVhB1Xlo%=C zT;A_WhOC!uzY{ybKYZEbW}@7^F(BYWgtImM1NQjnQkJuCe+t_gm4q;i z0O3zT@eypV*rR4qhsajW|LAKd(ARyxAo$g!sbZT#I9RJMg6qW#5#`@7>5y~{(G^G~ zj6<76Z6+qmmUD&u5qYI%dlrC#s^_jbtnBYgfP^Rm;2R=^zXRQctd1M!$(qmfNdj^;4(lej z-7E?^Pwed!g6!C>CIzKpb448j{9FwgU-=xZbcr~u^^%#cyBHuLBb)*r6cIrFhxuBk z!81OLNI=|EMl2XR3-oC!fUhTNW;Wjx0Xp(?{Qs0-)}38kOdBcH#bsq>Nk`8CL>2^! zPMXPv^S%39W23;~ZBOU>p61q&mFTIpPmE0EyOiTk{-n3x!ylcW%w&5T{G6EY=$)C* zRKYoA13R71{>(N5!g$Ayx8861X6$tiA-KfHn3Niw-)eo-g=tUdlm_QLap{`F1;X8N zhWU<_nh^hUl=lg&)=Qz64u7-iNz%vgm{LL3Ge6v3)9L(xCB(EoBn{{T>$^r$`eBij z+{VFRsezLTou*`Db*vIwh*W{eCEX4=rB#G}dFnhFYnfCCAG% zDQ^2ira3n(OQo|G^*{O6;~5gLKiS=RLHqPiX|YosMneap&Q1A6ti(-9tA^2TQxP7M z1SlH@;*F-X3l67h>ZpcR56|NI$pa`Hjol;bCUEletm zj1bzkLU#eaX_&=$AzAaA0-hhw&jYG$7x$i(c<%N1)Munwv$~N|; z&@p6#K4ADEVg~JU6E-`whW1P_R1bO*7lN`qkpVX@(`3>6F2zy6t4lJvLXwl!+7^$` zUTEq(`Xa3;6>w4r%euto$Ma>EvsSRX&4F5_@pX-KFBQW?+h>oUorOk$7%C-ID8~&q zE{}7_w2724SRE|4o_-{QbmL1S=f5KDK|lE5^nF7OVbi4PpC+D@6Jvru~ z;g3*>UR{$j9n(Fhf%zl#Qfd%WHOHKraR1(ihBRW#KS)T3Iy^{=!xkfwwLFGiYq99X zu3T**DFOwr{mR?(8pg-)A3r)_QfgK5BI7bLii7}ARt%kb$XVb!?H#o=VX^M`k;LjR zdtk1238I=&0AL22IT~FLn>Uz_*7|yc1>!IrI$B#1(T%!Ghpu*V^%{LQI-oB>r2O$y zPub($=mf>HR9TUAb1}WVk_yVe>_7(7ChFO1BI!C$Jei+Ii;p0<)hPO|4~Hn+S?RB7f<)m zX<`3L0dEE|$YnzRQ;hf+ivE%DFqzQ~w8Wv2 zPfwmAIsEfY1u1;x1gxb15#!HVlx9&j#P`DwLfC}I5&2IK(ckp%-xnWaz&YKJB*!xo zQ0n}*V^&Z4x8%sznC!;7V}L&2eD!<$PtetW2J;jViy6zN>Wa zn+dkqKb=$94;3A;LoF+N;FSXiG5>c7wLRz-(+LFk&$FAl5dmN(;?6;NVzNd$|fT4ES%_%GJWgJph zG=uwNtAAU>{#?Wdemwd9Y5~bKg|AKWuK;_c1Z(w}_jAVuH02|xqmRkyr9~-Cw-*@I z;s3c)rQjny!Kr5Y_yuuz%)SAv*MDQ!|9qE^KQSW+E0#SBEElLI|9%mDDwyHhsI0ZB z(Ryu2=SZv!zWJrSt8~REzrOB2j%gOcO$$-oj!z?#@J%@KKbj&a361acNsoYH#2mV4*80)QNHz5KW!UjQ~ueT@0#EeKOU-DR#uJ2OE`)k^y4`NCevMPO8Zug$MnQmTkdaVHY ze)ejA#+U!-Ut##8hL1lQ_`2YOiKTntyCF~hDCYmqF%|~@d%d+L8k+F_Mx<>L;yDJ5 zaIu$0L0H`YeiXTamJ>HEiRBrO$>V>&sc)|gSa9RL+p#Kcc+AsCA+A4P@sE@EEB5!g zFvFjnJsFbR&T(n}3QArasFWi6*WJ@tVJ_R5A3>i;q${Avet!&GKNPHXG~1r!)eNkG z;T22!^S@^MKQHvHVKd=&fn`iPKRf&TSa2E&Rzh>9i<0NfLzSsG;{}Z>=#vrm?cn|6 zJmL|4Bjxti*Ii9KGf4Ml&;94+9$rxdmY0u@3ebQT1QjIWgJgXW6pkvkB}|zW->Z zw=6+#7PTg){6C%yNa%$^@i<5*BqZ>-?5kBrK$oS$KEK!IT3@2$1Lv{*MT9Co*56ls zxcHd$k2+?#z#RW|Rq8bV62h(&L){w#Qem$3&Pd%5Ci*{qf$KpVd#r2J8U2DZ92Uwf z&`Mz+?`ag86rFeW^d!ora=)vxnXB-72^kTFExpHv2{-SP{66mSGY_D#D1R3eVzL2k zo_PFLx#I-dkc*b^+tJlH2A%Yn0@cA~iSSY5&j0K0cn-lOAb1`gwD}Zo`5zx5s7m@E ztYMo*EgG)?FQx|DBZq&M{OP5@M$ zN>14ZlvlGPpDG9nGIb|Yph9J2vp=-&i@$|G&USvSR5UVZ_~Ymf=VU5YTpUJ_w+ zbnDr@2G(4|y+RCX>D-u`X?h8#ixZ_2# zV@qBq!c>`$tc@0Xd9?qMbqo)e`~DdYbueL!=4U|9_PWGet(OQmYEzlu^Sp>44Dy57Mi`Z=P{^BI-^QR5EYun@YQ;>9VdP)Crzwyz) z;=42P6T5$aaQGB0zbK$-UC;B~-Q6W%V2Cv7zi6}A=?)3-9KAAnsB5^#vD@wuaJTUi zX0wG7vcw*(Gko7;cj|s$Yrp#AYBqr-Th|B704QFcr7D3ef=Y`$CRa++R8bKlnad$z zyjVkqL9ZeDE6eUs?D@i|%whMUa8aUiHewc%IdWt~geaV>b{1bCy&@?lO}43pZVBz> zwR`#bz#GlVL$idO?(J`%pPk+a&h5{)n6i2u+ML!<#Y-9^D&)vn1Q+8wr)0O}hzzra z4Bwe2gs^#syGh>EI^g`Msxn;tcqIIqDDM=zlH$5lrQS|M|gI7c&itv|zlYHVB;2!h{D&`lbs2YqG}7 z)%=O)HG73gEieBW2TC7oY-|XU^lJUi3|b!H_G_C?w7;F2G0jP92~b#U78`Z$Xlq0AB{e0^LRudf z385vf{JDA?cScPoK`(mS;Gjeuy&y3c8jM~uA>`o^)4``}_xnO+`p0=;t&ID7cV{zE zU$J9F-b9}!KQ{A}bluRX6T6Y_EpP3&Tvl7|?wE1k>7^{i^GfB-?<*#^x7Ne~J9$PD z7gVeY6f_36RHk(?PD3~M_GDWmLNaG-j=zvwP86oi)wyh0hS~p(8xI$qj1TT!>q?ii z<+ncRe}1G7n|Ym8_)G+Gwcg*~Ubn&OCGa`BFiq}YvF6eL+1DKC2vOGv+|No{PGsL2 zXj8YOdfUy#Y^`6jnU7^h$C~Q^!Pb`sqqMX1B z%iu4rzxIUG3Z5pP;lLNaew?1WR>7D6f`WU*){u!$E zvWsvL$HnO{9aN0?!c6EuC@PxoH) z(zmnt9vv)-Y;KNFnBzSGV4eT%E@mGBU*!?Bv}Pjw@Nc#zNX!PZ1VxKoW-TZP-#yvL z59Kd*oNW+f-s1Z%wn)h9>%RkKEsEWRMm^hgP>dK-)AOPugteZnP62)Vxm9%3&mXp$ z1Wr4Xk=i;s{&3xmcUL_h;6|sPKP(1yRSD7RsTv5mp*3M0I4mYx4mAeH56MB^1jc2U+kUWy^S+>JY0Gjy2@cH zoZ~Eg(2CiZs#(UXoOuJ?R<80xs)kPTn-E}41shmc!YXP?Ji+GmR5 zteHWYi|g=H5Ux7mX|=1rB*jlu0Hk(#FyBxp&Z7kiep`cSPmoegB?{C^GQnVy zC5Q04eAs~JFZ0hJj@M^&TYzmY-)pdm9e%PIM?Ne}77JHdwLZ-4V$Gw<7We7IsJA$> z&2lKHLmVPYx7{!_YzVqR*6VUN%rt8Zxl~GYlO^M*q(E@Vo+!~B$><0-zfPUm`1Sev znM8L?PhbLvPwLUtrGl)j?P2`&&ZPsWVp8ueRH@l6fHrughm){dLhP&IFgM;J^)ieX zsL$WP!NIN3ZBZrPu0IESHG-BQ1C19^p2rvYJ;7L1-P&s&@CKb(!8l{9ifaaDltp?~ zs@!bXk%6nXpQga%^&3~ht83y{eD19~$C(`;J?}LuEyTRNFDcdNZPzwwg4}35g{o}l z(gmjOI@+M`oHUjEg21p@R(DLn2EjF`LpFc@-rtSoe|Zc_kt+FUs6jjX`*J0Ejp=ab zL}-nuT!0@(cK{f=BPkIPk$V^H4*qzF>4Xn5BDGEeXp(=+G^Bt9nsBt@87Y&XD2n6` z+CCW_A;yN;Fd??Qrx%r4-BhCL6OW(31s?%-I%Ln+EUGk7vT{0+)pJiN5k?T*Sse59 zczp{x;Jpu>R{m+hRu+)a5th#8ngHB;;72GcDPPU0;XASpG;ApZizuiDI3Mu5aX-ZqFTo&;PG~4j5o}H`9FHyr#|3{d;)6~`cRcGmG_jbpmjxPYj0O?y;<#1 z3v#Pcsv0Wbs(UAJdaY1G8OCv9LMm&dMBpLd@dDq{${}NB%;SCryXK}pgS6Cxj%_1dCFbZ z2*pS?x=^ocyF{&oUpZ)w=eMvmQAF0^$Qfp{`L7;_WzqECyG(7 zXMtQiHnfdfuxT9rAg~q8)EelT5DwkAIna^HN*6FjvJ|Tp;dxyw!hwl2L)Ie*#B43b zjeFN|KaI-!eVEw%hP>zY?8ki78HI{Fz!@ z#%u(Vrg%HGg`#&DXFa8U(`k~_^}{w?u?yjkZ4d*)UL5e6$u zOSA!BLPF9d!kasXhI|pRX+;710?w*70lPyx!!YYshBj^+6kxfMDRrJ&VqI^&IG&GF z3n5|Ct)zvZ5MD@elMz0P8(<(qMMY&|5b(LvzV3jTh(B*%@X;e?yq;TNZ#Bi2^zA@<6O1;ukGtHyYZjdc1B74%RD5Wcr)tt^yQ$TYY;3}b^0<=A zVg(-AE`zIBV6UvqAVa*l-NR*nIEpNI^UllK)+yaLOhEF%|Epz~&|R%1?ln{2i9~C# z7+e-{eqAjkuZ^w6XV=?Z;F+S zjy|Z}Ca$(8cQ^{reo7)JSBh`)6h7&^cCcIe5h}qJuyxYq(aQHqk}5C|2~#kCz9dyl zRH|)j`31T3Y_*h&`kHN{)mySBHydNyu6WGGuT)BK1ygUC>-t4K&H0)o=rAl)bpLxXfnr<61z0#YJ9ba!`ylyrAXcbD|{jC=3* z?ESrGpY#61HJ9Ve{GM9RTKBrwy`)mxn7%J+Pukhqy-QbUKMoagbak-P0tEM))fVB~ zsqlz+h>G{#gUi;FB7y;bfG(skHti5i?=4h?yeZTy+%uLmnr38) zF_{YlsDF;^eqtty7ysXo7F~9jV{d+^J!ygbUGQITeHDdyn|O6oZgvvTYQtmrwOO)f zEy8gN@^rt!Swwt@i{o*)t3R zQA~Y*{Q6-;LIPhTB8}LT+QvjRN73f@3Mut@FZ*WpUkAV(b^siVmAAu?F@c;*Ynuqm z#;R1L3IjpZMF-(knOqgkp`@f95n+nhfHob(T$%Y9jwih)r_SzJh%3ofF;65k`ZoQksB|Lh?qiM1C7a``qh6;v$(xo?{fI>F8L(Cfy`yJP9|Rbz;KK3#qGOyxaTNT{^&Ku<+2NeRFs(1N97-DmhQHT++8LN z0+{3{bXkmUXnXYsSXM8O54)rVLJ0C2jppn9(^#@( zho;Kz25ao@y8R|%RBAoQiv(^TM3^@9VkFYk%-wkGs)z5x!*G$)&k;|_J>&{hFjK#K2l?^D0kFn2%TC;G^ zG$+f1NFTi=4qCd4}h~+Y3?7UGIsy@=~j^XoGjIN}esZHF22svCqvr z)>RgX8LAf2VUHloJrjt=zLnAYSb|FwS=A7N%O%)Saq6wY0@P|rfCFiAdw z>uS{>P^}l!q8uotu32WCtVJHWb{5&0aUGJGk+U6RIAdK)= z&jdqG5P)@7eGAC6ssy$F!lysz!!Xq)FAIy`YM36U#9LY%>oOp|WxpSVO_^E66uKXs z6^(<;#u=ntAEc{I?~+mLt7Q#~%mB#v;dy zbY!nn%IfDp{!|#ZN=UnZ!u@-Q$#mv^4uqf~+M;&Ry!~CLnikeoIv$!vGm2uMb0xKHHg>2Fbr+(ErA< zo%vq-*X9RpuBG+OVg&-3A^c|a0qmBupeK}Ns7kn-n-;;nnxCde5vDD!PtkKgD@63* z+apZHPkKkUYn^qqHS!g?V;j_%-?SR-smF-pSWN+b&7Cp*g`?VYpFpeLsX4pyJ3DYY z?;i(k$hzIZqi+>qXGq@6RGQ1~H!Zx5CjhDwK07yBxx?J*uR-0Y18BGv59Bps5D&%Z zLlRM+vuC2=^E}ds26rRE?R1e|mHo|8i$CUfMe$CDV3!)Evk-yt;lhN=hUplWo3Y$e z0*9Rww&SDhO|Ed{PXqB>(md}iCS0^6L}|2|h9?#{=9)6_*pyOiR0>u5TT09ysQ~pV zn!UT~2GEKud3&NzB6FKBQv{lQ0@Fy?Cke`zqk%;5Vu^}0r6w6$84=vgoAqkuK!~?a zBrN4CEm|LQyQ(#D$SC^wwRN`qhNH`;F+B?9e~yn145 ztnIdJvN3v!cRK8^39WWHrJ3%zO-Lg{ea`vQI3Nk1{0|8LcFtG$fD!JPd;rs$=uhz@Q*9f=7p)p`_{#^~oUS>zapS=mHa2#*@TE|>E@&W_ z*m(B}tMPPWD6O1Igvzjn$!uo4021H$$~?%++qbm1)+@DMc7OjQ;7l6J*Hjwn^JuMC zi>QV3SgyU*&vc*g?y=AfJnF+xK$qioR66HFvere?TPiAB4||Tx;jw;ZiN~^LT#!K9 zUH=8uV7|kNyX6z`ml0{n^-}o<-d@kI<`wY--qtzprGp~+eF>SaQ=F$tvGc~~oYx(A zyg?PbhlEzw>{lwNvZ)FU!>6?FH_G{{{x0X6w7oSg9vCbRTW`Bq*GyS(q~lrDKD}F8 z?Da#zO)q4LkO%}tg0Mn|6o+SuSyE8W(gCqv#1g%e!h^1)EzxwH zO`%M$qZDz+Yk=AC*@av>gJ0&^V3a1*xC4RC?YMm5eNImXq@cS!TdQYlNh!MHm#5Pv z4d9?ASrcUAI?tgGl32$$>?qLUH&VP^v_z1nP6r5oLClE4Vd1I9_IXRpQ=X{*p)BYM z0dSK1`O7J~%qX-+sZ~1yzY?5fMD0Yt&yhq@m5evpZ4utv4G}nzm6S{cYyU{rtI^qg zN{AcBE8bN$p3OWnin9b1?~GRMpF3)Zx zVR8mg&oS3@{DaV#J7W_P43q^PFA~_Tc8kpBA)yOwE~V-t=%vE*m&L2D;>cMn1V$q2 zU+q!ADNiu!3}U?5#G;6u9-t$$G{->1v@~xTHY*^5xSejXonG!~6zuWx9!|bn7P$az zXj|bF%2=nxQ$AZSG>RB>1dV4eQ~Ds|q&y}S^S9L^c)Z$@?cjOc%r90MSa~F{JMAud zk4~6Hwy8h%o?hyUFD-6nSJ6?6Ak!bQvrd3X=*vI)a-zRqo8D~90l4XH8ynBIX4ZKM zZfD~b?`qviyGInERMNezVt{|`Em@+2XDd5B?Ed(!92OXfRfF-5dZU5lJd*RnVB3Bhg#nI-8@i$+1@B)KB9^c zbK-je8qgp<@9QX#Xa2x{mFx@E@2kYLUs}*O+7#9;+OA8I_ zXcMTiGLj+2ZZ$~7ozkZQHu)hO9kEQgqaH~INXH<@vKWI~4ltx00D+GH3qcMbB<;@P z;)pjtm(fWWZ(_LYun)g}*BtC@UF(ZIm7!{B#Rc$2OnrU5h{?KqnrOh_pyXBeLqE5C zWSstyj}MVQyK+WQI`g=L7)l#a(<6?)&F8vat!!-+5Mha(R<gwpHafX>xnHf;lKZ!55RMJ1m^-_aJ0&19BEY;r{1{6~8FOPt-O2mwIjimDBQXm>h z5EtVFc~Hce?7Xaw_QYlIV~VZkvNZd%HMC?}ctM>Qv zK^cv;U!pK5wn|A2V;DTBXVOnKqnSz^$Cg$$Q;wh}1NFx2`B-GWY-A8tqxlmI3U1EH zk)KJ^PXzeg2}G{GXvxPd?QKB-=0MbcSL5UtWvy_-BR2QJFyaw%*XQcXx+KbYpGpKql*=OWvBTE$^5Ax=F$Ei!=TTp02ey8^(j){R_n>qKBnL z%1^pbEXnnj&MY-Rr)Uv?C-_RY;|UU#VRV|jORWGUh@Dm~pAOCBQ{9rt5B0j)f!-dm z!~VP$E9exCA)Ux8F)zJR(+O}J?UukFpkz?hsg*fZQ$nZa$5%f$ScC9`1E{U-ul3#A zES620S5Nfx0KMtWCW}L#g$1&`-;s0fhk?}YXH)B`*KPjGtd2XA5hDt~uk+!Q&jnrs ziC$wGo5#IK+A7A2bw)C5=T#D9`JZp>8k~6K*l5`(H;amE)<5V%TsgvJ)J(e%JDU3=GFUv z;4LO_Jt_Nidz#er4x-frYTRil~Y=VOp>Gf{3KPjR16h}M73#9X)PsWV%(o^yR&wI?t{6a5Hs z2vx0h;@>)Rb~ilY}C-VAp`zn?`#}B66OL3E))5bh|O1N8B~igf-lvuQq@$b)@zQjfha8LoWZ=E=dE*k zeO@OHBZ0WL9}1Q;Lj+j(Leb}Th-vBfEQbtI$>_qzbvK{{1T*OuH5_$A0wFJ1-E$qH z4xm(8o)blWgCPH@P{C~Y0B9B*uQLh)fbt2&T#a3v)m&}NFz-7Cq|<7ry)2If^K$uG z54(ojYQ&)lj-rE6zPATNjstJP`AtVeCu`lWlFIdNxKZm+6U4Vsk&)B%gb<#a)xDdBps&>da3~C^Yz{3SccTW(hBa`V4$C0Y+yo+)MR{PA-kQjy7)uv|>M5 zMF;ICyy?e)McMU*Z!p{yDIO+wp^sj=yu9r1Dmxqv+Ecyaf(pj@1*{PuI4caRFmP%P z5HKC1Khu(!mq}uhXW)(qk6FSj4}gB0>;{pdAjOM zRwyCy;)XpDSb%zFmdxDa4@`w&?zh2F52Jgg2Ht?7Sn~W$i9Y$`;lu$vOiUphMs0DG z2Y{23^mg#uy^|G*>hErvx+l`-)*@3WO?O87H-T(hl(I41aEmp7g%jrNxRoZ~A-gqR zAg1$vkE9#)PL&23=wTBB2EC_*qu4(Fpo26erLi$8#ia~r2LJl%+%)k0Nd-ry+fjth zSke&0UHKlI?IPL9}!-Le@RLs$7Pd-zugls&1a#f9Lt+X-di}s z(CSa*lLCT~F;ROa$bTab8c`DQnN)q>_vvd?MfsDC0-RiE!Bj%^fxwnbc-PV|SXKSlB5b63(Ae#630<;N-I%gcN zj){`*sR8{ijlfFD%Pq_onXIpMc-&WyZb6)7L{O!aSOdQPcZrvp&G`mbpjXGYs>ON) z`dkw;r2ar^5k_S-;wt&hn7lJ7^ke62>a>tiR@?KaKT?Ahb~I09BK$#^&|BTNni_@6 zVjS-6y%pP!Xe|M@2B67`&_*Gc(^c=E3n&1;OJvITblda_1YoBR;88NeG9&{^v3jCM zbUb%QvI$w8o;`%e#xa~l-V1H@W8LZ_4_flR9rYx7`0%0sp{HKz9Uv;1^+wK9%E2^=n7qzTCZ z-b4n8NWe?43e3$%0tF?%;s4L(wLJ#9d_tt6w-76}$DB@A&5FUd^mq|j zE@R6313YN)X-%@)6WP&8_Le#!-BF#40hx@`BImD@dh#lcX5*HjNz;fSpE>q@Ms{@j z&OPRdqobdr?x$UHbYA40n|9T<;w_(C<}zc^reAXOwTvNb9tF!eG&E?j;|(^DU#y)y zHLT^Opn+|A5)PY|wyvcGW6dBQKz%y1uFBi0NGCrQpmxn z?7u{jzrjWP3L}@#TO=oZZ~p~_>!QJ+M6U0p8O&f?0=^;O1xv*tXuKj~c~Trf6I!Gkx@1R=Z8)76!#=z99!ch!SqD>mY+Yx5{I8(gq<=gKtP6A5r@m_m_hz7X(9 zuE$ic&FI)WLU@w5$OP7!OA#q4A0L@ePmT4x*N^fbS1I z=bi|9A(24%&tFsPt(HEO*su5FH~1bDx7{G1Jlzcsd*bh>f`;mzJ;YB&_UV?(PF-uf zQp>eFQA<%%J4=R-*lc-8hTv8sk$~Sx(9dw`O^sOpMz+axjX6TuUGBk>8ZXmVyyDY$ zj7Hbfi7lUiH)8&%td|gTb1=<%G7p0qcM%u|@v*U|X#Ji)eA+D(Y#xo>(!8=##pztqlGIPhBWkoxH zvVTgv+P(Q|w(;=@M^|39d;!sAa>-WX4M{Elps&{{7IMqgw|@i5=P>7=)Kp!oQoJGHw_rMUEAkv5WB*HuDPXP&y8NOHES$4p6L-+3Bhg;+nG}&%nXb^UboY# z1xMo)(WK70oMTW*mjNQ-06Rp?G1cCvl6J;q2-Y)zm{=4Sm=L+Qw2|DSVU&6EmIm?{ zvhKfp{J+Ndf4ugxC%0LT>h@B4gH2(SW>N0Y^NR`0OOd%f=GzQ{z>_D%j~jTHh}oipFUKb) z`5!O02{oQl9Le=JdR)X*RdLpOT+|QoLUxT$;Mhko0CjPi4*KYC7yZAi+}|nCL|+R* z35Jq0ZUh(rXMuo)y%FrofNYMg{ z(3mjNgi8b=X-OQ_B5q(?P;Pnbgwc0DCYg~M=>v5IR*N;+gdL!P&BMx zYW$9fd_i_Oy-6EAQy>df&6XpMW#7elJRa+}3M?EOOvG(2GLXsj?D~uCdVc`}u#v$n z7Pw&Wv6hEwPDF^9Wd~~poBuevzYi7YXsB}P{HbWgoE=QP=b%+iYD7l zScAyHKk6Z4$!Dri#!>7~{WmzDP1H-5vIy*TX&`g&ZbAW11sg(?Y zkH(sn04dT7$eQiuTX%<+aywXL0Xga9(N=SS$Fo7&_1 z*4UVGpW+DA6(;+k6Dok>)^-3AsDFNn1FCMGrAVVCD?yGTUDu^DEg6&4p{|EiX(QnhWIK_uKP~jgiOP{Gx#}O{V~nuUY&N^`Xcau zy_)kqK|K|%OdM{nk{$^TDFxH3pEFfm>}7AB{kIby<0DvU;kfcGF=J|G#yE;x4AQ(1CD+-fM+#!2f+cON>NjM*sd1v)%gHaf7i{X`E-G_iul6y(hwu z`%!(tmvVb|?1%Ou!u{%e#(Az9GF5tZmxNwTO8cwL{Ocz~P^cF3JJD`?jjuF?(lckw zY(|Ng@!1L$X5#pM!H)%#-#)V68dZZoX;Q-DFb!iwojutu3bP=nmWrZ7+xmI?(f`%% zv*qW2p(|fldub+-$gj0Fkd!1OlqcAD&=Qzh1faX{=T@Drs=F@`^j;O-??0c=RcM9UceFTXXnZE#{&rG0t=;kEr)d?CQ`G9xM{LKSG1FO4hx$A_f+ z8WlxR2U%^au2xWJeC_jOf*sh+nfeEv@}mn@95QQZHW!{TdDki8;XNqkQ1#@)FEdF~J^Jorqf82IWb zEKJ3)tnN=pn4bdtFD9orS;0of$Q5k$4PL1~?k}qY-A0u_x)*DUSl`7Jzw%<%ZXj~H zVp}{T0E?WDRLF5(CLG`hoxpfwjIdwKIeqlMpx0y#A+%s(=DW#$A>arx8_OqWGasXg z4PMOscU$oHfBXE(t6Zz@t;#e5wPk>3TSs)@t9!9QVE%+Y7$IO94?rT{Eq{Lup>yPeB8&b8o7H5*M;H*gj~p4lF;GwHE-ecA z^^U#mlE}<8-Bidx{?X0(@c;jXzx*H^sSWROb-qU3xCI_1R`2JxkY8^uB7>Djqv(f7 zN42#HfAn8`Pktu+>(_p}2ivlwk2Q+Gz_vX`)c@(&dWBI6GL@{%DXN1F=0l0G-Q32G zgp{c%9hFWYOA1wWn)}K^`fK2FrC@MT`B%6W<{wchUPjmzr&{>^uW9-7p#_^CF-6!l zyV$YAVNgwh>BZbZP2{6h25mfq+S|hB=1lQ_AMZm_@cX*)fzxW>TQjo=BbPhANEF0Y zq#G5eixl8$qW|->Fw=gmG>_hqoFUKXi3t7q)0TN#uoZO4_A)_ib75j8UK~h?4-X4N zq!3M0e24P;4Crfp(ABp%`=IOX-w{F>ev&4ZVKL=oI-MWW)=q&_@cUZ*F@=Advt)6k zw=sEB)q37<-=<5s)z~W3+Q*PMxND+-2b7zI*|-gqRbEm`wi9 zGNSihs^}DE?QNXL)}mYXxExk5urTfR8S+Jbe{e5duu|}8N=KEzL^@sne5c5E_!-!r zrIk;Yrx~^x-Q?(>u>WW;{%?L?4g!bvf|m#sPep?MqKfn-^*K?hwNOp2Xn*j(pK8H= zoEr<%IFq6WoOLj|xx((q-@i`I4g4~8k}FmpEh@0i>tiWIUku+uZBoUh6}d`8gJV&) zU-Uh1Df#EK+bJaIXFcD*BRves5Du4!cxl)pIaPY-ywh$5TMjTZ*hDKqAks14f%dcg zv&vV047wgn^qQs8lPYj+Wy8yG%CDc^ZDgxw1SsWecJ)UyC`;n7{PUnc2tIxI#n@>2 z&hvKA%e&P2&V#4Ok22z!$XhfYFzRP8`zFL?&cqBlPXze8(flz2B3qbEeU9Bh`Uw*< z>bOmVPXi!#T^tTQ4w@npLA*iWIP5qp3;GnPllEL;6?4hS%0Jpf1w^Zw? zlR`BVzkfI&1(fA`laKJDh-8bitIbY-zP+08+L#l!L*k+FPQ!Z1O5Bctvm((6FwxK zkL8!?VPZDM(L?%UNS|oHSd~h`O8A=F!rl>@{y7JKH}rp6G_VVPO%4yVQ?6e*Pjo(x z^FBBZu3mu5(evRpT5_2}`hMl=;G*|Y^VNP2fI9D6wLXH=*ZPJ;!TqX2^*s6JFJJXf zzfnS7Y~Hb7*{rP38l5S`)e+;FLp?$UN;3oeOU7F*;}Kb)@Qliq7M=RZ%?TsQ8E zCEjo3;hL~i^%u+sS4_|tk8B+?&+-16@uqAu9%6zuhmPJs1?aivkiU zU03@9ks$)NoJ7KaO=Z~mH3ir@Q$@CSxnz{G=+*SJ!e$eN^a(skrqpkWZY9PGwanLn z6G;gKZo&evXs5TrliZFZ8tt&Ya~(Ixi=4p8FqM4PCWwX|q<<~b z*hic2{qK(^CwIT(1w?6ibj9>_d)vn?%Xox)aJGmjb+;7MI)(8;vUrpT=mec5jYQZG zC{tIW(MqT5M{X@YH2jrr+M<_>ZPm$@3uVSt*FTp-UV@lMLP`qREa~H9Ht3^c+e2S9 z?FflEN`%C*)8}TPK7{~1At=fV&cVd(y8Xs*&ztS$?8J$MW?LR(51yZOiD7_asxQ%4 zSC0DM78-cqs$QyS6yGJ{d&LtNfF_y}1f{aI7~H?YDnG`X<{0{9c;zdtXK0F=&dgFi zVG5yA2~rAMWQ_091#-@s-Dwsit10`y+}x&dD83a z_0bXrsIb6OCex7Y%d6{>vV~aDY87 z%^K|V1L@F@{_^{3FEH-GeSDIwlv6ruk$X1Alj4!$gV~Bi0Y6qPzzzzzV^NnX%*NEQ z88nHC>W>tt>cED)!0$wU3hAwa_i_Gl?TC0>8n9~xhZ(qAu-x*0I3KB07Zp*PHI zhOuPiA?IMqNYy;tonocJ2#qrTpIz)&#* zE90>J@$DYhc79m~z&902^hIL09dg}nFO0Q2Hm57{?6=3Yz(FEEJY0PXDC(s^QSM?T zJjC#HYb?>yVPgsC#YuwK>6SB&ju)|P=5K*OisNlwQDX#X_PcLd0TF%$lW!dk0L|NLwDh}1k z)UoMQb+soZ?N}`)#moDEe;xs3eWrG!8MJ6>i}qLeEA9Gi@ZCcCT&;nIqK zE%#a4OBI!Zf~=hV0au5FV<t1?XI~5rMnp1=Z#IOfbhO^ncrm?HHH)4SQ3Xx|=kmyDX{GpYe;PR7UaZ$gUGW%mqG=NPqhK3<^9$Se`=+*Lw68ltl z31EHcZWl+X_gc%#wbp#U#{~E*zTKOxIa}ku+ObQ;y5}(b^#>4g5IHv;PWPW1P`h2Y zyA=a8W;z^grxZ<_SJoQNC3>yCj!mE^ku(|sugQAF{iS%WvfX+QuB)B0)qT&V5xaaK z?H?x@)D(9^D*>>w3;-=U&M-DzD^Ii|~Qlg>Cl|==y)I6w0I7N{3GqtETAPvPe5SYmsBZ~e-APoo6;KW&LW zE+elndW^gp)-3&{pwUg($@aBnn3{_pCk9^QBhq-)QE$L4ZM^fSsXzSwyi~6hz9`PQ z9ZRJf$QAFt#NTs1*;qFO4ED1Iv<9#RPKSYR*Ofe0vF%b4&$?;!qkQPbfaadUZWjNp<8(L<+ zYx_LIyX}p%a=QJ#WY+Dt&yf)I(H2v8V|b!x+vmqmaB$YK5K*4OqZnO)8R;Dys&Yz@ z^b7Y`2^HIYS&-^<+{dxXc@8nFFwcc!u)HAHu(Q$ zzCqZ-O!SBC3^TlCj<6fcWghG^CAr@&1!B_oJ_3MYes^uBHz$nB0A85nz;dV8MC(hu9OZ1aI=)kFrU-AWZwT(BPrPCWJM&v_2F{DTXF#ThtAz2Tox z{|~F9FG%#p+rM9~pPG8)t((FVEKGysq7h-Z03X3ueowG6vQ=O`W&+44DAt_srh)eZ zdVPh%qvDB!Ba^OPv84b|*&Ml)k8>({C}_B0d^=?fh!kHrwl=de9P-A)5)&DEq8ZVh zP+>+lmtv#Ac)+S=uXcOK(W~V{GadTqT112rP#q2e3(0Y`?Oqdu94mqw~ba#;_q z&U*l#Lujr*uF`tCJSHMIQ)>C8LE}Vl*m+BnW6b9Oov{ z`8rjVohM^*>Pm7q+!5xs)-$Pwv^AHpuN>tSmYz)&dnC9zjINuH<T5AwE&&>r zGEgQur6N83q|JO7%rRe%^^DD?+DdDF(GMhtdK%8Zlt(|IGI_RTo27Lr$uv|T&$@oh z0_8lKM@ZMtkR;}CTMgJZoF08IG+)HzSiMbn9=nw`c0ZAu<+vJk4aj1uM$u`L#l*zi ztLodw!a3WeOc>bFmo4+SQO8Zw~Uxs=!KFV<(9Jd@}&YK8glcEVq52ONF8-kS(5*AhUey54nE zM6D^zXTMk4^$>%oE_;D|xWvF1WWY;$6JzkYR&fH|1CMS7P??7JL+I6^-?l5Jye8hy zClZ;DUq{Srs{S*$^xOSck6;_t-zXhYMf&OcuWMGk>`6(?uZvcW#EK-Ciut||uB1}i z(hJD-c@rVKv53Q%nZn3F;!La`#`VL__3_B(c`L5Ax2NK94DGu;L0H#UaQtI zdfxpqwk1XF=({=NdN$niotvI*ZW*qOjO*)TvpThXejJJD!nwCYEe}C3TDJT0+~vF^ z)xqPOIgN|3_Y`aODk)BcwNU^K*Rg@s+%e381It&(^)zEvri1&RK?@8-1)?{0rbtKy z1sFnHDg}6NRrFW@_>1n+;19cL%HsRjRG7U4?(q;>e=30xPkL42F{#| zF80ohbx0z=a-+^|!NLenb6bIiXPGD8(o`oLUY>G+l`pFm2|kZQ6c91W12|_K$%5xT zzUbLb_yCJ~!*2PAOtb<;dZpRwIcUWknjK#_~}<_ z>(G=0+8N}F1Miwrn`V_oEv0+=kvccrczx9uQIBmuUL@YlMD-o5Juh10d|P}Dy!yh2 zF8d6do;f*T*MUg#1C>dKW&QkOjh9ErYF3FFIA;ywGTfVQC8QILZZVdgPb88IaW+ld zOS`6kZqs(33vhffar3nIds%V6&_mYn^`8L1zl_$Oue>^8;952oCIC&Jb#s+kwatTQ zr|?^Wk$8)d5mc|B|LD@ZsJq!4p@mOr@(OERH&qe!9mvAJG#PZ@Lb0kp6s=hayLGJD zm+NnENua&^*&(n~3l3P<#?Zj}11N5e`k8J8qIce_KB=%2CKsdFpXPy(PQ1ZL*%$L`faXX1gZoC61 z2DfTo(%@Y0Y%5Hy%j14st zrR=I%Po&hUwP#+;P;hLpW|F5>BPS2$h@9xgz4CtPd8?9{s~=0JUM@FYcvB|XZxF&~ zMMIHb6jIU(hq>09V36BDAI(jXJyaX?t<=)*~qLMYoSBVDWJ<(y%K52yE?A=&B(x>A4HYMvTMii5d zoBY6m3NM`NFRi;PHuJG~sVBM6)l(y*1tevXEfyNJ#)~v)o9-It-rLojl+vabI2UfD z3$Zdn?+m|K&LYEWa?4G}FX) zS)CSMz^GZAOOeCpk!c6B9>4$xf zuxL9e3HvY$!lqLUj9tG3Kc9#*ixpVmtYV-7Zf3me{KGSrdh-bxwc3?!x6O(Eu2$2c zGV6svhA5eYfpTjdr(4_+&yjfLC*3#4I}tsQaEiWkzl-_8$j9!K1?fL8vXZ)snye1; zADv%^I&E}$yKDQ{y6@etdKA_~`yFc@=*Gl!uU&cZN8>@)!{FUcae?2#4ZAn5oK44Q znyvOw5_ab~Mla+(`n&9G!=th-JeOt0vO(|3rXuw{nsYIu8;P_b?QUIaten-amA)@>!@KWpY}7AaLd<3CT-@BI0jZdBIhFZZ(E7gO z$DdjN6r&qxZjp>S^YQ!oveg4zg~zd>p$v9LeZ9G8~j!O)1kGeVtol*DmCissU5iFtVLi$CG*B?=za8K;*SLmgEw`~osnpDQ4 zk!Eh~;SNu%y8F-__RbQDKPdS>J4O6unFRe*?a7^zqY6hlu@Hjd5h;=6efwA*JUevWL^ar4Vw@)zq5JrioQ_7&SDBX{K5c_2O=PKtVOgaZ0cuY8G5i9+{^Iu1^e zE0QkvlA=AcZ%(2##3sLG!SkNZd!FyUY}iSrT-Zj=aJO0jxca0=ftN-BBA#*K4o&UQ1YY0;hz z$R*V5-+E5zmE52%5NzFy7{JG#98aaK*VqP>j2z_br?+z6)f-i~-A+*^niZua3Mhog zC8?xnCe?Y?>^HeOa}GRo80}7s)_E7Xe$@+#tSvIM3$iux-dJwC|2!a8^r=lXWDL?x z^&mL0OHpJ}HsAGi`y)&EZ??>DULWq4;DN-ytqhxwA@F;2&vpOI1brfr1E>@zP^xM@ zGE3g-VdO7c#LIG*mS&Qn-BIRfWg%n{;%PeT4m5H)PUtt&NRgw(+DdPZ&rzI@JUK}_ zYk!G{;_~sGwcH9(EffE1aX*|JttfcDt0XV7Qqi3u0{LM;dWSRc zL8Is}zm5)SwAr)C^ZLDkR-7bHnk0{-(1}w(%?PjCuaWJJDb9fpTDVTjO}+X#v@zi_ zEIyrgW&U*_2PL;P&Rn;5;pxuJaaB=SFD`-BgU^@o+;4r`$8Anqe2%3*)P2O~=98=F z)g2)87poqiwbWty-L!0%ymn_WfnFG4Zj4EWn&mai+ziC9BIcgSP{~K*h%%KZWOUmO zG@Q@$s9WuMNj?`bQz2jitrT(<9hOdZ zyTy+eM~et{wybJG#uG7;u6Xr_1)@&haq%-2$RF(RtJ_XjNooRa3|We_#!!IKbB_FT zJQ7ae$`VW>QJC3?&>C}vYlrX@r@ksihdeX)<_cjk{aNhLk~2K5v^pFRyys9G4F7z; z{!06~!l>S7%#KFG_o!7`z<}_48!I(5ui1*--YHQjU=`Aky|6PeuNwqwJ+s!EXxb7O z2pQZZDXWj0Te&b6>jLn5e4mhugUYq~;f-w!|8B#JtBFEImGZ5mH>oo~%Ph$Gm~DW4 z&+*18m#pz{x`)d*g8#f8d1c40)Q`vARXMiCx=Qv z*%yz0tUF?Rq98JIZGKyBxlu8F*Y4`p=u6RgKT<>OK*sr5q30|m@Zm})(q9>z+h1QD)O3nTXfx6}dmMD|_fa{$%dYoC=A^VF$;&*>!;Q#GygQx>T2W8sZaM#YaFezoo zpimW@;SV3Et%)yXbz;D0ys{rb2SaaJOsSrK4%jN;dUpRIm0Se)%z?C@F2U*Oa#(2M zp2}LLhE-YXX>F@(t)7;m+QGO04TTw0npUEQmgW*T%E;bGI~$oYOw3gVo3%hiwP&da z2Ofp$Vn)Y1P`yOT4`pmIPsiiXxlXNm*A~HH_8vorTB|-cZ=tW#wKNO@40Hf-o1F91 zH`>+F%3X`j9f1)373=8aD6aL1q`7&g8$%cwZs7(#mRNZPN|YlbD{u;0swdWIdHJ63 zU#wtPZl&$<0EEMp(Ox?XxD$l}vmRSJgt<-HuEjS>Rbvvg7l2yW1+QOml8_zj`V|6v#cuPZETa>cUezO{cmas#D3gyNUc4%gsK#fwAF*UtPe6!1ILsU1M z_Uqh-R;miXJW=dZrgYykA?NW_%swAjV0MevnygB)=PwJ~Tn>cjByHABZ@V+C zhm4ZWu19K{{Bh!eGcjmZtd8|2FTe46$?gny&*!`&ZpNx<1dXG}8krXARE2c1btiGO z{T=nC)lS?kL%898fU_~u1@i&tBEY|^OVJQOz|C!fHzJ-nv5}Dy&zLbVdL9cBUEXJp zR}J`}e`3g`e-H8Ls_v3O7V}N6*=t;&094s}Qp<5Y^SMb1 zU(r%FtG9Q#)M{5oJb$DFwXf>ou;17z zYAu;}nZZ9RK+DT(-R4$IzY?34O*r%0Dw-e!;KuY;eH5*VwtBe$Qt9aYGJa0}}p~5BGW4t?pn%4Zy9oar4_6OIe zKi8cx|2Rf#wWZOsVgfqDw7xhmAiI3iYrpFlMMhR0O4!RZhm7O4Y8)tl^U&_r#Oc#< z{cs-2+U5N@&+{XjMC1unJTrd6Eb-|=t)nI6fm{DImiHG}DskO)S<@LlSP*+Rw$3~+ z?f-J50gZ(k5As4FQ8%@TA>FHuPH|T(>!o4$q)zD@rlw9h^EHsBT(!oDf{|{Bkxi8I zP!#ER4pM|N^;H~KnfS!xo%`F`5A%_5Bk&(7!>)sh>6AA!j~s^stU~V29~bqp9lU>c zcW=0S(_g#iR9bzS;Q}}nws4Oev|vl$k3?ZLf07sEyzQVBVK7`ghNYrq>A{d=aqHBg z^pLgr|8e%-;c#wy|M1@FAtH$&dMZ((L?=p=5JrpMJJCB~3=u6P(R+>Fg6L(G=maBr zC+c7@7z{>v*X*;;InO!I+4-I4y{`Nb;~I0%z1F?H?Ne^jOlUIby3Ob#V%y~smMLxb ziRk~H01SLfxrBAJ5)XM1e{pkbILd97<9TlMDNnakywj;%yS?>q;zFH_^wMs<6}}tW z<$ecMv#ezpp9xd-({0I?Jj$7V#wvsK$)!-;4O!cNtTs6rSnaAdH$87NTepeT$_OK% zIJ2=vgc^MbI_QFQ7PxmcBAZr@VrrYh=uNA^oCXGFo##uU9mJ#D1N)ZRi1h)vBb_(l zHY1B}Gcm&=CqHe|&4nqkeNJE5&ED~Qb3JQz*RybXSJNPh75U-Ft8ANUl|y%WgnB{2 zyG(?&)x*g9%jjxoG_~Gzn=)la-Gc1aa@YNJGIy5+jB1rBzK`qoIfw;0WIM*IQ4XBp zD+Zr;H-0dwAEjOjxxzr^$A^5MEvj^#UO=47+$6Ib&^0mEmDg(yHy5i;Y;#&#QXFLn zEq;7W%X_hM!r5G!^+EEy#U>*N&bD+AcBLx8-V2RK`T~mPHf<7xNx6otRz)-qwKV(V zUDpqEcN@XLv=cp9`4Y#82m_Ok(qYsTDM|8%xP|)X&j>l*GdZrXN*IpEeIuGYSsZzo z-?Fy0RVx5HY(wH}!R4Az+s`dbvPtjvg@kgPPV2&2*bl9hwG+7}?+76C7(?zi2nRk17A z`vpeV>t0|^`8%#HamQh#T3Twd6;sq}75+GMFKcb;d}vtS*Qx$vP(pE}6IkiJw?sY# zcke~PMsS77pu3K)!Fo}7&VFsW5ZqyUIk=uRg7;U)ZaID~O3FBV`~6E9NTyLbykl%G zv3KhurOX#yc;$+{9UlEE`ka9J=`abH03Ay4l{gng_Yv&W@{t2HH2xHhR@Y|$q^Owl zm#=qnW~6i$Fg`CXw#i4jtT|_wi<~$Ig|eArp$@xcmG9D>!VJ!F)Y^d3zI1zgrw>P0 zN}3ewjs2AQP$9BWZ%SVv?pvn3K;1^VKjE_$l-!L_`O^P66v4+(MUB3$>t{^<9aSQ1vW{XO%K%t~N`cvydu93oPv z3l9O-aN~~FV`0#5Rod9HrDMXQF&hRsYBrIxI<5O4|83a!^Y+YB$_V&ayV_yXtXPC-u5(_(yfkKgn9`2fk$0i?s8Xhi`?lHBE_N z_xn?bmyi3mw%n%Og^Hb14T{(l&j`w=U{7j<$dm3R3=W1SphXmd8;%mo(W^DiOkWJ< zeTjuEr3epJbLf_)-RO_tkUx&gzgTe5FnsZ49T|34b2*i4+TgKyDk8!{EQp@y;c$U^ z&a3oLB0Iow_<5n+GF^?IGf#pf_pz=$!!qQG#9e$kg~T=}*18CGSIP$-45xXW$O%kg zijoEE@^kqoS3&=@Kux!tG8H{^^2KS94T-J%AaZO_#Gx$k8+Kmhz7w$~3K}AarnM-ZbxX9LAbp&h@tlh&b2aKIET07o7SN_+ zOp#!UP}x0Ntjz!nBq}iEyQ|Cqm{x_6|H0mY@Md{z8UP1;?>H{bXtc8j>XSMkxcBm0 zK_+>FDV-^p)}4*D;M(%u#)5IM!n6HcbJNeR?mXKK+%nic!QS7Tr#N0kpB#D!jt+HfnJD&0#3HMxh@7{V~eqC4^e4O(G|jZ}^tWK}~?!n-}=_{F(hCpnKd0V5Ueu zfT?9Ff?T=n;*$k2ZsZ@n;RZMffjhGgMAA&{m-l?AFKW8j-`!PTV4% z*#w)r{Ok5uvjqo#)2?!1bskKPfoM-IDQvOoDDl#Z;s&#@y!(`Ffb|xUbBc|dW*FGN zxL~EQcr<@%P0JO{#jKit+g^J5&p0j6d&hnDe0IX?M~5y8mneAm<;+V)t=O@BR)LQj zuPz^ld-&n%2C^?X!F)EoKQGxfPo)rgpl#1^)31OPCBMh+dzfvpR!wsm{L=hoJ+CZS zB_AOSpm~mYaw?;N0%aGQNU;M?_uih5w~$dvj;Sdis_h^q7o4Wm)GO`019YDLd@WX0;IxI_#wek|mqOgfx!A$@DdedAjJnx@9*wJpccs;E?Wd&itO6n^osfr$9_;X<6C1>3 zLL_@?V#zvE`!~jclRfJ2UFGT7=~KmH-;Er~ulbr~F)80?=!n8BFAf07iMUg>?f^3d z8)yQN#41mN;gs|Q`N!gvL7~+fD9WSZzA(;1y~wg>RrsUmB{Ui3_^zXdsGny2#3_Vg zWAq=b8>_$P6g)i}HJ>MIQu~isCN0km!`;v^V1N-P^4`k2K_sdy?F~cR259$V!TH?K z;T75sV~G1!p=>b%BWl2;T_RyypHvV?9dDy;7iz6XJGlP}`_gn3PZk*l+zrEHKsl0k za|mz{PV<5>nlsh0;}d;_AVEN>1vs(xBz~(Azx8;nNrLFHuFGBpk6)a23)dJg z(1oCS>TKt>AXg>h8}MoBgJX~PQI{0Y)(SkmF;8si!cLM)18H7Ta1i2XN)Nj+X;naE z`BNbWKg_wS+*Jf-QTz31^1^d@_Zoo4$s1M3&_=U`y6tnC!q;y;<;5Vcm90ac9O*GD z$a|Tme*yC^>H_X(`S*T+@?=>9srNYzVKF!p2@>-fa#?nyf`W)8lQx1Unj_YIBT*Zk zMC61|78_F@fS>}woj<%hsNnK?4zw8W?Lnfe>asy<{u*5dh5xZ`I2}Ztph~U?x{>dQ zAEiSMlR=&wq*fZ2RE&an3OsE`BqRe~BZ<}L`&;uto_I}+wmCz-sB)1SW4s`jq zkEraz!JX*V!vu2liST~M+Sf__VqSgYq7i@G9R`Pph-az*HhP6#;DjFYWBiCyJbPQ$Oc5ry@$%d7~uqlARRCbXtNQ zc%K-(!imnj+{c z1>(x&na_D0oa*q`i(lr)H(F|cGP8YhRhyJ?OsgzNyIMSDAjTrl%kI6pQ>gGwp+yS0 zyJC?~RY^WeSIujy!1X3gDr*i0_NJQ1iYoLtM(c?7RbFH)B(RN*m4^sN7^f--QTZDTnhm3{Ozmq6Ar%dh_M zL?!fQ5y(7LLW}R!6SCF)fiKYR;sjh0awvVF!C_XON=>uM<}NROgjC$?U%+Uwh5zP#}HN3BP1=i-n7!VP2}fj74DtXlqIR^6*tX@6ep)2(2rrH z=EGC_=0vfx_0N)!?-HvkDI#hj4{2Ya{XA~j1r*L&rI=I6NvaoS;$ktlI5fxf`tqhh zx(5-!-RIfmBP`n{OX!n4z>EfKc!CJL1u}-*2bztS@ZdCs z>pUNN<6Lu;g=qwNt7l)DeGt&i^Ll+R~9{mCaOU zo(hNfIdd~pnFI<)jX?d8v^Y$Hvqmq#08V_H1j;^3*x4#5(dDGkQ%Y8jRpN2O{lU*V zn%y);rAx1Y>1e`7N{ZTh4xUW`h1o^NSky;C$SUK^KhHeR%F;Js8wXlD<7-o zt1VEszgezZ3hGRLYhm&x`S5bKF((P|gzL1}pj~_eWt=#zk2j|+%&zR3?^wSANRz(v z{x#3PB8f*I3?Nm%j*^>US|)lambFrqLQjx$)Ez&9s|AjoydXjzDa=C9WCj71@=K$5 z2p(O|T-;ye_n@8L8YTMWGD)OdTkA`^MmhHW)xB#=>wmwoX-OZNb$?Qd-Fys2A&L|2 zmH5)mkf7XpT&t*dSpa%9a@Jj2?QB=vQ13eOx{_$1s0jLaX6G=6uG=o#vH+cVZw=r% z#LES;FMS0Frbn}KI~(w$n$CF!$-B2fqa^Kh2_O{Ry^-)% zZ5qC_W+lly)hjI*vxgc9aQ&^4mFsr~l{KBW*Q4wDj<;U|%D_;edS6{kS-~#xtM-Py zTA&v>I?gq#f0>wq6%U|{W>)L$po4{>kqZ}ou^oc{fIZWq&}9*~NUqY?3f6HZIROx< z&5{IGU>U5F&%0Yc^dVMl5|PqezxxebbkRciib?4SM=b9{B-bBpP-_krtkbc5p& z1(!D>HS_~Ged}Hy!Cer^UN3XRK-(e=XrIqNDwD3^VH|W|@5=J~M zI@%(@8Bs2t13J8)z6bFKX#f_~;lt03Nh4>a;z3zGPPr<=$w4jmZ@|DR_VX^i|LfcR z53)_0!rd5wrKO6iu;AXE#)V$@szjlH823fBs)w zw*TKz>^#Q2Eh_l7a9R>!8p=WDZxT>i&Tr3r@v9gbR?~*2Pt26F`_yfv|Y##xnoyFMVDCk^(FqSU=`ppauUvN`L$Y ze|+Zee~emN=eZ)$yqc1*hY_h0|xBmd(Z?Qg&R{E!fzgD(dycWZqacgeiicn$GiXdi&549bG1Kysoj#bP)_Wf2>{Ry z=G=m?jO!+k{NJv{4{V7G-Orp}lzyb*4G9jq*uTnm`TxB={yB3N?ZTJ1Mq*-CP$%VH zMFdHEC_|ivBV6Fge?h(a=dFHx|358=34THTZPxt=4j=p# zI{2R-|L6aFj>*86Nmu4@2%z}x4mQ~Z5)8b>!SnyU$^Ut+c+wCGl=?!O#`V}_(-?@{FT32k$#f9aR=t?4$Xd7!HGLs!FTIiKj~xDqIV{0xoa*zs>N}Sm`}oV)e2v# z@*68^2Qf!;My;%8&b1cnp9Opmx_+hjKi}T}a0!dP;7D0FFe=T9<6GURx=Oz+PPY(t z#qUX&YW7Fz!t7TyuIKXpcm$YJY??$Y^M&{D+DL!$bCozs-ec8Si!TsT z3&k*!i|htaKP9~ZIw27xTFI=v@crv~ZH+9)qOM;~^lGtmOr{InT?y!v=t#JSx@M0+ z%%fCc4w1}-QjY)f4gmq9J1574cx@zTzXja&`z*RH;|=%cIQ=JJ#e#!4UqwD*medM115fq=`MOP^VE$SRaM_Hy3X5VqU_bdvB5RqhRkKGUZGEu9qcWP7! z$Hylm<_noz?Z$D5R!kH;G3U5fX%~7tdHxUBg0QJ-Ts!546(YuU{N}#Pt zevD|d@76#ymbiLj3S{Tw^h>FKq3HDUB7p3@DL5W`3a0m0uL6+{1}paPv?NT%hZFZ6 zR1wuf0Gl~;^08vYYY07iqv&;dNFFcf76M?2y%jtHWurPyg-Jlpe&2wCV%4#OCd&L% zi1qEzS2^+J&(H+!ukH2S(a{X1pqAWeJUdZ1+TXBJ*jYX%+Ud;}a&0gkq;!OhX1jU; zR+r=130Ahz>twN1do#MDy)UAd*{nN0c6g_@nuWwu=Xj*baSJQ1*L_m&zM2)A<-985 z8-7~3t-Iewp4u&lu3Lat|Ck-kRT8I#t~*fO-L8)VS~y)rU&XCU|iRRUV7}WKLQGXQ6BUV1{hl@q-w@PmaE!PC;+F)4?A*>=S8>ZRD~`@$LhMqU!&sD0m`sUKu|eG z4@kzY)DsK~M>O2FJtNwq{4lWJfW?0EIWM`oLvW&%bQ%>O&sa6RU-fp>*I1MinB4zW z#Ca?F@e1H<(thXXcCUrRiMF+RZtPQDsQdYD#yv&cyQ|))jetVv=rA`Ra|+ql*$K$^ zM@aW4){0-xWl>gzZ~AVA-!xZ=R@UaJVh~yQ$Y}z&vaVh;3XR>nXswR5OoU5N&$ysI9Q^=+Z-EeW- z8&;qE=Gf@v{fSKT+d_3}wAMv?0KNIW>eC)6vCwWpvLGgA_UJ^FT#q&_Cgnr z98ryFdQuMKGuTtISQKk6>RP49MMuz!S68&LM<_=Xwbjt;{i3}1yog_{qPRGa?A#*h z0Nh_MR~t8W_BhOIX=&yhNoJNsVUea*gH6#UJLN1JVvAY3+^OlZc%7+&f@44ras<4* zZqB}E#%#;=c9oquR<2`*jpg~wu@!a(NEa%i#R}VLtq746wm$C$rG{h&_iaun8@ zi*!PG@-ftV+I;phMlvv$MLYZBX!cdJb!@;V%Aia6fSt%$>~dswh@I^=PlY8IyL+)! zpX>`}0(p4XJBvV5fvID4$}o}6`$&oBthTF6?vQ|V(T_wvEE2$*)KrEHwtz;!?SrpL z<|*#kIjKAZ#Qe>sgq)ZloTze3i zo-WY2Oc|tg*e1I1j1}$MX zk2F1i3c=zBwuUQjikkJp>0q1*HcV@yIX1l;lujtwrU38srByGrTaX@I)t1e*y;Gn% zBgNAJ@!(lX@aEdh3A6S6{jQg&hBD zub82=gC?My&@Kynl}-CL%MEzUseTceuPD7WxKB!A6PpJ#2;b{6?DkGKiB4+=)(w9R z3s45)0p@2`!2_a+8_@J~)jTWPrkc4L&G`i}%4814ZHf4UURS{>OfWIM>`?&Q zLy)|gPz#Vnce}l_)r#K=W@Zij&XM5|R_B$setohhj-%z$nP=am_qX3DYy*~tn8MKw zxS}WbP;fa14{yNV?-as*EZ+dbjZmQNv2-U!^?W>FyjPW547T%ZVERO2fk*|Dd@oD6 zRc~S6s(m$h7&-g)OH0jqDcyhi;Ff?#nck?!oIm+@zmqp&<~)I+(G2%f9i z%Q9#Y=^t^@F3WTFqD>r+JBbj_J^bGv-rr5m`AcLIiNz3bX| zS*)h83eY9l&@766Q+_`bJydR?Y%$wVPn4lrq|>G*fLl&91w=5dpTM`UZvEilX+Fi=y~ommSTra9W?{#9bbVw3iVUT z{VZ@}XD?vd^(>mMfdL+i_{5~n*VGEyr1AP5u3?e#mbUpA)hIwKS61ET?7wSj8+qws zVw`Xe%ov}+xNc|xv!v`%RxKh$aTkVE&)`C`ykVs9!ChQgsSAn+gx6tP^!3RL1oUeG zZ1uaPTtHU2fj63t8?r2DL1*hdVeu-t*n)AGTd86}{ zLuv86HWLp49WM%ORRs3cQX9E`Y2PL8LqK1S05%58V=u^6cvKxz+>a=+2r2^P0^f^h6!88$SEgqO< z*y{rETDNO%B3O>87iqh^Sg)G#OM}Q=_dHT57Y`77&Iu3F;?Twe&3^q=*5gKj?_8={ z;@$Ms^)|Nm2GPWT9~chi90_X$BEiD?F0bDtHyrPDzddmU3e7<1=Hhsr`-h$sp>9vF zj7i=Wi^Q_fMs@E|Bnx2$@sVIdqv_EU|3>-#K&wi_vzYLER1p7#Jms7>Ux0|oV*sY! zU0>4)#bIb5`a48tuj8s^M~epLqsaC{@9c(>b18lyRe&*gBc1IsexG12>OA%0w3~UR z{b=Om%a8$3y?4seZ}i&7(9!85_J?bnkOxAkxUrgEIL_HNl^e?;=6<^3B|n*rn*}Zj z7|j*SiGFF|g!$S_{^)z1?bnzETq$lIM;1mdpin=Z2QWV*UL(SYv+7B2|6NFw> z`4xUoTqLdzQ76)2kOD=V9<5a(P|(lNMuQ33wTkLceHA3WUNFvKeO2h;!VfICuQIUm zhz!!~Lu;14TRq-}YgZU3xb%$9I z=uFjpt{z}0X<4kgiLqjLSRX5SYCXmt6dH=1kZ%D9bD{5-nvzIEg^#>>qB7Ckki5~& zl%xIn&I=Bw%bJ<0qg*U$k(U_DDZ4D_e=MbxYneDYmQrk%CtgLE5WhSI=k3^yXeeAG z!R<21Nd<0kK|51>gzXg*s(PJOSJf=mlC7f^T5W3Hn0^CNw>u!a1Q`81_i};}rsJbM zJrKNZOSa6EF+kvcx}>ugJFX=;dErej+ORB_`boGG(%aZmQNn-vZzs@q{|jKNEk ze55_8LmnSpqu}4s!|9!Wtss0T(kI}}iKuZ&ZoIqu%_ny9w@5T>sBa6XdiN?WC_ssR z-=J0~xDY}k_yW+W=^3>vzl`Pqwd;p$bzAS$`B2SHfi{_p7vQHJ*EPhb{}EAJQ{&0m{14S`XuE`OQY4WFm`cfbQU&vqcWhx z#lxycJHn`e4xSo~uE!RgxM%9slS~Cxw1iq2xPVBl*X`?0BCmgS?=WL@u3Q&=CWwYa z+!GJ*@X8+8JK_xU;;FJdk=ul$Q`6^|vE?wFD`)EwrqrknyV;g<$dGc73JixviW<*O z*Kfd`rV+C~v% z-%5fG5H#D>@5K;}z+>UalWBc(7~cj_MWF|)8&v#II3E|V;}qpYi!FN@ItMvTA*p38 zK5?e<4rzLZb=FUAJ`}zwGbvsZv(C&!t6y>JY?VeJUSvJbmg%k~-?kN|gKH+51PlS$ zXatfiytAj^ZlRuV>mX`DvgEb3Hu0c>ze~3M@0<(Z9tobts@WG3oI)reLl$P1r8KLN z21Z-1_v}`$Us^->ybG$`>|#jWxmKLt;-G8Ggy9>k$Ie*gQ}5f)9Koh5tYU%s#aRhy zX%Z0t{TPhRwFKHMahliTTtN82r`zu548kvvaC>GB?;OifUjJbqN%Hj}=x()1cAy*4cF1vDR2wDyereFkZ`eit4 zFXI}YAxunSCT2@-C z9DTXV!;@St+o3V1vxB*O<3*yAqynt&zJeiT~4}5+Ob1GUFO;($(J6ukzD;ggk z-I$;GrvI}O#7y&#DQHlc@5g5h6YV(_rO}-B;Jd;W{%c^;I_X~ccJ;WV9jHDop5o3ds`gHH5Sea}rK$W%88e{et-Fz= zJnQFJOmGB+cWap-oh4lEa!!-d@DRu~+qx!Y46wPXlB9`{*XMq2?Z?{2s z_g%&A9qwP%MM6%gecd-# zPv<;SuT*R_>3tYXncvNyJ?mTfp_!kMzi_#Ct7mr1eqL$v0xTxgP%J3A=W8DhLV9dx z{g@+zk2}=rPvzYI-F&>FB>Le!5uKOswAK1pmGySo4dSNdn}1fh&tSncE@1{n7m^u^ zb@4?IPnE&E&4U-6{@M2aTYdkZw5-poYF?TsJR@ydH@I3Y-&tNp|la4OQ~pyD+Q2gW3vJNKA{_=cGrdsT(`t;O(NqK*U1SHa8MlHOfsL&_QJH7-{+$@T8o zv}D#6TrUC8SmMsSoD|E@%oeyp5?>PnoDIB`r}!_t{-fzgZ!*K|DBp&L-!Zd8VCtlK z!)|WOlFIpeLEp4fpETZVV_FSY6Tk~35AW;4xM!~g!pB*OcOOmd9~^z+P~CEVuZPVX zW@f8dyaksQk!n!gpYgEzNHn#E4QM>sP=hBsO}*ajwXb?a&;EBUfXQWBUvym~$|+{G zGHv(ytTBAnO8>0!3>QjNwECk<%LPI4U8hCRqi;_&$KYL%t2pLSRl}lf;H8Uu&>dhB zXXG~gdH7@*>2rbeOSyc*uzWHMhEALw^Xvzus8PCYj?ajag3uDhh(@Y=)ih6YKphvg zdk0O`W$rIde5n=osUjZJ@{=xl-ogWDsUwWPyp~HTFyeF7YkV!K49Gi~_nI#EVpdxt z(mT`Z3@q=XB7KTC)+qeH~n$2`$LtNot_|g+O{h`t|Dn5d`jX& zN0$j?<@l6xLbMqBk0CX7vvg?^7|a8bzv|D6c9H$PAwSt!t}D2NcAHUJq&xptlk|I`oCv-a3~0U2G)WMv(Q^7z zK%B+=C=vbnR?O-}yR}+G48oY6vdV;T_`qzk+l)nXAaYW)GuiEQI=~^BrXqj&?eFKU zt6Q(W<3l;(E>_ttT&F)3fg*pORT)0r&dKt9I$284Ib-_$Mp)WA?U-v9l}sL&UNGgq zb6+{$wA+^O=>>srd+N`Xvfp0moPiFOS}^W3L6N>h-cc5wS2h|qG#flGmVHRiM=m&*bZE9VpMw+{$Cp_t-M@fhI}|ys z7U8y;Pzg5RYpazBFETQC&OvDNOh{-IG^)erMP1)~QOUbiVr9|?JVKRoLQinSp8-p- zv!?OLlDcGUy!I>SUBQrKa)iS)ypc_zpkgcX{rfBN2+c_}kZ;WNIyvfMD*SEuwMYi8 z_lkB!$l^YA)dJLZFuO0&e^IAnQ@u|86lYg#(sGU$W#lZRVi~fF) z=pwffiw4k}l0EhbC4|p`IHn-1woq$iN2!~5t+k!5{y>Gs&B2U#B2G-L>_#k&)*mTV*Gnf7;L(>ZQL0=Kq6 z!j8*Y|HAnX+?5uCYSk4k;WmLpR0)d$%!U~is9aZh^I}!4hK{Y~q)!Tka`4!XI?5@N zD=w-WTX!lq?Iw6w@@cs2@A6hXmf=EJ&3V7sF~4C`;sX2hWpqW0pLRnlsV1;ytt`+e z-7WP;d(JdTJ~5q*gNn_1eIO+))!ua@q&0oQWF(`iig@^ou9W8tLfp;obF8fV+*;4s z_cx2uq`SWvre6idM)KB_^~zn>MV?*fsG)GA>c&_ zHLIdIH*PF<7`K0XRC&$JhXroyVE8+&_hH`>kS7$|-SNFKd6MdBiw>=4tFB2^vo^M) z7Vh8xt^9VDv5Mi8>F<_9Zz3juStAhMjXr1KRi8V*t`&8q=}7i8DDr~r94lxPbClhY z?lnYpHkSd`$v_YZgCCVPopx_Tp}Nx~RSuAB9QvZ^#HhDEv`W+UywIQFj)3!(6CApc z%!vd3^{YK&Hr})fhz%>I@J{rtcqyZt0t&UH9ij3Sgk)kn>iX`{`2^|+pf8(e>25;) zC7QYMf!XILFGe$#I^I3iW~>{(7`b3X4rwsU{|bF17+8v))j*EOFnvbg%}mz)LVMb6ie&)Qz7jaN&2&3) zRF3<{A6p-|N~V_>)4^E_ygZY5?HVAcIw;mQzFik8k1h!xO;}r4KM6#R>Uqy}9}8zZ zValpWc_YVP?|=h0fJZWDn<8aNOhH$yzmPGJo1wFZa~WS>0TD4HcfQyyHt1qd$?p!+cC^S6j`||Rdne# zDqMDs!}*$Yon+t4l=OnQ`rx7VHY*8(024%~+CKdD`JLL$X?PC&l8A`N>cbqD<;8$? z6V~@7{Ah8P@U}Kkn#;&YRZ< zmUC<^@YqaTk*Y2#^$3=h>cN_^em{vAB=O$qGSKYsw*F-0m)c(u@7wSGnLIUrVHvUh zJbA8H_4u@VegFs--4cAiM!J+AL)k2$jZz%#o%mgu<7)-o?ggm{sHusGpL8r-)Gq$% zw9whtw{68Nw`7a%j5CMg_}tFsG$OR&x9E3}w_QU<$mG?5|2n&-=@ZD}?ftsIam|E_ z!&*uu36X*V&_W1oU|FbL+SAfzqJH<_2)x;Is;>r>Pkz2wQd@Yn>Q9jaHR8LIW#!1=Dz z*G4O)Oo(G#SKbkx>zSYllC0?Jk-9>{i5V7Ozx%Jgb^rFGrq5eAAqg|#V5Y>jzDg@o z+C5)(4pnTq+MQ04aT0pVWJ3Pr`9!;hdsE|<8rAm%ZhcYP%}7pdV+Y(@$WuQa|9h!P z9L54CV1t-Q#C0;t@V8|$iJTtz9+W!AcvuQEDP2^rE@0>QG3wjCw<$XA=d}1mB=l8C z_Vg18J2Q>z&wjE6p}!=`!crKeh;PvjAUR_PT*yr=omAqgjoRE=n}wtZ;O!N5XW2Ct ztl>sQQlTj-jexpy%AR_I*vQy8^S#x{(cXmR9Kl$up2zB=+DAGD0?x1P970lGxA9nw zd`SZh;)fP3q~F_sU5t;k?`aAI-DQ!(?{5VJP+5-Hk%`R?(QQHQe&0aSxYDC#4eKh_ zn7FmCbz!fOVXXqu{3C>BR%YZx$?jT_veOy;KyjcSq~E4JFH`eMm%sk(u|QP?*~V`k z?+7wZRFWpPZG=WPd58NbDlMlL_meEmQDc=hf+gyLokCt>)itokt;qb`>LDkn)P@K3 zT!*oPmNQw;BH89k?J8SRG;>C#@_j*iM||%D;?0u!UZk>J)j^;|VNc0;QqXeLtTAl#nxa zIG+D-Qw5ORO6AS1`=v1wx^B>QuHGf_VI(gDT4aj924$xbcQ9eqn+v?oJ5iwpFwJxi&~<{(MS2!$(qF=7HG+BH$IttuwK7!Gu@)IJucq#^gg7#L+O(hT1dq~ z*=B>LaF!uS6HYm*$C58+CUigA$*kV-J=K56JN{{qewX>?TXqf&Jw%1oeSdkwo75!A zPEO1vVF@iU>?KBRG6TsUY22%mgrG03RCq`~zW^u9FYf^9M-{}apnXt~mhY>6@X0~a z-mypC){J+fV1@Oe#@AeG^KxMGogUk`H5}vGY`U#GSD6beuNEwTeQjm~aDaWH9Z}o! zRWx8wsGy>@fV~7FEJAs_iMoAj`|{G88n&e?ESZXw0y8zP;hU#?{zp|%p9X>tpBF}V zbqSMcrj!ilfwgE>+0U7?{Q<3e7s}P==jSD4YLZ_j*e5iDk&EKR@b+QNjY`Ak z(qJ_81m?0`398I3cC>lNyQ)G$nC)dBGETguzlXau6b)R?WU!mfV! zd38I{J$b|KdA$&SnlqIW?xNs93a|XoGAreh6`H;I!Gf~Qf~w1fldn??cH8!6a&D`u z1GUIm@^S~p@aQLo_p64Tbc{P%92OvmPz-rbPHv|(;mxW-I+Cq7Op+TwbbkeOHRhS% zlDcjWpl#zg;>!_Jd%R4L zpQAqO{){*&DymL_uhdof;l8nw&C`Yc?nGrikw??d(ZO^z8)FS}tQoG!wNc{7Z&sFj zsdoDi8&O-oF(z{^>`C_g+X?+|KgI{*4{TpwxxA!|jQg)0-thSa<<+%LaFBjUq!HPM31ZU^P3`>MiU z-)+{DGjIplXSeO~lV^Xvq$+lOPuZyet7&C;AMWV7Ii<-%CF~h@C`FJzOJ!I0GFiYS zLSfG@h~?=>_O9B=0q2!sWmI(@Vq72}WouH*2R)m+6R}{X631tb&|v~9J`uOSh4ggU z>=vndGm8uBtbE{2 z|AkQ^$i4OC2r(_V8+zl>P9v&%E40ayz`+PXEtd3H_<@W=`hnXOf-7%<@$)bKiLTwS zcQZ_vS)!(?q0CECHvb?*JFIo*0CXtd-!700-? zgIdo6_(@0xukDjDdQYpx9f*kXGjV^`DuzqP@p<1Cs`J!IbL&#l?E@_50V=!lGXCs+ z!k_$3%ReS6Vv2&2Y8~+oOm$^2+^iAXlUU>J(XVm{oMW4JC?~Z z+bzT*QP3?Pdzkylp4x=%P6-GK#KJ4jL5Cw2rjdyQ^NvoH?9`hY`^JWom5bXA?QQ%W5|daqsS!h2NV^FAPdZY2%|@@}8-8*zp@+mdg2`MC zw@6|0S2c4OAd4zn>rvmYJ4`fVKLXl*XZ|BuvPAT(P7`)QCYtGGhlvf{1E}O=M?8+W zFOiz}L38V^M>6mGbT}8GKcW~Tp9n+wpE6YS!_|^l1%+mf`B+tV=NFtjo>h#3x8zi& za*nF9T_UX#$mcmuy66YPc|8_3pH<6Qa%curoR@r&9fUbrWHUQZ^4P_qVjf$m(SnVI z9?-t2AQPISOGT!;5j*Xd1%~4;^w}^sEdCi*J~b%t!T$^@*3*;L!%meIV4^f1 zS+VxsTj7YrTW^+8GAL9x%w1l8c3tH|GKtgT4H1K&EZy}azz(3CGl2YO*W-U!Kifmk zZL&g4IwXj<^__<-w_z5KL288|HGFanV#`X#~J%Adu;v10YTksL6*m`Zw) zfI8@YMJ8%_F-WIR@+y9i%AmZEuhN@cmfbK>qf!szU7kI^<&Ra8ouT*7NU6+2JZ(l4 zR^)`Q7QLMNvh1o7*BPS4a@-loKn(KMP_KhI==MdAOlP#!*w?fh-zvjHf}d@koy_*V zGUyJC-ild3?gQ9SBqX-yx>Rw)4#7qBqMlwq?NRF^0I*v!J{_!cCp1c9BX=djVfu(1 zi%x){g}|v}oa84RPzWom@-TtKTv)il2u+^(-Dv%LbU~*OLaZcIc#VOkAJ|{Y;&p8V z?-R{b&3Z8>i;eq-4MN;Jaw0XyjGsW9U7u7oESmp*6Hd&bO!lBy7ao(Ik+Ede2o&F% zhs!@L_M}5X;@f(3G`5}@wZ=C8Uh&bBmWoOoXg@^U|5%`2{QU@&!%6^yxFqB|%H_I# zCq7uy^@jHwgl3sp_k&P68k$G1^iLmOq?1eFx@l{LmT}{2Aoc{KeMiqtE2}4#I>KvL znLh4w*3Nz`T{_qRVeTunpli~UtS6nh+ay4~5DHUeDc=-?l*T1W`sjFpc3lFOMY?B? z_s61+n_j>m##b07oC!L;<2t4%DQWU!l%rQfGX6b#(-290kaR9O4h?Mb29gi@GbFZK z-bJ*c-Hx@k0Jv2q?zJ5of9Z8?qo-!Q*y|1QEPUg4bwc=Iwm#=BE}nw6PMo{DN3(=* zmx#d?Lc&O_#Y{2YNQE`^xS=m^9q#5m`|J{Y5#W(u5a=FUz6m-FhQj8~#dm7XwlcdM zIPXK&@nGH27L*ef(SQxq8gLpvpoQ!;%Gxj_RS?pUqX#3Nmy5AcWUGyJPBCa(zeYN1odqGq6zO z@6xIFZ14{xhH@iW`P!?6&a=vV-5lB_((9er&63C4cH3T=XLi5q&+TZ#U3GVi9gM8M zNbl9Do=&oI&o{^YTax$hKmJ5qn9>DqWF({SRS?z_^GY?ApCsHSZdla(zU${xsZlm& zKi7Pb?EbysN-(gSC+rRp`~OJ$3aF~Ot!+h+QfW{GDd`rG?(XiAkPzu^DdEs5Al(hp z4T_{lcL^N2rBnFV(f8JS?|t>V{}>Jjg6y;RT651e<9VK$v{qaYMW7+f3Q%gOiQ(5Fxz$)}_{emPTH=K2zs!WIEl50)CVqpaM% zcC+S3>Vy-n*B~FTanm>W3a5P9O`&|e-f2K$ZXCwVw|8P?56!jSKla=*SQl?unqsGs zUa|p$&S{2*k00}qxGuMnYT~vQtZF+QZ#`I8V;xB{j&JFDfhb6BG`eXw|H1q5x{Zck zry!y%eE~|#o7;ER7*k*RLpB3)f039F^5>=gDhO8b%%rmT;%Oh2=HzB1!~h>y>Hg`%G-q z$l~Pv+J3u!)^y$0s!_&^#m&6rL=mjbvF{YZBP1)-Tg4)*LsWA*U67pb* zV!y1(CiELidG%ufGnzw?)C}84q8%NlIXv84r8``{cn;=V70XHNJwe?sQcAQFa@(7j zmO4JqzwrvveafASWHt6>39fLea1p5C=Y#o^`}rwMk-Jq}o?ZS*ugg*6rf5(623}k> zo+-Wu@}qn}?EhJn)tmrtm1D?~BuIO@K=oBJED=K=8mAWqrWL&$^!A1Fn9lR3bYwhc zqhuRvP<^n#BT6sK$jfVDZXsGi9d5EzKNaNNsU%Xhuu3VHlopjO*{yV$pms6oJBtk< zL4F!t{h?6}%`+WcuAxP-tBU3}s$c_5&{BFPFZ`NL2^PA(Z_l2bHb$NxlbJg`#??A` zrgg-f(`4t)TZQ8F%%gsRrR`)bS!x#r5N1Ruq%vd94|- zIt^FpVC06x36Dy@nB(dz>T`HRL@ciG{MJ^VVyzm`W?7Ipw|wZCQm9ZA6ueab0r?c((0jy!C=GJ#zxIV0w+B4-9_E zTrGvNJ(-}e%OFI@`D$_~hC+qwKB|`%Qo7ce?J|As`v#C_U-8qbuFbKWR!!x|Xi*cW zuDg!bHd^8;0$(kib-+_t5KZuq^`$VqRuwo->h?fUK_5}fLSNMi)r1C@soFH1F-WtC zQxHX7tyq(~L?&;`vNHAEbeHF1v*_g1v>i7C>WF%tN}fE)!k6_=Dl4rQp~;wWfy%X) zt^>4vC6skMS!|s#)Feae;U}{I`05R>`t|JlARH_=2{~TP5ryf4 zJa-7g3XDvJcHYUX%w0D8S&5K~A+W+N$79sxmN<9a=`lC9!NIe5dGPI9J2sW4c$woi z{@w$#Fz(Xt(NX5HxVy~Mkp4$?P(>xs$a%it~*B>oQT#@iuw*NjsObV zbn4Jdf>#V2Qls}p$2PY#T^Phl;=W!`oj9yiAl9rxzj*jePY3lYgmJ$qzIc?nXt3nb z+BN0E;8r$KUo%;-y0?|Qc#yAgc?)hm?9}~aUZ7EE*xBtuUUsh;_o3Zv`mrheU$sGq zBhHYd?mJ9m_-)KG4nZqOdoMk?u;ZI@;3e(BGf>siS_tLkoo zEB)$gqeK=zq4{iEaf+KWQrsuf<$Tq`lP*T9G$nI6XLPZKR?*>NJ4(8wsU-ZzIQR#T zUN}8-3}=BD98)&Paa7rMM`dTFZ5COp0*qd%%+0uGOQ2+eF6j3}QQLWcNn$%6o6orH zF;`%j+kMo)a6+z?fq2pJ3^w)_T@aPh3VT5eLMhh)3~|^zN2}9PkX$k*f;96}0NSuk zrY+;>LT4KlApr4Z;W4&u2Kw9BsziX{6I{wLH zxcvS?oW|G+l^FR~<3X#7V=K<7-kHA0CL_zOrCVQp0e8i2%|n;#X|DTbm<&lqm*|1Wz+4ZRZ)=S zH_3gw6lJ$!OddmH)v^@*wCKA?gP~{ajIt2(gNMkFm z9tl{WAX(E?a5|)5>H%6uMmgwsq3$i+JP6!vo=#wAt)h{N^OOQ9sfyg}e*7s@iffgn zpq-O$=4CdG(zSr?8X|3F=D zjw;sFtwceIaa@k%Pe`Q^?<5%L$+vZ(U%r?wutGf0bb;9Vy$V4GOER4;g?Avn^%O)t8bP6&3P!fh>tk!1MRVt9Cn=PVuph|jyH(ozB+yE zx1Z)hJ3GUBJV(GG!f7PsZE!iOUhe_kpH5w}{^>YV!QFexANbJxJ+8UFm+i)gpV7|X zDg1nDMd>sUBEh&89QPV-iwX-50OC#7T8d7`RF#`hJ+hrIm>?P}C@84NO?kWPK776X zI?b#t08`0UnDqDE7a$3G3?G7mW#bW@_Eh<1*qit1SbtfR0reVwT*~>K*0#^2EM^&} zR-x!%kL_^hw$`f}8CwV>s{B61H0^&|5PHYw^#}->j_I=0u&=Hr@F(k82w#M!rXRV5 zDLrE(3K&a{j~5rQby3=7)6E&E+Fb97BS%7UkM-Kkul_1M{6gL=Y}BP(D|VU)$$rBL3Bl|EM)xhW}AT4TG3xkWxRj z2hD@M&*Fq|py8f1uIm$u> z&e7_J@FWIZ4l>#3-;fbUrZaH+htYgMhJyuUtd^H|aHtjAGR8rp(G#;(qS6JraMsDJDfpXc)lM;R?p*Rfx$i8^8gc zXD*;d41#vo+ERBk!z02^-apG~{2N%$(>(w_aalN5E;R?V4sx%u;&1-ehrvFQco_XP z)8J$25ZwGEynq0q_;@o%1~`NtyYu&&!Eb)i6#-8yT_pSn+LG6$f{lxNTi@W#Og0kA zZ{N&6BT;_b*j^cv%^tKJox=ECaxnj2Lsot+;J^R<$se9n2-huQ{SWHpfl*$j1U^q=G`HM2pf8J8>5Xld-{*YK--{ovbkhTbT zSHaqkga+0A`?~(lcb*{Lbi$*!jhLv&Ay&?Wk)OoUnIjSd-jM&{&x5!devlmHzQIV0 zN@r#QES4Qv5u^X%I^b6le88nBI@{LrkWlXG_$l`#7>tv4JtdisZJ{`e@$}_BcuRt| z%Wd|AlH%r{-URP2lEix-WnAqS@3#|OhhdgnMQg-){{l_L|A8F58GeQtGvajz{LU*; zYRb3|+EyWWT{Tl5=*scwZvFWc8G6eiGFk@wm*AMBTYDnQ~&TbU%k=PDF*wWfBdJ)eOAmr zno}97O3v!{!4YXMlc|<6zN?82}&CnkUznpsNcLT9;=3R`+xGV zY!t7R`^1;&YWVyhmhN~ThJNw!|Ljly{`CicV2e+Yu_l?B>FDl+K^SJV?*DHt`omr1 z+6JaFTWcorpz91$Re|`mHy1=wxBv9Y{N6vUnSq=3B_9OsezU<05o>Aty{lI1|Ly&@ z6oq-Qj~`*)f;9F33d>MtUtJs4{co3Jpa8FzaO`IePFq$*js|BdefGaJ=>Ph_Y>#0V za+E$qzZMZI&H)y|PEo&Le&c^#G7^|~rRi*A1rHfTE=4SDzwotH{(pN&OL5qmeP(8U zVvFM+;1Ao&(wlS-{_L23$LsU|G_h>kFav!9SPT3A%f$HOPu1f=Wz_N%?nBi7V(>TM zwWV&fwn<`|+AG8R`@d;r9;}*1&HTfuzBYvS@d@gBgU6WSRCG%d_TASwH)q6(Ue8ni z*$4c|A^!Yl78z_8RPWu(5#F1_Cy^GWS+$=DjK}}6avz$I`Q-tZj;IjvrW*POk2V}^ z=G(t@+1fY%9>nTY6f^xTIb#>Q;X}IWoX!fObw#+^@W(HF@PErH#TjAYf*-^@Gt+c1 z!ylB>#zos2e;Un>47lh?^OZUeQmxO89kPHu@Y%j%L@E(Z*N&9#qes{euV2f~G|O<6%w-jq)vW0oWGI;n8UEHT zbiMkyU}XM=&>^c9eb3+1j;=cr4qxypa#>k!sAnMIe2$!D@GU%9G@b0Ws}w=Pu29@NK2FaN2^#2D zqO2Gye~hT3vg4z?#za049uyy-qEC=Ws8lCI~Nmp1ZDVu9H^cRiAQO2j#$3VvX7Q z`hmR;yH{O(t)~3a^0El1YG#9qY-Eeq>pN`Ep1lFnV;F`j!_etTrb`u)IWq->i^zgOyP=p1a-r;4;~* za(iEelUO%=d=a|536PBeG=byhzJdsO*0OvYhu6ss!omI8Sz=+bG2YY5eaQj57w$+n zZW;H1ZjYaA3U}l}MzL-ar^EJnN{IPF>sckxPq>3e2KO`H{c{-eFDHc>2GX57S;yOR z8K6g<(89vT`OItFbN<6k&1QFMP|lcL&<6)M2Zbm&I^Mr$VyED2v>QN&xtW>Q{IAg~ zt1O4#;q>8llW?Y()~R-tpF zev-IgEFF3(*Mr_;09i+!B?k~Xe4FIAT1n<)C3c|NO}}vu>Ek*;QP{8c5eA=!e9N+y z7obrmZn30_E7i_M#beY;va41y9*EI_6?=tF%FW^+Pug26=}WepI0lh4vmrFHnuT{N2fH7iK5kd<|>($QGyd6 z5VX=oBE0?8mY(i?BVE#?8od^QL_@+l4!1X=?#v<3#l_L}J9bIX+qo-J+VUwejWV=BC!Wx;zvf z%ov$pzpY%Q>99~4CzBMMU1!&l4x24Bnj3eTCpU?CXz%I8>3PBM-TjJm7T401n!3)9 zcCJUnC(piwpz`b`T`#*U4f!YX_05+8gO%$neu>YCLkT#1!U#C%Rsqq7`z{f$U@eMn zZZpwwSs;lplIlM4$Iq2!B#P=&4Ng`lNL^xheW|&~Se?VMv~LCZg8SCLJ+4)B*~cx3 z5DQC2mrXt~0uyge73!X3uX$Vh&Uk&OG{$*Xv8~b)Vr#T8oGFIJk|jPul?mpa-49hO zO~oWH_btM-D(qY*k+nba5VqU^*% zW%-=BXNNg2kRpwO)7%eV4ibO16dOpP!o_pldivd!T$Ev0Glt!A>pq}jm9fuZ;F^uz zZf&b14R!gCp8KD_Ih4p>s_T*G`8`+UcD|R{N1rontjt~8wKb==H*b266i>S;H@V)O zDu2P!`;PTfI(hw%Q1$&1Hcnko>!(j7()Om~X&66t)CP{R`IHpQ!IMC-aC~*0__kPG zGET%*+l@R`{N#&O8|XO3nQ`IKYl?%B(P0E0WHoHnk#;QRDmgbuD3Ux**=HrwsT6us zwL-=#+|7b87LUHx$*D9ft-Tb8q~EFD_|*EgYxDa~gH_Md*~^bF=RbT@24H;>erv|B8FRn)$!?zYDs+9sE zEHBHd@K|0pj@g)rKq`#;vv`~MVq}cJB*`|p9=|Qkt;D6QKj$@QGHzPEf;Kx#1$z54 zL~>I{a{DV~gp2oWk@-~~dpJVy@$O|fwsPzhSd(5lpOCnketMx`rK>i!e6W|{y)31G zOv1ftOLdI<-R=mVu*oLcV382o_I%oekc3VKL7b}Q`r zq}FSFY2)IA8mkIVcEQ#cqsdoq6#GL6l2TKN03tH30GUl%R*Lf?QKL<8G(=vT zoWGJ)R#cs=GYyA#@4%e&`^NZUOO))}OYPG4cI&PF`u2P~k30sxdo)oz$mko>{eu3H z9LukY%4T|u9+z~hUhw|AM?Vg-sE^ODE72dEQ}B}Vxr$G|Lb`WW@y%qkP<|oF^Xb6= z^3-ERKoikdfQsAbp?y2b={bR#CRppg5XjK2+g=c{Nts-t-Zp1p3B)`a^X2@t)9fmM zC-}}VH0T%K!B5h||_-HTsl8 z1jB29fa^gb$=1Ac^XjJH;ZuPeE8XT-`NJ8)IO+#0^lPDPQ^T`vPE-MUvKoNhl#%IW zUzOH1hDfS)1W+bnF~h?EWa*#cR+5jMSfXAQ;(57;_+2DRznESiy>MgLn)+F8IWF&P zgImDoxKgU&HraPi2XlP0Yr@g!wb5w^u^JpVU)fzA^6Hy2<~V70_m)yhF7b|SN}$phvSMqQ8AsMPIgfaX#~+VwuzMWD#r8<%wi&Wn4QofjU6ojSjnJZ#Zzu>5{yJSS zl7<_bo1F{-8&c5nV?$t3f{4878fliT>O*SQa7~+eZ(qc?N-CKv7a~u-6efH3c&So z2Gl)MS^dP)(w~L37Js}P!qpoV$XF^NrA=enfiiP3yD}}`k5T;t0#M6Jng_&>BziLo z;RCBXBzh+ZA53e;bWt1Zf_gmx9bXpUC@W~sc)a8FpaER^k-FjOX)R6)UUY^pIt|U6 zT>!Y)F{UdW_naVUIeblDU%;RfDv}qG8vfPHZZ_L(?{ItlKryWg z+C~tLN#zC=I&e867H6-xm#-1aFxw<5?YMJj6u#2OF8HmvAF-4Bga`rmO%cFZ-+IWFc zNagTl`k!vUW72mY^Uu&oXh6ccb?a8Uhw(f6_KT%qZ~L>M7k3e+(MY5#dpiMl?ZKd?_%qe6SAn5@xPHCKDo7u`DNvAS^zh- z=4LfIcTBkeQSlhSCW{CNq#@82)>h`o-f(Ujwc^OU=k=eMd7iyiB`}qW@7k&Z5#VB; zd^$16gi6r;J?IFxib|yhGvwsAr>gSo*PpZwG9bcQlUD$D0;B0UC~@RSlJ&N>rFx!2 z0H076OfMh<;#bU991167Wn?K1U?HD@{*RP2qu_g-nvLNUF2o zPB(Db5~PyQrnU>ePQ!rq_;~d)BClM4EL=AzH`dJ($0*RdHltB1Ny26(;B{9Idc4i? zrrPzp0}TVnL)c2iZCs_Y*my+E$4f?&!)cR4nK|?`SlqrC%RiWJJLqo_hqa4gga#Jl zS_Xf2S9%MxrVZPTy^DJdPyIf|_Vnz1oq9Kt&p?h04*bJigVKL}; zD!H9T=p)Z43b`bH<}zk#jr#QF5=`PL{7!j!hBYI(m^{K11Y5coDQv6HJ!*8>L|)EG zx?G9q+Wv1Ca^NGQs-@y&rz{_AlodC{r~8b+vsg^o@9|>syJiSm8e8#5COI#P-Z|R7 zNH|S`CGGARfIH2+OhZWYE)PR+V_?wS@iM zlU~({PTA)-8dOH?A+>5R%0b^*YW|tq#zm!+mKNYX7dS7b_w4HE|rs`TQED?AP zzOX2s=2^5sD}kV63eZ4IE6!PJ(;%06i*1mTP~Lxua6nD-WGKTc{1ML@&?O~tv>kdo zoGTZsUW1I6;i$MYR&DWc+w5$@RL|rrkJYwb+VLs0GP}S!1Xga5tN0Rm@*z#Yci9z| z{wF+}`3l7*vjl3b_UC7-slB}bY(v?eKXwtRBxF}V2%IH_#C1`J;R@Ytpdhl-W+q;> zyfw-46yU}m8%%?0g2HN_PTM1fEDHvrRLqQVppS^8pOyWbhMc+lMyAVwF|Hj)Lnj@l z$$QGJcN$IS(NEpRq^BBRDBTY3JF|wB$McJoOsCJ&mhzY)OW|8qZr>r0_V+~@J~CG` zyYwr~em{FwXw(?+BYp@KGj7by1Uc`gV8$k4!Z}y5`dQfPUFm+NNR6%3D%^bHxN{ly zGG(RH04jz=C%ky#(qv%HSWtaQcKdBpa@n9>l~kc21e3hYl{<@A&8lx{OsQO0;>?`b z(@U~AO0!j1c5bFcP{Q?;D$;nHPdLCTo`5@AOYE%CB~Q&7;q%J6Kr~u%j9Ib=5l@yj z1bL-Iq|IcaKcz@8*K#hq|BB0?L~a|=_j6nt<*n~#lY`Nf8l5B)3JRp9tL;ACBk8Xs zrW|I{-q5LaCh-+rcUA{QSbzX6g=^_|KOF2-P8TGv zw_V2cxH>bzEw$(@jVXKk(}}4oceruTN-DDe5PB-_X+E+n&CbebUl|cIL3bP5w3dJg6U$d8AZtgX0bbG7SRG@mREv ze)7gUK#_LjPEs!>#o0edk8P#iliR!6kv7w251c|?ZIe2In$4&93eKDc!cDO5dHHgy zWieGTsDxDO)QKvECp#FgVOJ$97Q=xmWU}b@ia3V31{3DDEE&SM8o1c0F9Jr3Bv(aT zH@)3-HiyhH)KOBEOLdd$9a+E6n}H(Pz8D!b0p{$li~GbvnAV34T%&!HBI*y}CpXaa zGrB>?!XW!g8mfLqaWb^kwU~VX;9_e_n==Yj+TxN0zl=9sTs*;)CFFA1H=?FnI_v=` zzbqa%X)_Ux_%4IU=aIRIBFI1<76-1FzC6{@vgCQ$tl!>Zc3N<%-4yg|(}lP`UT*k` zy)R911!jasa78T2GuE+9$gcWMu z{o-tY8ERai&bz`l_Qj+xNnmRRK!X{)uFlY1mOOwWC~<;fVt>=om=@HF@QkE4;UH9G z!}#lUKNum54U}cML^*BiNkzB6vekDQeRy!#KT~(m-Om_M+i#!grb-%m2fuvwJ&471 z^hrONknD9aiVb5yt2keL7Cv81_1e1Nc6{vdD5_tb)jP{sQ7*=l41LlH#u^Q9-$dJ%j9FV>mjLBMY`&QH_Rm!} z`%J~OHYIx4m4xEe)oM|Wv37j${MIaIcCKILSXEcaUft~dTfVANi)@Ki;=|z|&)8s% zKa!GYKYxF_5#+o~45fO?4Jc=>FEYKguG87~3?HZ@;gH+%5%s@%n(s+p&p4#uB=gCB zgvMAbTuCTL;d%3AIY-0n@kL%~rq1BKA03&$_d);D7f*0*inTN-Z71m@9XTacp974e zt+X~4jzD^Py7=-d^UT_EUD|v0!tw0lS(D554O`ZyD~VQJ@-g3n{N1+#Pv^X@HT*y> z0S+joote6IfF8ze{lK{FvOUAC3+fANfGCUWq36CwP9px)L!p~G8Gumf`)O|`s3v7^ zcR>Z4l>6u;%?HxFu^~1^0Mb9?mTpT1oJ?3WDRJhsJFet zNd;uiNWdKy26mF3!sB*d)8P8*Rvx$o#iDPcYKx}BIay|}g@is)d0k!N!fB;Q_i&Sv z3g+02-QH_OWkjhd@+_C6<-Y{tMt-N?5G2LL(FJEb?EzrYt_G;x3~!R&=S?U*XN5{_-B(Y#bMeA#03ZwRE-3<`=>tggLE=bVF1eIO`>j)E8l`&a zdQ>cqXSfvQ{E=Q%`t-8OMEg}lQ&qs3JT3=)66~g~l2ajXzK1rz$xQk) zm0iCjJmlY!V-OXF%=EJ*;>i@LMMM3V%253vA@B&lwwR&V*O_y(98>fkDP}G@yv!0 zrD{SxPi;;jTe9sLAisi{Z{4|ZoD9=m`Pcx{UU7|kNd41FUP;B@$9xj|`7J#yf&oy= z8FysnTZw6er3lc!8_50OXQ4T)&lu^jxaC6t6i|T3bD~qe4T}=;T|J$2@*&9O|4E`I z2m*<;GfO}t2dkySd=2Vrj#0~_ z4OXN2SpiZ6_TZl3f(clP$y+=IP_5Q9dd;NCps3%0954q2{X<`h5mr+-qm*34?r0?oOmo{*yyZYlg0%JPy?$)p0hA4Lm2^TB| zpFs1jcYK$~wIeoH_cBjt-(v0VKEk&B2EScvLrbqP*jBKdA82i(oSzgLgvntV`#AyO zEfK2s3sHLUg9>cCOIS6Ek01oRYeFqiQ*DzyBJl|y`=oTRc1z<6~ zfu&o3^PdKIb8>I00pXJxOhfsW-WyZs36+`$K>~n1jIYf)admr6)sc~r2^T;S>ZJ(T zED2PKHDyo^)YCdekh?0ObQUIBt-`pm%RO=7&n#!ew{mjT)Sq_rj7 zT|W*D35lXMEGEP;>3t^yI-_hS5E!a89E?81qptO0&LvsBT@t9!a1y%1Z1?`bx0|^t zrMllG-tm}ISbU8dIeJnT(Zj9hvmbXaE53r+{?(?^dmwJN92N@j`oD5Wa%;J<+4YHB?R-} zDd|Oea>j`ZS?J(n(}-{Pyv@=fl{tcsEW!T`Kfq7yfy{nBo1D2l@-oR{7Y3gF_>t6H zlN5APF>{R2DGEGd3dDW{CmEP}+jBMHx4oXIcT@uzlo%Eh*#KxGnDhx#LU~n~>~^;Q zqS6TBSpWqzE&+#)k#vBYR;aPmd7(#6JRDR}d2<4jflnju-Pbw zfbG%M8OBsYF1_S23ZTXXdM&(X=jWgIMu4Qy{YYF_l489UUDY~HQPz}q{a+O>@GHj| zn)-RJFM|c!W?&gRjZz8cL%GnJ!YHeIjP(!g!W%0tx^~cZI+en1@C7v_@?SGdZf-?T zzeLkF*g(PxMrQuTPa=8e&X=D}s%VOV*q%5=`{EG$>K~y;WV~X79EdvB7O!q~cXl40 z+Zyp&yfYG;$~AsyZeuXlOw_%eBZC^bleiUbcZz=R0u$t)(`ds9f? zXB5(U{~XMiR1Q48s)-vb(J*A2sjX$7s|1yUb>eLD1ETAFQ`%!MCUv;=z^ywQwq z|6~{;?xa~{&(9QFkyq6${rYT`2p>oW6jfZY*ssZh$(5d%`Wb`Gq9C=N!qn63OvXt8 z3C#}?kT}>-7yxrLa?$|dA$OITp(J%P7`t-57(VBJkYmONT>jis+bjupQyy`k=9U#0 zvB`%4H|-&4+S87)Qtbz^y|EWC%mbp%*EE6lLrKs^z(?Fy7Hqu*RbET#n;B&;*h})b zTM*9zWoBZM4-Ci!*#GdgXgS28WvOGrA{tg&vB^fB^|lU{!+BZm(KU5{ZodiP(r@M) zb5_@6sY%Vsf9?dZNcY!&zgAGghx~o5Y zgrdhyOHOaqq%J{W2KWB%tqft^fQoCR1>O<{;02^ZmHX=aGM&znCf8FF*X^#K?@YE| zna40P!a9z+w=*-^%3TiRTWD|~v&0uWocuNIXgu=&+*|x_Uk}CoaoQJy(;n0V@7#L^ zYkdTz{lL5wgvPuBuQ(HjzJYj`GL2R>UD*fV`4x=47nZt}@_?EfEUF^GT;H~?ovPEg z-vP(G8O3I$d%lv$K^m)LIaTjK8~TVx@|ixf0MG|mHpIPOJ|M64)p=1S^2t!l6HQv_ zBqmQd70j_Du(=sPMfh{f$0<)R1S9TXxj&T;0?T#K$-F+@e*+CVIYOWyY1Ov-M4KfZ zFUVfzDRT(MuK@;2G=+?RrZFBh@pPpNR&OesSR)&`jM+OHJS7u(EgwO((M@Rx4IYL( zRCwDuVUk**_|v49U!G?Pcg`E8GN(z*5#koUVouL@&$Mezsb)-25EZ6}+RcVX)!(@s z#-uYVRzxc(7~ErI#FsCAf^&F~9jLTwI*KrznySd+8FKd*jZ0Wt^SQ)_!QCAKi(FBs zY8ZQ6g=TfFYgBx>=$XPxB2f7Nxgi+pK7csOmo^Uuvao}sjWU$zx{Bjz@wblTbc{P#WAfgdwtqZcTmwXW9K|f1ad)VrB&vDHo;SSv$Z>vK)-}int=T|acrr) zH<&*nrsv7gYQT$I2dX#XD0#{#Hfo)w_Td`v?{22TpCS&73rc?pbMA?w&nEJ`{AwKY zXp%c$eVZ7iKvg{Gu0~Al#f29&NuOfT%JQbjXyRxDR9HVr9PdOsgN2Jh5&B8&S*K$= zGJs-`NiU6aq4p=TvNSOYL-d{$={9}FiK7xRto@N$U?T+dbz=?$VO980MdEF3@d-xx z8>I=nM8evMRO2hb@Xe=u`>eYI->dSRS=kGE$oFF~DMG4iv8kB?6tAg02a z+X~Mj4R$Zj4n{yJWJVe{#jY=@?g@iq_tg6ZH0VeZ0t$8-&{xywD47D}Y;86%b|#uZ z==yN(dROEpQU^oQSUQcU&#|;7vWuql(od(xsffgcZC{3Jtas%{h=rU+siXIh1LPKv z>U&%=j8S)8+pPadbf_sB;dWzxM;M`@Z0DCoSXk-q{%!uIh?v+Qpq5h2VkbT|BTafb zM~;hXTi;jOawQp7e9F%3eu{SpG(si3;dj5MdRE)$V}enO&lr{ZvuOxPYU(68$mlmC^1z0 z%PG`SP9-zh*Q99c)iw^~pvj3x;d*h36zPsupjGpzEZ$?m=j?D*@1eFw{+&=0DfzVm zS0RD)XeD^{q^=iW&W-F*PhO~4$bD*|hs*}f_5Shrt!=NM9$p4jLCRhI0jenDZG6f0 zGOy@nFsG4g{#G?RWV!`82?6?|b%>6u&j&AUuG!8O>+xziLM+J48V?j;7X z(>}HT;c{XPq4@f*D~-A_K}jE4Wk!Fml9e*Jc49k%5Q9Uf#KCN;lKNDV9tXqi= zA589G<6Hd<*kFKEnZ7d8I8}#6z)p-1F~h*X5Y{Nn$%*^ew$AA~MSPe;F9`od`}Nh~ z+MrOaaYE8j<}n;{2$VpK^qSDT0F zWKg#Knc~m|I%B5n_{P%uvIJN2w8Y-YqJ!E>^lZS(7KPwPAf>(b8d3lu`}!Xdsme16{PVi7~)fnjj`Gno5;Jv#~;|) zGYsTMOgBc*r&{K!%w>`J)sWFGLZhQ52JqmAf?oq1z)QlaTlGV_$Af3>f&E>VvB_x!p;J12KU%h%D%BQyS{kS~uIb$V#omqy9Qj9SZsYaAQ;- z_#)0d4oP%c9D7$PtDE`8H__u6iDd33$TF9W=kEr19KL&;ZwG{!03j&^uzvLQ(ZMVP zl6?7(aPJ2O-ajU*uns1?1Jq1t`~&I6E_AgH-RBgq_TrW@DRGkizBtDezds#rD|Zvp~RMC=e=<4iNVNr8XyLe zmcU}t%?ZS?)XHxeftq2Saj)jkdZb|^jK}S26xX@ZtJO6!Jf+-c`yTty;jLW2Jwl_G z`nYvfugoO13Jk0R48i!ue3``R5ir#j2x8^6M`=WKxfuW*6@&1kD)!uzr!PkWHG|Bx zb&(Q)lJyJL-A!{S1<`{CBuUtrDoO`spnrLIJiRMUq8yBSo-saJNS1XYQm0DLzp9W1 zoVs}9`8WuOh>5FjaD;p?cO)a%-PV%{^pC~1V@<|8p$&pv*bx~2hez} z+)PcjKb%llf7e~A&*0F&M;)H{sirHlm`~2BfKkpOv7tv5D{kzBTFWP;Z&$9<-+F2F z0B_w9r5#e|N42+1Dxl1%c5lj^^{p|1%)1?Ka#ZW8G;xmsd=6Vb`~2kzbtB*;k!H~( zS#tWb8cAbMz>}|)pog5Cy(fYt7$v$5g3%PxX%)|OPpCEQB+qXLV;6jddhB+UVF|Lk z$lZ%23m}TcVlYN)^PKgXf8YMCuexR}gpxQy0;v}C=5>xiUsI`q6d`+Y;pIY7twP|a zMYe;n)AEnD=0Z$YSnynGi?o!S-oU-MlJIQ^rXCeKe{v5to}%#da*8wG+4?29rrn-q zj^rFSs}VlJN)OQ7(YbWXoD=h~V8k@}Zz1+SzE6yWwKiIaHd=aJ$@KD6?PZ#QLCI!G zhl0KVKR>a<=J6v?fbgw;HAz<<)HgubUyu2NM3g5^B7FxffN9Xx*XZr)7L9tkAi}z= z2`0);E*Nhf(7Jj!2!?UtLWLQrxrcH>s@eDfc{}^Q(e78C<98hPmfz+-3f?)nQ+8VH zaluBok%`YS#76Eu!oA~YB-RR4qQnO`zz~-8)4j!eWMIZrlzlyn6h6$8%DJq0GtPmy z(M#$rod_@KHeG`s5b0G5(k`AhOKsrnD5~#-^OG;G!Y<@BB)KwrOXU77r514}dn&n5 z=^2sSx!aknBzj4)YrB+oV(!#4jr^3=g$kSn63QF~++K`c131{)t zEe_%FMWXxbmKEWJ2qIR^le+9P8>mGs*Pfy1(Tp{L{s^sLj#-e%ECj35Y-kDDp6uCT zZBqUXR79LC9|UQ*hbp;YKLNb-guKZXr5&vp@K3OA0#tOR`3W}Mr{i{?EcVDv#+f>? zLE-*_Waht?y1~*=t<}l2_os zWCU=8{-7fK#hECI41fFfP(1UZALJc1*4sgwqKnyPkKi|V&O%D`#_>2cYXX=6a}>}G zi=7Zt8bbI%GdQo>+9Zklg)OG{LoRCB1WeLl?o@PW4cdjLDYKR2x#k@|O7Mwqkl&Nr z^y0JTyM}IHE7u~Ot@cWRT=p?;vZ|$uw=K>Wfq-jvK{YwO(PT2Oy-Ve*Nn87ieVr*h z2k{!2m&)brd&N)@Dt0-B$TtUNg+-Bd28;fvsp6Y;hleh4!I&J6)KG&aL~0y1tB1%( z^pK?M+B!N0z;sa&42;4o)SRNrIU>usW)H-dj|r4GEY{!L^+Iom>3}@Vc~JJAOe@0L z2o;@_%4)&5d)eEXIT(X9KbTY2vah;7&|FlSID!DSdxtBFm3@Tm9##JYaVoCWGtN5f zB_Ozt&>zWTuFnv*`=)VtQ<1}D5HeTDzkKoaO3s8*xfK}z2XWH9pe{D>#eP)J6 z-bSweWfhhf=;n(~9-IzMCgZKo^o2zC4U-Podq&{`j)X30&NvCvk4o~_!$)~`oFXa# zXhhg>MUm9_pC3-T(b@Rpk;E<$zOgHn3x^E;) zc9&5(Zz34$CRwJBK6*T^qYXOvi+AcDKZP-6O?9Um40>3y9G%79Nv<>pA}L_>%;@6*IT{f zsI4MrV#rcccRo0k&SpMbwNhB1L69&)mOY5+s~33jUJ@zj$pnG`J8=Xu@;q-8G9$j= z?{Ema%70R5#zn;dVGtD%yUV$FZqXM#|LCJ!Z*TTs5SGC-if6ByN=WF5t@3k$9qU9= zcFw-zVses!^{{^+nbxVBED;f>C?JqXRMz#*MF9>dzP}wG0QdU(!Z)DBU6wd6&3wf93Xl>3J1)l-a&*-TOyW(N5U5A z_Fs95fs}q@PE0URYWzP>Cw%?45z(jA{7id-Ow1%C-p?~qPtbaQ4kShjy5XIX#x#Ts zr$GPVBr>o0GKu@Yjf(kksn?(2ktphYAQA-zP@l5{WD3r$DkpGGCg@H7{~ zkA!f_iz%pGFM8wOheQ3-@cIvOH+>+ZA?mhJ%yff{RJOm})j$20zr27rBR|ui3Ntgg zOMY8>y8<)w_q(mXT8KYQ%|0djaS0m@$*8vW4ovC8)s=Mmzg&U8t?1t`w2qL$6R*xg z(Gl^Ok{w%Qz9*`bfZIkv~EWB=D1d4K@62K>H+ zWQ-p?4TW)|kh<@`-R)o5$!j7wcq|J$;SzVev8yo56t%!>#ec`$rAKR!}Zu;1t!(;ivOR)Xb>ipwD zUZ=v=Nr{6|P9mz-^d7~z%iI8gcLYj|7qlnhSZ;NY*pC>x|NPFb8kX5|M}|v>Lu~s!VFw_p7Big zZ4y;kS=r!2>5#F9#0^(IHU$4ZGx5*c`1d_0)`XA$oRFW?+a$}xtaF6H-@=*MF5 zo5Cy-Oj|TC01gZXOUSKZkn8tW2z> zO?2E}TJDK50_YHBFjbqr69fHM%lG#c083+A&R>a$WoV$S#F3kqpM(WnM5b6-N=&vB z`mgKuAAW$;1iMNx5L}LW`y|$G&5AAT@9z2U&g3svH)0s(X!2+&Rur$ZA2Y^+p(8XD zD~AtL4*qYqQT*dJf*?I3%6&k&iY)&A)O6_A-!rN|R>ijdk84OsNIm9d2zzcI+p@sH z_kXaf8{Pvb=+gEw%SlDPki9*4m~Dty?gFWuw^9ss$|$%rkI(C{-U8wA?)+%V<#4{^ zAkRLZf4qXf{EA)R^>e8Ib5bP^u7xmwW!hh5B#u+5)dt<$zgYJ_Z4$Z;c=-zxP*b9ksBFs0l%+#TruhykMn^Gdbyd2{(uFtg*t6So9;bSg zBss5VFZY%JGHP}GJjOp;)Gy2rDG0W{g`I6(E=O}uaHNfBR?}t_ISQl8X+EfBiAM&q z=Yx^YUA#oTZ{V@Wpixi6e|zak6^W;OA%pt?lpM8af;-)_5Fu&d6Z~ z0nq}6^qr49xPv;F(jjX-o%6qM{=~2oju9RU3lkHG;?2S%`$H063~4&Gl16Q%sse47 zb{xebVH;}AtUQj@Marq6xXG#fmW~!+vS+KRw8N;*F2OV4A6finKP9 z7w<>mIm^T~GaPXyW(o>X{8^iT7;3vRx#x)Yw&KG1&V&J)WlhP=DHM2VCH-VJZ%&7e zuFUXfc!X(3F9vT;0sZc70BG?rlYRJ`_T^25O&qV@t9`W8MlRUiMs|2BeXcM!E(BL`0D8R3wLzZbk&@9zwcfhLRYN zq26;)@AuyKcR#3tK z$ru`2MEf6?|9|*pINN_DqW!kZ2BA|^28Q2Q3ZnouB>VBP|H98rqph~~Xba5P#{A*F zgI+)ki-ryNdz<@JpPq{|X_dw$3GHXGYL!YkA7XNckNR!z#>MG1Y3i?7j)A6NekW8^ zFvXt5_X{p-WrOM373+(7f}ZnXcVRTEFi5UvwIapC7c}yaALYh@DvMO9V8Ha@4kGh& zau7RS3g2@Tiw`Pzpw)GGvBReH(SHd~|90p8^{1_ASabT;WWpp(LQWye!5Ort95T_B zYLG@qUv4p|1v&@mfNm}(BQOx`xH5-ZftB3sUDTEZuxdNX*BB}s~-kA2sn#8&>H?spig^xpo_!F* z0n)dUfdc3!uyaPeIoNHaZ$`p5P()Y#)?dDwN2I?q2&4F_4rROEs+JxYFMqCNjlJU zXk2H|azKDuzT&Y$CC*M%X`Oo=4On-rMmDzF_I9QbTEG!EQnpJUcjHsL4GI|>N-4^$ znxznn$T~{At`XXx$D|xUG6%*+>)%Y@5M{aQrB=R(7IPLgWu337kFqhEz8lT zO2Oz)vNDiEr(3fd2HLD(IY|etU`>B?3YaK0`*e+OH97qg`iX7tG`H4I2R&!a(ftKtEYABx(s6WGj(YMt@4}5v9 z>H7xi3b@2@nXtu}bi}p+e&bN2yhdp@)dJtFZlFL{o67wMEx(-sTrOUK8&Q9W!Bl46 z<(%S2aSzG$Q9h=q>=ps%RX!#VcREvqRRJEs2sjyv zsgo%QMSp2nr`Q663TNLq>PZk;P^8FM(q!{sw`BSuW~K0vaA>D*pujTv z5ZegyNz&x7DbP!CX7zqlw&Golg7N+m4;Lo&+R9pfqc@kl+yo!_22MH_mv_a!(!=m5 zT&7pgbB)Gd3yBcNBa#YD5eBXcks8S>3{6$IA^J!rnvD)DhY16b&%?5t=WhegZ8qYy zh9;E7^~r4%+yrK5=;L< zS1t9=y6xlBzwBO#5IQR!FFcm7E5 zx7I{R2AozJ$aw4l>=+sZQgo)hec`=v#{1eL*jXVJa&bSZJwewA?M-*nh9)2ZXobLT zO#rQ$2~Z}Agfj)p@}0 zQt%$ru)~E$v!E|t|7B(p_TU#fp_dY2%%xui8_sqTG1IfyGb8J!nD!@k$3{rw!=J+o zO@XBAc*~~NM`JdzW~m-}@{-^m+ru}WoBI~L`MxF0B?gAE-N_kp@j)hAQB3wq@{ubY zvx@hW_cXNRL&wTw$$wv(!4=wz4DJhU{ZGN0Qm3GN>Zo;3IdumN?v_v#oLu@wZrn2| zEW-b6Y2K2fXgp)Vcr~{$9@%`bgIq&!7UzZ&$^(7nHq4R{EQP@l)ZT}EsP;Ld z247s0=HL<7NhFG|fcQg8^GNOU+1Ju4GPs^-dnw$vAVG-fqMNq+PnZ4Q3sf=3OQ47Y zx#lm70c?og-euQItGsfHPYo-T7dD8-zyDNkbwZM@JytOyf`p#) zWnfEr!zgj5fuZ{2K#WitQ{0WbmFt~ed9P9`+I`e1Y+ELZ7Z`7H8dg>?(2m7K8>AJy z(8^V}evnyMuSIwHdS@hP6LY&w*B}x4(CUAD9sm4;G=*2#c$t`3|Dwq7dDVVL6w{}# zfqwGbB^z-4!b~SG`R)|q#OJJJEPC`{$ub9IN(8ffj(fw|>J87wXW^P0eZx6PCAVY- zmafTzuseI}!e|zmz|M8KQkb{9pgNylpeFGAiYY?&8+CgfK(o&Zgg#O5V*z?5CZ?@P zkCPaX7YR1z00iIyiTZy(*8k6yQf9%Tx8It8Y?Ybe&77?-;X{HOd{Xbo*=hApT=L}- zgrvcOx>$j0bWVg#RpZ;NT~-?S&>)^J zhYW&zKnbcU_vx0ED-j3-=g@e8AOnm~D0W`c*jo44FuC#c1GqIa(7j0(5Q(D!58d7l zVR>-7vEJ7pO_z?Z$Kf$Yk#wYKf2sL{{U42FB-9(i<0$ETAOPI@Ij7j3qslmOfe5rl zoO*NlqIxy?vibp4-aN_w-4&eL-dk+x$+^hPt{-z302&#FhI||Qz&XoK)gN`17EvE9 ziECCH7hSpaP^~?do!$M`I41~GpkdBP$lT4c(3#GJMUx%r}A;iXS5i+CUID3 zzb{JcW@A%`@&hiLd7xdN@$+PUmE8{iNb#+qgi(u zWlpPfyA#OUz#KOA9WUiA-6+KnN>PhU+sXYgTQ2(nJATj zOb9$^Hh8_^&iLZbEC3QGNzkMb6F}uDMR@x=yK1HaH`L>RPNzXaI5Y1xX`MfbQ|fur zvd4BYMMf=wg#F<1szRn5sn2(z!f)}^ii2U@L+8zaPfs4S`A+nA$+Z|wz(olUj=qF; z{wG~R?P}eGRXLV})sMicGkUkJ`Eb$Qwa6K|fc8E*$wn>#kjHUai2PU#<>q|^Y$Z!p zk9+-hvCv*Gx-0FeQ+w#Pr3i0H1+E-9UiImc8JkwE6ezvp%&BLtFrXUtNfkO-qp}a^ z;DcCFVH=#{xvD|5)E#_kX2K(^&|Att` zJ+N7sPWA_dO$5D6dr41u>|=lYL_a(gY%#E5KK=}(+qs#A$Ev2?N%R4sw|9~0NyKsk z=g`*`cDSRK5tq!wKS@VsNwtw=U~44c3}dYL43`OCZhni+{xNNbEynYnZPv3s<6!TY zk)V{Z`dzK@dmYAIxykixcjJW4(U0iE5}1i1GgiJPPvo%J838m)c)b)ge_I9_GXQ@l zk!xtE(oe!YXLGxusnaIz#n`$fhjNWt?Us!BAgnCjS4%@-0KuNh?=Z?<48-iRC7JT_ z8BN&YnuKK5q@@s!84pnP4Rrsq{xvZCI*3b~;KH|_BN9qay-;g4vK1M8gHs5|{E^e6 zmbp2g=#ieRb(3Fc0z7Ry5J4Yhf!RO*j_Xg83TOD@<8A zW0r`rz!&`N$fwK>6170LD~r?uJ45Nx4#^a7t!vj^)7UeqvR`Nnkc}tiUEqlG(vw!7ViLJhh5P>oB9^tU%=w%KwQQ;&fYCnY1m>H>r?8JC%C-XAt z^%(`7t$KD0bW-I4U;HJoG5_K>(a6leCaVzf{X3wWI{REat}C$J0Lb-io{ky`aWI^F zS>EWXT<6w((jCewkw=Uf;(u4=(#-xM-#b(zOxDNw0rbC4NVxgx62qGt-+R_4{3jjB z&yya#zM||UTLz%*wC=oo`SQ=hVp)cH(6!Jcc}ZapyN`1XZnd3L zBFlc?b`&({j%Dr6*v#MG$!vMb!C9;Ec7;^WJLE6XZ$9}`%E$2W-s1!BH zrdd?dr78nv5SySOm-fK(%B`nb9DR&u{uVz3x8@bye`+3P3mkiC9Lt*CX+R=$s_gk+ zsND>(KR$FDDLOLigOEZsFEU`#B>omO2d}C19U!7D-rVPZ8K}g`$>O4PZ8Z|43srev z7eWXaQA)ELHO}owg!hw%!Rc#%8#jr?z96wa7)$8K%A7K=$zF|bEIk2)Ngu1jjC+}k zJOF0@WWL&ouI<;`<{cQdh`ZjGo#NDd z3e)|v9fCG;S1$g=rSuWQ-Cducd_jJ-PP9RSnIVCq5)`Xfp>z*iu_x=(3P_e4@x$+x z>Hc@W<^Z{C~aMPj+& z_1{N54^l~L@)ou3ke}LZG^eCq+EZ}v2XrhH{&(HTTW0WM&y%7F;6n7$vlkhj4o*Q8 zPMy{l9ALMUc2{ql{ojp1tQP=FByyefRd;{sCPLo@K02Xz8u07oyIuuv6*oZsFHGSo zsItQi((2t}=^16LtgLn}kkakia-92B=h5I@)KQ%zsTKPgz!QZq}bz7@EI*dt&>o>BUJM27`{OT3D?d_TBR^^(lX2+1~ zq@*i)KEfkK7kg?( zbS4YNz6%_B-|#yT_;~HJ-mBMJH^K*aZRI5U2MzQ7yfd-sv$e;U$HS=pD{X8C#0VF* z@>UG7A5P1Vneb6cS(Tr$sfARo)aDA+FK>A<1N-DrEpOB7-HZex3a%SH`BS~0C7(v? zPrupu$5H(G(XW8$f;-Gim;CfphOnH4EVw(>Os*2Af1hUH?9k;fC2B?$%+h7NUJF$5fm@0=9-pU?UStiz{Cqjk=0h`Y!hrw{evpP~*e-V33>{?coeFYY)b?M4zR zQ?;Cw(i%ZU|FQ_5%ReyecH-{;gtva55ODl`w^~aIf}$_KRmaOUoaN$<-UbZYMTY

fUdD_vg!>XZx}O|3ZMo`EyMFc>b)* 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

  • |1$jBK)ZpE=6g^VQg)*8h_i5+h{H`%SO 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𝔙IQl(pr5cWq}+E50<6ad@@_(^?Z!3e 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�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 diff --git a/test/integration/consul-container/test/util/test_debug_remote_configuration.png b/test/integration/consul-container/test/util/test_debug_remote_configuration.png deleted file mode 100644 index 01b14eada6d9a561bbb4a8b9243babd9463f136d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 285715 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 JFm^Z#- zHxQ_|9goFB%@P_{P9Hn54@u-AFM|yH7y6Clade=Nu0by<1K%`>Q(4ud@+_IEp%GAqO5bIH5 zeNZ0G)g-&T=%rDR8vgK>)3vfnNw8#86v#a;bhu%ZJuq|Ynj^ z7g9Cx3f)B22a=cK$K7GW$Aon9>!?ai--jVXrGU(JITd-L{bQ%^SB zi4$aOU3OgnLf7?e&N}k0}~oDM{5HDCJgjGSG(f-T8c#6HdaOo z1WB6jh(a%`hlGY2Ov%~a{prh&<2<;zEzp2uKnJZlZq9SD^Q8<}ZK;7@&*lmZ;fhXA zGKa3v#hPyFY|o;@*oedO<8TzJmQA_&K%jXAKU0ua{J0KZvMRDNm2ekVh6Y z7jvw|PzrL;)6?dA#5kTprhE9&2+vHuAYzdQtQeWCYS18J?aAW!tz~l~T@Zqd zF(xUmcm)3vDr7B!bapkvW53UgV1D7<_69YXNMl5RWc@Geyl-xiJ~&C6sJA75$!5^h z)qa%l>~za$ElV(VV13VHN4LuB>NJlwpDosQXNq}eZRQQM&VX^KNjBA}%sPA{8N_7A z7vU+6OOsDsE>}0k>^owlVeGR z*EHe(b7$I7XCx?BD=5QxEm?12vRr$0&ttE4ife!iZkL+C`?SrEiD?BqPLF5o=xp0> z>T0E(r}n;8iJ=hI&A!@<%Cr@`uv%>UI%t_)rIgMOvOq%7pi9ZRUQN{R{W%ZjP_NLH z5a5Z28|f0Y(lD-buv%H}*yp)$8lm>qowivU6R$}Hr}VmoN{!DN<-;DQOq_gK9*sGG zh|^~rg(;)ASNn7*q^|G8*>tP%2qI%UWfNR4(s`X@VikEse7_tqLfW)C1sq~&<@0>n zy_cKRNKGuk4NpTE-)9J}LCZ@bv0qN(&wv%XFb zl92rT$GtaYYF)N_yuUcq@ND}|hwn!wHGMVDM!QC~VRPYe%oBpwYgG_mn zMupBQ%Pt#mq1EFo#1)@00rF~pDlVw*q*blYE>XQg^W~y^#tsV&QK-p4f8x_Fu0|~b z)8vyqjkPnIuCQc1(s|XKx!HPK(%_${|qf7*qg#^jye9-C)FB7}~} z&#QM->G}lj{LWaBXtG{jtCfMxW6{h{E(r7+WcM`*h8DKx(w?RG__;q9B<TQ83}=KYU*%H{+1)vAmF50cZw zFT-(S6?Y7ExU_M`fs+>5l3czHRI%$r<^0&rJ9~olPT|+{L9k8fCi;nn-XD!K zw0@#hU{V#!@}%v<<02V?78dgs^IBB}sV#RC6mzg$1*skl2i>zk@~FnrYt_3cR2cd= zabn|m0}O6HQX(h&VoWW&og20TseUz^PhTj-_H50lWFMrILO6YVO6hWyRH}B$>ldqR ztS5*@GBZd8B=K1*bok6}EV&+)vxYM>#2{nf&!n}UEy!XKa>1ILy>EDz*gN zz;W|P)*J{VbC(v+xD#d0l8Sr@HB1o_qNiu<6Qx>^tc?MLhOLJYZ}2#-xyu(Z{!mS} zH2VC!P7h^Gyz@$JO-jNmacwA*RYLMv#Y^P%!qr9BBl%!j$3J-G(JcPz-jfPyEB+~X{qt*o1Ea(YoE%A2_*a3Hfn@A&PG>Ax zS#3vhB-U<-w{=l~asb2X8`7h4U7_?>B7!$gzEvc))K@#L^|%X)}*!AzQZ5cpo9xiFYynl_63;c#vc=q7PYShD`mr=-*rVx)wDaB~xJvLBW3 zl6CRLe%o2wh9vSI0pEui$}G#84-Zi^AI@s%xr?};Ia@mCDr3!h4TU%?+whKX*2qW9 zvDLt{L8CogqIF*iw$d3~OSa5GN{-eYYf&47FfIwon1mX{VqKktzJlFVhp%yN_mN7F zL$DqvM<^7FlR_J}k!K)Ft|g^am}>E&XR*xF*NDqv`ysQV-RuaWVG z8M-I(2o4F|pBEslYYax|n&z849;a5g`=^~+IB|YnQqA6z4Oyq!%@)ba5qtnqgqxKy zMbMXzLslo^YbA*1$m^M=^Xwj8ss5jIyJn_=pRvd|r6U9{>GxgA;HkSh&1}bk6fV7J zGv87$2TTSCEatyh8H2j$nmx4UMFQ2LPc?j+2=@P+-9bfPZ!@pO(!MhqR5H?`=<}g^ zkpHWeNi+YQB!U;dkif|^BbvGC`3Sf1a8w2c+Zk1JQu1fYM(S9LKZn@TeH}_#EX9-} zy1t;nJoc&rNnE~VkA$f9rh+&QtlnsnxczF@PdPz;b(Nm1W%PSV{1pT z$@U+ODGH)S4qnrfwPNxw$gE`9aMFb*Y8<36V{KLrrDv~7h1$#W9vdzV~*rS8I&`w;Hcj75=x0@x$p?W6WVT2cz>us12BonMqlCX?CkqttVDTIeY3C*KeN0o zwdygMApz4FXOe7D=gkKQsxdvDz{Dsj*g`3t?1QxHM|}^X47Idk3kT;H!-xbqTY^05 z!q!x=`WCS9&@)p!v}{VJZy;4^Dl!5ryOh?aR_5d%sR*ElfIKz-f zESW6>OQsUq0r@%V1wvMSKvZrCEno_66-l0jfX>a64=tmp5Ma5`zJxBa; zXq+D&yj2u3GJ0EzT&e{`>E6tURS%=3Z@(GjV|P1z)@!?{hs9=-gCWNR@;RKE@(e%n zSizBUm3Sjt57Pw)8ajF;uTdvtrC}}9($KT&Hi-*f82jok4f1Z2|C$ z-rtSNLR`rnTqY;M=t#&f!fsf0;$@;b&%ulFw(aQ~-D>4oI#WY}GhIP}N+YrFxW^zoq!UJw;@ljLE>QDu2nOr#tSjZZvfj_UQ@a&c*yL{^PE-Gc6 zpRkHGU)-vwz;MI_od<00_uyk`OjMb>>5sBHI2AfF6ff>$P&XUZCAYsQ*r{RDZ$JHV zTJBK2Fl-DXlw@F%qK(BND}+ZiZMxp)%hx@WI=^Oyvm);O`(?rqt+^7s!hj7KwYl-z z95mP<(YNsRwCbS{JCCx-2;N7DzM=(MC4#5txO*;N@L^t8$I-Zo{GUr9bgXU1P`Itf zc9^f#ARZ}C2JeTmwnZt*%>jLQSB-H4r|DELml08rLE*L6a76)Ya*jXn@jC$3S`(!5 zs;!9yU;_3$BagACIs(Zom&92Q567#={Rz_a8(lcSOE__0Vt|}?&Qd#Tqx}_hi8q{f z>#BUPHu_ZZ*`)pD7+iXo_kDhT7(hpdame>CChB>2GFB|z^wOoT=x)orT5v4!b>MZK z3dkz6hpMGbIXh9xl!Liwo9ZjL$x+KC>KlNiAfl@zK`WnGiwbo z(NhCS;BPrX1jOQ}cD{$Nsp!uhW58xi;Jm#;!HUNZ4=1uh>UTK8jS=_yQrMcS`w3dFLVOSt3)WrZ`2+bTu~-he7s6`F%3^`yd4WGfmRnW`!_#+EG;Yk z5(3&O|0zIPdnX$;Jl`RRGC!hCWXky9?pprr#Vf$#K`(pqqu|EkIL2guiva3tJ4Tl$ zs~|k~-2k58$3dgNnGu@%gai?WCS0kPYgtRhmoyZIBO!yFBTMnKye-@Puz8j4GYF9% zwMrJ?$*zTyB4sL2X6xB$1)X9trES|q0+`ggLIkIu(MsWT#!->ycv$Qjn4_L#@!4a( zc1nDu+mX#7S~Vw*2Z7a=)yaJVk zk4T$6P@qbaQDE35wX+D2uK3RK@Z<8&#x-Q-NNd8@?B4OCDKt>PVZZ5??_qjtp8Z>A zW&+xRC+VA2E>;Zz-^|-0CMqY`S9$3iogQ+cR$H|yWq7N{?MCg}CT$1w|K{H~zoAI! z(VBn%<_)0tYa~DI*1|--YNxz49X&lnzg>aMa|36}Utq7Xo6O;xL7=;vh{#1hheD#w ze3RSRBD=j-dn*5Qa|B>23v~?-Kqp1!_7Rhmy(5z*lK(OZC&H!YJ~J9kKIGq}p)RW{ z5AQu|+a7kDTw2j0>fqqeat#*|$ptQ!UO1c6>`eu-e0(6f;g3uAJpDGm8AVpH z4C#9F`$7dDdg0%48hkPB^5r{t4*UFia%2HxmyX_(6`pPEieRo2Lq&%{T5p>??`}Bn zewJnJL%I{$(1v63rCYe>dY^{>I$n;k9WpY_o84CnMn-jx4 zYjWqCbh0GsW3yT^-ek|oI;*9G`j6gWfyC0bo9-)Fx+pqTc;IL+et`Ldy zI1Wxl`h@5)4i){Cf2`S($*T+tc@Ufk6UY$sKsX$J5cEjbL@L!%3CS@&mDAjCjy{vF zvC&#L;UczuPD{QNv=*8yxxi9>QV9m5C|6GYxM1 z>hP6-ZAf@!nwqkD=X8pzh1f(q&&DSl=-us=$4#-ccXv8itqRJ&Kj)Zd)E%MM=!&#D zH>cBh93%Z%AO*Q@s)$E<`)Dwo&jWZwz!b&WcCO-mo%v|5SjriZR3bAQR1M>l ztv5zqZO48Yr@TA+O>#bPf^)!M8!P2hU>*=xh~Ga6b}S0R6PJIX7A?q#k$SktNYROKr1qc<7wCHdA4)+r}5LZ#&&0p`M~?UYzIK$19sU zudVg@8`fxQdu=IJE-Kin!&UKPJwB|$l)G|xWWe!jhdlJ>hjByxX0q46vYkQ=kt?{2 zN|J?Y^lx>eqou~b{8 zloF?*H+B>D>EK0On}5LJ>Bh&?&OTe`)*;tR`uGN^Jp1M(CmjV@srHHYaaA`J(){HRwt&YXRglR;u{&HPi)Qc z+1M!gwxCLB>RDt^2@Aw>OccJo{R|J_saO|3zr_hS0-8zR>T!bg_8D5p;6dduOl__; z)&Ek8+=sGyy+47=a&qPrH$3~gqUzIKm*&#d+gAz=A<(n=yZ6j7FNYSwx%v2Jt=u=L zb$P+jf?W=cmQxjb31H8q-a_Nf5Ii`*_J?4M%1~?^@{ZSyu*BlU4Q-EzRBTP~tl01{ zK9iUR5UE?L@nX$RYxT`aN@lA~kI72j)MTW}OXe{#I1J5!4m-ZY>x~#I%+#1uSEn{t>+r5oHj=#T!;ax zj{?Crm)lnoMtI$7Kb_4tM`^mWYNTC~o`|rRGa2Az>ZDxWr~(_=Yc9Cx=`E9o;NXSe zE%ge%7W0cC!EL#bhT7ZX?_$_}mnYk~TC8+mbf%2qJP&R+--c;l>DO5$*D48|fA=f5 z+hu(Q$s(!gnEUaa(D&(dsfu+>x$FeVP4D+J9C?jIhUX!$} z9?p+6latxFx%prCn)t^hB)HYb@bqp@=%82ZQHDGAW4VphIpf(79THnMM_W#nw9T^d zn4E6x^KgE;hg5x=;ed6c_6;}BuZ2It={Q9)#uFcQ+wZ&`hCiT4hOupYdA&gd#IV#E z$(K!(QRpLixuN{Bzaik-P_qOd)=lCShe^cQ!(}}$iehvsnOfSEJ1JkxKwC;j)81zV zVRM9fUO2d2CYuUiEP0(yYfFZcY_d|qj7RhKjgJxrMyE6p_N&kIaF!Oj$$gkIy~v<5 z5w!G{MzV>_c+PZbQ-C3@y-PkNk<)hY{4yvXb{!Y17^Bzf?zY?M_!I*7y)!4?0L!QR zWRSNdLh)rw)tU26hceV)McS5lgR-)+yN-=pu)b0&GbMY6TATvydJ7N$0dq_ubt=4x z_HNM&yJu}6+u4#94zV?;x=G<`I#*Pi4AiBT1SW?+f!8_kW4Xta!R0Ps5_unm+{>7o zxM;Y91?JbzC?W#nW-5x>i)m8JWHTx-H)@pQN<}>8(V(N>-Z$12yt+A?)wstrxII0_ z7k|8@U8}i`h0fAojq#Fa~$&nRjsO;+6$ z=yUTFSKG6hOinPk1aK^B79wyP8{1tcY&EtJF+Y zE67o0_R>MG1uth zF|I<2LOGncx2xrobBX#c<^u?xG%P{yOmUMuvbNPuzN^C=tM7h+w{61fs&7mq8IQoGF z@SR+w>Q>rk>Fh?_jm$eV{c|$$$k-wFn>P=4M@v z48@DAWh z`Ee}y-Fdg(*yp5jcQNLy35KcsiBgTe+(-cyugl|vSOxwOkTyiZ;xUQb$Qlv6Vy>g9 zLeqRntWdv+`P?;sDqIZ&%z|cfLu?imQ&}>T8ah7L!lq5rabAeG z-+e}bHX2ulaawQk_R`?xPK2LIbxl+V305~}qB~9nkkyi&P)_tW$SqXb`;}={jcUC` zG17;}^H;M$&J`>%XB@;&;a&vsfu8H?fV<6Ji`(Jk?EZ7eTjJK8@4;FFC08f#&;i9Z zxDA8h{S|YA?hEJCwAisx-8VI7+RQ#`Szwt?5$B;Dl~;NdLX!~2-0rN@bqzf)t}in) z@$&v>@GOQzyZFyL7ModhT5_-B;9g6E=W6JKpV#rQF}Nkemv3^(Nm*d?`{}~E3GHXM zC=SQUQsS=2u0Q+GHY*kzS!Y&*`W_4cPR=_u8_Ny;fD3I9l0+4l%861@wxi5p5-U*&*l~ve3-is z2<}Vsw8PPdhQg|v$IamYEof1wi9iXxrJ8c-+LnJwew#70F4^PXg)5uQ(QRV@laUNd zm(Eh{?Vx955&Ewu4Q8zLmGPXWAdBCRHX}Yk&Jtsa>2B}8a1U-BvntF*}8IgSS1YPmRSWg_i{qfO*5XuaW~p!)d%5pDXYp)dqr%elMuv7`wR-AcJ>{&zA7_{A<&iOvnghJ`M!f;BtF>)el8KgRU5&Bs}G ztojXO3vDX8nSjj8{fgGK^B*8W)6*uNyi8-sV~OR+mBe|(?yj#upxJ(fyYMwS0ht>bvbhC?d^J#p6@|WHuXpR|xCu5m~=VJew;sx@UgSTe59m*Nb$6I>rb z`^3jf;P8j-6Q=M+#KDI#&<8q?)u6$6pM@8D8W+|b=3+IDme?;xVU=V`V%A0^hno@a zX#i|k6T#{gvE1rqvfBMCDRxDrubqeTnbR%L)^RdiA>mw@ZuuR#t4 zGNJ{S>n@juL_@0gQZOCJ-ySGmlJO}B2c;+IAy!da)P6-13o8RzVvTb#r1+5=`u?Mf zZ^@j$Qi=lMLk&*RQ?Y58*iER?X`~a}ho2q`>hqheiCSPzk?mfysAYm0ZUd65-AX;% z?L$4Q+r$g3zU@Hj#s*Wl`VveAQc^Rmw%5vKjBs;%HfrESPuzT~^~4Vv`QQJV7__|IxhHM#sWEqL=^3ee|0Z=YmiBja>h{S9l5KVlXHB*Ujawc+M*Y$)Nactt(OnNi+K;f`?Zch zwA=OW0e0|!%m5NEyx#l4&6R9hu`*&IQFAs8(eDAge>F983*}3UvW>Opd8Vmi7zx?g;Qbd^`;;=wGQlG7+rtTvn=JGXLQhu1IY`JVpjMgOWQf0+p0iJ3mwS7 zh)oEXd(II1&+GeD^<`y0Mb)BbL_t~&xCFei{jXRchzNJ2-rsY;{gj;rQVo?uT}5Y# z^9p7fO$aY3LTJr(^?z^{bm;!sONb9(!>;FXcY9Om$-(W|4j85s_z7G81AQa zY;m z2rE@QE~)uvO_a5VR+Lp%T-4K{1i**kt?|qHz(N0t^}ii)C8`HVt3)`;e^2)Z*WL@a zQh(RcBOu0D6{VuLgpJ-kiQ8U1G9Lc-`gvcx&(fj$w)yNgwg0O|6E4SvYitd4m?r%c zuPg7rFYUZRdJ+fDFYML%=l!etG{_{o3|ysDVcbFZAG61G|I`nj)c>=zj=x2;$ks8q zB{qex`x!jFMI<~;jkNj%Mesj;g8UGC9Y~^nD=GS&{8?mh#M9y6+X!ud134o-u2>_P zpmYG{ziuj$MMQ-;%Vf6wXS`n@_g}khob18+A+K@vTpudz1@5X=wNl%~n)Z&BP3wtb zEjOc9MCzxW=-idcuULs>$jCACoO~7TsoaS@_uxP)xVw))-xEiJ6#XyE`cs8Gf{5Fc zcUwQ!KM~oi0ZCO!J#+=WJ4SOWHNGv^_7bvNxk^~Sb35!cwW?mv@KCqrR7|yh+QZI= z!qU3qz;m7zZ9f^Lw=;jRygJfN7U3PM^Osziy@E4_xIfn<=byw`_#xH3CYHy%mxw?w zJt}(c$}@`W%{sGas;iyq$TY{n#+-HVyfaDy3=OBO@#o&xM^evHI4`b(Ebk=XFU92> z1)h#JsWJ8r+E}z;8q2u3HCn*~di63bW@3QVF~R!14vYxA*!%QS**0YpYIyLOP|-)vP|d&!-c!kHM%g`4rCR7k-!BY4dY# z7{*__dR21!rn4>EJa- z3Gf7?^i17=teFG+b)0zfv4Y->k)fUxE=#NVv^0{&yW7A#cMU)7(ze z{(7;bRsyaq>Uu_5{<9nY4<3DJqWO-rx>RM9mqo`Gw|#0pZn)1tyXZ2jpRZOr`SJt` zf3dD{vtZFZ$3eHVBSK1vg^@9qZ|@vpf6*eC&od>lDvrGR{rSZ1$$M|FJYcoeG`u`j z?!sHL5_Rf+ve7pPB0S}<%`yK;6yFPXJ+Whfl>0k;z=@mSpQdJt6C-g+9xAP9lEixb z?xS1^r!txM`3qn(z!*fbk92f6)7wd)PuaXLr~`kmMRl+B%treJp7F0^^MJpsQRbTZ zMi!2>fp*PC!HY5@-*Re>8##z&#FcE|iT>d1G~2S6S!uXX?Hti_8M@=fLe4nV2>jek z2SeN7-mz{Xg70C)l~wZp=#M`sHe88T-^&Hsc7OHoyoR9fg<2)$cyu3xEz z7ymEXm6riqd5foOEf@9nT9#RW%{JjW;9ah|a5;iF#;~h(6mm~#d?wAP@wDv{6-r-+ zeLa7;e9Q8U#|)(A*Ng}C(pET>Ch&~Hqx96sEFBHS81EOuc5u1lPBR^l`zI~(Awc3& zV+$5M8H8Ef`{;r1AxQ7YINa~TL#`-ohINjr_8q1ThG$+xx~puL7#DzBTdxK41n!1*TagH|6L*>_Zv9ZrdCJy*(=v3DLAzKF3>z1`8eajTkUDWI7g+sui3{WRiGAMpW=hU zbsDhS$xp+y|J&Jx(-N3u>HioRXDRlt*z<`9a*-CvaDVpf>p!yqs_r}jjJVfW-#k2s z@s_TfFZO+R`})+6nbUc$Ol#v={%t4kNMjixG=1|FSJ6NhfVq5PrilM!i~UE)0Y3uG zladMtg>VDVaitm4Ff^Jzq2#r6#}Qgiij*bwm1Vx6%TrkPiA13N92Ng zHw1wUk0zkS)j$Rd)0jUaIkNoyys>Y2&*;y9>|@9xnaym7BdFEDD zDH&f3Dc3DC^~N}WptPo6uiPb`&7h_gK8W+j>}Y}6QL0-L{cp3IAu0&JdNUd-h?8zh zZ2*DLcEdt}llS9je0Hy&?&jbR3(Y1|;NgDdjrTk@!)gC^WE$_fm3#0xykN6!@%6&$ zP*ZVLudS_PsSaF;ghTgUDVg{G|CkcEUzg4G$3SB%KW3$JDKkaf3}Ikqnv^O_>*Z*X zq^?6Zzetg-_fxqRSu4SGpGkLaG^{q`MK8l67A+=5&+VT>+9E4c+x!mGzDSZKcQ7RBxK+G=uF}>8A~76XVzVbn`m6=xP(sSxJs@FKqZQm(x)s9Y#vpa$cz6DF8 zLJ1bl_8p7;f6_?)`zQfgigQ;7=nz#YyMcX$+G=Nxw5&&q+~u|$CaY8( z8rEtnEEP=y-Q?1?-}gwo^|r$88v3$A8edElTMZ5Ew%4rD6k20TPTkGUAoJA>Fu-MldX>Vnch96WEQcqsqky;>WLl1VD?h)?) zM!p4!7^%G*^W{0Lm`ju4S^AuhxmFF*0i@zUe@vnU`_Ox}59Ck!|91*sKzAcO$mJ7Z zoZ@YZ6p%ZvTK{1G%b{nc-vbCgA0L{22d+GKiL`6GP5NKnXM7Z=FP+y_E923@yT8uE zM-V~GO_?br>RX=-G56FpE-(EPWoR8hQs$hKZHx=vlG+;?jsFUGnVMJF09TXZ4>ovv zn=bPzA8v7$R@t`1upo}*eaIXvu#59ILVET9yvD+t7oXyA1SFC;?OsXC-u$nl@GKNV zJ0ll6di~FDRbbcx5+FbD)lN!RjpgPbgc4chA_r0#8i+%U>lGuB&A2dte0#2>gs34*xunAOgIVr!0$k zDc6j~b5oeN{yXw^gBOWm6I}oE+h_jtAoG0A6&C?o7ZpFZkkKaJS=Sfdlkxns6v7$6 zI0vj|349mvQa+sgO#0Vfu6Bw$7JRNgKaOzRKg(nj{Dufr6hVamGpL4$EzUNWxAbp^ z;-Leq3BH-rUl6hvq$n+V_twq-K+kV)DZW9>VB0HDMrsQ9^*=I1WlB zw~mFLnEbs;HW<3K*0H)be|~tzi*eHWg+gHZzfZ0Q%XI{kFtO(gtA4$wiOv34R|7+= z5hdPjP3oLiw6D%^xeAcEoc2ms;fEC-@ zDkYzrogL5vv&pi1pf9gF^m=V}W@Vp3qW*gGk^=c($1C~@#NNODs!12@z8X8V!+(2G z;ZIk)k3BUOAKHDs1<8DBpS;zph+YG{wf$483|f|a8g_O`<3y$(4_lhtwuT?CizIUB zJ!I8{hWc=h@TB!_u#oh$sSF&-be{a32msZxnt>sW$GFLGqc>jVO{ZAD-EUaDH#Wx0 zb2gif#cHN6P7llh$B!40^>u(QdXtoITeLuE7va34!e(W)Y}o34`};m~IW0`M@8ltx{8l^ItY4?Qr(;WENc{Ifyv7$Dn!YHdxg zi5fHXt=2pbt=%*E?h)%cD5?b*y?~3^(GA~ergYTk`N#CY`qIP2tltz23oT`R{~*7@ zVPHO56whtHeqS|g-i@)^i~1=TthwSDZ6Tl76W2{NG9h9Q{xe+QZAS!UZ{}N6u5*qw zH{{zRo!WqRY0eHQh~dhz;7uUj{W6%!J{8gK;x8|eIOcKDK_QGMQQs^o*Maw!eH94b zNMd0YKj^C*?x_2X5Jzk`Y_#kT2=A!lS(RiBY#~-=VFCAorI@5Yw9WNU{(^y0q%MFNe zutiXUfI-QQhhNgBugo{-)jFhs;?2aiOa220YGbbJ8y1b-xzN$LnTK2kue-}a1b_EO zLOQ#0L08LO_b~%4HR6ADw0^w#vt(bphPjcSa_+`%TJ|q4;LjzN>ec4v^&8VQaG^3k z1;5m>F7!LOo^t!0U)_gi_V-q2;I*sAPa6cA#J+6LG`#d(h=eSF6xM1s@Z)0;!dmxj z7BnG4^Ld2F>)(U^KCGg+io1(Ww=FQ1&UR18{#LHi@?e`cWR}Ef!VKA4E|xg27?509 z51Bh(#1itypjsITP3*zk4VRTP&mPY?MY;3T83Bsy%uQpZ6h6hv{lqErt;uQ*+eFbw z3SK#A-Mn07^YDqJnZjK+dnLS1i3NRJ7JYUtUOc|-~B@3G!Ty?PEA>KbijGO zEo2`)HxpNLia?%6*M$5a_{Senzcn9YGQ62eFZD}CT(Ae>yHYw9TSViS=XNwwZL2i_ z2rhYG*<(_sG!J)n0Gp==j6*RWT%aOaqTqWgdOWQ*AhN+`ZBnw@8BS$3mthd}64?3H znRg57C>BV@r>qN^N~av){T-B%%d#xu;zma^p5l5Q9pP)-zDJvBp*bPtFEmLnE`JVt z!PkFs%?02;@n2?JkjUzT=p|cN^}f0Ex0?kMee%p*7r%UFXLNv5w42+waKOU)&&QgA zL$bm%QwyU)o&P=>+={j2(G6o-u!BMs&rS8S zJ&95>MJN*eNrw9In7(Ui+5uQz27rfb2R#wNzH@RGH#QMU{eRnxv!qO*t8H3e62Rx@**4 zza)mUrNUTd)+P^li0-Zppl5ZKsL2Vi@13A_(6r~9M7Se-W*xUrThQm;WiOkWn)f;= zBWeq7(sk_ciFNMN^V`bp&S#EcMWd+0V%xM*Clr<5uApc$sg7K)NE=XA(%PWoN+BIt?wLhV8rd& z3m2Z?c1MZP3p@N3Wx>)Bq&%zGh#hBlVWPgVM&RQqEq*l%ss)8~9In*jgbAaRvVYbM zAtJ&r4@b3(x@j&6a9frJJ9{HCZmpc9wL5oGIZFIAe^OrgI&XohzrUZ?beCv2SC;7f zoXdH>77V|+_xSMyy;(>2C++mybvYGHPIG@BV!7S~LBtIm{@3uT8SGZTW{$nnG2`xD z=w6&KJW$uJ$!eA8cG;i8&!gE3ilUp|9Ktz~1CrkQLu6|RD!ip|AA#Gq{)%uaMt{7) z4NV>*Gg;5O>vxUa%_#bbl^O&0uVXzh_EcI1(kIQt{*thwcvh_*_)aA048yuI>ijq{ zR!L~WvI&VusQ@F1;KJU&zP?46x-R#T@2}-&^nk%<_DMib5>_K_{PmjkTyqmUEKI&s z&)}8qlxpw;(^3hz8z|(~IwmglCXlnjYb}aGCg7~OVE<%aXu~(4@H{QAZ|E*M{9e~V zsX4#s+m8HqnV8XwOfp@7dTEj2TCd~Q$H%2N=e2MrNgNUo-?;>d5(8!R0>sGoVEjb7 zNP%I5#zxO;l6=5$;@TO*UYn>?+25bk85r0nXas9{Xx z_!drcL|lo6D1T zaMmMr7t(+@8uiE^spEV)?p=!`dM8QTXs+^w7yY@|3tx`Ke}Z$g4n~YYhB<<5eeU&o zSmtJJ-OnF-u#^^~Ip1Rgc!w70c;^Gxl2rgY>RLKNAA=>V0@(KVf6F6@kST(q#j*Ed|GY$^cq@$F6lZOq=&1P3nGIjCN<8g z2I(ZzXK8u5qQ%GqfU(RY2*2>K7iOkfT(YuI*kf7{kMUX%J{KIJCSJJ8PeBT8&hZwM zX*E_sCm?~CBrY45qUB7Zi#;;KMlrC0;|xf5Z6;>0J%?hp<<$9w2SpC5Jg3lD+dP9J zW*9AWC2v-VpD=-0XrF+W-Ol@5kve0bNtv0^u-F_Y=0mo-Xh4@ zO9JV2W*r`|FvGaG-s6kxKAVbax#=H#7=}@ud(4FPz26%@0uHoQNzrqX@hH)w&-Y15 zPgA0EqQs=1Zbyg7EVc;RpFP!iyBPU^*wKVz4}pfoxUMYT22{dETe!i%8LfIZ8-Gc~mAFU+}q{v}2K zY2*O9o{hPA#hI)=#Xw4;#7IsP$U^^2+jAix?ut>n)-GC`Elk z?jz?gr&J5nfbsd!`U2fmK_&=urZn#;oMw4^=Vq}j#A?o!1T@=a0GlJI#+NuA$U=`| zGsXW&zZg|$FqVui_euA6AZVEe_YF(gC@NvZN1-Sg6_~8bg1h5E)PogLCa;l1_k+5n2g}gS1%#5*wzPf+d$6>4@;&l<3h_@RFO_ z2GctB$G~KQuY_oXW@13_uynTJxO=9Bw+Wo*XRoj9QVYD+DalpobL;9s58Nd-V|3?> zq#PLYue_eRHXQ6yo^nR>(L}nBP41J=Y>rFo9jXAI>(f z!;0k{40&;S#Lp)NOP&4@0~V*kmLFn z#oH_Evs(UEKYJRyD=qo>YR+q=*nd0LFD-wxj1<4bs6UwxYw~(EG+WC}MAYMqY;nA7 zM(PyBm*XCl#S=>ymme3yy^^fc$#6_HAZV=b2qj9{YmX_F4*sQkvTMWTUCFT=tT zqw0>xr0Nf%sLL5>ddSb5WT;hWSQs6`e(k7eF*xQUlK@0?MnKeUmEgcY&KEvA%6kMf zPmd7#m;2=d@7V4kIWn6vAD--ivS6PcqyX}j;`#Tf2>(py6>@6R6xUBYCiK!)U4&?A&q&; z-d!^GLe>qafpC~E&-q9LlF}T&dyj~XLC=--BcHC!%OjWdDso=jAJEwWAs><+O%*`f z_>S|RY?x;e80+sc{qjQ6ib-tOEj6TW6Ej{O=8Ja&V86etm6qu@X`P=^2V0q_Xn3Mh z+=xTOIBtttP;VDe(>Fq#cL1)i_c)RpkHmdknaW<3#SO3*-ttpRVUd_I)Pjp*b zgW_lf(5u(f`boXhc+ldpR~XoPvbXcO2E8#O4s_p3t$3VIA*m}m8&(nBxlmKyLf=Jk z)S9NUF#w|I&u0rw4M|=xAdL;dwdJ32i*?5Dt(-Lbe-RPIAcX_0P;V9rXegH{qr|#+c^2Y-(@64gZ$)2&dx(3p+&ByV>_k%$u zRtxqprwFw9jN;&Y6rr>L;&|C!+H~p#yd=YC{V}=dnT{vx{O8SSI*Je%!a>)NSN)cl z^+m)-APd>5S63TbPc-x?oaxF&AAwkjCN;^s0KsI+s&r>cSo&GZ$j4@mHD8}u@0Cu! zxj_F7Qpw|4U)Y^Hnf3)K{MGX+o_onZ(@sEe;_=-Ui}823Y(^QqJUOV2dg1*#&1(*e zUH+e{NM-=ROAr57;+Bc^IVJdk70^BR=WvH<6wqxiEvG;d34Xk2nxA~Y{H10H{G>otMZ7%Z7x(SSl>KzO?awVe3Pc+n&jb&0!n7cgU*Vs3+ zIMJbBc-(E&!k8fR!8|>w1t0Cx-v4;istSm}v|(05jdS*M&HWz_VZAr;-%nRCokccq zokgAbe?HJ%x-wP!9V7IaRh#d6hNq%P6}W|%TKBs4eq zCjIc8(Da%$ZAOp$Z1v;JMl-H1uP0S5OB2V#JvSb0DcUVXq{x{MOrL)HvT@PyN+o~< z4^#{(ZvS1_Q&GnGNh+bUcZK*nwzl^Ysv2yYmXnJ`*TJr{P!xZxSfTdq(vyz%1-Wgb zkI!(93_jiPjD>;5=@b(E7XErjav@o0F=ku?A?|?Q4Hlo2uhwn8*zYa*yt%#MygB{| zF04J%bGd27?^WwYEkvWpqFy{TV?4}d}8)R?9ozTMUQz)R2C}C9v7d1Wr9hMMaT0r~%x&0~;g&Z%?<^XkxmAix$EX4t;N+ zl-LqHIcK_xw_#@e!kWz+tOEI7qG$DI<&hK%UdHI=qoYm1gFfF{hV0i_A+TwLHlrgT z!uim$~)akf5>SOje0>tfn7T1HOa zPHRHZ`1;k?H06I8`+!bS32olCU%)|%5td^w>Uf58M&Y)qd&-8svGv318iaVX`<~lc zUgCH_u{s|)zSv201Z17GAt%1~u<=i#tm{rvby=U`j?i&I=vYmabVleMKB_z!i(_%* zj~pI;MfbyCMTcgp<2#K_H8i2IAv0OjH=#WGE)MMSn7Pi$4QYncbH%Q>(tc0P!1!lR z^oCBVhlT;V$1;L~NSO4u#ErL*CrM+l9}eI9l=E7Z-N|L1Jqd(+*_r!XJyD z=49i%{R9jJ8SPL*oEM4!*!wrCo&LPwO{1^#uc4hk@vjOZ>z$k2o^hboa0SE{-xDeA zKI7n-p9Zfo2w8OHWP>xQr$NQ!Ez5#yiXag(oWxAm(4!*# z*Tvk->Mid(J9(7iyoK!tptm*gfoues|6yflN7qJ9f+WO84i^#C{;KoSCeOj~ZzI_2 zltM8&-e{F#M@1q=KO449^cJ~r!B`{6jAtDLRLb@FA8Z_}CC_`y*nhJTv$3H=G@32J zp|33FCqq0ohwF3PHlrQ+3=_NTG8oD`6s}k=)e4b}xWZhzEp$m|P0rT#e5rLm;aXW$ zppB?mqR$|o7&L3;$*C5}!fd4ttkJT*dS@JVS z7aKPp#~KVO)}<(xH&VP5cN)c2 z2}&{c0a}{Ul!e#jFRM!$SP=sKV1Pu1<@CE-cPk#HbvQ-D-?~j^Y__x>__9=E!xlJE zN~V%_R%RpLt!e~?fncF~E=Lb-OoBH3Yopi?Le)v@E(>3F|_*h z9M~Ods^f0)+VL_#E)~!ocPPjp;VVsnYCGV$5wm%3m57eIS=%U7wQc{^Cw}@$TGNzTF^-k{(nmnZWdckNvPUs?uSVxbWo3 zkGwnDr;}1e3fZ@L9?1upMYxx=?%t=ny`u@Y;ye1iYIL<(B6E>xxdjR^KhqZBa(mCD<_=HIkW#5 z&rbvQ7WZ`H)9r&)LDxsyMbV{Pz3%0u!ryrVw4da)@=|jYUIr8r1dM8E-3s0^u)V#` z3dNoo6X>Sk)KOCmGi8tMnXV3S?-ot;n)8L|?KzE-bwDo6y3(qRR00-1$=Ek;C)dq* zEhsMgQ<}j4q*6u!rwnxJ!KQAfoht(w{vK7;ff-`{4G{|^r;*l*C>h@?REak1?D1Uq zVa7%cRS?;E$J+Z3N&M}Z1nmS;7WLU+IkG|wr$cg4$ zFp_VD^x|RWA`GV+ou-8g^8Yq32Zg0&;b@Q=MD2t8NJ^@({2MR3QSu z_Wfg5enkp5o|m{xs9-KVe21k+A|=(aR89C7_2*yXGF0f^o-s3TEXCY^5^Z?UL>-cz0V zF0MD!9bm6N~q?KG{d%x*()Sy2=iVORvmPCD7nabrp`s!XA^>&gD{OBJyvc~A$ za10vWU}A1&zN{7@Q1u~H@!=fyRV(?38}lPBGH5oAv56?p^9BwaJf(le zu0pnX@7QHUDFZ#dTX8<)Iph6!}j8KX-9qy}#JK-+M3MJbmGb{dn1| z=`*c5p|fj+j9jeD2c$wvZ97_ZP7n6>ILQ|~*}B3)&zkvq@1@E3b# z7ued0z7ExE^G3LC+}85Fv3}ybP?&lW6K-H%`I$k;LBi> z>&jh1v|VoL_HcwS+;t_lbI@aH`mp|8`wl*u+POlDgOvtV*7>~JdD&aV-Wl^c!L>hM zFUc|b0>os=;Rn+iU(~^Pte!auC%+}DbZ^aO`T=*Vwy@5b5<`*59mkhijR(7_0~cw< z%fF5Wa^L$%^DN**j(xk~2FgAK+U2Is3GNFWcfj14v|VcC^Hd>UOd&j;^q9lTGb@~p z)BA&MhXuJERq4I6O-S;>%NntfDaz;ZoyXxt9+A+!2$QJNCYN;it?r>lpEO>grU4P&|4}bCIv36hczW5!j|1J zN#j&}OnQ5X$eQkWEe;sFDRWr+S4qKoC5(f>YuInV*E3xD=vSB)(*2rgTT`CV&f)^l z$ckq*BysUw`JL6(VnrDN$(-%h22b1$v7qaYn!CfL;!FykpHcEVs65xzpP;%Qmcu5J zzi1AEmQ@h1$J|q|T>{fuUAzANz1Y*G>+$+vOv1N?^0I~iREEv#g)@+~$&+etzVZjM z`=`dw>^2`6Qg(h>YO|%_Wr22m(IeXkbOH01q!d;YE#^jT-?y*y)sbY_y+wlpNLxn> zA-nrqWe>OA=UctA!Gi;7aO`hLUcpu{fT}>R7D|#+-#VJsVg%+*Cm5COnzm#di(+D7 z>XhisFo$WAY^FT*mM7NJW**D{*TkNqx(n3EwT_@2Wu6f``kTlF7puBSB9-&QHC8sx z^w{rH3mv~PuYiSVr*E&vm0k5ac6qM;m|bo$pn*)k1C>vy38R&bp87S{4WkHaQU4Y?#*Q0`3jkYk$6?_pv{t{9^V!)^%8w?gUmm>S^8o%w=YwU0P7^@@zFH z>SK$miY%Hk=J|%xM=H_6!AF+ByafK3ms7CS)5`Q;Znr>ho@Bd?755l^xwx@WtThB0 zH|=;u>f)c zrZnufw1JIsN(Jf#6Z7{cgcgad8r)9wFx$O<;bn3;L_IR_1z={g78jp7+ zLe;ioN{uEDC^G~KF_u_bMY%f9m&Vyw1~U@3OEemds-a*<)TU}^?x6|$ot?DlH9{~6 zB3IllPH=RqZSuekK*bZBcBzC2-Ky7*=ZX1wrz1gWC{66#E)Ek<%e&ZpH#1);Eru%y zc`(mObRr_S{UjfZYySX-OFTNb09c-3{-!KrgD0B$4i)$NyEI~UKbycn+x_0)!?lrK zZUYrd`3u=t#@<8*0geNJ+us-e(%!Ie=;M4)wwl6eBxWXJ@QVj`%lv2aCQeTy3>cTNOFe4z`n_l4e5aPHkz$i* zFAEC?=ul4-eM!~?uWD(nkN6SEnxhA!@l6{G<2{|895rVJ+H%ZmzKCWt=^0W?Eo!4R=z4rlyG1UNS^C zxd{Hwp*iv@;2RLZFJg!OZL`;IJbw3PVvy;vnP)n@Cyti+VD8j=fAJH6U^+CX&9IPy z&yGID@A7n|%4G>R$J-1IZF9U&9T9y#-FJ5ue5I*80@TUp z$c~QeVX49H@gYs_2P@N|OT7fX#=TiNSD`0Rxk7U>(6gVH0h%3|F*4L(SgQr)J|qcE@R zMp6<@L$BYMJuwVnC02>E4;JEyIvtZAvT0PB4?IE>qyw-_(1hp~Qbw5o_sURGK2?m| zpn>aI$}ir)#3cYuOk&%7d8<)%Lk&BN=6ctaNUzJ9P;I>|^&<7hj}=(Bk~Z8Wl6H_QiQ*@_)PhHzh!UOl zl=Ldl*@b)Wdr4*=N+#kgT)T0x zE#U?r0uXYP9*5w62zpOoq*hnpD;@C0G%Emf=G_ig2`3UDW#gx);{$p_ z?{`d0nhly&GAWX0;OmY%MFT--(aAECcTJYk^=Gwj@lt=UzkD{Dp&_=z8%T+_%^(*S zhi23$Q2F*bk>?IC>BiY~(U8a9&K97ZwUg`TfeRF5!;Uv6Dtp)6HxT#G=Xp$(D_;gn zAvoqR{frSpe210IgUqN9kv|a-1i?2}L{H97+bTVmPK)JnK)*LmH>?fu{?zrw)}*^R z7v!!*v2MIuR)0bw^-V~g0l4~AMKnTUJu)w!>y^ovWi7MA5$(45fOzp+3xtQC!Q7niT>f&HR^4XNBss`M{elM#4_V8>yUUj}y zJ5q5vQ=$a#7qD+#?T4;Y>7u^4T(I=L`FFGE>H12y?P+5jk)%1-L>8Oj+cn06ugt7k199RCBgNIpVRi<8D=Fc>SBmuqH@*q8rIHU)B{21)pDQpl|j8H2qUE$BpiZ=A4lo?Qavr8CaM)mg)~^c1pcSHNT|Z9S>1!oz(v59}=zY z$6-+PKD@dQS~ZbZlh3fUKl$iGMcJzlnRW}gkFu$UDc`l^!fPFWAf$}c-g1u?{v3f# zzP4^zZA;K_+iElPY4G;lANU-S5Vb9-!|gM%^M>LdJboQRL__6ruQTKQ*Ob_koBAL@ zm}dYpiIpFA@kVdi)fcdPGRDeoR_*{Zs&L@kHKJ zyrEQqS;7{3>oj0-EaJ~9RJUd{P!d%- zkgUw!cBFn$`fd=!2gSo}_>PXY^nnk!uuiekYOtcrc$8EHWL7>qO=#6D$)MX~lA9mW zX0m6R{bfW}$~F6IFf6EL>aQ)hu5hwTwjVfOwBhXC+V?XdoY81_w&Kz7wevVKW>U+q z#cDGEl@m4Don==a$^V`AaX^dqE@}>a$;2KLufgUR*wR=>%hsgx0AXgoQ6j)7+_Kfr z)#T^rXC7ZlHg0(Y9W-Nw4YX^fxleo#o_8IfEO$7nQ(EaUy1z?$3-MU&db~ktt?gJk zfPiLgUskwI=I8^mz77s5w;crpm8{fU#p#H6S$pV6o0bND7Qi+kD)`K&&uy09rRXzI@FGV#Hrs)x{^1+ z@Qd%T9O#o@DqH~GZCBO_4|$7zzu$zfR-RmZfk&FqFeN1f@oPu>XmcV**_H=ZsdDE; z_=c4z!y1YTr$?k_g2(mg750FIG{K#_sMEY!uS&H_#>FkOV5E#<)?TS zHP?RebB2;~K4e!`$`E6i8z@H}#cokCI#`#RwioEv?|Wcbj6pghsp88=H~Azn|4RNs zX@3<4R=|Iit9)~oJjJ)VL{GF_p2-I=yN&tbkSDU2o<_a8{MF_hkN-fxcx*DE6V$>) z_ONQ>qDA)bQr_>^EccbCfv0kahoex(b8VbV0(RK)>LuI-JO&i*Q2&3cx!BFP)5L+^&0AJ#u$K# z!WYNGh(vl3>C=7UMLaUAfz*V}G=tdUmE}zl9D5MNqklLLQU4vAp3$yhd(E%J=1%$V z_s6}$u(&K4D^z3J<1ev?i3)wAlZpIDswzGj7VhWwmnGrYp|8{C$+i#ZvLY;2ZeYKh{T! z*`IVAhwDDAabDn%n9yM4OR%|b(YMN88sZK{^t>|X&~H@Gf*Fi~$2K>57dT~gnv8|x zelp?g1|cyE`!|kaULfZFP+qUrsC|W@y)JVY@i)ndf$|s9ozcqOaz6{cUt2$)CyL`; zSm4LLYtZ<-k}vIEwu_zBo zPrjPVD=!$kEK+W4Ju!Dre~f6{dyqiLT32oK4E}_ z|JEdLm6J)yxv>V+C~eQ>dutLoOs;{6dgghQSWC}=RR{jPRdPk7yBjYkv2>cj^w@Q) zqWALS`I&j~_1=S~-wxmRdxd-mt&PElILNp-f&`J;B%VscoNB51VyiY=o0+2OvX@Zl z34ecff}r>ByHu1n#?aQP1N;LbInF}Xn1Jwh&;Metv!YG&wuP@9(#1DDSKlI=okuC5 zG>k_)G^&Kf|Gib|jnjjkIb=?!vK*eJM(3CUInOKOwU~<4{rKWmiqmvMcKx}z#Ow+d zbFTVlmwtzXZ@(8Y>%i=?9?)It-EWM(xCo1mer6GvX}6+1e7cxD95Ffc3jtI8vFQx% z+rgy}_F!uQR}WQmYUw?HJvgB~w>%oQoQ-cw8o$J<1*x^JYv72A} z*nJ|0S$rXMc7@*a%iy-z6apJcHa5q}su0V8)ZahkWUH0Kiz@>wlEZ?Q3f1y|DE)5c zV5j$3`-Y%kQOpqQf6Sj!B>E@a`z4D(%j`RBojY6o3y;#(suyv%=^?82MWGGiST1aL zIV{N#*#cq|mUZcX1>AEdVXsC5{Lkn(jQR5z`p08|^?%{RtM6Y4ultEPzv%RL9~>=} zA#b-zVNc=vxKq#G{<$rg*L9igu+MdH(1&6wikwE=?BTnSt=%P(J7r z*{nHEIFkgyJ%lqi~67f#^I_zd~&3CBT}l-C3G3StXEa^d!pSQ&ipUJs8tmfc5x;eZLZRAbv|=J2)7;k9!l8@gYm*PMYJ#a8 z&mO1e0cEt>*&(?dG|GRc5B>=USWR=cUBN%WY@c4`pv+J)K-XkFA#-!53 zHDtLutX_aQlQoU9-ETRAH{Gmx>70=#>Mw;w6{vuKVgg8qMBQ9$@rRIU^5c=bK}(X zumi7pZFML|GILAniU1f9c$Aut>@-6q@iWI}Bx`c8_15iJ4ksoo1?dIFk-@<$(=l6svkEt z{2Sh0yFT~`ILB^R>P^$5LS5z9T2JX(4qER0>s!<1@!NQ$RWA!O-Y`M#nkZLqKCCtQ zE*^e zP!asipQ@();{F{y_c*1^^RNM`aV4a#d%g)QkuF2VIRT$WOrbrDG@s^JKf$5=7Tx+AlkTEyI@Wr)q{lN2D}`2+I|+-`yiE*m=Jz`kQge2KZT ztV_^oH*_SwhP?<`t3V2_^gM$!wdihBgQe?4}e5Hf33eZx$Co2 zM#KXWWib8QRnz|yOY=VTL9XWB^r1`rMVzp$w2=Q62m7>ZWW}t&^Ik?|*4Fvmp>XFM z<|;`u8{Jau_^yTLW8djs_y6v#;#vH%2{G>XYp7nS#o+vi-unf4q3*N$>n(xtxvZ*A z{F>I?Y%!-_wBO?&jv=?EmIx*5bd2T3zgpef;8JX|B>rdCx-q=IDD+LS|)i zZTJ)w6{Xri?g0}8*>87n>4ym)U1hc+AnlH{?E4HQr96G_LMh;s`B6fpbJa1;MB=ox zmO}4-%0x^1wYop0Y<{9QnVXhh$qes-z4s#ccNF|nE)fX=Tj|v!YfMG^OX#{XNgTNT zl_}zvS7Hgo?{q0~_}UMoffu5or~uM)6%f9G>io zd$IN3D;UD8J0tBYVDNy|z=~2qIjM|%AuguJ{t8cL`hLl?j%a;h4)wqJtpW9o7jJbr z-5t@sH(OaY+34+>GXoHtb>HWqj;7MvoqZ$i<3vnKWSaHU%~F7FHtV~iQ}?5W_paU# zpsmx;#_SxN(2+>GSzY<7G^RSU&le<>y6tejnnr4Hw|bhGzwTWNc4k*mz0*lKJL_}} z?KP*{5_%z0z^Oaf7utQ$lf<;BJg=?Bk9&JnS%YIgQ}H0x2`|1n971=1EaczF5Uf^A zELb6WCjY)WH$vpU#)>kOk0DxvQ17>$aUGyU$K#@wPi0KGIfvCSEPBa$uA5qHUK1ua zFywh)K<`1%B0Lq@sZer1BeUrC4Z+a$%cC0h#4PW;xo#} z(;cJNHrXnalDOjqYSQH%ygS|f{rnM05WhyzVXhN8RbE53b`nhD&2o0+1Qs=&uWaPA zUB41;aVY5|TPRP6z#Cq+7p9S?{2(AtAaqrh zB|YZ)19{;6pgB{^^`)oGcwqax_bk9Trehc^Tf`d_7q1QUEfXj^g_%{e=`nBJk|SNU zxd2&L7|_K@5E2qzNwj)QwT@sN?Zj7W6$6O2OSzfhg1bR?(*J2x{?)F$c3t@)h#%=L z_q4J8O6Xn@s03C71#ySf&+UM z7V;LZHMf>ez5xwhE{jHyiVq>bUS4Kq&{M}*5$`Eb&9V9Mt9)u5D2^1d`_wel9=icy z#K1=>KlG(Pp?D@`IjsXbvk}}w5w{f#h{u-Qk{=stBtIzkW!Uyq2LX zvP55Y_fL3!n@bB0Bb=gQ&$oLCZ+q?u1THQl~Q?iI^g1%GP_G9lEKehBV}?@$6-nzF9 zP!ScC5~U2JLAqPIhHj7;I;5oq0civVknZlz0i_wb8x*8Vy5T$HRo{Ex*Z*DLT6)*$ z6_`2aclO!)+0XOr<69J($)2?at2*TY`hCjMVAy2_v)T9qq&-{8jH?>1FhsNNR4JOl zAgFJH`kwtsBLiZiNBN{cfOe<_9hJ8ASShf->UA}6`n1et^r7E_kWHrTZx=DX! zkoWJtO^ikPK!=I~<-Gb|>q001lAKn2RGce+)rKf2qx?~E>esJR6W6~@F7hb;zP)Hm2;t(#p`ZcdkBZ=7;%W(OJU(Ki>h(?G9%J~r^3^4$;Xc(d(+&QG12^$8QRDB z9U45hN-gJv{F8Dgl;!;%X+X}GGmgA#R#!&~20-Fej!-xo-P^XG>0(mnweI|Ct~i@x zoRg1+4Rh!OC0pzr0`^pIVi&WJkdXeVa+xEtFgjf!|It=HKE8&AqZ3vSdjEDRiX8be zV}*xwI;qtp<%xtW=DC(VQABR1GL;iSwg+a^WUD3&ja_(rDhW@MPAW!knE$9@x|!o>2DHz~Em7vjN(=_T_>sW;p=^beuZ_YF4jfOR3Wm~LI3 zJbX|``F`}Qs!jK=4Bq`4@pom&`B71aNzvV4ONTrGZJDTn{q=|~mp$eUL}X`}*KzFy zj-*O$ytC%n$KnN=FT3*h8lE_8j=Uq=Hvia{@hyjeO#Ixh1s-2zKYuAsbxM-9xNRg; z=G`?6LjGm1%C6<4*Ku8z!73tU;h=jfG$2Sd3-X_i70@(-ggv*wleDFr1gR-rBP-R~ zmTHxDIE8}Yw>BA}gsayvAQ!G@0ZwXoCVWT1Jm+^K8p8t9LC8tDiB0j~KsX3LX&TPM zw855AunyWIgMjqo?%}Td4GUE>iW=#zPFmQNAVs$+Ejg!r5^Hd5Tk)R zUFu5P#|EFITUh^DoWC&MFXSjvahx0E;-A@({}}xGWCorQli&)7-J{C}*Mt0?ZSMAc zBRIUJU}8Q&QVLHBqB@DqCphm&9uG{Q7h=Q8iO`R3K_GS510kmN84ee+ZmJ% zgXPu1h%J!CkE^1Gfd?l=Hcbp~kLRM6*Dp=Ty=`}s=WV=Vnb@<6@=x} zU*Iv3MhCc8$(}DH*@jytJeIpdv4y}wz;-M<=MGWkaWylA0Y*TtF0}IsDXq6jRfR_q#+A3eZ{wjxCUMiKqa&x(int)a%zD9ca1i zF=124w^bVO#h@ycn|4RiCN!Uq(O1c3C|8Vb;J_UC@?XzIUg19ahN-I+t4+BMU{IB& z4CWd)e|O8P$d7A|tO~o{(*15S|HZfZ=YOAJUdDk9_+EIt6TAhjzts2z8wX)`=b1)2 zmHd}1@7*Sbf-xg)mD3)Kl;!;~%m}aGjojvM1165LV-;>8W!*OrlZBEo7@nDvqpu&G z87{F#E-e|30|!tWe;2t*?{cX%#b^y(T(U2$%)4I&-W$%Q`pWi}5jGxAr*=}QV`M|9Axs8-h$VJ40YHwlae^Hw7RafzUy8)-K;Ek2mVVZ*8{+3tx~ z0T85#&esJrvfTEbQc(pU8-Cy>NCs2DGj(D{fJcPb$nctnYK53S%NW(L)#NwOh#Olo z$teVO9fR2lCMhcwwyTEGJ|U)Y;M71l^*V8TG#<+dJ zVe))?F?v>RymXUg`lNNLM$YJQ^lDKmsl)^6TEg(oHLbn>%I<##%YWXsKmU?=8SMcM zLKXs+i&UDJ07?c4pkP_2dO2Tv=fo6mBuFPYg=%~hGps5EawhFnO5;5Ifunv!Uizf;z4i7 z$Id{pI(C6_uCnTwzUz2DAEoa$;1T0G^DN~4)3f!fE_xySr6}=~;pjRR-8J_PldFQ0 z5|@c+A5I++019vS{pyJ6$l`D0BAP1JA0q9A{O^3tIOuz)rlhChtWzu~Jc&e8!7tvM ze*vmE5x*IHe-Bc>UZWAe!V`$n&_sU(RVL$j{*lB5tIT0th28m>>a6Obv{0%XD`b67 ze|3)Ph*GvGZ@|V;QhN4dyU5P~_~9Y)9=)C6!}asW{xdfGdN1l%#2}jZwI6Ptpx&TX zVTV6gCToR4W$qJT^I_=rhgDQm2v()U=#0tSinTz%7E&b`F+~?;-LjbqQyT*p-KZ+Ibj$a`$TGTtg_V&+q#C%`e#01QgdJaGT`@qu4ZP`Z!LjcR+^Sip|E z&-~Uu?=e};jk{C-wm+W)(3WrzqHEji1V_imvctLDgnrjLetu_nnE02Csn^vmC*`A; zgiBt#c_gm6wtT$&ZyOf+?vff=tIq`vD(y3#izoE1^aYK1bg;3TY)bi)Ffa=5+bF{V z2sOyZz@3rr%jb7DsvUN&73~$*V4^_nFt{aCk83^zRAzaNO>*eC;hnl(IwK!rbizh6(;TV5SZ2oAzO z6g_kXU`(qC644$<2SdjqdzPCx zcH<%1udg8{ztPmx)H~mSJH?KT0F*Di)Z zua|s%Y)5VkcP5>xt_r`~YIC2Oz1W-^daFhZFXicy;-QA$*7kF)f?Xfm^$++I$g@Ta zMaJmjZuFerGK4?HXz9nFa1d+X*jWuPAE6fB%c<0@7%7D8!=C!N5wP%E44`v8@1L4r zFCTWX|Z8PD`EE=#239~jGE&QBk&BpQO)hl9P4WSEIw&-~(B@sw}T2rM` z@n_(JW1>Ct{z*yy6&?Sv_U?>Ayj8WDSfvnEvc`Gan=Y3cJPonKGj71A^NIFc0Duxr z_pT^R0C%%DS2Dvh6JM=~_O{IrT1KaNDVp0|N!<~G3?+`dk+jEdN%n(QNVaNOw&^~A zRr`Ps;M}Um@k>yYu!Xqmu>K#X>Bl07JVhZyNALinLoyw*j6v)ANSdeExf34ODqI6S z^n+8dDHVH1i*$idM>92ED6o^(C z?A5X{EXHy0LpGuYJ*=)jCR2*+*umnfQYlH_MNk&yAA+7FKWKd0T}zNN3q5goZ5%?_ zd&8snI{uZ2|GgRh_BZ4oKv=(xK9BY0&2gxO!;x&@uuGPSf>!ojWm&}{CUB+IK+h{u zlnmSJ(CKG#{fLGzIt@x?Xp#?zI3!CBJo{&MT4cI2CyKf2h{Tk2JLVD-iBqb;Mf26F z;>CPVLc-{o`GPP`&)2VC8Qso3UfN&I9S%`Ng__i9YEFlm@xJ9z$XAc5g~Lfs0EX2E zpb3Lm0pl)CAeI{h?)Fu1Afxn(pw$XVRa5AR*{d2=eW|C11)A+`is2IocAM{<0N$v7C!vP@RPqPoIvEUlCKTd9(EdXt|p7iEv;u4vS_KvZ+3~2Dn{Uuiq&i z8#YZ+6*k6(5p3nDABnE?7F~5f4~d%F0|YP&KOdhL{`7*o;^voSxGaLYN!a)tf&HTt zVfz_prL~1G8#Bs$Q>t&#@5}iQFNoLgBJaX?xU$+8Prz&~*TVK`Hi7d^W4aT)St8Y7G-P>Oq-)Ftqn%$j?@93xA z|2)JalkWdMjz8qCwi%%OW8J+=+Tn+>wrCoyg0faeSNlrrIR?(x4&6jJYYQA|n;HEO#sZDA2M*$ZQY>v`@ z6+B6O9klhPCS)q*R`V39)izmz@F=+2tygm`W7b7|3bj;QhYsND@U}Xxoz8mNvfFRq zcg1l;^7GF+qQ5yms-AUl>R8ypIpMfVA!tk}=Qh1t<#x8Gq{A1Xg;FSme{htMuz-oa zTQ1Ar6WH3jIPBK5yY0FCVuy1S%&;bZml&%k_3-3pRq*F~yNTpKP!oQvAhfbpO1;~h zND>!jCaFkq%sJ%CCc3PfysUpsOEs#FUN9swFWts)y$7~+dO5~+*b5DN7$ER3fe~AH zL?j@ll|9H83S1dXmwYsz0Q!s@HYp2>Jj zwHq^FIwTD(bJ1lci|I*aA~n11 zY87=Ty3x6p&R2!zkYQAAmpf_>;83H?mz(i?Xm}R91scO@$|^DQ+14_v7`JbSOYGbf zS0#xrA)((4IY8`n!g<}VfSO6DibVf>K2qy`LQK4Jr|H0gOA3L1i;@?KBarpXM{RwK z1!2m#(j3qn^6xGrgcx*Mzn*1n0nYV#qb#PQ#2rWP$Ka2yj<&Np(Ue!Ost@fTR>3ik z*84nL>^MAj-xUGN!f9kQgd_loopx!_Uag>z&_m0zy+z4{m>$2pfFr@%u9`%gZ+M;a zR}O+l_JP=E)(4^A9mtZ{lXnrnJdZXX(!2Qiir&Lo_r%z17zAqnR@S<|Bz~n#CeDXP zQ-FEdX#3VZ(C*J!Id?{*h~s!FIr%1nKmYxN#!`|kI{94HnceE1pXW^zaL91XlXBV~ z3k5tN*O1BC0%wtGj;iESneD0~xqcRV`K;-1Zq{qtHF47_gn1lj=O<@3pJ6q!Gqbac zRYqwVXlEgY8w+Z;>7i|3NSdc)Qn*t9#@l{gotTEM(emYqt~5k{%dE-gtL%6EudpfY zk{cPaa7S9ul##qe7u5k&s%0ghv1av*Z08|x*QCgEj?&nic1bPFX<_V8SZvTe+dG)q zJ)7K|@3=(u-5$#_W=x|^Lw*>sFj_&UcPa5e|MnCFTGqA=|k}4s$bMRkITEvx}voVHIoK7Q+UJ*$dDx zdI@^cAp(UTXTb2yWtw>O(YQl{gh0i{j+`;;fggv`DxNrrvog4(=W2yy2bzbKD!0oT z!LJ(ePuWH%<{K(9+7CF0{%4Q}*Bbc8I0y8Wm;Z~F(D_MIS1)#**yWp|LbDA3l^c9xY5VMM|fmnL1<{=ly^aPk1!5*^`Oy!A)2& zwsPw^mKoTVy~Emv4|jEn)Jc>oSJX|>#@EC^c&_Ql8olrQluj%-+N3G*EafQrGQ%<;dY2VO zPa87!RTV?OfB*XQ7P`sMQX|HMEO51+r$(Eydm`Tpsmoo_H28@jJ?7ITkvd^FmlAAw$Eq!%~Qp@YM}QDyoJSR zas=Mr=?B`}+4UK>OGS^MYDT+DJ$kh&L9`sEqpwqZ?;nnu(W-G%uIhqFS2(ox{cB_D z-a`Gwxi}!=hYtNXMUGld9#){~mI>lyf2d7^r*G4iiCG%p4T`gLt7o7)myfSNjkQ8# zLTu)aZ>RWaJSpigvfIp47bvN0SNyd0T;<2su-@4QNpprbQ@-_r^JCPRxz^wTP*Me0 zh2t?9rv~&n9c@F&S#zw)&GR+k)d5AECc~yj9&fV;3gAv|V(#wl#XdbTJ#k?__9-%q z^)RWsnGZ7s!M;%5Jrr?bx6wuydT~&H(M|`<>`7-`TdNH>`_mYT_L$XZq~kfgKp|t? znPLFO9=~d;8BSnvF*ga(+AQ$j0yKumEm+lb_|M}4?l6dn9nx`NU>p1Y>$JS$i;^?F z1+{aaHic;?nGzaW?dsjzca5KwPcsr87!aPpNHKA8&6sGl4};{y5(=Z44CAEkUo)Jl z4#&D$6`%KXY=|xc5XWWOLrHuEWv0T*atB>uWHS8K<@!0jns9D9<3aXZFY%PmDV@DZ z0%XL*yf=r}9!7`J7%uaVq|j{ZNJ9u24T(X?C((j^zB@4Oi0kjX$qgqjv@udiM|Z{v zG@Z+6{~|hFQW)MAf?8!-tLNJOAu$7E!R1-;;Okyt6o_cV2vaS z(S(ZTbsXa>z^j=}h9#;g7Ed1WSyz?YQ&Fx}qF`@L;`4tte*IzCz>&MO!0p@20@;wr5)rOaE)h=6a zjuySEJ3oHp@4Dixp|wMJ)Qmc{tx3mZZGJp?ycwk#4+l~q{y|GnA%wYyQPipU~#=Von+@6FRXBEB4LYTQinUv*1gaj$D`wl_6eNmhJ%AhZhyHa#?-as5|&SU@t zQ8l2QzZ`T0O1I!&%k{1*{FnH|T_94k~IPWIwwLL(6 zrnCUoA$%PXXHRyzZ}{Y|X>7nBk=l4`Yo7I@ z)DuOANpR(#fU6=A029NJ`XLF-X4$14Jhm%Xfp`px!&O#)Ei&B7h3=QW{QrBI=R3l~ z;@-XU>M*%@(&TRI6-ci`79$*8$~EAnm7%>JEqhH{l+|fK6roxV-%@T(^TnWo-Pb#`#i8^|-G(ijecQ5*hhKUU$}rj^RsM4)ahQN~n}S4s|k<$uOe! zKOrWbMQw35F(%i_JBRD?9$iHa284^s#}Z6YEUkxQDO#GRg7h0Y4!Cesc%o#{8ia=D1_BVCjeXs0wV z?Nm+qF7te4n6A3ax>C@R-?OYGa3&R`Hi+{Kshc^iMMa9i>b-#13>bb`NJ(I|eQ;T4 z=|{5oM`b}V73MM)*Yh*N+cMGJsSw4i9m^nQr+A^io9!H~bzpD=bXX``jjKLxZ!C<` zr2Gvb=bIZExDCa5sp>q|aWvn@jB_HhT$WcA_E6Druq=JAx3MDV=;(IA9Kzlp0uF_; z+Uka(_)D46uM{DQt2&W=Q`NR3?@QY*Hr+OT-!$}e&6S@Fmt7N3as&DU zU$IDVLf*${HW2M^AlTPaI{?taKK$`FLjHTv|Mo%_^RfnHAH!#e=#3iyUE9ccDsiP` z?rHB9iZEsOuN9#i8btJ%=Qnoa7aFdJKo-15hFhwM6ysvChmjgPltLQVQ{g+HaTBo> zrqU}bT2X$sl2c%`C?&2fUzQ`Ebw7^NLH1@(c0hqKL9BtcEf|*`TP6aiUzp~_93to& zAnogK@-0$~tYya02h6cC8+2U_2vAr8wNFV8qHdpx+hoYmkNfnyK%4r;)?%W=$R%d+@aL0n~C|zC`FYTP>G4zCo-mnUjM<`(O4d8w=O( z;A1V?`*M^S?QnDLbTSmzcaI?NPrHo7+yW)@OFUqbDeN{@+aD16zXj`OZ{OaB0fYC; zy_`ixZ|=BdPYycpv2E|$-c(@}H1&eVPDm}+mdJHSzatYUzm(#R$9DwYZP+jzoVD<| zwW*p&{jO-UfOb5)>s{uK1Lz}Dk+fP7z<(`$xh34#h z0Z`U^tyse+fS{^TS-ByFZ~sy5_4g;LHO#{<^fNv2T>kX>og#pI_V);q}1+tJRCMDacLlzQVj)YIi z$UXv2x52H&o4^h!k*>1sBQ~r9M*ei_?T!PIC##Bx=dhO|ijHP9;xB;jXH)5R=#@hh zvj99Ho4R-cxDvgSRWmshb1R7HK)yA-Sq@x|DZL^F^>s9aH1|=eGu^u>5p}p@c)D}~ z->K^K*ZO%xu?`gtpRvXbv(5`%>9V>zSLwKJDd-A z`(I!4uzJYtZ2GSifjaU3G+xOU7O4>u3Tg*P%8yju(ecL2atqJudihZEx23`o?@Uv` z_xadXt?)VszYfM?p@|^z9ISQNey~%h%xS%l%lhO2%i*^$X`l$AFJ1?6)UeSzuqmR6 zswILPQv?XElEGMr4#%Lh4mw)}*((Xv29{P}(4Wn06WYyNRFZ&Tmh|?mvi2$9*)iHI zz4+;x@%0da6ux=b^d&cYj%p0w4Xe_`g&k>D$m)*_DCMgssWt2|7lhAImO#3SlHf#f zfi&MOf4gSPIIdFb^u>qeDR=8vjbmP#e;Mow_N>aOKokBTVhQ)vlKKcb0(u=Ak@oB3BvG4FHPXN>V?64YTZTsNW~mi}c~0q;aOu!p?V(6GNDqubsSuD)6}flBAzN)@CX* z4|+LKK5_~;t^<#ZzZe&RNgv)!e^35t=!Vw$h(3b}-O;dC3Yj#VtvC;We+#^-kJYeC z9<3hj;EGVb%0sj*+-tCoq=`#=p^r7*Rw%*=X!rh>uut}2st5Tj#n-WF4mIkF-2rEE z-W6MgZ26>pf^od$0?k&MYWuZOK4AV|N(BfzMPAtSxaDRimxuB-CSIH59T?CZ_NR3K zZVyx?7v0&B1E4Fk!XESoj~MhB=Q|>$?|hCJF?G)iRmtB+;bo%H(zpk+1^~`1)Ski9 z)kQtrfG+A_r-Rl~Llt<7yhB8~nfi9PjM_5Scqq27O)I!Lfn;@mC9h+T0fad~VbCZo z;jpls9=6`vLCn_Nk67<=S=hw`MD9vk`?+}PGlR~LqAV8Ej0jfU{Yj)BQx$jCFEfZ3 zMP%`|(ylx6Z^he}hkx+}RNlyWC9XXj(OY(*gkywTOu82@IGf%xwRmjcN+=*>-#9Bj zaX(D=$tGkvabciRLoHPzjZgzYD$Z}Fa zS^(oGsKHuja#F5$E>WPm9yvNPjH$DLzk$lymE5Ug?OHhqL-2o0dA0Os&m5V$gs85=8 zB05j zdlA$#>7gXzcda2vAfErNmN4qgZ=^vCW?U6zZ&v5S`N{{hK2^G1)ajiAYmrRtIrXmC zm^zCyhyISP?Jub8C!9@V5)Uarzt{WDgm2#Vg~8BWy0N1RlLCzz8cyuBWI)eFlSak< zc5x8L0)c!oqGc$JNtC&aV@KT223%Xn$}B~~YjibgX;%f>oD*FX+T-)f(kNid(elLm%5 zD>up8F$#f1ryck`ROZ)FXy|houbReL!8`elfV3fQeIddQspd~s-kq;dJ47gcLt~@W z#8CUVBYw#g-hH-CB0X6HFJqVM9&P~X$5R~dBL^t%7HH&_O$@0*G>i3oOIh_z7Qn!x z-m#KJl#?^N6E&quNAux1l3{pBkAO~Bq-=|O;#yr8gG7g5xSiQC2Q3zm!hh^ zjYqHSmj>c`+WFaaWtPueH=dzgR`ak5l?V{!1nM5>0lol$4O3e$O?7y1V>;dZ@&N<< z`Pu%Z50k!H{Mx~|fWz}ayoyGrC__3y^G*4ZApB%EshA&su~e^J=NPzyLAlG$GUYPv zDCDV1*1g?XuZWm_@LVGH5KVAoff1zX0=K+P_~vwWyDbjEp@5P{m+{MM9I- z%PYdB6Xn!QM*Z^pI&|S&*qOTx=zB;CXa7KBsgay-BXw#^)8cUAXa5Gj(};WB{Ob&P zFCZt92%zCjO%42;Z2j*~0lqmZ-flV?(4>U!20?UHm&C5(rdt?J%V!jcjB8w6vU2V?*Pk$C6Igw zsp;_&lOvTDV&m~FxS*BE6$VD#BIVs_X%@=L4~jaLwA{)9n6$F`!v@o=4Ype1>ti{| z$b1&MPPi>`LqGMwJ|dFsK^A&{l*5)$=@v-Rvvl9bSE1iP#5>R^WB+-FSp|@61}Z8T zI;oeJmHQR1RFYr@e}NcJ%u4%%pw}A9l2P;qcGcEF*>LhWd&Qem40t-l1A~Mt-#&%` z)GwJdA(zb4OIf_MwXBG(d|S2785L>!F|1H|-Tm29KrLv8I8D9;W!aPXO~H!%)$a8P ztJAf*I`g6Vh3r{I;-5>*C%81 z<u z_NoETG$gk@W*Wue&!i0z%wG*oRbs$JEmE4S>YKNnu06Va5Nzb}f;me6MxoOxSV)P20O$cPH~C@`mT^m>Bk;6(Zwhi^DO&h$u_*(emt1j_Xx*4 zb?#9x>NK$F@6ZPD`%7T$LB5kcGgV`s#tMuRHy_X?fZp{>fC`7Li$&5%0v>nh6HE53 z>$&l)w*+6mF2tHta9HftSOR<&xeA<-r|&WRAN0fLpdWg7`VVH;R8**_u%{}YkdeY_ zf~b>vs1N36!kNvuiO(mbq))Bx@NAws1^i{3@;6q=Uum0>FOm}rlmA8S>#ov~62I;a z|7pGo)Ukz?c8gM(HQteP=_Gu>7H^_Wxsi$nI9hp~pB-quHyx`kf+RH*ONzANX*WA* zEr98hl0f~38!y<8+4@Sq<6GNxj7;9oS7zrqEXMR(gVq_12g&@m!bRGL`!HTQx%&F% zS+Z$mLLLJnr!dnV4@Na%YvYl8c%gAVF;$v1;`Oab0BxU#*@8_@1NP7CSaLPCt5US} z_>_JnU!3O=*xD-iPjv;YV+}Q(rfVHA6(9=^hi>@n9#e89ZFQRoE{rA%5{Ph0+@f&S zo_5~}joLSSr-4zD!&&s@grHqjVY&m_7@#$_XGYIzy}&3L$3FD#o$fvw%n$O_{Fsb@)Lo#d0}H>V{zovXb3QiFPtXT0-a?BfX+eWxm2n} z3N$raw{PE01BRV9{J*VRQQ2)x*4Psv?F?!Ym`t7*i5rK*MA{Edi!Z6w75ke?Q9VRr z%`jm3`Sm_W=y>_rr`IH1dqK0;b1YS2hp1s=;mqg*RPtJXRnhvDhxzJN^hJhBiM*Ey zxn)qHguw>~$acS_^;Di3%j4Je4U$L&lE-HyoAXmPhn|RjWTxw&e>`Ro;ZcisO}|H+ zZoc{1Ztk~hvV9o(tOniqRVknaJph2TN1Gd+R*UXk+!bK_QPB5?-+7K2n!uzpqpev% ztGLq|M72XR6AWxJ)fPx!Hh^Qxt(J%^kuc6{;}PT8(_{9Ee0zT)kbT-+ONgB8qb+{iZ@C#XYux zC@t%yZzyxKn88;mtl@T`#O_@l$jEX!FlVlD0fZ<=V6?gn)F^|sDhw%sG_w2mEZr~w zVC^_N+5p09h#(-D#A$1{qv|&Seqn}8mTcM*An7&mmqc=hhbWodmxF+%1F?^hDmbux zwjC&8`~lGSbouWPn@7CRaGTB!M!JIWong^cxrf4J8KPH9J*uhKK^Gt z`zn$*7rJdGvsr%7NVOmZmHU1)&h;*0C0tjEjyd58Cs6-Ynb<@mBJK;&*7l$xAY39d<7x~JE z(mf@MneT4v-(5EZty(M`oad|G|K@e|_jTyMdAS^- zPdf6M550{x(Py+A$=KZ}g$#e)j&xNiK5VOWMyB;)t9xy~8%|BqZv`=MzC3yIWN8}y zx}sI0TvJB%KFn!%N%ZzZ#t$@>Gmbe$OgA$&-g$U5i`%Mrv6gv*-mrEFM$cz!%URY> z6fMP+Ptx%C9KJRXZ*OfSfuzOnuzkQRUqMBVG~KKCDIc5L`6=i%@EWn1!HIEB4lNK= zD#Z{TG=zRnM|er`w31jo%a0G93qJTH3qZCS#H!GNfp6n1Dr$ZWFp~~IJp+yCE$ZLg z@_&{Qsc2Ua^JRWXojUXx&oE&FC{WY;KdUTRHe{?=rSoH}qisF1g*{|)e5dKSOfsgo zF}bOCIs|-}gOstLAs?G{)Rw{I6r3#|wf50wq>UqWa#h@qPj&>x35Vc(0#ia+ZWD2L z4$B%1w#mp>iG`!6knw=QtDrF8VVi#T^@{V^F%Oix?#wa;?ACys^ib%!3M04Uu1_H$ z*R#nF2_MXxt^)(6wPW@o6llpJ_KYUJN?1o%S~8J7`12%Q%-Eu$aJPwm#|dft8;>hj zulnkeSyuzg7Tcv>O;4=KEEeJ4)^mR^9)L?KH8=o{GQIpj^yEoXAV&>)xIb5*A0N2_ z1|1QBV8-U1`Oc`Ye64yKDm)Gj8}}TYDsOM^elQ}GG9eHQ1s4lh0adN+$Kt(DWPS1# z$MbgiJ}`Zhd0$My+C_S(r?RtL3uC$6K@4aLM01^3&*sz(<4~*00*2lEuxYcSzWwyt zaEu&3>bynWk)qEe>Jmun21^Vu*u2kmCo8w)L3ivWCafzylF}e;la%RO7qIQFVxTSQ z$$L7C^fw>vVkgDP1x)x>z4s@DSQz)0AB_)3kpD|BJZ~Dg*(}6$DI~a&6Jx_27=j}3p~e}1We}mt28Ho zU6!ilcGjFst0n-t>q6crY_DJO>}}4>WZDa+GCn1%FddWi8?AkdY?67RMOebZYfSP- zP?1Lc-p70X8V6vE>r3_V)_nL_+IR4&)8-it#4{652c&n>-oh>Ct`)_jae9Uz)4>!W zm**OO6U7k4+9?BgWaCVLkJo4 zsT6XRLk_D>zP1uAfq9G1aD2uBnRmzm+J-+7kvIv)MH^4-3#eQyCb;#20?9Y8^=NIa zh{;KFza=cppU4RKxPn@7z9f-VS?g#%05Cq=XD*l2lX9km+|R855WQ&ctOVudu>^&M#dGxP3_|RN zvcvgdWu+cAVEHJ?N``1#IrLcuhL_9l+F}r}lj(E~7u|(bX+-8XgsSZmF+Z zZGkTZ7y~W&_+|wOkYBMe`nPumPlZ?mq7fkg8k^HQOoBAHbXz3IZ8}9Ro7XxUaL&2fV3SSL)6-RJcV(!lrxj|zPyxbVo~=su zreC(t|2gkJ0v$W&WoS|@EA(+Q$*yO|>K(UcI=-K2(f3R4-DG48LO3r9suom@@N%f$ zU~A&2A`383sFN3=mcW}7gOxNL(n<~Yw`c8-eO6Xi$yrz;Wo1LXhPE*Rv&ln3Q3rGK zqbHU))!@%bGerEqN-wzZlef34;*pRoE-v~Xw$u-8J1n+5vPgbpUdiV-ZoQ~!WE+IR zDzrUWrPK$M{Hah|ue)Z_@$8~N8H}@0zj#+oaaBVz=bEy7JhN@|^Do6^i<*zWTN6QJ16%QSPu)R5GQ+Kk#0cQQ2XNB8_*C@)YJy59t*;#tkY?>F} zyXze%B4tXds$zf`lmQN!h-z7mv+18P$ix)PSA1jQr{bdb=wNf0qFf!GURJ{O+aHO3 zLOZ3z?%fn*tM{xX=Kzztok$MQa}z;_cSV||ibt>Q?#ckEs81CWve$z^u=nX5mD_ED zDOBlz{2=!Dw0y$6jDr)$(%;|Ti^)2BYDb6x0J~x!&rS&qy+2+-t6)vJA>rif>+9h} ze;{hTYByS_-Jb_9NFXBMv6INxDEAirKaOU%5GW>S#c({VbZFUJ zaKayx*_VgEJ^EGtK0>;zTrMDxKResJ;C57j|*HL6NAe9P_G@;G%S_=B%@2~!R zK$i@`&$KV49DhM%NA1!|VBdy}M15dlnka}sp*WuhGI|ohAmND6(9my3v~|k-M9$y& z1fXl~Z$(iG%_Xk{oBwgc*q^yy<8yE?g+zQld6l$wT9$vXN3zoI&tKCb15w5j+!ZO! zR)@KGAbJ+$jHb!6dBQ|BpG-ggl|$Jug0?otICfcl518L74rn~XIw^xgL-#HgJL=zc zrvXtwp8y6|=A9zc%L8byrlMWZUR?T9DdK*IKame|9((`3lW~bhhskZhMkzBh>Y?l2 zvKoSTM-G?{&AaJ|OUe%&`}VM~2!|lO-I_;Z{9+n)9}qiUg|T6x3brq~-TA(0sEAEZ zbK4mcqyJ1@#=)dW#QLHt9>KDOtMyaK80Ns)+1Vxw+${l-XE@+9W3mVNyhsq64nB97jjjds%vB1o+Nx4|Cnge*8CzW|0f8*H zi}P=Da{_=)@FBlIt@JA6wJU_gZ*5mEXBz&>M*k7j5(j{D*7hvS3kx?P(}CX8t2mAX zqNFAqa#dK)@E~4ZvX0SppNWwz3tjNqiHwjYxmhP!;_K+Zf$x9{ zH=5JI?`u8~!U?LVklq>*7W}cb?!zRP_^LqHo#jtE{i|d*q`o5X{#J-aTI!9+5i~B} zAxKaPFqi&}otdAP@ulwRGJ=CJ={@a=^yl;28`*Nw*aI9U{a%@-SyZKZ)fSFg4=0~W znBmlbZid>5bG=5CRQGI2~ao`hreg>&|yg>Vfa|ke>P(u!EGz4Oo;+B(DdZUvq{wg=u z0m=gNX{}G~OHODC`HL4HHtJ5yqq$wYZ8*l{ zIjE=#R7$+3T~Da9Gcygd4gF)Sl_2rJ@}7j0)-U=Fvt6r0% z<<5`5%X<|(X1A#d|7M!{zaNgk_pK&GiWM+6PKn7lDiPDZ0!G^w7m*tT1X7LH_QTVJ zf(a#oU3}O{2gbMF&^Xfh^8%sf0o1ECMo_!8(Z>h&M4bE=lbSDAFHY!(2xmxl0-QO| z4>1|F8&GN#RCxExb|CYP|I-r05Tr~F~ z9)N$xfktC`X!FpaIdAtTTpkLZTi^33Fpk2Old=lmCQSz0FU&b zsuRRgp?B9Y(rH~)g$oL}#W?EDeZ=z)R8*Y}YHP*Lfl4;!0O_ zfs)g36@>SSJxb55|Epn&Bo4i$yMixJrFkkxQxMLUWrTwO6FNz0wVNFed-)>u2i-pL zX5&WW8yUUV$X+!5nn@SgTPS``1pHBF0s@i(0&YFDqPc4;3cbyBc6OP))|w%1w8UNi zY~R)KxcD)a6;1bcoy$q4bOQJ8^1kUZj#E#6PuA-RS*7>H9reIOWw6HHB5wl}rOQC1 zkvxzgZQ@`IW!6d|D>a}rN!?}@1DG}vIqd& zlYy_*barmYReLZj;1T*V=O!VSP8!sjkI((J06Yj>osrMqTMrE>$z8afk+HJ_pW~~U zxw!%Rn={foi*Cc2(@1ErH}NwJ279@+wKaaUK2afOWJIo@q%^>DuI=E?%i&9aj5$l+ zkhkSF>f7bt5XJuzuWXdBP?1@SiE8q$ZC7iqm1LSmC!UUCO3Q&pmdjrAeK5&|AUJP~ z(Q;NV+G&qTUR_BCWuWT4*{E;5PC&I;+NA~ z$J;~i4I8`V9aozdGYv<nhzQDZ*lF9&hd-vjYxrUn*y-t=xlo-m4k^qWT9xvsv~bOO&qtzg^(?j=H;{-L|;FB=*Vaw-Pf@KapZ=UfXv(`z5MU=>*`3r{pHNO3JwVa(zVtX(z9 z`a~LAw?in(^v$Gz3=bQoq72`tUM*!F$x{<{yExeyFM`KizIsjBx9B|v(Q_O*1)Zb= zkT{oGCFON5SC}T9v^*+6&v~UA8+Zf3ITB-jY*wPH+p&tQJAp{($@|WTIeY_lPEK_m zFQF4tuQN~-B2DkVvE4uf-hKQ7`HDtfQYtUW{uDNThmiHqw|QR0(EHDCA~-L>MJ8dH zYo=8Zwe($pTsU&Z5NgO<$^$PxW`!<MGf(W5dQ&0S$2` zv8_!c?@^E%-0gyUx!Q4Uw5VxL$q2Mjc0n*iG&*g-0o};u|FQPhQB`(ZA258YpaLRD zHv%HH0V(N}P>}8xa08Ok(ukxeh|=BNv1w2Qkxe(7RBF>mH@s`3-p_NN$8)|jzV{u& zKae4A)^*Lb)|~SfGgp9qRuOeZHXE;m|4S6c=qhs4pQ{|(RxoTmrQlt zx*SliMzF!5SqGzlxjK(TszRak4d-X>%;dU1FKXa8!WnhxSEBxZHw^fWC_rr1>n*Y~tAOyr=%v>ja#mhyUR_PM&7ftCA>DV2rMOWROeO9o1M_m5`T>$& zVKPN3;(Z!fW$eE!MIS|^&9OZY7_eh&qBh)uO9dt5olLXR&1)#Ifl|bBIpC?CaN(+cz9kF@j=}VJBkqgR4PStJ3fTr#obV@R5<-!A36M zvT{#yP+EKL3(JemH?CLD-UJ1W(a;)8@%27erB{nqPAU`-&$Y&~Ro~P2s zrRy8k%lPM7wvUguW$szAMxbWs-a2=wR40c)3lv^oX-GLim~Hd8jJUeGI(D$~juS-> zw*%kW(gj)pI=WY2-prKrd|bzKb*163!rIy~xUbgk{KkeNfI~F{BN7rGZ-ZjmVL?yY zW!keUsz(qKgIrkXXZqeRNXPXG+#JLLFMgz`lREt+t{wjIqW+I#0Q=ijn(@NK?cXhT zE&P`^N?Rol78G5LojG5Kt7Wd`>t9D5g-vPdsULECS=6vwd++Bp#+WAP%dvab$0!hK z*4$w(&tJg6ziV;YoqSH(1xA_)E>JovPgWJTmPLoXdgaRm5lV1@&TQ$0nGme_&vbS^ zt_9$-8b`jhy*(x{YwHk_X)aes7ra(<9S$=oA4r%iNcPg9F_vhO2GSl{wypDCkWui^ zOu!`c^%I{HH->|}&zhN;xl90C9D#Z5=0z6t2$Wy(Ew4WOyY->I-)nOI_9A3470a zx+Gld;^v)Kl$&|(ZYDCXiC}pqx=~cOp4P!urzcngkRF=bqIs0#3B+_v>7~ioi(Ph-qHwtp-J4zNa0AQX)9PfjMNqc!{EiGgD?E-3YhmM{e z+dNlS8<5d};X~)caFp;pru!Wa& z|Eb7WWV}eyVar=OIB`-?1@ik^ZTmyfn}c4{Y~nk;teOKWavI7%R*#wZYCpA>g^S2- zE2tv&i~FvO=u5JDl=+3uMG8)KqHH6A8IlMzx~9r*>LTnXOo&w0GJAWK+*Dg=LxY3E zv-9)v7UL|7hF^OfEoBpslG2CC$;mCbG}R@_%F0%3*K+}Q+ieeltf&`u-|tNi6H22L ztebtE(rLZi<~-A4SG(OUn7EdwTmz~qGF}@BY?6ELfTQuFQXo%&0^*S!${sK3nz;6Z zmlqk1c@%J0HocYlPYmN<&g=@g%SR+|3^3H{u{BeGeSE5ps=U`!CBePb%VbWGD^WFj z3#DhX$oAtFs=T~?8g}aAsPesKyQvQLhR3f0Z}cf3=jM9Bt;7!OxXYumokvf1Gah{y zq(NYogY)<*P&O(Go*yEyGT!AwgA!$^PeqpmbmoC80{-bN^|?}@f-UOQ0=>oWwROc- zP11U=zy%!&YDkMA>K^OWLldT^6tNbW?$p6SHD=sn;NYJIi~w&@3nXA-VM*!DyK3xO zk$P>m;vInzR~4KvUto}Vc+(STmd9LIf3B4qRR(;#?EW7&K=^e=EGTI6i-eCAbgaNG z3%~gBl+3{i3j==c8fD=SN)ksFl8Gbq!zXfl4GxzDUKCh%6m#WfA&ep-Nnb)KW$f(i zbf~SmP=lI!`!hu?Tu1aAutBoBQ8Bx=BrT8ybt7rLSQ8nue!*?!Y>W=Y9C z?Pz3|U8MJ!Yo?HCzBN%k$h=FqffT!Hv5lI%`eaGbJ1c~(_F)t1Tb5YQKu5{ceO*>luzGRk?K9lqP$h*}hdMJ&1ev?nz{iMnhv`W6MmwNTET)YXh%CsAtr` zaSYpEc^h1q2Wt$nxHSqUY@70&qlAw7F4_~uKznfNxY-(QZepT*2%zK^UspX3 z3Uu_V&ycG%N2Yye?B0hV8UZc`wRYsvGcvk7ei!Yq#V4rjz69&_(!a#}KmPiWABE>t zC@Cy5WjvJw=27Osl8))4%H=uJ8Hi9>zR2WKS9Ivfy|9xLj|Aq8oZiB!sk@T%`5D#A zIX93a!^8c+$|h6S%K4gg{AeL}-IrnA)v>7Wv!2a~J0P{8Mb~#n#&>YhG6ELwJ1V!u z@1|{0$;pa9dX2d@)gX71PDJEolIsHLa$ma4htI|@j||U`h=GEkLb(R$qaKC`7b*-7 z4)$7CO)^hfkNMe#CTP)_CF&qSVc*g2A85w@SutN&vR0&$kI*H}N zi$nR*j@H7U)Md$k3R{JiM$O(G|3U+^POmZ11-Q`T^8BR*6#(Qc)vgq!139qji|WdU zN(Rabf_}$qts%q%poA=p15C9HU7MOn0A~*cVPky;BL*&#yw__QggulcjHe7nOG08n zV^+7if(tLw37vA&t{RompD#IvmGPKCPx2Do88Pu?;MM!+a%7!hY94+^BIK>{zdH;P zW5I1-Xv|n1(}_U@moLC%XE#!(;Pv^Ux9g7iI>;vN>8vWxP-MmI2V@Q(%L6TjV;;6| zrrkj3?6@7+*WYP0h`?!W~XY1s1pH8Vy9@5h) zm?%BHfsO_|-M+EzX=8P2k4MH2EIoXJ1?>O+{j^|G8FiynET`{&yo`VVC(W zG9ozJyPI1@sk+F=nVvGC1Mo?iuWcjKxnmUWyljJE>os2YJx{u11rl_buV@IWlluSq z@DyzPd%8*sXIG5dR7X?D+j%Yiay^!*Fw!9*yB_l(r6@1R0`sQw=F6U(t--qvS6>?Z zvA+)fvx&RCV_@`!Kc}M4qyb%kJy&!YEbIO9a)W;8D?MFZIW<+OT@kP5I7C&f!E>_T zUF&NvVYeB%a)-}ohD3^PO8&<;cR`&KO-FhHtO@D)j!GGW{U9RG##z>>^jp2qJ-R2FG19)nasCmQC0H^%ILeXq`ti=}K|H zLiZZ%-|aKh_rEb+HWj|6jxzQ0Pe~Y+Q|RfCd)WCPFsxvI@M$00?-wW5M*CzKhg7O> z^=yc*l}JU;Bdzy+=76QI ze_3`B_tA?GEa_`S<^~Yeex$PxxCI_TCSepgdNSYWvNJe+9e1?MvleUl}7z_lv*0 zWc?i)e_HB`*FM@k;=8`~&HUoA$m{>_ekGLD60C{n?=>;pzF5=nf4L^cHl-rsb6_wS znvA+nh;API?d|j2_hQracK+9!u9J!06)4eG+)8`WIMJY4zJF75zkzM(^)=@c%C`Ey z+H=1ea=^cRS>k_!JLn>~wf@`SuB=pob>jGf7%Jyqb34X8JkZ(K*L|R-X_*-KyX3le z5mOe`f4?{7X|F3jzYm^Y=jd;|Q-J5?PQ?SN*e28qB!YthPT_Kv3hBF6rt8#_B4;lp zS<1X~5p{&CS;6B?J=Mz<(J=@cs&8fv%7%7Dr94 z8iVBg%mjo6qKSuLRHLv6HxOw~)7HA@j-mXwiD&}N6IhC+^Lh6@2~yle2+AQe`|SBL zgn~oyPsi%ZJ(-UKJyPJ<$-{uRC#!lGvxlU-A%U-1z8uE9Ro&)uOHEf_>M%Q0^@$c5 zx=d>|cW}QiMIMAHjjeR1@UpEfT%cL}4rvOazk8}b_%f76*> z;WU0TyCYuxdG~4v)15n`M*B`qPAa2<5m5@UGGQuoLsLfbJqaWtR@bq~_{8peE$=+j zsk2Ep6A&1&u-qTP`(S6*dF$49$4&q8xqJ7mr)1kglg)!^_$LE&!T@%eEw2mX*T+F; zMH}27YCOHh=rnza^VqG{UVnlzUvOnA(k>2l2mO7o`uKAW|LH{a5ku1VhND9p^FqFX z)wA2&;^oiKrNDk1lv>c~2ygGs0t67%eUgxs6%%x*nw9|_11ag8jBvW|oR_o0P0G=x zWWW?sC~Y|IPo3pgb6d!GlRZIki@ujzvwN=|0cP27soqtLuvI82@e~kja}L_l!g%4V zIQEpP{cDExxXaiaY~83QDVW=9l?3t3@=Z2~1&lcPw>33R--~jP>jy(_ekrR0k6`PK zi@vdCGd=lUsa&qEiLy#I7L#=f19sTu==$ZyE|0I8iKT4c`msZ;kQl~jda+ghHT-)G zuD>{{2|^t}91-}EH=wb&4{919a+7?oni&OB*>^*KWDbcIM=$^)tNGYquDxhg#(Rat z%Id|pZ?C7=&|Kp52F-Uh$Gw7yWDy4=?)7#SeMvk9vVcG`gR#j#j|yPAis{8)4LqB%+g z*ZS9KNk5-eVl?V(03}iz1LoW7Y{ldA%=_43SwGf=bBmut8(cr@+)A(Z100i}X_9Y_ zWjVgxL455Awf;w{R@JTQP8Jr-l9PcbD*k{NVz1gobV?ov`H>Zuu5{b~KBOy+~rp8L3?nT^h%_2yQl(5dx?;-l6y}~C^7Xg4v51xB7v#?~Blqm6Ig@$=BX8Xx@ z6RET!JeK3$NnSCQsO0NtZKWrmppevV_Klr1CPqG0c2X`fx-5+jwY9Zf9>u}i%OK8)_mRYmky7Uq3Tdo1BmU&3}X z4a_Qmui|SnNKv=ipH~M3yTeAydPrqITFL?)GMCw7`t_!qMF^{|QRz*jhv$rCI4-qJ zDvfVla&f%~##Ell{WQ)nqqRnVz5_u=tz zuqD-lK8ZmbjGI|1r3(&zST4>+RD`6D?CeU*mIghKE7^8TRNo}%6T{M|4C@vb8B0y; z;JZ5N>QXgkTa0og#f60fM{0t5M;ge%s1eg-k%oDix&Wk8!F!!Bu)M}uW0U!~V&cvE znvGcoh3hPOA(rmyJ&}cdyEH4oD;*Pbt+jc=#D+rKiyVRbMM>9+Kjh_ExZ=1F?{m2G zeQj^gw6bGmLDy6Oy{JKT57CzEQy$60A;*ENo7>x1aS60x*6W1P?a_LpCe22-wi7`W~jbx%#NhpPAJ6uR?xRr0v4)ilpXW#LRT5m|y&`S)0r6I@Kdr*TV|?Au@G+8*LJD z*Qw{S%LC)ghLnS#L1oI(2%%9}{=l-WvTG%kZ6a}dBpWE;+h6-X9B-L94b`t>qMOZG zV+w3TMNu)n&Btrl%ZgT~mhoDUiE7t;Ts&6a)V0H`Q0*Xc(KFx^;$zL<7;xAuf9OgV z(4oo{(lq#bu?_ZUrwbK1N3|YZZXvrZ>>Q(6AU7B*vEz!2h|)>yAJO#GCB(f3QRs;g zkup6mv$>Kel2}Nnyb_K+uR_C(1Mbj9p;SU#K^~sU3ePr$O}sC5o-oy8>5*$8b+fI) zB&-H#rScvdS(((S`tE!8-CV_bOd7uNSbcr6*(@HTj(<|tswi4~i!E=({7Xe{%QXIx znxUbh``&u`tH7Hp<%N6vp(ho&AD&Kyb!gx=iG6-F-4wp^3`9?(enZnFWqxC0L#5fy z*tXuz$oc261v?@%=%Y*2w|i?YLZ(}uxcrZu8}p8fWCS7}3#3==PO@8T_%N6_A3M?yNDV?l9bF4i!NUAt^yEOck?+X_L5kTHe zS+qkl;cL!>#|eBQoVvaC0*;Jb@HB0V7xEZzNJKX-5qxSU>-&)k--kkNk-PFFGMmku zvG^f|6B?00v+&_si$+K-tNz}H$iJ50^$=lgtf#QFa8{Ef2O}ez!|Nk+6j*U>J;DCR zp2s*jcjG4n@N#z!t+c5~NFL5NGshmA(6H*1Xr5+Lx8q)3EV_GKD%?)HKG=?5=|nS5 zq%mwY*|9yxevgRuP{6@LLCM)!e-Ww9++s}hoj?ZGJLjzRbgsqtFs^cCzVWDcq^dzA z?+w6Sjp0tC@I+Rp&&|z#yY4|&0V9ZEYr(lV&9(bgJhdV(6g)PzoaS5DuMrRssE9rJ zOX@m{dLvQ7=vZ7^hN2sl6%#e?H}+P8B%JB}Ri2mlZ7-0{&8-yLH%#|Bb#~jgp*?@W z2YecFrjVoU9@FL5&rfkWDh7_u-s&l)@88GyICMNdS-QM3UL>48l7#%Uwp=XwtET%1 zUUwiquMo~m`c|A;`MBS!5J|vQboPZj<{8g`LeJvd7 z`)b#-E~z}6T;rW-9(;d?Q+R*#4fp2j8+{a?j8}KNlb>3XfG9 zVLc=As}XHnnD*FD-`0RjB-fh{-}r7Upn|zm=RcqC)lky06D-l9Y0SAlosiNA<>RSh zvqHAgE`=u6@o3abyBb)Pwm)lytE=cmUYmJfIIS_L3Qf2bQ3KJ9*bc#S3pr}>dqL)Y zX3k_$E_Qqx*3lwI)LqkbzgA?YdGYK@ptUkzPog>aFwO|DX&#YOZGY=Td`SJ9DU>TtCkK-sS03nlw|(_ z_)+#X>jtzAodGcdN^~zD)%FN?@hjS!lkbD-FP2DnZR%U>fr>&_(e^-ibV`dqE<{9B zSorNtDxuM-tbolwHj20(eEjMVZW>o1U>%iG0LFvL8Zfd(ur54(?rQC1H}?4@*fPac ztta);K`)wfdWGeu*ee4*<4e}f2c>0vbtDTh zu%nhJ7YeRJN9X(V#6f)d$c2f7=Q(45cBd;=CYFsyuD^^f7y7-{6UoN1`L3hPytAkp z-~Wfl!|PwHYH}4JvW9kuOioz-RNByD{Z85k18!r>#U&)k_-hLbAy2pcwC%Px?*rqj ztQ_Fbvh*`>azxe}&s#8^Q`U{`XeGUSdstiCb!1&wL!#Cq z-ByK~On6zybus4+b3ROZBycKnC;ZLhF_>qzh06HVkkR321N+o^VtfB;n1$0T#%!dK zdnoyn{b3Ira0Jh0vUv5c8^tn-9Grb87T}B8I>L@ugTdxUKWXZD<({mUK#Mk}hb}IT zm!vgKlcX&Bxy8lECp%*f@q0y0pjG=qC_$(89JmU7t=<5Vn(Vsu+JXK@_{m{HTa5Ct z#)s#K4~in<<5j%%AA2Qv5-z{I`RLRAk5YjdR`q0=9XGMe;hJ+A z3E!W3YGQPkrISLqEi!`NM0wpDlhoA6CPSO=@lTnM+kSZi3(E4?`uroQI0B(vk(DB( zcA!U1Yb;P+w_MzKsGw6YMvg3q9mqh>HFyDy{_N1L4S;-Les=#EhE;K+NRPU>w&BQ> zNZq0^V}aN1OlpHY%oQT5@A&EQQdTT$Ji?ltA${Ba4jDGNK+IJfGRD>(>L@m1wpWN< z*V&dC^6b3jWoe0Lv;Cn`%%^;-HB3m@=={Os&G&yXgc`c5Ro`*B`<6uHv5s>&blaub zv$Ra0s?Z%&${9gl4wG;r_Nn<83+((W3*@)<_tR@M_3k=YcP!Q{N(p=71GbWfXCuDG z++IN#qHMoRjy;@RsD$U9E;?`Yn<5-f;k~~;u2-#PmNr{}Aw!|rVmtFA(~rU~)fXc_ zC1H%(PuPU ztfFjY6Wf)=sf9A>bz7IVyy9X*_an>2WtUftMYU(Bw#`UN=CSR@g_w2;Ak6RC)iN^f z49v8K5Heedf1JJ8`Qa@ZG7feT8=F`&($@~y?5#DGlhkyYcu`NWWPagw`#MJ<$fko>;&voZl)lJZuA z%I972x#bHLg#-)`(FcB&bRim|U?MNGzT@}Dq_&Y^+E0b(B`a1F^x*AXLlbiOWfm)W zDV@G{I%Bs${)o`$3gH%FBgBc(*C=1Ha1Wm4cWC~r7e?@9oi^40bU;HK`!f5IG(TRD*+A5{Ym!?PrRP&WG~rd??$oI zW+F5p1=NmQQ?`uor~2&$VC96?-={}0FKCg?IyYOF!K#P;=Kr=zQ-p8b+tO=^JgnSt zP%=A)RVppGt?mI3s~eBIh9ab0oR-aAMFKK^D5c7CSj$5znwMHMbQs}$LZCi4NQxH; z%)it)`Lj|O=apRi-<~S4V77H6Q<}1<^pcd!?&Fs;pUFt(Yc;Nma`U8 z$zKoDg&sLX6x+r~?ea(KOpw;mGP2OH$<%XyLS0v^E{X)KPJoXZF?&W=2B0}w|JI0PhLHBEZk#wBWPIb#>UQ`ZR>Bj zy70blH+7l6?54))9xl84<3!F!RA*(*4MES6==Kw}8Du+oXc+?o0^kQ-6S0kkh?;}v zS>9~67O5ly2a8JBPgpL(F@ee{NO zW?%Dt{WZjc&%yW%EuIyxU^dn#$11mg@gS{y9Jh9W_K$s>cTL~zTd~wxG|%odCsC-i zRurb!j4q%?H>mqn zp)d{W?pw02*QA$#JiTJfNeV$I?plxAgMHkQy}; z3Ndki|5I)zIy5xet@61;XHoHP^9ZP(`+Uw$pC(_!$;7BaEUDd<6!DDXeCGQi1@SpG zrGR~W;^Kg{Q&*1+Qax>Gd{nhZxr<~poQ_o%cU`S{Q9m>^M0wIg*Z!cg|Ss2 zkI4YuTF+_#7g!U;y0}hiC%cy%8=IT>`Q~*J`X_TZ47#PeAgzKePbInsk&_8JLniIo z5}h|b#l>0B%$$jBH0&3tC)-KPH6YjB7wg063b%$Xor9C?QR?BgsH(R8iaFcS37B`% zdx#8~{v_Hj@{ZudUIAaP}z!OR1R*s|3$ zT*6hk3{3fA{ZhCZOALs_XkBcY>=P;>90z_bsXwUJwHfkr2`Gq(VDqhNJ**+E-z@B< zl&Cmg;9^s9K6Ea%YLzA3A2RS>g~1+cS(k*^dV;C2k?STQA#yti`(*U_zI2F0)Kp=a zfs#R!9TyauXr&g-72z|IAUOJ$(MykcLWig1$2b&e4Y|j2jd**nyOT1Z9hz{V@h~}m zxhW+MUfuBCi|hNrRUCphte^TvY)2(mIT80aDUNnZ3z8EOxFQUdp6F)um8PFj%&(B& zV`kjn7>Sln;?=ufX)>}dU0QgErW;l!XfSU)5tL$OtIx;9zCNAwSNq|SQ!_is>eRp! zo*pFs5^Fvs23*hPP*F6b`lD36Wn}Z`=Ea#1)Aky(pqM#`-p`z^p>pLu=H_w5WKje? zi#yH1OulU;XZH^^2#^ObPu*`*Gc;)vuH`!2elkR|<69=Uf4^#J`6B8>Wp;N*dWSZy zdg?n}+#(KhgZ-yf87Z9_pS_O;l6k@i=LzQ{SPe+NpH~5UBV0TqV0HsU6X#~J@794~ z-Bi{TvgIjJNtvG%H21*U7#O1l6>jo-0!s1@V5$eQHSDO=9?Zzi$zcM?%GN~t2Zmr) z4t`)cuUBrK#0kX|Msd)SMYX;i{rHSiVY2GuqkLKV?0J7kA*6p99qO`?3J9}s_j^iy zjNeZ%{Q~1(JlpI!v>YxVV%Ml|spABc%i=ztOHsIF0B7oti#5zJx}{aw zdI*G>1(64+@buVI!>92o&nZ0!nyy&2ZW|fd;=I!|VFzM6C-rM#9fi=YzA?{3iht1P zequ&q3=9`1-dCL?{+x18%U_CBvzp2p`$i*WRt83D!H2t%!%-DQk4Fi``T6)BR%bRm z6!|LnA(|b+?EUNxSzC+a2Q~-oce08-y=dd0s>8z>a92qzSvBUURjUpkW^iT@G&<3W zt#n;+7I52%nK0u`A=baAx?av=duR`NqVkLC zAM13LOD*=#i(<&N$U4b>K_m${l~p(*JG0QBjUp>89hZ)XfuBz@pHYJ2r|#X6>-+r( zBq*mixD+1-rPtSA7Wfd|rp*bGo+Gza&R7$j@gkN+_7~Q60`J2gofrqoqGA?sW@B3; zqYar`>i}1{543gFs>X)Fky%3a%0THpNJ`yNmBbggC&+-B0*btN7gzFDlD%#8{rv+S zstS{Ijsn%>FyU^u0w?9c0n}sZF&eoJDm@N>ZY43AS z;B%?xeOkN({$-RCfQlF2@){63@qRUN=Jz~aYx=;p%5MUE+IBj*6gwPFzM}${t&Kgr ze!F|TOjIQ4o{=wZ_{KmZPPL*Jh9tcU-;1p}$+tLvW;W5%^+@S`AMWoFPh6`LS2DQG z8j;DL_ksvabT-3)McQAYAxLDLUxqf^2sOEO+!t_Lt)5T}3j1)GjQTl64^RrKDy)+l6%tBJni!jZ^YKzq zGVWVDrjC}w!ewJ=y=$brx`AY%zH8rU;`}+D4$MkY=eb@etHj2}b{8fDf3!jKWZXUL|i<69s2oM8?$bmo6Sr|T69WeKcJ_gz~?9+9Z zrVqz;&g&U%RNjx*S42^YRiN_a-fVFD#j>v)XgXc%+5r@79V&LM5+7iNsJce6Q4+Zc zRB##hT8AS~5}QF$8QY=nzE+&kVM&y4J-N5#dI$HO1gffYD^+J_taHcFcb(Te0yKBV z>{7EHo9|SOpO_81-cI)QBnoO$f$8osB1el4jQbAW%b8-?@}~P`$3iQN{dYTF0&@bD zoP}vW*lYF?(C@YCPf8!X~RgJMewA~tukeS(Sz@F-`8eL655av?}RQ~GBa9Gd7*YHHg! zKCgr~^b=~{kO`})+P8k}HmqF<9FeuoOKCvCfvB;>p;VBo5@;Tz@-2BX65Lg6W={>|gQX#A3Q2qh z_!QP{&213B^2ldNxM+!wein-Zl;W}DqD}yC$1lLn4X4a(b*5fSzu= z4smy9$ao2Zn7s%JfUSK#d_#UUDi$dcBZ^f<7l8ADzX?zi-Bv7jeXrD+n_Y@CtS*U` z_0t`9YKA9_M988HH9vJOEx+4gH+`PfxBLCEFwqB~GsYkv+4^<5MzVOq{z7Vv@4e?b zbr447p{v~uUDma3-gR6W>&3Z8-FgpXrm$C_fXi=#DREU4$ucT<|#@ zpH4~#7CvLvYa8C)F9UF@s&~wIs~}2tGu6eA`wqsXhv4QXMzO%Dcz3^pu>)%4eAg~Z zV^n0MtgZ`ZEN^$%d!MdwRe+gZbpt9zh2`btWNfzfglmacWou}JeVQdS7_Geh(IuGH|4)>;3i*p(5GOttYlLe; z6bXEFONXQyjIN558wr444N!V&WeceO?p;ISLm}6!T}h9>))jpj%F~z!_fHKc7XB4K ze|p{Zych5C`rf}+5lBd~;Wc2>b=X}Qml;+sT~!l?IZrj6KcS-<*zT?FACj8d==vUW%@ZFpjTr47d{6-@lo#Bb_NQ3NpK$jWpv^)BJQQOWb- zBD}CbLxs`1!~AuamGW*$&c*&YDSCd}r+&lu`25OzSNS-+vYEQ_SXuo`ti86$h_3ce+ z5lF#%m;R$&Fr)xO9KlBP6o&WfI&ZkXf{N5~nJ{wOleaXNKL>`ri#k~~O)~5UGfpG+ z@6??mTd2%!YFcNg;=?Grq>`uAI=9%HPGrwuh>B=44THN7!)}40Xu)lJZX6;GeuL*eK@ap;C8dZ+tWBl`^2QCeBFUYI zc%nTH-=-S5yXiltFn5mbw)qknqN8~YzWe!ebB;vy`-Nz{INhd`eklh}kkCPN%Ab=m z8l>e!u=&PQhvjcOWeGLu-P5eDKyE(oG!30xZGQ^DVh-0C00tES9B9A2KBT+Gf8E@7 z3mEt=71fdHDG3@E6kI#3H&8kQf+y&kSzxQ)H|a7xpCh0TG>*+fmGdXaWcCzAQS0Z{ zUB<(dE)(LQ+hU_8YFK@02(yZ1JU7gD0CRPoe@ltP03EPL?68Xxf<}EB;jSHKvCyf# zlW%w`Tkpd-RV%!Y7jsrW#!Jh%g3K9H)^+zSi@Vk+M?n843U!J#-bG(BHin)NhmuqB zCKtUF7*4s!l!#H@PJss1EHcn#(lwN6aC1yGks6w##*_XOKKWHnXwH@`l6XGcR*Gi# z_09BGGUYk7Q^q_9J>i6Fm$N|V$@ofdIAcZ7ugYF-7)KRjEmnmP=T3cA4I_J1Qfs&x;JIzvzX!~gMKw_CZnzsp* zleD2L)Pv8-tq}r;U>igqQZzZ02F+T;+cX}UlHIqeKKK-MyDdw!2@J9|YCq6q1+trf z%Yt`t?`;Kspc6+-x<4H1=@uz$<#M^&{)UumY07BJ_6`x)o% z(m>lg|FZm_k1nCcjqwVKqxmm?7Jl}0`(PJ6T`JC}B@hcc*GakcZL9;_h(!9)066-= zi@ubpO?yfAuz97oRmCN0H{WSIhiSAqRSv1Cs*CS7$30*6n0ccE`Pi|JwgNy0??KX4;F?f^&7T7;O|ALuPx>yC z^3nRHx6+yp7cAYtLxYkwqzHMRdBlmHmrFZ^U%Cvq^`O@z<6Bm@|E}@OEZI{QiwI)Q zy#~Avf{qvMW1Czy41hg3DUjuRKh@g-ib#|!tv~0cna3W&Y|a-!FqV7By(bOB}MEn_cg+`jL{eJGT&claDts##MMlsuvKrg~xQ zlPm5I?n?&Ap95~Do}IqW*llPyv$wZ@hAa|B@f;flz5)vEkH0P$=(zy$V5MgaBe6?* zE_GUP(g^SFjM*}PLP^w-C|z?KWhQb?2q z?p|5IHl%xxJ5>B5F6wgP$BUS32;AA#rZ`(MOil%38MV6Pw9oBPQyCcfT~n*gAj56w zv>snCN6@$s_b7`!@u=1U3ZkY zj5?ZfbV2hHFT&NMM|hu?jNd+kf*DIkF8Yj7PiKRmG}7eR>Zlzz6i#r+sR?WtfY*l! zu%z+gVXfW#62BNgZu72aM1(`47d=Q%R0^Y(cz5Cdf5Huv^V{VM1_@kw3K{GYQvhfKh*}Nkwu( z*Zs+TpwMkpZWJ+D>d)K(77EMde)J3FaY|VVcd(+zxBXVE6^IQzFeZV}beVuvyG%=q z&pU_GOVK%{MHy;LiVy)H_?wD;8>MyG zVVyh&h~Ztow1)z~kbcs0Uq6pLa2x>m4_joD*m_W&FD*oGj|lMbAMj2(eyDhO6ANoV zp){y9stvMbGf}PFF|yHuVS58u+6v1j@I7*a_9l09b!CE)m!pJfSAgy7Y!Pti)XQ)4 z6xyFCF9QM<1CLF5BPL1)^wKtJ?>C{;qD8h;$G4vZp<-clR{*OzVRW9mE@_wn#Dq=Y z%Jj*2yuZ{I2__cK2(SEVK$79&!67nI;}9g7S->_hnlH2_EG*2qC@1G(gyEfuR>kzQ z(___NHb7&pD7?B@U8t)3X*==U#s)hiZ3IJezehLGIq+3>qg=t&px@?p|695Nta~n= zq4v*bsEY-a69$7_w;u5S{lLX9luV5%B@=fQ^p?xqS7ic9N-2me%I3o+KEDl#klF>J z&8L%~a9OI=*`TV+y${BmGEQ2Q_ja8w4*+o!ImWl6?a^zOG%;Rm;h+|rbgk|c@|Z?1 z2u{Il0(71#fL|U8nF%H5RTzeDz5pXD`h}fUorFBQL69G@ZSExWiTr_8QE}~Zk_TJ! zHZPE>O-X>+&*PtETS$H@y09-4T@psW6q`k{yatcB~130a0E^S-<_FG10HY5 zy{can7cBpZ9lVw&1i!ChbAttZ!x$`2^_x85@zt-wb7t0 zO6&Dllw7}giF811>DaYCeVuFY(#ufr>E3)!YBn*%e^{oE*fGNeQw>P`*oujoSCNfEhN4 zE`=rwzgGB-^U_b2KPd^bkJz=l-*4{ja^n*Yk6-)ET>j!dbKw3RT~AWq@cf?? z7qx_5R}4orpa3^0|F9Aza%?CZ zd;5=0oaX1hl{zqv2r%&t4Qqa{$&}pm+uDP<+41L{?v*@}PL;#1e7}GC)x{GG0P?J# zlF9%01ao}L>|GleT~jNR0)QQC*_RbW=Y(jG$H^7{s8yN9OX3<_`MD6{IQ#$6qK)V# zw*59ps+Rcp|BvPf+jk2op|tJ~Bw%*I!&n^EQ@UEWu|iC2z39a-+b|{-=rK4#*{O~CAdr~I8aLHlyPLlvKL({UB=G#L>`3_}K??cD_WFCz zrIh16R1};G&y5FC(VF@I|1udi%N1@N7Rhf^SEQA!oe1ZX1r%Ny-6EhMoK-<)qVub1 zt4Qh_yT6aF;)POA$%&{WI_HuS{5-9|RfiG+Kac+{O2myQz4~uH7;q9`L~sv(#1}%2 zi19uhGc0IR@AakOS_8etuQ6J$G4~imso9x}^D==EWto$C7coEcXqYd+&vh944>Q%( zBHU#SPL{Xu@|aj`h9v;cKqaUf=%riLl(og_=`-1eEly{`!+mqDSCP`jz(-E04^ghBp|M^n()WBD z?V$EYEjAW5y#dZVVWb*!QCDpJ$^A-=_~hVBNz0;VW^HphdhTQ_J)b5w-9m`N($drJ zgc_HA0b&uLPBFK;ec?;<=cn)&nof|9b^s5+c2VsPIovO~$b~E7HU4Z?mOP(}@;oJ) zbKQ%*28%7PA1)V!gs@mL(iL}FFh0`vW#SgAZWoERki7EDOqS``oNOqH2xA0c!IXpd zwn|g)empQ1AWt^G%RslyXgvu_k5ySnP6DVsCI*Hx-@Dpc0VZZ@S-I@abeY_6i;a>j zGld(}_x-M7Q`{yObvoiM)UPUS6*Mlj@5~8rVaFe>l{B+E1$54}aqo9q+gLjFw%m&` zK4D?JyDRaMKxvfilo5TNo(f{-7YiOMW5eRsRgC? zR)RNoR-z^80z0~>tvk3L>=8%VQfmJQ}B5vMT6NZ~4$H*ox!nIQc> z(_sFg;bEATq1B;)@qtodL%IZHL1YUH(~kxE-X`i83kyLdTx$s(J}C<=bFi;8S*?}^ z4>7Nb8_J7xSKY^2=Wl5inGO`j#|P$hpZZ%l!hBl2yuPRC-@z$bB1-lK`%SSicvGN! z4>)8VU`o9DbzA=V3W8kXLWe&4=@DSFCs8?cx$%1+!BhjoE@4ptudNn~F+sEvFzv>D zAMlkX8IqU6MXSJ>ZIgONKyG8Fo){O$+>&_%laNERO(Eg2%oaR%afc(1wL2R6)Qt=te%s*$bO2_>$r!;H9qXHv)9UOXk^LQ-RLWA{1d*V3c@$E*iUe=~(e*E}X zoad(h9E0EXavT}cLn`8R>$Obave~;Bj%-)W%!KaDmJzCqR%jBr%HuzGPBZ}2d`xT% znoyJD0r*fqCjvJA3k0zKssf=G=>mdx2NBPAe&>F3?%Wywcn61jb$!^p@3@22GYXDXSHoE^KfOXwKH6n(>$=4(pLe!I%W(RCj zL~~X5_I$>6c%P>{2qzwrvIHG4zQQ|U9 zM}Orw{+96Uw2>sh#!Br;jHqd--_~vv!DUtl7k}AQttVFsAp4f_FYRnSy%aS~JdoU| z^&lrD6&KWQWn+gCA3z=YAOGU-V8SjUlA}yFUo8ZhnMEFbhow5%2#A7iHVt&tIzlUX zsMw{ZZI;#ebeJfeiI$<T^EZvI#PZ;z7+7-;jQ3unWBOuv}R+zjPm)qlP;TH z(76lUN&SIcf^f2gCgks3!W_&beE`rB@ZvpyU z=yh=0gHD%-MW6+$45ARzCDYPN$p8f?!V)07)hUGx^qgDa+xrxqXxHWYN1n`HyBI zn+KH&?uVZGNuD&&8$A3DeBZp3pr2F52)LnM$m_mqQ)?r6o=CN*e3s zKP_pruJJ-Hn5&j9tvfcCTWMQumM;SIA?=N*6L8unTuP+LQKuUHW(i=E+IrFPfZ)HR z*uqr~W~S`)yb!iQD|DtW8k%L(zQSkOcq@=Dsx@Bg1$+~y-UvlAj_& zw+2FS8~vZP*0<1LG_-_G7>@J3+U2H_G66PsCE~DS^9aAG)=es3rWLnKnV?-vvp3Pl zAbqSR$T0TD_f+>{CSnZbvHuJsIFNzlW)eWGMc@(ol~lL-BrN5}*blNa>1jqv=#sj~ zT{>wB(ZKBrl<%u+{e`HMr*%*Fem&{`s`NlgHth;gmuF09ohHq4WNPEe=e?5FMlgm9 zB}LK*6&AS2jT|hulm!#6BZ^!rNQA0DD`o}u!=jEZ$((5Da+^l!>LhPU+Jvcl;`j&0 zpIV9x1?~&mXHweK-P>qigw?gVvFc?~4g4wnELy`_(Xl8b^9^v=e5@aupRlHx~$gP^-6nOFHM{_(*%3-Byj{ zc-Msyg+ZBl8~lY>nkq)o(nwNijnjJ~=JlrSa1+Gq0=z)(B5Pyy8nTdoopmPA(VVV* zp0?IDuD8opc(VvviIs3|*Dse4lxT_S)UB{BF|;qQHfz4XDWF{>V!a_&6IsmbQpKw{ z(xI%~r?6o*Wf_Ty%+mgHF)jY5!^XU@aMB({(QEg`8ikS2_888F zBWR?nJIjKnOQg1ISkTxqKGHzGvh#XQqs@b9FZRnwXrHtN-6^@^*)6^Hh^o1ixH;{y z;h;ECH|lRk1Mk6iH6Hd9__{g%c+xwDpiRF&8MsJ|$#J;h)Cp+$b^&rL+lGh~E=&2J zp;iaZ{deA@xzw2T*?~3fEhqUM^(vC2`8Qsq%?QOyk2TC9R8J&`x_-VQ>BL`u^06SXY$6d?|rq|K|BP}f~0 zI^``j(h#Ja4_$j|ZMNjKhX);INH6Jcedztfh~|@c468gcYUFejjm_a??IYc64nQ{- z<{K8A?EwuUwl96QT+pSi-E;26h8j(eZAZ}|d5&KTo|Qf{G23iAA^WpWx5niaZ8U?E zTWc4-xK={2T;8Dcakg5@%x)iAT@~`f*3cpkskU6=osC`C;lJbk(B3t%IM{3VR&QDH z_sQB^$F)xAm>SIL~oI{z`y)e>Daqo+isFfke(SlPx?iz>MfcvvGe@LuP*bZTW> zcq@JypX8Jf7S???=l#P(afjc4-H4WnaJGpZ!(7!7yrmGkyfkxool}?o%hf6=c4Q}6 z?zC(JH!8>&OF{~N33`+NqYM4}hhN=@G}w{C&-vNnuygW`NqxUiuqepWsrSK9+`L7x zDoRi3{@ZGnj2kt%iNe<9r93XI=2MCb@HRdDWekr-jbRDQ3_l)Qb}@~$Fn8M{QCl`a z1v2NNzhEeTH+i^mHkx})>|WlZ`mGGbE&*;`K_@R`#gR}2O}!b6P&&0)^Q{^x#rvjx zQ!!L6p4ef;eKN==|@hHu|n3+NKPD4^{<~;8_VUK zu=dC~C%b^*H*S=?mmZD1K?nH9IVsk64u6CUtJ{3nt`pVoiF4?1i7(w_oTn?X5i##DE;kqlTyRdomkg9fxyt zmfkZt4MZ=`jysguU(HQini+EG3By?TC)ckzzNOtNnc^w*G=fd_lv_u4tX%p!4vs*5 z$U66uX}4DXqG9X*PIPrV@QM0day3*qBjo|A&BPxn4AT@jvQWIjTl$EELuYUM#9De> zP|G>xf##C4y`hPvZkq`e3c0$jx9hChtGRNE5q!E6887>DPnEzvYGlC@Q~cLCI4@6; zf<~_4q4bF0lD3vSt*twicO@KFs1w9oFw&OknAP6A6h(HV_QP8H(W7-FGdeLevRu)D z!&shNoJ(1*TC!Bye8r1LyzS!cJ$GUJ7PfItxsW;E2CnxNICheR{Y6_`* zu49MEoO$`v$q5C0biu@iS!ho6Na6l@i5Jzlh34y`ZM0EY+`Qb+dfd$#OmU<;L3HvG z_8&5wdZyxL6-H?}HPq_G-nmz^5tVl}q_*TY@t4r7TV*bhrAi=&5*^joYv~IlE@|%k zRup~B-K<){d|j2&AA1gai{P*{e5J3zNZ|rJ|4-*6j{=NNe$~ZC?V=-FPsr#^wQH#WMy42coJ>!!QHUV*-@od>iseot`si0eTUS?xg!WR(uh_FP1O(cAj&>am&ULeg4tPAZP^!k$sIzj($LE~Gh*;h(tL+7?CqBA1^ZhrYDEDOg8xB|RQE z1>S~}Sr zO`?Y2cMd)gswx&6@msE%b2*91Oe2o#@LKt6srj$+`EO5!5IzYv zI@xgQ_@|93WjZ|={=~dMR;;ZPQ+yl8Y#Rqsn095@ZJ0;ja7pqzo$XMm?8bY{4UH6s z0RV!26jwKT*@t_o!uCrbCYpE3sH}Ah{kq11o*hj+4hW_xGCe|bGtR8`(=6M9`$yj? zGfgjw?~V3WlDe_={8=cj`6bP#ycd&c6L%>vw?iYXkvZzQ&<7WUUS~$e*`^lF*q&#{ zdx86#v#Ks8H3tpOp-t5_0X>va(j}6sranaVz}|u@=x6=fIT7#eU?r0q@71H(RJ4{y zd+XwAm0Xu_oa3RJl?$|EJLa7uyJP8LwjK^u_5=-47q>^luYHT>4>lFR^yOY`*RKm+ z^;xwp`XD^HmWOj{4kAJ~J(ZO6%N!* z7uRHEK`0u8*dtC{X)%Itev0N{HO^)LgXduB&1f(b z-@ZAwEDXahin=YJ7DR1G)!=8`zm3W26h11#O4!xm%{Z=pn6yF7w^s&JYr4#JQwGm{ z+|xws-1cSKVT<4rd(NS5vpO}=`o(!;NZ6BJJhT|iTu%4Nt;yN4FQcrqdeSD8tleZh z4O`@ecx3N2^trBx>#78Dot+cy8@rX;CU_w(=e_Q4Wzh%9B4MV4i;Kw&xgbc+%dKX@ zcaQxg-Y+N&5SNqmwFpeaRISp<_s#F?jXB@I2*e;6q8WN?gRj99wb+RW@^3CK>~~X? z^L~s4l<^|iNiUnLxytnhqZW&^@c2z!i2JzQ8PkmnZrvNr?o(9rtbW7KINf$eAjpvV zEBYbWoKy78A7=L=|9A3EsbpfUva=X4gPENSKKLUUR_;KY()p>ec{dX#Q5(n4!{#aO z0glJ!p}TcOTzcf#%nftPmxb{Ym7hE~R5MDQ{n|)B?C$(3=Cp|usPnsZa;}F{GmT$F z8T8ap)dbn~6j!zB)c9NhQ@OPkoftGjr!X(|AC@TCXtoAJWAZuU$P}c@iziDx+C@Yh zxy?$7CCuPLEgG(h>KvLZmyWUNqvjVX_1GU*E)bm{CB|2V@Nv#-FMres@lc71i=Scu ztr|vE5}Z}Se7xl%X3?!4#M&8Qw9e+i%3-_GXDu5aoEg*=}jduUgeuO|+wBwodJ1K1+d1*U;ZU zBsddoIE4|}KQP?O4b*6aO?HO{b_#)=M4aS_3)%i2mCHNc^Zc7*-(8JVuR4mU}FX!i)@!US(@>g}JFfJE+&rXztJm6_Pz zUquT?%R(LW!?5%kf*SJR@;_YLifNo5J|wwApJdmMQ5|qp-8I{#>ils8143lfkg>wAAAvk&A`eB-neJ5KmDa zP0~xa${(M`vsNCL+wDZW(f-UL3%Qo@)cITo97pp#-kpq}JqR1g%^9gWPZURG$fjXX zWc;S**N~$6!*6YY5{h|T6SrDlHsq$inMl)Vu`5D;}+PtiM7^+22Z;}SB5t4CyHN$H|eR$OouOHXRce-fSKq%k?( zhk>>-U9hTg1wnOm@4Na?a2xgn3`}+=g?TtPG+#zP*5Gw9?IAcMRZ&(9=yJK@3-~$P z^8{m?>%A-bykY7`qGBcT?zgd;lF}Ex9iysZ=en`Xz_6K3CgwV5uQR9iYYjKN1|-TK z=Z-gG$}?V6@A^|#*%;jMTRwH!FL;8=d8_j?w5XPYI6dIwzeiUm2Olc@;Q}~9U7q}_pbTvk=Ysl1tz1ei8wnYYn7B8kq}GK2Y7yWzQuB#-7l&7k&Dj0M=DyjgzNduf?baOAcEpe>ni5g^N4FDoH zP=bWw5??i+)xA@oS0|^XYv4AB?TrTMi}XeWX;ofp;3bV(TFNOG1V7z|nI4*2EXPDc zZ?wNUeVC>U(^sMCpDv_(CW#`d8BJNkVKXb5c*C)f-+lM_ z17|fS*~FfHz~Lz`Y&e@!4s_e>gH6*&n;4$%!jHX&oThFsr-VA4#N9;&Z|JT2bl0Pa z%{bjcBifg%^waYQDqJz{!kUz5zHe*$2(~tO!@4I=`pj%!Sxs3lHbI1Ys4q#J%>Z3g zB_fmy+M9;j#Wlx^XQkyraKFv1l)*J}<#iv@f?ZPsxhF+altkGz_37ACV~(vB*H8bW z4Cyx{LvSc-pu%<>vYL6Ost~ec(h%e`2Ul4+<)W2Hc0-FdnqB6^_>P!{y)-XPZ>QDC zY-kJuj)#HZFdfgsskM#_55McVx#UKF1sNIFldJy9McXfzt-KeEEUS2C+~p(TpQXIJ zO?~m=mElE4i56%0+=Iw|8X;X#;ME^7%{423EAB9M71UgrBh-2OOt7<2?Qtpq)i!Zn zT^CI7nE&uVH%&#f8tR_?!r;f?(rl^PfQJa0MV3^xBF_G`Z60M2$_2q?Ud)nj7ILBM zb!BoPx|b^K;oJt}SyG4H+5u4TCg<0r`NcVy|Di|N>>W>Q%!yS#d9FJlvpw0dm3Aiz zv~N0Tqu*oZ&pcItJ~g>-<84!|>ri)Y|2kdYs7pv4dfqqxpiR{-2@ZnX#9*a1QnT{w zJyZ?TZ+pMC>^U%248(z?g?_tGov(L;S}Wxk;^hYa9Mk1?j^Y@u3f9eXBpDA$xzs6k8|usEYiHD z0sV2fCP^XO(ez8j%ItT(MZLSs@b|ifY8{9^n%jRsAb-x+&xp;aM>L|H9J_T>g?yFUK=h;K}N^`0wyEv;dB-O_5jkwj@Fhmdyw>$;Zp_NAuw<5&H z{`nmTPF*uk%d7&M_kH4V3PZ&kljhia2(m%y{=7=p&{3O=`WXJa9~{cHm5-z^@^C$l zcrh#(gqZ34>JfSs7!#+2zSO4<%Nv+ww^&6BGzI(j?Lfyk%kH&2;I(_P*&k0lwrJu_b%#9J> zLEd1xqFEs!=*N0LaHj-_4=!l;S5jJ4g48(EH}5~Gy7?+aZz{Qbe1DX9!jy=j=Th=_ zojOLD`?w#1>5PUm;fF(X|FyVP_?lpV0UAR@&p_9GYxj$r%pQ4;zOas9`R@07@||=X zT#;AOc1+E4$8$BiAmRcDet!Ypbi<75NKV*et@Dh+4zV42@*NZWeUg+ZG{0remmES( zBdc#W3#q;2e{XXKkeWs=zg8do_U&PJrSk0@YF%Zs1**kqA={A@#Z#u%JVtXWm>I zjBq-|xo1F1LAycU$2CnR=-Kj4MR?((o;+?twj+}1^&y(}5D7RTOgOt)KBNhO`nF%b z%HY`tt!0v8%Qs2oArtCI!3L>tjP)t_^j#Q*xeh~j5}Fg^$HYvpDh-~I!= z+&tc2=i-bYrDh#6x+CMS>ak7p?WE|-j(G98uO|n+73w1k!S!~}*5#Kxm~g<%O9}Cs zvsqS2fqm3hh@NyVSo=Svc#&@hOJ#9#s2 ze>fS(lLVg^_s2v8qR(?0y|~f@>!6PyQaKPtsX}tXf)0&39f=ewp01#JhwnCOK9NHH zP-g!=Jjpzsr$a!Ss-K3_NYK$@5)Gu02m9wIcK;Ecw9x47)vCw2Q7Qg&P z(tV3Zd#d@IZ4u&&Qr`8Rlhl}u>nQU70LXc~?+D;mJUoVOTA~07^^(5e0pbl952O7( z+5WpH5Tw(ldH{4w=l=I0?-)LjKR3@I(#encGT7#67sQGh3Wf$yNNIjU=4%IkcmlHj zKH`78kDe4iB>w)NuOsFmC@`RwErgv#ZxLA@Kt7r8P!Kj#y71tJ+~3Ta0ugEq3^KJy zANu*}I$Xp8>N2e0s<09mYRAd2+6Ii-G*S1@%ATAm$c|@0%i7 zxT73oc>3ipSD;qe^`rM z{dnB37Rsze^9TjEZ{v*qnCUQi72%jaP?oJ*p*!&yxcPT#+!j_WZO|O2=Db`5Xea)C z)klaYB#8D5P6;Typut=oGxVx`fnv~q1%>uY(9>efwonXz1mX#^5inm*mzMV0AxQO6 z!r1$Ykqa4TOI!v~w@(4CnxU0ExrK#o7mx;o}Vx4@V$lzlzDc|#+>zKorzwa7836A`fPjfdX0 z4NTK6G5ZW=+jF}pvcefHD)P3PnlxWY##0K-b( zE1>tybYAL4UaHMyq~THfgv#&kzNu5}cyV{rca>o!;oPM;+)I(sei+B=gic0rpXVO} z`8b;06=9HQcGalG1)M5m={;l9g9i`N>Az%t0Te6@E8fDyy<79xH_Cs8kQ^>siup0I zRyHgOaGVehs+*)1x z{{ENatt7@%Fo^jn_}aJ7-_o&C`k7b7Kccv+r!s*C6H)Iqf`pe?VYN|h8m&qapAZ9O zId@QfT=rEq8l?CgJL}tZix$?tD7=;2N&PyH9@Ji7ndr=Tkz}?VV|k~f3tJi8Zgx{t zeYENqM(T0%PQ#S2y`9ujk8&N9Ua19Nb%Q1^ht?-$cl3mkynITf<(KJ3#3~0i)3&g~ zJn3Wz=1}zxAEa-;9i2-yJ7wqQ&L||S15pS7hDI>x++T@!^8{q*1M3@hgi--rH(|7? zRd?1a>hVZTgN%hiM*ZfMm!LaGHB&Jm%Ms6^R`2C5-|$*7Q!$Yx^jDQh%UNyBUs>8E z*Fd+6IKTC~r&}OslCm8vPaR-!g>b56kXehRoVM!85dcjr$O|_uAlOA*2_TFw)Slrs z+&cwEXG862cbLhq6TQoMqDqSApuv8cvftHRd5BnQgzKKxP7w1>JiF(O@u`>2*Ww_L zDML8+ofU$W$o0Szgd6fx3)py(JGMBEt&vbQ^nC}=7at{edF%v@2G>P)q_t*H1_iGq z7uJ+mcBK&>XYsD9-T9jerHhSz(&EgB+((m=v4rha{#X&~Dt(QSs#FE1S#Ik7`PUrm zTm0>Y#jniTv{{Eu`?B;BFVRF{&&;YtxwtNg%JViz`sJxXR^3K+>niV80$rRcHdfw&d!nIv#C}2dJWF-6f8gr4?9f1h7yiLp2v67 zUIR7M0Jz>qb_Ll#yx~io0bN1rEUmU6H#d`=xecpw#51e_!Ve-Ln|>)Ub@g(3T3Uan z+w`Yb&rj2{glW4EOBU#f75x|TBmM~6s~dej+~tQiB?>Rxl9cCLlgrq7BJgA z(BX2rZ>|W&d89VU#HCn$Yed{M@347@8;UY;$E&+1N`j%qceWR6>=#=4j~?|UCm2%| zh~(otqO&gMqA!hy(oWp;T=wuadS!ch*88H1o%O2mb2PUKu~-rb;R`*glO z>i46*f*)b1w#A}5zMsNK@6eFT&m5oK{R!zozISa3_f_5ba|^dcZOU4>~{K?a6C@~()l7ujwXe3 zpidA5>quBVoq7$=tb{j($Cp%iEBGQP25! z+f{ORZ)Yi6wY%EI`oeXi6O4v&+TMT_3sv1-l@2P3A z(Q%PW(;*aQ-@QlcvN@d+uc^pr2#rrWGq^Fhg9Rnql5mG7;gMf3E}}E3d}x!aqYh4F z9?;6N$+exp{F^FTES|3oW_-_;Sy`#FoTJ|p7az_|&r3`o#oJX3aSZ?TWU1h&vF_uE zm9$5TtUbO6wr<=nh3KCbIgFCvSZNcl&-O;jj*la-b8oaL!owaIHvRHAb7572^6#%y zvJ$)+$~Lf%%8r%J7Jel0J)4&t%h!aj$B%ej%N&d#<|_m=)#_R>yh7+fqS(ul zaH+Qi$DgVn&7{WIpRP}e70lzw*9q|D3mGWO;>>%z1rH+!XkqGwp-mxf?F3e-WqKIwK92WNNNRR}Fnbf4MsUytwz6~V*)yy^A}obC3S<+gUEk~;fM zUkIq!M{#JP@4L))E91JJ{)jd-8wkU-->iw7yp_IGFZxuYz`#~Aa|zIHo$5}OJ{BYJ z=<5+nL>?!Sj$22@&}+HMp!wk_0M(#~fLnd!V9%23KgZ>$^YFHUf#|APFC^yynD}SF z2NJ}0^scXHlA}9=e)(~4t^xSm1X(oYj5Y;Ut69-i`ifDe}aD7Tiu_}CBu3xjYc^R zuJ;1Tc_p|!Zm9Fd`?Lvcm#hm4dLpe+-9g-EmZ5I>^HmX-jT8+3ki_Q1Lbo);T)2J9 zHla|_z(Pwy@>L{stISV4yZKCcWm8=eQ%w3(kF_1|Y_Awf=bsb8vpcgEbz}j%VF40y z0yzU?g}GF%?4Z59N6=GmO39#JArYe(-6v1WSq?6Yd?SR!L8Nt<20L=RIO$0bDd?c= z*s~73^d}JO+c#B5*W7-A#^166dq4)rLEStxGm#x}b1vG@0_1bIEvtSlRE*wJn0y~_ zP8Bqo@+WB0i+ik*gE6~Pz;S|7u_-#kAT2E|Uw$l0W{t&^11}Q#^fVdq@mwN+&DoI{ zdQe%(qe$@$RciI#F1E}fA;CB-F7~r`#V91-Ti9tUR&pkypum&6kgnU6BZ~JPQ{6}$ zsmybQxe00eV5-5Z`TomxKuo^zO2_~oCBu1{MWIuI>4FeTN3hqW`@{iYHZ$|ez^)4hahX{SKgESBg#EW{?TsVSK*Xwfpw7o%4m6zZt)P+wj3e+ z4vPD5H0e;wt`QT$Jek#fJ(}<512k6!YC?{l)1RcPflqWharIrFVOT0D4F`GO(w8ar zsV^HQ<%(vUa7Dlz$JqXc?-(gulyUwznIA|+)Qk@mJ3P41wZt<+DtehOW>0*AQ@$$R zOlx5)b1`irf3|hC1mWm0MD5hus&|JA_5%pvbQw*i+0Gp1sCZ&$~qquOK>62@Qoe+ zYgiAXE7Oa=^&_4J6F)YdL0(haLB5lx_8i37f1BIiuh$uexH&$;+z zFic|m&1_&mUQ?6IY|os}dyn0n&CJDN`-mwpLEB}Z)Dl$wpO-#j$)xfm@+X47S}9ga;LLKI^S>`xW#H?m<5wCaYaD= zku)^Q#T8))@>KC+$`H5N?ifJdbwb;o;Nm$>&^a3ZvKT032Q!sJH|B8)PLplDN?@%0 zPbhOg4FntT)i>->oZjnZXZ+P%9)ZYB$IM-gl&GgxSgslXbIuB|5p59Eos?lVX8+< zRYj#Fcus6`*GEmUvQfg9&rgv_l55U98d{~lv(cUQvYm2}r!qkFqL5v(WEA&mVO0KO z5I7c`43a-o=EDc+JNtp-(P_e1N86|i1g4DNN^xu7Ad-Ar+VfV2l;~ZNt5pERX;CbR zfT|dzY}oX4>}iW4v8t<++*u$Hq-Ggv)T{T3c@7}|HLeRtxVSQejzjImhp;4OYAuSc zx{W{@>`YrsNvX#=$3TOxWF)6%XgxJwGMNl*a&YkJ3j$WufZI}PTeNI zb+4?{c$AnLKI^7vRk-uk?W9{ zQy9IkKfyN!5aUDrLP@97RGNceDl71@TNpYXR`~3=Dqo_Nv7TmuLHfg_`x&-1wxr)Q zgt}8SPmXY6?MED*jBK}+L1W48GpsYv1ae3*JQLm;BhhB70q@hU06ZxJWwy&H@Tp5) z^8;l;lbtnana$)Jt_#4+`{Ixy_7BS<_2{>kNBXbzVtya~KH1aolH#$gugv8MB(JGX` z2q-pEK>{P&W_!7Xehn~A;lhfJ5$!R9Eb1){h!ep|8e@k|AC~Rl`eR~@sU#nH>Uw-d zZxqkJGRd5Y5vq^c**;bC(r2mX4unNaPiOrs!*&^}ti+(xeKY}DRq!I!3tM&zGw6CL zO~}7dOG#Yg!bF>pB*}I#q8NKr?X<9nL&IYpC zXE$)0HKhyhCJB=LGPYd-VZWlC2AaC*9q$K_k@jHaxifO6& z@?gPcM|RT@0A9^8nN zUEn3_{p9w=2dnns{&P`;qce`OE2Y}Vj~K_m86spi%1hm3saE50TEJfKnHD|v5=njH zt)xjF-1Mh~@cPEU>ZiFAFnhz^@nY`KT2@9SOH0eeKr?pbX6GkT}7}*RT0&jtJ$L zAen&fT8Mr8Q_uOk2_N+dWeYgM@x>21CLvicXf!CiYe7KIU<$p3_pQ=*rjv8Mzdq~wBkZ_2beha&I^Dsbogb}E)RNY$-1;R6CH(1Azr0VC*#ofKFMdNU zwib8ugtjvf1b++9rR&b1GOhOE%z6$Xo0>+7mk&HY^Nl}FoQXlw+mDue_`W0==S*H# z1Jg9L9UIRVireFNjze2syhdRV|%NGWVL zaC4cm-CZ+Nyn_rRQJ1BZ|2fEl8A1YJZ8==X%=dT~SjR=;GY1SD!cPfVE35B^RS$xh z7Uo254HTWQXZ$7-OOwyu7_yeZcxt+lbu{1Lm@w~vVD6Q?)Z6KKQ#@Bay46E4c=mFr zWgz*ugzMO8+r3qzjBO20q&Bmwr?-7)qH(++zKT-i11d=(0i=H#RKUIE8^W}3=%yV$ zfQlffr}XCPM)NmGYJiv~&-7W724?-j&5n<_kIamJ46&3VsN#TnX2ailCMZOpsWI-$ z+f^5xK%TiIxTq*{I#hHi4R{_3uW)6Xyf@4PwKfG6tlY-0djj1k!ToDEdHCi>RG<>0 zrVYWK$9$$C;VF3Lc}d#iKza)O_jjuBf9#Yr%EqpIk{ZFUpquMzJKMWJ%l-rWO^Z#m z{^ZGT(%B%uy>yyF_MdLsQ;@u!OO{8?e_e@9<#-Pjeql}}^T)HX0o6dTz>NQ~K#>26 z%NM?fYNHgg?2;h`H6A&qW8Vwazuya``F5_VqTKYabm-*_pm`B&@`cBHbJ z!89M6D2ySezI6NL9ejY1IKh&1e>~`}n2;sJk6HCDksmR{h7heAWiTe1s)%Q7>-b5s&;a2qfR3n7ZbmoKNPq>?$dEPLMgR? z6PZbhaAYME>MRcnb+uK8tQtG`wEc#e7j z`>9&r(Zu8nmG8+Y>1UiR7j30kCH?<7+~VW#L7DX-D!yilPVUbL)ua2_qYKDG2}%Cc zzD!N2(Im0vf5J^!&VwJ%2@6GEW2%@kVY842D8W4)UtW4amxCJx@sl}opwJQjF#1F-A=+1kGkPkQ!OOpCcO zmZ^+*qg7d3?!l7md!U5Ga{DD8jlW9x@nolpRXKa62u87eE`k5PSRwglVb=U$*=`;E^){BOIUjbdQgYihaND5lLA zel;oCpH=Baf^%-V%&&j_;|I^bky^u0Z4RI_13uD!iyTIY`$Z1uADxMm(!%vp^MB!<2U{&&|Nb4%y%$H>77_4v*>~OHI>{q7)bgR9Xd7^_)zW-P3(C_Du4+wHohlVA}^U;_r+yx&V zO7vH{7xzua#Gg&;BPmRGlo|Gk88V!5;W_X7h}=l1FZvh58SKQ@O1*H(f3KOZTqS%t zqY0!0YyB|wG#Oq@_!OVTflz*r-QN_Wzi{OjZ!izxy0E>jG2hRz&?>!HXk*}!GsF|O zi0CcpWb-Ceo$-yAsvWKJVOI-e+a?&?BANe*e|Vxuu!ZTcL<-3e4jE1AYSWpuSR+)P zA>;gEGSKuM!G^IO*nvZ!!#^MVqzE8`QiI`Y$GgkRjd+*)T<{lHG}v#W7_vA+T>qrZ z=qL%9RaEJ3+4@iNc_1R>04)K)4`lcm2UYfJV^(3Ya+T+Vwzvxm2jv_oo~wjg3~Kq? zR2&BM|9oJE5st2h1_LT17%@2r@|a8dXPyJ8n1JqUJn}%}|J}s@%iDdih7fwKL- zZ6Y9rD=s^zzR))?f8njcaU0d97Jm5o_xF{U#QeY9900Uo1cA`d^>Y{xu5Iq&s{84}f((3vRUf zFINI5!=GNZ_xO1;F!W{Qa)f&@fPMUbNZ_vJF_)OXf}^-EII;h&-~gBr zpff-pAvCWU97<1B96@>lbN*ZD`Hf{EKrv(cMYK;-@)Z342s0cd#z=UB<=<8L?60c$ zzg?C1b4RelTvWg}o8?c{Kd@MY8XpL>Z~nKPuONT^0k{(oFMSX`B%}ET{`gRO3IzLe zqWh0ZRI z+nF97%$YGDd->0LX7-&1QuwLpJ_dCHl9FDS@xsI*$>&G<{q?3+{IP3j68{OTQY43Z zM!$R{L~JNS%2j{G!_I0JE&|9uKyywwKic@{cMa{0+b#iBE=pjnU-rwk};e7$Cyv39YDmopu*QQvR>PgkmBP- zRGI&fI8I3IpC;n4=?$etkU0>J^s8 zY$-nohe68KNFLqiDWr0(Kap7WQu8Su5%(1)_uzB;o8nh1P1x6Q5fdcyR}#M$14_z| zBWn<>#lo_V8RZCL;q`)~=@qm?jN;{E2e;i*#BZ;@O%Xjlo&j@i*78$excuC)@czY* zB!A+?X9Rt)TKn_GZ(k80u-WoGR{Rl5U+O$vzu-zT8Oi7wA|c9wR^55B2!yqbqAz2= z($3}rA0)))_s0#%fRC%1u`=dj{(6pRE6XT1jNSL;_MSyBI(}I3UT(mPa(`KY zB$~z(A8qSA*3)ty(%N;z<6P-4-n6(2X1Eg5aA}46{B$_UZBX0qb5@k_IcF~1%qYfV zRpsPPF5t={LK%c7)Jp&eCMCA4S+{WPgXnUnWU1|-S;0VS4&~@*$OVCv>1hiNoznCA zm5=;FnSKTA{TM%2m87m8f9$9|vGd|k49gX=%B)yv5)zV9^Uh0rr^0G(EhXiF+@Nw0 zEjQc*v=60#0>e(`!%`w5ALj5czLMR$p37q=0Q+eU8JrI^XB+>`&Y%ja4LTcAIFb1t~h;4 zmfmmzSP4TC2)4KsbV-2R8yL=8f7SKbaG|mZDH+*jZaV*H-#PI$^5MrOy5H_>gNjD;j5Le1LVJcM<{+Jw5}3LQ)=V`?4VizG$1 zT2bez*>#mxF>Gq^nR|z1>t(?%Z-3oAm*p7AkweA~GO^JJd=~deiAa&pu7}55{=?Z% z_3bl#jXV%neu~2F0d|DiwRd`^pgi(aE|lS(ZiStLLvIZimy~DAnKB{;W-T8eb7Y8O zx7ByUH?n$0J4Zq|JgursqQzBA?Rojl9MuO$x%_5@*WWrfw5Zk3WW-HZO(j+Y{oEY& z{qjX=vxsTO`c%Wz9?Q#p6f%gtj{{UI;|cr<@bee%emhL0Ke@c0VwCcm{smr;8fQ0~ zQXQ^gT>GZMd*^ImAjjP@1lb6f(x+-;lgAa2n5YPH!D%yJ#ur>18$(|~V`$9sU>!-4 zNLn7fuWoY{@z*zoINozt3_*{blDHDk;$%15%`R+~b$M&$OUS~2s;SJ?1=`-7k?JbJ z3*V0F7Mn4#q#xffDQ7zbyGE+pF3uk?}h-o9BxHa}=L zce(zU9gBvTQ>?%o9T-KJH>AlVyrl!7FLHVCcGfzRTICn9(Bi1qjSe2u<*{bjH&5jO z)b2!%ZUy?Z!do_+j!)YgKA+X+ekUwM9p@*=iQcX4pcV}w$htVO#YE}+J)aFbHJmDz zv1a}i%Z^7YoyLol>ZX@(gSUUVWhIdEt6;gW6pjnRcy78mwH4%X#UTUwrK+ zooq+-9OV*P2ffy^T+Qw4^5Z$&I%O2-r$JpK;x#j$-W~gJVmLnLre*PqXgwsrEZ+g2 zeecv+Q@fzy#&h&5uOF2$UK>6qx!NWbpy9Mq_K2MNR1C3}_d**aZMG+uEiWc919W=d z+uF4p_CGOwUzLcSmWnuI^xTcjg63P#sy%ZXlAc{K;GwEFT6Kf?&P3t(b2u}5VO`Zi zyIpjWhCaLNx0Wd#sS_l969Z{DuMOhg%rSX=uQ%L=g?!!Ad-a>jV1;(SG@PEvg*0zc zN+snh0+ljahQF0Ey?v+l_1n?i68@^9M>s6N@R{Gsz1|a@yHJzjm1>Po$UhIJ{oQjL z^$yD`H+ttK^7uP*neAZcYQ-6~j@9DqEbfDu(* z9%J=?I?uJcHI=kB9wzzv6;wOgdVRL%xrY64&8Xb^Twf|>K)m-2TkZ_CGvU|0O@JWrEWUB#yR6WJHZ|+>3eCR zzvzmpx;I1O%6dAwg!!xqh>!b?cbk^S8@D}C3RUadXI)CZHuEs+mRWJrrU$A3HgPx= zpbxz48i2LjT9LG94y17$%?aCJ6b+)|W3d?Dc5&XApLy~^IYoxusw=PRF>ainTerAB zS7NrWfR}bn0_hTi+gWNb@9&7SKYOLVrJu$%NkXaBaYT&SYpkpb>n8u=IaOd+VquyY_9^MnObc zq!g461?dt{kq+sUmK;L5L_|bD8l*+KyJHljX6S~YVL%vifFXu>H{5zZzxVyt_kGV= z?^^Q*%5uE+wfA}MGmhgpuLihTI(!iVl1kH5Me*1fa%aq^*h}h#y3Cax4@Q3fzO$t_ z91n1+&%wOUD9)u#muu6A7agw(r}TxeF7X{DlpT3!5#^U)2BgMZJVLk3XK%6!U8h%( zR++3%n|Ad#rERrut@9c~0&<$cI~Arjcd)lJ;Dv;%9#QW!6HE({Y^%})z!Y%0x7!D> zKWZB5YPu&q1d9@%#q6#*G6ZexvZ37gN9qq67Ec-qme}fw+J2(3Kj(KAPI%_#;37@a zk*kJjsyPv8zP%=YytlwRY1i-bZOPRjrZS-G=C-}$ZflqH5Pcic#}tDJ8%z1)i_^E# zu#+#ZHHe((d;@@b6EctOv1defE1;iYAtt%>w9W{}s=R7SlC-H)~~L7ct*%8y2iu0Yf7{8+2J3XW)I{ zuU%;^Z3>Txh9LuJPhxWxyS(`*kCRbJJImYU^#KB*DU=5rEdPXJzB3HxNcAV0|D!C1 zoc7ZNjdimd-~WZ|UpS-Z_F~I?oSlTsIyG~IMF4@hoZmSs+YmVjwBXZ8=||jFA0sYZ zf@htEi`mberc>IemkKhfKMAEexVko3H*%mF(*_0~#^R9yY-hLX7t&&DudzxS9k)WM zP{gX~+nTxgd5fcc+SMi3EU@`p>#-_E{D~wuh)SC@Fng{=K&RH(_~B(%c+x9(_jsje zJ*1FTp;~-(q-zNhfN-nx;r6+I@VBXcb9%G^S)N`wc_xcCWoBI_a>g3Qji9LwW)yrl zn@HF2*(+r-GXc5#i&(K2%x<(QLe)1vu4k0{`nm_e6kW2xl!9LzPH~hyB~LR!+wxTz zSpk!@=1P%n30s(+asnmdmAK(54QsPkj-IELNaM zW=a=yT9E@N%lgEk00P=fFe*Txd@&^Wu%gfB@_yYZ7(1EO+pBb_Q-6Ku?Q|CPp$g6! ziekUOLzhNSN7s!$)N*7;_7$6jsd#Oj)$!_Y-5H1CYZh{yOYZrHn3rK zJdSddaQX(-?erlIzVjF;A_}G}82?jmx}ARIsOHwnjY}YP7g1n}dj672VYP%1*Hn?| zJKNuqmi>9ww|cS)m5t@tSuN}7$TaUcQDd@rk!M>v0mgfH3}!3SYh?l~5}orZVNKC# zcn?R(*e(TY_Skn;F1q)ypce7UBjm3b0!ZV*#|ge|`!;HqelRhadF~!!?z4Rz64vioJgBwBBuo1R7SKkOyyuhZr5yl?5UrWI_n8;7Z2O)Zc zAdc^w`PoBMcWLR@aHMqxB^eEaQU41>TaERYO6t?YcKuM7Q5Js`ixxmwKc6Iy(8y8A zSkSDV0NKZz-@PNQ8Vr9fo0Vy|PO7Dy!JNpZChpI$C}v~YZCanB@Q(QAnnEG{swww8 z-F8;Z;%~0RPqaVV0rZ*0#cmvH`~tQ%Fo;b<-%Tx$nf>lq>Ep1R7hQs?IS!_?9}hWa zzqo7Mt0S_lunKC-{nU8tbEC8S&B#Y3GEu~*2=&|4R`oU@D z2>{~1_QGX=sL#Uq0hjZ`tiIt_{)6q|^!^#1PHvMPnEDf=z$&hlk=6sgr|cihO-$OS zA9yb}36%JYLFHPcLvJh>2zRfc+G_KsCUD%3^A`p8me=Z4(1M}UlY6zwB8uzW5bvTI z0|<&a?zjfOa+*MK!yqYon+hy>8%}d1K>}vQnrv_iXBitCul49B_TZ)gTocTpaiVA9 z9Vc4mqORxfz4Vjg`HsD^AT!gL|Jd0GkOQns5eZos-WG`tZ0p4B0RyJ`PbOAYAh^3i z-AE4;P&>@+VuESplesMM?yhNv(V%qOO>4G-h~IR+e-OKr$X%2?Eg#6*#afbt+AcYv z!|{0S1}0Lao2PW|x-OM=;qM8iPs_MHEdTr8>erz&v4*Xlf|CI69f{5P|*cJKV!*M!_H z%1vOa^25Q;OsI2?HWej>WSpMVb&(dGNQtJHup&;6mRNK4k;cv$dxNhOJN%!jlQitl z;bj&?MN0&eACuoOoqL%orxHm1lg4Z3an28Ax5K$mj@a!vNsz98ATs=#-&#mKRzS^~ zD^TKeQ^&ZB>r?bl{)K5U0!Wz8axm6`(4RoPK%1HEsaS;$aTR1*|5pMHTU!U7r{6UZ z$^4sY(gwoz&f=Yg)HpZqya^So6WzdQVB*-U|SGbT1}^!;k)R+7s{1o<^!$lUj*A-Sk`)(N~; z;w}DGJMxsneR15r_AUiiIJHViCVR^Tl89kF_$Zs8#g)V{cAe&Fx1}V^Tw4pAV3jwK z9oD7om{3DD)onx8>Gq`*esFrS2kn=ClCl&lG@4rl9@3LZPingu@TUb>p#8Q5E5ASD`!KqUhPUS%b%3`3d$+w;fIXwCIW-nyWLf27;{y)ec_V zBi*qjj7EwTZRy-A6Ca54<_lSOapAJVnvuYCIfVYT5CbOchL03{+Vmvh{iFw~rwjmx!)TcI zGag0nK$%sOp;i8M-S=>v3LXq&jo=HR9^@lsTx$deCy4^G$ek;- z|2LNauYc_19>YwJlak^iT@5D1a5C6^UBIDCzW3~3Q#s4HN!)xeJ-D}!bcZeE2I+cD zEeUbyZLofFf*mom+w42ioci0@jLxRxHQVxBLDA1)FjXK#b_zxx_Crs0i#zo}%2|Hf zks}TMYw7$t@!Il*+jnvn!lh}0I&af<1{m{}RXoz6EJFtrWMFre>4U5hm1@<^jkeTz zE6cdTUs^C=gl@+xD&u(e0s$LB`v$;kP+dpS0x(>vVe?eP@F-w45OQQI^8b3ZL|JbOS#oH185OEdSo~A)FS*F>o3n)Q|Hv(DGv{s*pVZZcMd+wY$;-) z(UdDd(d>p5=9v#~QceMr;l-(18;_Jpt8F-yCv|k}h4oJbb*{5E8&e`&3_NZ7JTmKr z{+x~p*uf>S;cVKU5r&5dA(seZfOZv9Z(MR%$~M3Q?n7eX$E>z{Lbu zR~&&Xfve*-IXS1XpdQ{F|`rmlo(E1JBj-D=x=D#gd%uI{HSW{tX5>UX!fpA!= zztXR6D)rlENC}R@Tr}}fLo794yyKK7 zA8JIu0zOqaiXvmgd~Si6?9#<|{=zvAk)HMvpS%4>g#c@zBG;nnp$1?8X+LiL383D+ z6FQHeYL3RB4tiZO8A9vD4SI!#9hPwWw!^&*&LF!9DBJY`SB90er5F_aZiU{ol9SOATf15T#dqI zL_*ITvdFua+SBKS#Q<`ipW4VR9j`tg0A=P%E|t7Uj^mEV|7u5?HX19?t+(P;>@TbX z6UqWyuyD@L#aVtJ*cv-{5<-es)@NiGBXSoceo?|3tQxkzCM&j`R^zVCMa||&tfU6e zd=H>GjI}mB`mja9IZ=+KOY^o#^toJ3j8XX+qmsDqp`|5(e%wY|q?Q*`e>zI1uO)my zM^I%I^;WB)hG6ILg<}#H&Fuarv4UD*E4T?LU+ z@l@U4!!>jMa$wF+>?J+;(b`(S>LZD9DGD;#+C*_ad?8a;{iOExYMC335VZgrh!dXi z2}0V%Mz6-f)GZXv&30;wmTm3sNH|LbwsjYKr6y~gBIUQ?SC6>ppiuw{d0sNEyT0#8 zJxI)zue4|ql-kKr)B<_L79}G7sr27M`v7m`yBtwdK|kgC9^b%9Nk=2laX(Bb~zSFN0NW=;b#?GTe4 zDeq$DD~WBog}MUv8!q46cUL-UI=8yj=B)Pmq-f3EOPVGtlt#3mm|S@;l%?&qo7WeP zgJYLNKpNb!#CTOcHNJ|YqfMzrK89z2=tCrnis-YEoX+U}$`a@fiCdmuN->9#69yZ# zvyz9`N{nd~vL)16Ey0hw*6L(|YfW}rq_9Y8UqjD53b?lU{KfHj^&$T6!5r>}%_cmD zJGD61D&L#nE%)|5n*C`UdvoAh>q?MtF2072o;u`zIM&?8tZ7uE!}iXe_G3(Ca_&Zt z%^%mQ-l%UiqyQ>n88}3@BvrmYvj;t%ubyVFI0DD!n~g)qCWalUA?xOaOPp>s>>|s1 z>3JKpF4H~kI^9@zgx2JSyMP9lT^)!T#*SAl9#kc7qoVwF-GPDOi@W&?Z(F&?e_DHnQ`3af>E!0pj*@GM?{n0A1&J@69^yM4i_E&gr1xe zEO`Y)vBicEm>pA`p!l`_-ET%oxV<=fl6zZE*?oTg5Qy}Dpo9H|WzhW7uV3#u8QbNm zYgkBU{itT}0zt0t+DB9OW%`8%S;Hai!3#Wfs?!}njS81fP-6lmvpufiF#yK)cXAY? zFZq?QC7C0iz>BVL+@DwA(9bs^&pYC6a1`{wu(1OzVg`kyl;gpwX>Z1P7Fq#^XRTMu zQXZA0t<+NDwb`K%BfP^oud+U!FbXo|gM0qV#h~P&3T20cJKx!wVmd)dHFiS7sR2j~ zO5|y2H87J~bI6w6HSYWV+|(0UX@lsfp4G*08p@-CBY6VrtWpch_|EU|-}ze5PqFf? z4wY~)%TpCFsO=aYrofx%UO^DQr2zQHT-J#-*l}7He%KF zc{W+Z1IC|!zlrD<)AC+E%lz_j=dNe8#_n3ZlZ#?4*4x=uQOtRylEo@Bk;1>U&*gL9 zc3PZw$Vw@QK|;_&u5MO?g(|OU1mAwTcC*+`ryrH$b%M>5PoP8^hFU8z;iSQ>P7vvu zC36vkVti&yt|OJ8LQ2B0gXZ;yK2qP7DiOtE7>* zZ~01_L;r}<3!`O5UXW|xm8bg-j7b07f~i}}0@0?3-rG{};>=e^i@=PLc#t5{F58Yh zCyd*zR8rl(M8xQ|)fTL)y9B%lY2iD{cFot;rg@Aa&f9>E7WtV^V~clJun?oBH+iW~ zO#l$mWEB*seB3^MYPL3`dV%+*anO_^YNEcnNVn0UQMuLuiQBN#f7?xaX!m0*Ctkse z(gS*^MH!iD{WIzDa>Jxzhmw|{ZK=A#ai+fsl90zo-h2a8?k5AZYhS2dL0fAp?p~wC z&W4XrEw76U`=ArX%y#?2jsOVAbq{-d8o8)Oc9yxBxVThWd1(cAc$ytnK1@~ixkN@x zCkS*Oe_d{-^e>HogZe|lnAOtSXiaE-L>6uisNTeke%9ZUN#%E?Pm8nScHJy{yWPbH zH}nLJgB|QfkZJHRXd9>)8GZj$aCGJ2g9oDl%R$1J7rLvzOWhr5fA5AY3cBPi>^c8) ztLC{+=}J+@j!j!N+}iNa>8YVM_~N&=*F1pLDA_`4yR42%|9Vct1YJ_|SnZBEO(BK) zAJJWA#pYf|J<|Y1stxn?W^%Xa;KIuFb*^~rg@Vj$6niBgZFa*c z?TOL;bxSrQSI7R-%ttI6R^GFP+@B=yYHTuX3LYI+SIGxjsk*lBExkEdf08yZvOPfj zyZ=%GUpgvo5wo)?WoB7DZ-c4RO4**+06h%k^rxeKX$J=`ug#y>a>M3p+;pio|8Z%z z3C}~pW_2PHRkme-%#!%#^Y_IH=c6f8|v(j;5onyM_$N zhMu12XksuWq%*M}c7qw0>1SoWqDtR?*C@i` z=Q#vh>gUg1Q4D@fH!IJYEai}v{KPOE;sPQ->LvH@3YgGd3ERe>yUV-?1{QD7^W@uQWPI$fZB*J}1n}z~qVJ@z}8tR4G+A zr!BC$3zYE!gWVdO*R%n7sfzl=Vvz7Hd;#kJaUhpb^(wm}$NB_Us`9;yk~RgY+;w_V z2{~`QU*7WzSn4>=o8LrgqwK=~X-gh@A{fLAnabx=1WFD>J)T3lEKwp2DK&-$3r@E? zmw!x(EU#n7as&b-U2O8205<3LbOvWfGYDTZfzDCRE6f_PqVRovq6%j61HK5T7=PR{ zy;4u|3ol9}0*Br?*hHl;{~%+u(JLi}llk}VU?Z;h&o&YF(d4$Fny1!jS+CY~MW6{p8n?LAhHH915pJl=w}zPV2HY^hGt>x75mRGZ2^Bl} z8pEMCm-|&xU;QjkpQdXhKFeyW2fU-lD{WX2uUmHWiW-ev^{54#{!#vU+WSvU%WoI} z9!YI*O$!P9OBqR&$^M{l(ER7gy0g#TDH>j+1c-Mg+pHRe-_8nXPDlsrP^>}tXN?Rt zb2ahfP*43&4jJW-wP%!Vs>fFz*S0F&QQR_0offcPogxrBQfjSTILl~+YDQJ=GcbGv zH7Vpoe(}t@V%4OX&P$bbsQ{ojLOxo(368i0DALBQ4CQOR8bsaS21P3cJaUdOth-)X ziJiD9bDEBC9VN~P_Z-N}ZTCRT8u8f0O)T$fDrnUcv--Z36$R5A(Ea4vfJMqiR>@d$ zJ%-VFYb5_Us|*q6wS3SC`G#iN%SMe9#+2lUtjQUCbx|i0s^WS3Tgh^Ae393Cf79g? z`?i{c3;Pagb$Mb@bVmTj@#Vmj)Qg5$;4PfH%uxc|<8>Xe0_$v0pqtJV<%NWm*3>yS ze$msTOe@gxC-H$af`Q$t0D@-3i9;n87cHIW8Q#~qyCnJ||R<`e3Z zz)$y~CLJ5Pzmh$}+onDRQU8q!g%@l=y6x@-ni*cm#pR6(iB%gBwdoYZ>%-$2`-BFc zB#Hxvg0>LsN1$u2n5CGK3FbF<)>ya+TlAYOD~v<~(bmlc??rTDJA5}JqRyj#a<5Fe zE^(vKMlBYqBaqC_c%nf4m~Ie*$w<#* z2yR27*j}>{B(42$F}lt==jb)|y{b?vrXN+9mh;3^D?$LiVD&!Bn)bOxfVqe8P4(NM z6x{0Wx7$}}kRLZ{Q5>^di_BvId9mprc68=h8Z*X+-d1_;N-_)ZOT0O%F*y7GAgtO+ zuN*bpvLySgayFt~3!nx6k~6{p)dR@d-1gb)`8-M>x*yim)MP?#9k`1;9TOsUO~}QB zihWj6mS!GNT45)$__oZRI>pfS5dT9&#Nv~0Oi#XDjJ{8rVaJ*4#8{IIZ(K!)@Lo08)&8RC=wSzIfW9!pU%Y6_mZRq~@)D(RViIY! zIb+ooAKVojGz|^m@+z+1YNfR88x}DOxRpUxGmxcNWhKuCX$-1J)&-EFH4{d*k$T&2 z0bc|0HR#eeTEmJ1NFViKBoCrzI(fUA)?bKUgzdmVE*VPrF&6;l%(&1?r_$`dl_jF=qE zhi#nQ)&N30GS3I0A~B~6UnA9KCXWf;uu@tpsZF`hJI%k}#{O7F2WsZ2+l<+S#-KqF zupO^QBvP?ob>j4RV`i}7^R5cc&EF|~4wu)xw=P~~L(lSVejx5I*l?`yM|2-xY_6j) z%2ej@zx{b`vMKXUxf-+1KaAC7)5LkKVYiKWRr-8+o=NN_g&_${xkjQ=*M_`eorzxO z`uDIVN3y~bzVSEo38bQ%6vD1bEC?p9YZjCwS7H+m>jN@GOnieTZ6|9p7kZPJ&~Iqs zDhuQRENk+lY;i!|x zMoeFWhl{{UcG?=Vn7@PQ9yix#x+2yD7qJnMIMl&vSC2?{bQPt`c=@tQg{2xwFY8oI zqXP_P53BWD2$vc&<(Nsmm`cYQMagT;q*;q2(=K+h-|S5y=wzA0!@Kf@fZhWmELAyb zghw?#bCTKX=s#7MTi!UxzeAYwAj3xK_ff+^K}0kf6^v1_7!sS36$lk_TCuKYi$39X zU$0p*0i(4VEq+j-)JL+Fo4p@=B6y~ruW2|R;KqyHb#pCRp7wdCHQ@FtVGl6P89>I9 zP^4S`^wIN!_`94S93n(Y+W0GXs zL^-UT$XS5maRZjyW-iL1RM`}t4^lI;wfUrhh?+>Tu?0b7)GK6qq|9XAS+#x`cMX&y zV?b&*C0ETC+psq#m8+3wt5+jVxHqf=8FSFpfPl7Sg-oY_ zoO!ICb4kE&`p_;{xy8oqFG+9x94@XYHMl!@P+N&Mzt{8AS@Luhx92x(5^*LX!A*|U zk2jsr;ou?TEi(oDd|r=gTUrY?xn6}l^@37$X-mRFWLt?%wLJYn&n+PsC-jJ|r~&Oj z_55XC113D4hwpJ=;Szi)#fzvm*kip$1Aqfe2h!Gh+xm)n#Q<9sg2f+K7h`i<$zeps z==4YLiH|qgEO{RCUU9@`s{?RLY?tHW!|mBtB1gqF+le2vG48iSwtmSWhVSwrhP#9k zBG_eU2~=L(@#k70^=IwJv8ZEmlA;)U&ysGpA%&4q zSRt3P33eylMyVSJ^I0%_lgcPS#IH%l6r-!1(Cc-jD-~mI6F9bq)?UemU!Gz_(C-UGR@ z0%qKb6B~XXw)Ki>$wQ33s2ELGV9@TQc+E{TpbH_t^d${AI*sP-hx5A&=0a2cTzb(R zFJFa|!m?8k&_}jM$JhWo|S^9g3CW*U+MXAD_ zB(DvHAyf5HMq^1w9S=voJ~qw(12kS$<~VYjcbCT?+%K(99U2UYA@${Z>U7$ln03C1 zdu;sCW1L0NA;Uk%8uR6UKk(;jinp4<3b$mKggg8II-(hP}Mwb`9+_7UuADE z{a&M$1X?yB-Z5$QqY?>y_pPg16D}=H{@~O`CYygpijVR99G%KrTdV1_(S~>8s5)#@Pww)5NW@?369~% z8iI+Pu|q*v$avBF^qw7>;Q!&huUidZ>3<*NDd@*m8Y1q}-Y}9T^L!h@{B*3!dJNKf z*Ph$JpQ|4U>OcE>6T)({ET?l=ynfyTG-S@rkK{5^aKe=f1 zzdTvMT6Yg&fV4u{ltP%8=rigkZ^G<-MKpruW6sanYxak?M}*&SP_3W^yClZ$_$Z|& z22mA7Ubqo<{z#%+{?VEUmAyZA9a8ra<4UM(-T`!H8NDv>IXNJ zyFf=mu2@o-yc=)pD8KopUQVYv2Q_sp2cFPA{_2>b*s)3UCna0}OT0fEzu!(D`qFe3 z#^Z*55XWy{5kVFXfrD9r#Fb9WJi2KfNaI#9-{jV`%s+8R!e7!H_Prb#5}=uFXi??D)D6}vY8mpZ`VZ)3$& z2uj=!HH}H(HgA61AtC#MjU%Yt6y0`|4c$MO>Ul}5uAkmT@_r&xJh{hk+j*eEc2fH_ z>F3>?$Bj?l>1;{Sdi`?MIT#Ygx{o^+N{mHMZyYT1RfYm}!s_M8r8o~!gE;G}r^lBe z5&={W+03eK z=ap4wU#<8zTKVKi^Mvw7k-vil$iT}U&-0wQ=<^SOZ~8SZmezPCS{Q@o6-dR#;=#$cm4{7w z_u0fO?`Ck3=ofGPy7D6IT_Bu{-MPZlC}L-K#DKGm*FMZM;*;Z#i#GWa#dChqO?4ZM z34OV}tU4t6Gr`hIn&KW})6iQA~kNfpoK#-LuNwMn|UuI7?w@o!ukwa<4RW4W+#Dmnrt|ridmM_-{NZaO2EN{fyu+K+XWa21pQQUD_|H zjkhk#BCnd+%oVQ}%`Up*7)M{tIH)rF4lsR7`5fu*H%wL1)iznm+#e`?ys+WN^^)c2 zMxz*uCvn+(WblQUi_5P4(&!&M%jkYt&gk%4w4(s_*6)3%%5}>~U_N*N{wr|rmwTyw z!VQ(2!p}aAn15q}Y9edLpvU))3 zlOJ}q^?1kSswQ_${#zvWCRkjZ7t>_?{U6xZU3MIy8Jow-G&=rVYR@k5O};JD8<#?z z0W08&X2&K>aj3x@dQC-&i?VsTUb`2xiob2jhQ1lAsdSb{+JrvNRLUD6?1^SrJIwW2 z=uxD--eBgStuOq?&V4_etumLRD2oCQSzE58kiDzL_UHb~M_!4z+s;&(4%ZN&sfRH|Xn3Dy=6`iOzxsKYIpB2vI4a-w#4jyr0NdX16c|{u3_Xwy@=B-_?fCw zGbLU+^kWpGC{I#Bc9mD_m!)*mS z@{c$A8_@q7+5h{)93Ais*(^~5y86ay$jmP7{Lgu%ow0uw_41q1c?v-C-+obTeI*&t zjk%-dVDU{tpfJX)@$Y-Pc}3Ds;Q!~VIZw>(!T(4@0uKL4`#|MJUJ_4HA9VM+}2z5h3l1inR)J=usoY8fq9NcNv+@jZW* z^#Af%-d0Gsl`1pwEu8K9qyOx?+}XZ!{qsu(R_A)Y zGHmrUcI5wJElNxpT&FTJop)i+cQaHTjxr8_U2^`<`@Mhue!u>g?^l&QDvONL-{JUU zrMnW#0I&-7u79oK(z#VI{g;RN4NPK;<$Sj>rvDz})bppw{x6^AY_}sSlqzo(S)@{F zaB~~{b%bBf9bwmBNBB3|`;UG9y%(y_+)b@^s<76|5F{*@Mo&LW$u8ipdENuQ1cZkg z{m4A3i9g%;zi-u_{d=l=B_bY2-awLqqbMYVi#=-I(rods8Inex9iEK1|I&4-r3x3A zd>&-ag}m(;Uat7RGOF@r1)(vP=%_ofBfEFoSsbrKa{*a_iYNabY}}V;hVlK(A<`Gx zq`e4PD1x3ufYK9JA>CKb8(~ic=zm}v6M3$;-2Zd1?`Rlfa$u3Fbn?xz5!Xet^(#$KGET(wA$0qI~S z92Ikv(>`{21H>(t>*nh?p}iyt^0p(~XWz8S7W;EvF^<_aiY*VNy7*64KLshwE;p+XT3)Xwbpxen}GL8H0p*abrDDl%B-z!G+GmW%o znvkFeRBl=jvWFaJa080zFH!+4eRq^Ym_;Y>eecL?aKy~^@@bI zLsmzswz~qhxQRdYi*YS!diN~4SHAH%-D(5#x-qK`8sWt@(IyS9r!jT5&wRlxfGhW{ zcl(=oiz6v)7w{nH*-2sIH@Im2TK~JVpmxWf0~EU$rMu#Jc(7aupfw2tJYmz}d@U~f zxrS1}y5X|_p8R_tD-;ka8ZE}2271Am8MBh+#SiFuvlI;mY_XcDq6a3ai9oRsDf=U= zzueaA-Olr(Wq=g0{14;RAACihH!6NFhGjcwxI_$B{i>M#a@9$S;GA!w5|)N5MjHYc_L(GTXa(ZCogCMwx@a)_!&6A+CRL2#tu z{53b8Ez{OGavD5#5YZ`z`fQ$H9hOaFV>o9+o){unI^4HT*j*++T?)T&gXHVe)FpAh z&sm@^m`W9OXCD0BKh_g1EzcwTvi&R5H04AWS0VgPYcAa&&7- zL1;ii5fW%T z2OLE%oAL7U@81<*`31WD_kMYXp&AWhDHc~!P+XK%I*W4)ts#!k`gTHd>bO12OWqp+ zXjg;9l?0^n;!yfXV?(hF)8Lbol6_DFX9a4?oYgqA(8dN##j}GbewkCI6drUe%ShRC ztPm;eVtO#g+fm$q)b5$y*OQu7i*b`2+gz)qD{+pfKe=T)oDV>{Af3 zn@m&-mEZ9#wSlvv+Haj6gs$4;D}nm3WzkO=H}pbBj;pfEE&gvIx(*!=c@y}iTqUpF z{7uUvn`t0FIh)q%S;29ekx4kMdO!8K^enWSKmSQ4*-_DY>Ma#3KC@r0u zbn#CI_eQ*+9Ne8lVk4%!wpE=i9U+uU-frRa-GW>jLsyQb2#{NiokM)^w9Y)~A}ooT!4TWY3*GDTi5q@^rmWhZzM|31xhLp366W zN&i@Lv}cN%k81e7uvU3-1G}T{G-k4rvRpDUnTBr4sc$b?$9&+?*{-nYPxf-`!h}dL zMU{oLloVP4C`h_;+M0Ds(VmKs0@d9UV}IK6jzrbxhxu(rzQkvlm(VwY{yq2o3e)o1XLFKfOf)c&}Q z%8DSx)hH7H&LQaO({)B5j9VE)11PoZ#q3h^rP>5F15j)x~`!AOkA=RsszeCXnnJv{&FqW74ZZ+l+1KV~a7 z9@D>U6yGSj*AvkIrU_t@#w++@L6XO!N$K4Y@etfAiU}SL-rA8@)>6b*iWv}33Wx{^ z-cOK=3%EV+$YR%R_1?gLJe`H(mh6hO3w4=v(m0qty;YgD8SK6J6K4{h<5m4>15~U~ z0#`QLx8^q#^qLh0F&Ga8Qnda{;!(#iMZ~?FDlgHaP08inR6lF0R+`tlb#5<=DX!)7 z1Yrm9mHX*vH?W3HAGUZs_zc97Ki$CyBoU;2+k1ICE)7%Q+4g|U?48)b=2K@|y|i{! zOj4Pu=>E**I8iV6-%c9$Q&>hFLRtu27TR^>4W`NJ97gn9#!J_HmlU-P;Ex%k`sKXp z!g{j5K?#J1+TFfF40><+)kB`x_Sy`dghLYCkhrh1%DFBFQ#b6XWR~;-3R=?PTJ*A8 z_OTu*%#{GNK-NnS78BqwpObL^6t*Wl8*NBn`9Qs4jb9#f!D~XEs-j?`{;gPtyJ@YD z8pq^&jo#_L^@cObCSG#FRBxI2*(INuuX_-BlUi`lW9-Nqp@W%*R*0MenRb|CkBAP# zEyc6D;i=LkY33*pO=qB0QmM)(?}Yx1%zoTHOTaeqfZN>f;t6zGN^+4&64cSEYBf(D z(`%8o*&8(`sN-NK`8rkXfRx#$M+?*}XHve3<$xaHrtKU-Rz~am_M1NzoY(`Ma1WWi zb#v{jIehD4X6V^2zUip@lD14~kDPp7OS*Z2T}_~c@~CM2=&BM5Oo51~P#mmYVV@4s zP*E`&j;1kSXruqa-^4;{XLz)~#pPrf7&4#f@9$FQjHB&e$9I|O_#*+dMLP~vA(7!^ z`XwR@=FiU13TUcP!}{*W&2F@?SOd>+mDX~IPqjXJ(it@@|3w7DKaFZ>d9{%2u`ZpU z+VbG>;WL2Og{Av(x$XQ`Mvq$+W#~DgHXOv$0RV&o?=(my@~6d(uAiW+$f}`hU$ghN zdmd01#~Z_!Pq3gE9sJ$>BWO}(%83GNKrcIrZ(yx&RuCB;N`-m)O_uZ90rbD6yt^379xGt-AYe1~w7%#41nO9!zUXz08-g6}d7KN{scGy4zosnEM z*52)B$oBH*4UpPpv$Lz((^T~2x4n9(T;IY6Vui2)1(Z<{2ybKyp(nMf^%CVSncg2R z;o5ViU+F3)&a?>&L5NldJTlY+gABMH&RqVYoMub@XyEokcC_6<-NaG1Rn6!}H-!L0 zk{z0khmQ9T)kQaOVxyHbZV9bE;$~P*w3mAy%CPk_;foal=T2m`(@jA# zsd(TaVb96+OvD}?GzI&)V}uc1u=M~6cx`YwgnW*I^hFE^itXsE4ceEyB2zV|Unygy zNE8fFB#Uti7-HxiP%$`p(BQFGnP1LXGgA(gOsyZB;KQ!h6|MEyQUyoSc<-NfN)fx% zWWB;FyFRzci@Keh^ZWshT zKb;HW{Hz_3>;TJAR}R>nd3_MP32M|jc`~b#;=$5lS2Pj#PVsq1f6#CmluT%f`mj>k zl!p%%>Iw1O*yOyyCqKZ{ZU1P(ND|rDlh@x>OJ&Buq`J}HhAXMaeH*`+ zjaK**!goi0a_h}3q`I#kUy!Y|RLj%O(=MmJlpkMIyCPE;DrQ@we13hrx+-+|J1s+} zYT%U@&aUsJDnJPset(ge3LeWD3uyg_2Wyw*rfA%Mr>b9E8(DhPcQMac!<*^B;2i!i z21VJTsAqgtxyFH1ha+mI!96L>2vLwQg?t}Wbr=5K=A?p6LhJ*PMO;Z{^W8v7NPUU? z8U5?)ZfD!r@jajVW3pklunO2Uwcz~c%pW=HH|r068@*(KOH67U>?DATgZE?h)6tV~ zR)YoV1yT4en{UKzb>Zv#->${Xz4Rj>-Vq4g2G%L(6?Qw*#~rIdWMj!nv8DKrov8e= z6M7#_HKcoTHkCI5Jb|?HguRqjg=MrCZ!=LlB`}O@^L?+)J=|x0Sao{rtJN7~V=x$c zcIfTB_lwaMl)y+r5u!?SKUZ*RV}2geuBn;l392+`FV|h{X(puqm=y(6?stbf*VG); zE>%n!rVJR~x!NFA+M%1>7~O*v*D^(XoSn6)dc;Ky#_>1+5N=i!V_fS4A5hM;OdJ>e z@%2}Md00s`r4PVYwo0~PDxtJKo`(SrQ;lRMa_goGm|4RY%7d~VC@ckhnwMux`# zkz*ng;lC-ruMt_2;EsJMFS@Y<>F z>WAy&6?yjD^>I$VBCntNpgyb6U(uTHNn-MqokJDYsYmL#XoG$rd;yvx;QGNlJb)i-j$NZ;+zwwnYZW7m+CTyWzQO9>KMoQaltYLCMgI>orF) z<3CJ4l`9_x7$EK$;EQi?L(QcFZZXO%btl<4fBhhN`c=fEQsm@)h~UsL z5c#o=N@22&uznRSHf=MCr6Xr-C#+x#cPileIIQF(t(w-00i^h1 zdGo9er4aP%WBC@XEkVynEqeX0i2;gA5~Q~7*$K5?pn zvw}m_{u10m_idj)Mmws!{fGR9!?q9vkH@D;I4kXuL`}`18E+ikP}M!D#toeG4wCPi zcBs$w+tHw1EmROd6)c_1MVo@pN6Y-?hgW~iwnYxXgk7T-jWN+LjpwSBp+ba;lEBri zIo#tHJw4hsN!9u&DLGn_4{u*XaO`=e05j;T-M7(;L%a2S^qSu9NL@<9gfb;I4KsIg z-`I7+-uS}ZKs(8AYaroyWo=`$4gC_}^2%u5+XY`xya03!5_hM3L!~&YXD)4@=%~8) z9fdTpTIytcXfKX5X()Y6fE9-R{vMP8Ala3fn_QSq?mYIeq8hVrtCa{_W?X&9js0wg z(PGLqsRGB&0Egqk)!5H)>azoXUGkp2zr&UZbMADpYN~ZGWwz2S*2gU&f3*MxKFdk| z$xcvAXCtW@1K&3Co9buF!P_UHv^G+>cikkqxrX9EgwF&4PS_fA4d zWIw5%rjCK`hL!YcgA?aqv$U zdZA)`&>f6$07o=Z{OLaTMQHt{p7TJR?jv#MxxfsAeZ}}E(qPt|5evTa3=1*pxuh?? z)tub%6Lw#LcNr~l=E)X{Q0%(yJO>sRLV{vB$xi!Hx|AiKz;H(3(L)p}?Wr{$UwgkW zaE(JUJ)~dkX#CoN<#mS?Q;(RZ7QyCIwq{-vjGb+_r_32d2Y)`Z1!|0|0qpvCd&Snc z2l+P#GGUzmn`J~46ez#AEpWSs^T*|;(GnNU9-?XQI{w|pfqh#apM~&%kc8ttjLLlk z!XwmTOnKvK7vli0HR2v;mDeNZpHgPIa?Ws-3_nUn8EwcI2Opooo^byMF9j*X4-SsI z@?vp#V^z2ZY=KS91y+q*H8HN6w=QsAoOCK0^ADpD#|mLec#E)oOx^bry_^*VjyC&|))V~afs#tc(J6x( z=gWmQVc0emRF;EJR`tFxNc0!|h76r)eHaw#d%QJ+2x@oIwvt^X0EfAj=yFfJnDZH8^pYl>ACB?o!exd1lrULy(D%^C3*Klf!? zkBaKn-7SXm;~G95Dc^dJy-fKzNyk>Y>ZCNhGbMYs*Rvk+4OzFvCEs{&`d%cqP{&?_ zET8;Z74o_!`99EGDaZbecZel+Q7#!3mp<}1rHE==A7m|=?|MBt~-W%>2 zEN#vR8*}ytcB>$#aH)A+An3Ud1|ZYE_Q!{RVG`dUs8(!TjL-XDq`d`Hlw12gd{h(! z6%YiGR8&S%X{01X3F%I0Y3T+50VP#Rx{+>%1_i01l$ZgAP+&k9Lb~DGGb*0nIqzD3 zzxQ419M>!s@jQFq``&k4*L9;n5ZV4Vu|_X|(xGYv?tqE$7kP+oCv!igxMmf3_!Yt3 zt|sZA-M-(B5+E1)i7H*UboR zD;+$(@7jOi;?&I!q*1rcU!=51ZI+Uru=2OGSq1{E#FGu=Qqmp!h$1T@q*XGAlZU+4 zBW{tat$hEM9zL=WnVzu`y=Z5@=GaRg3RP+7os)62>oqof?oz#*mE6T>qqvM)8Md=v zI`tLKHQ}r}(QuH@LshQV=yl*Rfh4&(YM6|ERgLw?h!Pih|I$5$_`Lj=?9q-Cu6wuZ z^4?!0`*1|DQMrNh9US%{7X_md3i0hJ1bI_~P3g;v72e_~(kxlG@Icp_)dwG!55Bdo zY~CmyI6MTv_P61Wd!@^SRN>!ye7M|7@;^5D)5a6}_EyHEeGeK@WsINT&T$i=5uO== z>nG1{jq`u@N|+UjFQ!=oQ)rFvjDq+khtP7ldY0xEE9=HZr{?ow89+k!Nl?MHiuqq@(@aQqc#1m>*&=H^$v9=V@=2&@s#Uvgu;$#T4dAtv+8;8 zi|Q|^z$YK<1KcVLpwxSsQ>&_ryuTva{7Jt#LvrfoCN4cQ)4@sji;ugN+ixhy)UE() zZPHN%M2^mk{`H#0k&1Z7@Bl+d=$#IqFNg1w?pBDmhSS>gx*v%b1o8+AUijsD3D~Qb z8G}{MSYk3}irZhz-RHjs(njAglqwiK_P#iEJ2P6-!k`?v|Gk;8wPM3On3kz-ZMFv8 z{Q!qQ#!LK@Pynkf1m$wxt<0-%#pMe}GaBkSsUkcVvsAHe* zC$kpr7=-V@zD5zW;nKLICbHI4~nZ+g$;8I zWw7{xy$=PTOxz$aS~IiP(^uhkM|NqzY-4+nDZUo&x+l8$+Iet&^fL|;FivRynK_ThwmMO ztnoR|-SyX=o5KiQiywgjxwseU6^Yc4mvU9PqbBhHf3=jHDIIeK;Vt*J!M(`+F1le8 zX}M*Sb&gXfVM_(d9oBb70hC3cp?1l)ECe{d&KH4qfDbk%ZCMlK$jjC|s(0+1`i#jjdKNL0a(t-r8$0`{J z(Fw2l3|vm=xqS0c95a{s0FjE*eaYaHqw7oj{mTM<#h z{u(|IRj2WCbnIMlHyv|CjGeUT&=%NTpR;JazBk0YMiD_L0#Y|7CLyAafxb+kgPf#y z<YJTdXx4)((mEo8W*|$c8XVbH{FI4mA+Xc%~bhj4;L&AJ9w1=Lqb;B|Fcp z$-oBX=#&b1M$+@89fHO-W7oGrGsN3o(oe(Nq+81U*cY z&DAA(A6~r*8x%h9dQiLc*|C~NM^;qWL8;SbKWuKaI)cjKlSpe?UAYcGg^Ez{SZ|cx zyQMyg=_dLJ{7Bta9yyOls>XWDLl7Jm5aeG>SeyiY+}YnHk9;Jyp}T?U26)*&VoaFM zC*EA|m!n|nQ$&1L-y?=QZ+|GXUQ&k3XnB0~n9HnJiUAJM{7^mOENj_*6JQ~j7TmI> zw)iN^VbOAJ``|s4JW*IvcF2uaBXjW##=amCdtM}&BCu{At4M(pHXs{0*(p$EDs-@J zZ6+}0Cvpl`lAuhMMN}xFvU*pWXh*>W;N<(R0u5vhCvNy4P`E6M-pe$VKH4q#Fx&ds zbFnfOt~H1 zz9eLb7_m0WFT->zF|f5o)iq#w)Em0;8XQ*5(DSQyNYmC33OfK0Ghu8>iofd^_eJ+P zZWNfaD=vj*;m;P;z_>C8Qi)ewY7-88HI53d5pKdm0iE9&@Ch4hYFf7I%fK&Sx_|%v zDkzT*W$KJ_E*%ceqzg{_yy|_6v*H)lLQJj?@+#xJ0_eq}!E&h1+Y(Dw33(zBh38*9 zC0MkeU15mt`F%w9$-0|uC^OlfB<+Bz^P?oZgwYy#SIBD|(I)wWVP&>AWiGS5{YwH*FwN^{Xdt6$kMqY@Ml6_d5;wn^l65O??(aR+VF2ACFSuBX}g7c%UBaUk4JJ z(8=1tJ;R+Kl$~$M3!nuK++CDjvR{b82%Xf?i#;K+u>nE4&61G!^x*=`_FdN#CH!U>8o` z{@y2(<|b$Iw?*n@{s*XaWPlar^ei;ox#L8o0CVDBFsH*+g9o8{xYsJZWBgQ>9c8@;Z?lGc@g7NJ30 zn2F94EwVK%urBwBn;>020L7L6#I>wVr*ecm8`kY`%xydhd}azs3YgAY|1Hkj zdaT$R;Ifftt7IZ_SmQl*P5Z3o3k-$Yuz{bv*ATQFepI)Ce=U$FbYcZ`F-^w4HhV7S zYp`W4AydTy-#Vk$%sSGbTX9w7eK?y`&#fqprl5rC`sZbrhfc0&19C-78c1DqF3P7a zKvjf#=O7_;79hkceTtrhQ6j3Ckb5UeP4N|6wg(4U+T^mp(szZ}Z&fNBxGYpnh1oTq z=Na1QA-4tnp_lK7Uf~+)sTp!gR%i}5 zAAu3tYAHrSN;8ZjztTzR;jJ}v(233~0}qKOy94j2Z(DP{nc63^D~Y+IUngtU8cv+Y z^dYppb}l(32m{H6x&B#vcRu{0Y%3Hj#!MJwFl53r)>?aljjzU+ojD6Xtk#PKDiYXM z-D+#o)MZnw5!wLcHxuDa9h>?MMOwS7gl91M$O|bfYz3tdgMf=xCu#J|Pdr!t4+KB* zpFN0>mw7^J>m||cuhOerf*u!eKGzBD)XztqVaf%f07dr!i} z66-6G8A|V>H4W33ws})cd+m*aS)lJz&jY(P7!!n~6DN7BN>T{b4fu8^-S+l{YBb=Z zKKK#2azI(YMhr@A5c4%kM(BAUqA{+SSx9z5_va` zlUMVKL>61UE;w?{yDWae=1QX>g5Y%iOYV^;>Fg2EIBs)y`sAwR(@|W%%05pM=9<&V zOvWBT=)V-&@2sNWi!*>hOLMEB(o*d#8aAEu;7Vn|s_X9>kdAAFi}1ZonXB0Q90l%k zfHuEzu&ZO%rWZ`k7M)i_^Eig}X@AX9p{)?cY;h@q#ZvuHI^VVLy$>`4F1~bcmjQTC zJbLGZv|b4F?56@PwM$nkLa#|Pk|ZY1N4oO$DwNC<)gbr2OyWnFU%4Gy(#cvo)C|OC+6_5qBC1X5MIoS#4+X4L#UHd! zO2bgY^VOu%FL<7Odi-Jf_Q{(B(FLa+&20S%IPDtXyJqPGRww;O{bHm_1rD8+wqMDK39n9 zfX0!B75tN~IXwA(a=uzogG!y@K{=yJuKIOg)uJD61I{Toq0Ebh^*-jZ=tV_C6bDk) z^0ZZ%$0gXi1iReFEOs~pxNw2DPek^BM1}U|xG8O|1O=Rm@^(t&`wEX&U&d*x!td|_ zQXzloR2cu;4XQ1oDnapQrzeI@lZ_GDA4}p{!}ee{b~MJbHGq;W5_w2G>lsi}U0M&o zY$kn2#>k$~F3l=Xyp8}jEz^en!<+tgk%zHH@lB`EciJM|0-yN{3K8L7#M=LTvtaFm z-U2luzR~UBO*FiKsaR1JvGro_BMC>h_|l7zjXFCq5$0h9aqHqo=B`~rGkr5 zUS4#>Vj^msNggI(-I}`nj2K>Xd1|R{ttT#YY=+~e$jQbMUZHRKO7FrR4^vojJwE3{ z$h>kVo97%2m9-4b^Ur`ic1ztF2mQvPeO*6Emw+iaYYQ2$NT5H#<7M}4C;NaN|6Q@8 z-SSFG@AUzmhr%6~9_-bwHU~C=Rpq4ZYp@ZnvqUW28wMr5MPm;f;oEKoYgDr@%VhW<&DoMI(F^HOgQn&VW|I&+-KPZ6!uTIB+g|@1vc5Z=ss2#hN z_ZkS1yY{dKf(>o|s$SZo^MqLb@WUzU zRUi&4kXEE}KPB{B9lF3X?9kuc6?jg#9b7k?5_h6!zV4d7u?pIJfBp8!-4TFX($3QL zVgMF8%$u5DY(<=LRPEStBao5@Aq0o`Gn~Tl&_219wDdsHdKa=7>H*53+8XtH`p7do zRf`|L@Wfad5@|IP;#avVm~N1|>mV4QN~6eB<& z)nJIP0`sJzWIW+AdkVXvLtBq-@~vwR91=sj%lB_P;@gG0g9<&{4`bW|ib6O`H5=)M z1>x5E6~Mq2XADy{++fz}m>Q^=ugiru`D)xVA|oTqzz7B2sj=~`zY<%#>eXf_NxrN| z;yfWJgc6(wfXs?z-A6@8pxp47Z@F%5{gZl<90%FAJYh~boi7(KpgtEo(5D@Us9#R4 zsY^1i<7^U*Wi9elSULF%@%M}tYmopdoXoo-ls+`144}dW*G@zO74P+k$K4rwU7BTg zZ^e^+rg|TgW`QVFmBhXOlG2NP&Xf|}D`WAM#^KXZ*WJKb9P_}^Z9HM#~ ze?Lagi>ok6y0Ops63m*Skl#*?tnp=hRZew2Cq-i}b!{aY}Bj9vog zoR?wAr_LG~u{sY18+{!=#}=pYY7LlYMxhS1xK|{f=k6)htQbM-iP3dd@(dBdyAIzT zlk)9lz*<~!)VG8|hs#(f2vQ$+z_t|LlX#ahczP^TqC3v)wf>GzI7^Zz_kkFZIO9jp zD4S%lYGB%y=U(fI4IL712(3Z$VCl%#(D;XJ96JFo6`65UPDG@G5Q*!+$r}y(+^h2B z(_yS+SjLD$@yhj*;Faq>j)Jw$!ea83DOVRfUx!9SQ)jXGZVI!|zo5FpgV=m)7#7tp zCp;#x2lzoKUjnI#a3JOlt(+m>s!u@~jRcrcPERHB7Aatv7cz1 zrfv%wR{{{*sY;uwUZE|Iti6k7%>wV5*+pIPhIdU^W1BZwc=Tcva>O&e4_dEdlpge5 zNkwl~c`p9q68p2ZR>=opu#%vdY#@xox7zN2D2kn*Oj@H17W1idmoN z1c3$*+XBGzoY8+?r+*M`{DA2Dht{3hBGn7S5lO=OMk_|IS8o4kS3#cJvxE4g>6T?; zlR(6%*W^}yCveLA(O#}AE#%YF5pt4c?;kYkRedKhJntR9Xn0{}z?xK70m*pdxhX@3 zTXh$QpfkwtDuSMJ2|fKn=gw<$C{R5;k?FU77pi{cFI^X+eIaJ?+Oen2M0@Udv?`lu z1W)?A)A47IFi!cI7$&Tig=;vgF-0-}8ig33qxMbSKW+hpV9O1+G4ux`B+b)%lxRlE zXaaS$9e{q^sK{uKmdmo(zB-cDQpoKMG1c`xaQwg>Mr0~z*AeX4eEaJPsLkLp*HXYP z%EvfwXMX|VHY4TLFBIx?9~_B!+XiFm(%!>z0FoX`3($D%{Q5Jd{@)(OFJ5MqRY;DL z$T{Z^19Rvh@{n143xEN*A)Q)?J4b6fVfyxcbDZZBa)`Q~`(gz<8FlqMCDglcj+>gx zyj&$^>QpjE??O_ZCPmSMYBoDtMsY18(h+<17^*@(Y7jKC{m!}ww>i2_KU z-LFP;xv@?_R~Y?EaB!H5oLpNN$PU0kB ziek85SPqbJ+;fKG4x%r%$h~^w2Y=_I zT;}M3RD5G1dCkCh{lsSYDk4AP<|C*DykUN7rg&dcTj)m3A{4pUCJxX|l|imDg&Y|q z?HQ!9;a|N;!KmNDI?-R?VJv6s`VUgupU{dv-v5g%@u`w7MpDL(da2&D$3sAc3O+Bi z)Khl)Db z)|MugoOqc=8uo@;2cPDcV}Ln*f1S-gds4F7Pc&7#W1s2P9ZbEiQaUrWpwxT*UwH zP8Z+&MSu(r6|MFX(;AeD3JIzPs*ZVZ@fM9Uzi!L-BXSt#&Kv0;R7Q0YoG(BQ90^sd z-6Sjh96$+6_CB~Fd|36HmHFa5JM0cHM!Qj7QWheg-3@d+p{b^35rO>8UI5Jm;y=WY z#hNQQ+1W|u7Kk3zBVZJ-090N0b`Zqu6nWE&|FhlqPM)R*)W%;VuA0Z^VIe;k@Uadc zJ>HX`VE8kl+owT%lq9G!Tx5JmfU1g%J?6``U~@CGKjh0{eocpBk(ZzH#<$hG{=WRj zk6VqUSXBR_j{iT%nooAGz`)Eb%gFzUQkIL4GP|LaVXfeqE)A6}^2g8#|0C-PL#Y1M zMf>-MA2d|ZAL&rd$@o}RSBSW$8cUxYnIj*Tml+HASy;1HzK6j!kQ)CXO-+RWmD3WD znGK9fQ2mw?V9rVZX3jmsHdyj|MJp{*Nb&juqp3vq)iB(`#1zvFEYJ zd#)^lG2%#*KQ-bQM1P3CosK4Wn!4Xl!;N_wDXu?!nx8j8l97%sL4L%e8yM>Gf6b}J zTz!3DsUQ7b>PhTU8~x!@XV(VU36=$vp8wz2*esEY7_M(Fc>u+MWp5qUu|m_*fJqHX4}5MqenYKh(IGvw$?CDoPZx{Oz>6e=A%VV3QrrKQ$i4 zA7MXmJFLTZ>&gD7L&ZI2#-Nq?=Hk?9jqWK8F z3$pX%3%80yDI7EYrw6(O!<_X0`lLeO7^*`KaL&mg_Xtpm7xsTC4O}O}>Qr1}`9sGe zni?VxIwN0J-J*sA6=U&@<@JvPB0Owzs76b7RYO}U9MVy0dBz}GzA3% z_4;xLlQu^H6VwQ(SpralN2?5Mrvsq3r7Fw^IUZL3ANG9nMpI($Lji&Z{(Prze9G6b zp92&0EUUf-ume>=*O^#TOU2E+6dc5uiU{Fknu zWLEPqbX$~ERJME%PVnq;n$C{Bbo=sOt^%nrI(a%e0YEHb2c=C-k5(%*9QWb!c>Q9< zn>QC@Z|m2MZSg1HiLmop{Yk+0%-jck7cj>|I0_?6P2=q$A$z0FMnZ#C`FfH@Zin<8 zVnD<%0z`Zv?kzbX4G16}CXJak2Ay>|4TBejZ*SzRYHw61%&c}rl>Q_8e047Y2mVpu z$;}-MqtO;T_Q#;#kL`iYQfwz#8-bi1hSY3kiy^v8hSQj4g>fuy-=f^_F@>eqC3j}Z zJE1USN@DA$L_=PRdY3KhvXKK`ZHZzKmmS=Xh7wK~>Qs^GmPlIDfhndvA0t#cM&E0Qk<$ z^p99rE4D77fxV$p!83awo#-nymS*X(#=TG{q3gLZSZ=@MlU({?xh~$xYFN#G74S&u zr&`BeUvvkJ@Q8r(lrXp!A}Xh>2&UNu`}R2<1*Qg)2 zGRP)CA{gWtan8&TzqtoYD__+0V1ua>;00cnreWTteV#)D=Oor{?n4+A`{;TTR&Uy8 z;B(yhl`dmFBZ$_OpPsbs_1pdG=fBFhW@Fw#dMg+4zA!nYN?U9={BrNHDB@2|f|q6c zkGO}$Tf^$bKr@zp2S_0p^*`dNXzBSuX1seTwF@pc{KdIJ=8VOMvtXVGXiC}vCYmwwDo zm7?Qx&?o3VU61Q0%M3+))MSUEa-)8ZXsiXqRIJtFcyn|yv6ylgZ>R9eN0LmXcRkST zqrJwX2r$c42~2D@jOqj$i$Ov1Cg^vT-}#qK{vwz-W{i7O0>=4{R;BWlaudH_{g1^u`F!l@L1<4{bOc%)IiN=tFq;YlnS2trgYGVn1$&y?_oqCl-PIsx-z*>1%G8m+3ZnL8>LbEy>KVB4GWw&$Z z5t`q1+*^bXwbpf((f-rc#VeiNBpyJmmjfvr$7yy=%c>#@G=Tspdoa z8w7sn?fob&{`mJ*?7f7wlvrtI!MtOcw4Q(<#Iax9$2ut2NoMb%P#&o%YD%q^nbYJ6 zY(V|7oC@fkLciTHl;{LKvwVXLtAoh%Ub9?xNa16($z}|r8wu7&U>1rim;hqj{)$qO zN;6`Q3#$qcFtAaTwdUKkyt)IxXAOC?x4>S#RMJM{VO#v`xv z1c4#Ops|zDYeASHn=re`@1SKC$3s%#f;=`|#*y3S0$;WM9z<6Y4;1MTQNpGdn;ETr8o%NThL zH^z$k-Fb@)0J--yzVv-uOdAUjIt~-S2X(~Rk9>r2p)91ZsIEpJ=mAGn#7>u~0^V|B z=#`@5Tkt1u`J+lh-Z!6(X+X(-QXma9AT;wXC-QGm&jEp(px4k1z_;ZO|5yy+KiVhA zAG{eBQ>1R4Z{Jw41O+`mtIm%*K;`Da?xv2;(hu?Dc1=8|1($1S8BLN5iPr(R!F>KQ z+zSW@D$QT!cOJddBfD-GIu#*1|JI2GDI$b#Jk8;;{dCy6cCmmRh~M=`<;g!uUsCTR zIZ?{2v6`si?Mgpv*U4gBzX30s1)_cTtAS$0q7Z;44G^A4c~Li?%XAu!9DjPS!P5?y zQI>MG76yS)Ef_%mx70vQX*+f6v;rbbm}Ef_;;H^v7^qhaogX8#oTT!ubM!mS#{53d zQoaSU8Kjt?=knDx{XNB-Xsw~cIVdq{+hCqr46XORg4gy}T#LmbsfX&U>4_FV=)0)7 zML_*S5XA}FOF%S1{1Yx`l`FlRy4PegfjYElzNAOhF#{lAx$n;3HTd|QGqW^)T;*^l z@qvVHfXH4hEWykjxIvBJh1&<0b}pq^jqcX6pHYDLaV_aUyaD$3!}TJgOT8Q>T~Etk zRpH^nkGq4OaR+1ytXh0Z5t(;=hM_k{0{6=j6^N8jKnj_=#UwJtxYPK$?*Tagj1{@h zP(2o!{$@4oX3Q!+;fssIOnHLI$;CKZwIX-ro&wKCozEbDQor@~viA`aXszC#C#}q%cfvKJez3}a+ytpu`RS>*2LOI%l|GN}x9^#Y(rn%V zpu^XKuCPS3vk-Y~eu6n9(-{8HN~xECb&ON84XI(s_9 zY?pWtvH&3lz|&XMTK9%5fr^!YM%7dO+!tS)A6zzGb5f<)#$eN1CSD9wfG}ASpoSlf z@sveRo;tH$X&plRA>8x_jW)9o_Ije5=baW*R8r7<;7N`-Ddo6hVl(W`Mcz)?R~s_T zn|{nKS*!pl*q3iQ)=tx#bWr-}&@tbD z+&G0gg;UZ0TA`T!x#0Wtxvcq7iW0t^B%78hdbD=hlf$~!*bp^l^URsdatvItft@-_^Zpwboj>N zEx6o(&fDD?G*B;>YAId|;LgbCknmGAj{IXaM{O^GI*?9bgWI$E0AXv&ue?&o2alFZ z?NN5U=^?=XkjjcA@eLaRlMx;Jsxt+ct(QFYnnK;Smc|y>&d~Y*oud{rRoK&tu&o#` z8O#VN4Yt$m!N2syj&CQp@k!fmzZrx1!c^_v{8YxFoBHiVdgXYgEMtI5MA%bOb!J zy0PS^y*N|Qtf3{`orogQYA^~`LPQT{HQoN&>Cux&Kl`eHzl`a%J#wToRwd9fq}3 z0Ms^YeT>7Z+<77qXn>TA?8@~wjqNHtpf)D_#a)H z>gnaZJpnbUYw97eKS;8EVO^YDw1!nPr&XkUKOh?RTRcX?~m+Jt4Bp=-BGPH;n6 z)2?bE@FG+yicwWzEDyn#gSMu0MRHy0Simvc%bwG5D%4)ufnaQ+I*IQwiorg0mn^b< z`(8_J7+j6Il>|T$sOr|Q$GE0nwP!dN)*dFa$zV?B zQE9uad=xsmvj(l`{0fDo z-{3aBAuC`VJwdr%`Rh%-ggmoD5o7EJ|Q!>O58SYaM@zB$>7rB3qYla7YP%t zj^tO^6M;^0*;El8b3rfb6!?FQBeNi+e=>6Wpx=r<-|w8Xn2pP~)T1(5sXCC`W`PkG zF~%V~Rq5^dp&^7_rEU} zdB@(>eO0qeTqzIy04<(%n$One%T2)8VsVoI+gv$G*H=d0Bf` ztLVBke>)<#kY6yNRi=)P^F_grR7=IFw>ZJW9)xR1+uYX>)&Q>mVvT<{|ldRV)} zBeLvFWBm@OvRIBmo7~`R4vQn*>Q+&O!skwhX|Ct2k^+}`b`vC`l$q%2lg20E1&af7 z%2W6*k&buH-M=;}K`#@lXjyR0G4x5J9Ylpi1M+LiSy*h5sV=mD#f->u=x@%)z4a+Us1`^7B+!ID(kt9zd;FQL+PG zuL>-?DWxWrWcm2C2G|jtEX-qTi^iiar)wtDmW}St44sE~q;9fDd&Edb(p^5uT3&0u> zHh$6|t5nKZ(al2q`}1>TMB=Fnh(c?j>dkl{JXWB9j;nCA7#xw|9yU_K&^Z_4kPiva z8$j770oEENXb!wOZN~C9LDHE+X_b+M>CRgS4qVq-=CPV=%pMCHm!K2B{2-R9YK_-A z&ItW8HGlQq{G@G{Ut!Ofx15fy76Hobdyd!=CW<1u1;3|*h3fYPVw7|FxfBp^;Txz4yf#@1SjG~t@U^Q9liX2Vn z$p>f|LWokH2l{Fi=v6F|1Nv%K>3b^!br>>7p15A zvvbFM)OhFg7L5c|WoR1Ib70;2K&N_iZA4aoNqB&V`JHwz6pXdQY59_TLk`-kKH7|cX+fH8(TZ(nWxzrHt(a}tQxNsSK(WpcVPpkTKxRNg zgT~hunv!aicUdB}VbmME7!?9bUg02R@3=6$D(vdl%o;A6z6M|o^3_TRiF19%)jfk;PbX96Z;b&_i!dr(gDKI8-1OI}i^8v%LY9GBkiqES==L(7 zfYc`vT)DFEVt!Md_6k}yFK=pc(x6|pdBLq7B!+Q1(&|$Nl=sPaXd4f-VTq#ary5JS zmQhU6oo8FGaVDpjr9SVi^qw)NZ&$$cU;P=`cBvN}?avCEEY4^xa5+<(3J-(ZYfSh{ z4^VOVK(U7g-)26qX5Kxg%C3nl=iZvk%Lz5YAPL#pj$|V5e8KW zyi$MpTXrO%&X1^{bE=%J$3KfnZg$4&-L>xHuy;j21-(W$qRcq*B>Z`K_F<;y=WC28;pFND z#Hf9xeeWt&?*;{%bC2L`SC{iRhv|~Qn&8AT@2L@~ZH!i*`FP!I7mL$~_TIaAZhXcXtOQI~dcH_3@WN-dg1YM}L2X_mXBI>6 zoH)@t{obbof5+$4ncVa+p^;INa#7c=w-1zCf-b3Kl{l?V-!gIck-;}^v|8q=2P1ID zWUGa|y?Bi&?LQUI?bfo`U+xvW1e+`74DeDqUrJ@1zcWff;_f~k4JA55}EoXAbyG3dGxbUHK?Ro`S9Jo zx|d#2ioeGswgk!)l+N(d#?nzdl;GwY|GclD42pzg+Okl~Nd^w7mN)lZD1D!4ou`Tz zs*E)hF1>CXJ&Cg^0%R%jssZUmfXhI<%Usp^d>ZXT-JYQyO8mORgS{Kom&uu=GAg!W zp#76K{Iz#~ZeZ-JQ2Ll|xU7Twd7D#$?&AidO+{LjJyp&aCA+8YBZm>PGsSzjMx`vi znT>b#&VBH_xL^`~ zCWD|9W!Ye&2$?z~{IBhl-*Pw@i{=Xf+8?462rz^qz0z=7UGQLCi74t{St!))q)4IP z%t<9}Of#O`{CGnMNo0(oZ0_agN`@qtv}#W4 zQQm@tSpBemmQU~a!^NR_RuHNr&rOQOKDUx_t?D#rkD$n4p^lcm_ZtwlNiUy3YI$yd z#aD_xxC#%oTLOZt@*vU5@KBK_8p5B!6pxv-i^BAJQTIq;?S_Z@-O&xj;^RQZD3t%{ z$BV^;45Y7z$OkFToWGJECb0U@eiy)h<>h)kHS3GEYQ{i~KeP)F+m$XcD&Izw*l=!! zOSFINA59Skg;`q1qXWXrdG>rUQn5^kI@q;2j+P;`ThsHG5Eq=En*yJtJYxKE0mk}|EGF5`mlN4Fm;Cz2Q9t!3Y4J}4?uFVEU z#NT01@~$+#uv-n7eB(ecdjN7^_t1Zl>1_e!_tBs>95c4o<2>`{hhnaacy`pB8n~11;Ga{6HF;V?`2Q#I+CLI9H zueFBEtPg7&oKGt~wI+}Qhnlf(Sl);)jbn7E`g+E(XL$Clba8aRVEN*;E98$= z&fjMdt?|_8ZegZPlkc&MA1VGy3nm=&AUZvU&b-mUlq~Wj1@1_a1S$sTR z`z~CD5>MSBw6-6K=V#*GuQ+e7h!&i3xvpNjNmu~{6wu^sUWzQ5oZ)&E$aWj#-lJvJ z)P<}>MM2=9PpCuhw3(P8PMeLjFKl2oPzaqLkPGyXi9S5nC^N||F*Ibm*unQ7H_)7# zQ_aaBRiMnJCRe!{A5;|ZUu_*X4YTWp#fF`54?ywHA`iZ&&9%I}LeiDSPd2E(NN}2U z)In6iS6-QOtctMJwq^}e_E7<9HX-*{K^d8fKSwy#Xj@ZjTXgQpvM^Pne*Xz(eB5t> za>PQ~JE`-~j{4QC&YSc7v#N$Wfo$?rLZIKbX^dzCz;bv{(%74&z>^?n^}Z9tUnS{3 zm_ivdQfvvz0Tv;pm+-Ii=WCQnu=J_c$vU?VyGYR#D_Tu7`0e1g7|iy>U%F%$PVN4> zMK*cva$#Qy&m8fCfsoph&P#geN?IdET2~%K;aF3ym@w4zlW}rWbnu>iLUc4UiGD0r^+40u1E!8qUFEQnS`NeSZLO z)`=QtLHR=&j5H3o;MP`%j<^D+k;capyZc14+L(xT0DV_+k7h}zw~D_ zLpCe=*g-%!<+2*-S};AwhKKi5?ELZ>K#i>RavF)Zhl&oHM1n$V8Z)iS>)A60*JSkd zQ*GVZDw`Jt1%w82?Bj+B$LF%fG3H={m{_9U+)>u96Y|#O^DzY$5!zLK$U5vg;*sG= zYzl4yiduBx)m8&qHj?$Ze*R2n0)Andb9h@OyMp{$OUK1S>1t9YRieg)QjI zBLY-GDxxIp=dmXu^2xr*e$8tD6-*`4sxBi82Eq=~xGxl@sJnt*mkgB=g_fP}yJX$o z0c!ZiVlurN2eVPe>I~EcB{KCuQ6Jn+i`jsMz^BrCWG0UB%h?3R8GfP6uVZse8%B&k!FXUZqX9tV6 z>arcT@!smMT=1~tD^y6Ac)8W0Jv~+bPd6vuhm)p>dx-!=abGi4TYXTO(n3=i65~Ml z*!AbP$_Jel=XyBYRp)qR7+A!zlqTErQACDirME7@WWEk_ZlFlzqW3t2GXd4W@PXw?OLaT znhm(nJc#3ilBYhHob*DD+w69~`TpXUs`anpB}l=g!hZg>eq~e>;|e|i@lu^8JWkR} ziC>ssqqn=S)6o9mEs&r$Iy)V#__pZ$z+N1cZ44{XH*)6ZX?bhkjQ7Ra<+f+dG zgK9!8H9GK#D52WpaKv2*K0nO23vGD z8>HG~a%xfd_!X?fy!EQ(^5cE(=TJYN)Q9B-W@SZ)es1IMV*WpY^LW9SCF8mvJgS^i zrCwWCsD0mRU;>LC%m0n)eHDn47T1mk%kCuSyZp}+{i_FsIo6_$XLBDJ+}*5={SZWB`Hdn5$o2;^$WW%?AGQ zYnrb8Sgh(mJ9U<0knv+CI?T_1`oo`xY|4*kAHD3fSipkEF5`L~W96%`zeqf|#^bf$ zzmMAAmgf0=x?D$jNF;Gka28`#-FSBRKPTI2W6iVamwEob-l?iiwpgB3DF7c;eC7AN zB%zBK8)r^u)ti1S^Q#5;E0zAc-_Zwujd}p^HS%aNOZ$7=R~>d~AOGRfWLu@m#31x5 zSdXXU2>gi3{_y7kRGw$vn#!r6eoOws-=L<`S20(CFZ=xJ{R{t!F8=;r zL}WhMaFHo|RGL|CO0l_2YL{SS^WO#v?MTw)z6|*k@`oE`>nf zLFM-jNichD^rw40E>>MSE;fv_luD)gd+bxY9OgVeH~GW!7zEt7Sapj0UQHHwn31=? z5bpQJv4(f=42b88`c;1{mmCgUN{NlaurRJT%$(-&vOuyM~=Ip3;M3|W?l!u!kv>; z3{vMD>*(0S)4!YmF&Npyl=3izOqC^;VgmW=7l#Zm=31kXD)5LYGS7|>#gg?vp6KUQ z0lAO;dueZ28v$@87fcY%+KyrpRt8!HNqk_2hTk9n5HT3sXu;fUyWkFu=!uCYnVYAM z+}}VW)POK;(Jlxb20%3J3ya<{qI=cb)xUx8@RsG^bk3KMn6QMv(L>pvBtQMNp`XIfVKiG(oyUq%Ye7j1aw6gBQ>vS^fwgAyI{;Nr|E zXf(Y8+3lBd1gZ&S{y6}<8s=e4b^AmZ$%#{rugBo9eIRY2rjkpV3s6nc2VgeKJf)!Q zm;3L4Xn1u>tJXuhBfRH#wg`L`B|{YS2kNg+U+`sH1J2;7TuKH)mvf=t4$!@ z_~Fp$Oflz8{L>rOBhV661Opy8T6$wSv_dI3TB-EFTh99uu#%R%nFP|C_XIZvA|z*} zJ6}3%T#z~pq@_v!zR5|}S6H_ilu~LeM1eQWvF32VHIdwZu3N{P&Hu9rq2PKkBLwn- zqZ(bvKM3%37msLWK7d&`8ErKuEA*SsICioKHZ$iA%zA<40SE}O4 zXGMMeA&SGpJsU2d-XQ4hqF$iaIPR)3OwcGvUO)l>Ch6wGrT&fqfg%@Q*d^eV(q!H$ zDhS;%dzY9M$8DC2&!{GAezWfODhMvKff$0fB*Mi2eY2RWi@xdY-suko*ITo1&+A^a z3tUk?^Vvkdy+uIsu{520A38O{8ph`qy z)SmUDzVRuwIYip=ItVG#eM7$4fP&DA*^NGFf^|=^sR`6GeB-OcR#YfnVyo_SCQl0k zFEF<#8)@CBqcY^R_O{si;BJM^&Z07?u}p;m#HI|F)56fUGY!a~ZinL;E|KF@zPX&< zlIklNAS*9J@<3b!4}Hugxg-(zqDyuro)h z0&MKDZwuu#|6+L!K0zN|rj9~X;dqwa36JSAJC45uQjK2!I;>)I5Mt9Ss_`FI9e@hE zG6v)I68?x)c==6W4$OznLUz0Uic z^QxAaM>na(-opkRGml-HD0ZkH38rH)qAe)~Qx2zv>;pxt>>E zIT$Tp&t=dwG-~x704FDzt^i;&Oh}Fh`T(9N8wM;c`rx+oy8xL%dzlN!Hee4NT()Y& zFF(FYdjUgzS)g`(G@sLUTYazla5i+Fn<=-A!C~<(`c#UDGlv=x8hhF3D%p~=eU(pQ z_WY-4FrY(c-dK3q$C9jY#kibY-@X2Dj7aK}{hq+31E=j?fH6$pldBmfv|LYO-Ws%K zbw38})K=9yCskA0XwRa^YR^@~?EbVQt30{^d~n#(nvb<6K4Mv|`^s)9Gb78S52ZrH zq}=N}w%iLqbH<}B9Z?+gtJCEW9=V+R2XQ=?gBHH?BwJ{ z3B2tKUBwG5CIe&kO2Q`_DdhGJTQyNZ3&(hRN18RjAld|Y40>?ft$93QyOdel2LLR0 zv}fytA^;4eif=ooxUHHExf2}C?_eQP*?lM$sXwtqVYyxrbNhnI+lWHiX4383DK*$tyncNCgELi zA-kpCuA{nmW9FLTqvpU(_0?c+kHUZREH$OYK7ihL_BRrGSA!|3>!0N0)&O2 z=E##n3NF3bkD&vx^wn04r{*OSsU4*h6vzo~e0@LP8(i&nU^;Yfe>MTZ*ltPPd`if6UaIuX;t@k87MDzF zn?PN2;=H?7{>v9qP()R<)az`Bcd|L}vhv{iS>yCP_p>1pVSw zK2eewnc~k@y~ED2{+(mLd_3bAAOIDZl$ljtrb|gMIE3o!gUWtK8Bfzs1COL8{SrQ9 zEbUBMgjSYXX=Q(``;^zh?!K*Tw_w_V=fHx-k{`F_XhosL_6tKw>_B`{0-#p*lFMm} zb{Ea($dxEeC~0bIEuJ@W#WkV)j8$9z36NB>F?TdhGN{}YK#~G4i_K2~G7!&74Vv|~ z*%f=z+uJ5u`4^qq0dg*Nfh{Fu5NFpxEzcH7U4i{j{9x7cb-KnfrROMQKvMe|U;d2g z4Rh};vgbOc)HnM1UUS=9<3Us8Kss-RaE$w%reL49;9iirJPH)Q!x zHpvQe8;8nOu07#QuZ8i**cP%8qtQpZR@3+DYcv<~3z*Lg2-tR*?yr?2U&O;%yQ$+6 zoN3%LWa4^(i3O3vO)uMy4Un0UI#hIQ!@Bvl8FMFW&5JvnHG(5VV(q+x7b}_h!_bJa9M zP;@k-mwj~*H$1Jf%h%DZg(j^wtTMM zK^TcA*PYUt%qFra4=|Fn_ba$9Mk_+uX0RX1&=UQeetKhDSXlq*_B@N9-u2{ZI=%|E z2E3acZx7bNMKLd6UgL6y>b(xg#r+k5$88(&rA$wCAfZS8a9S(nbxHma8O7(ogw4&j znAacJ%FMn$7yxC5cb%t>iyB%NsCQ$kjvy~$o(&dn+e@+PZ{Ju(l!7q85SWm$_L?Dr4& zug%TzfmAzY;$e%WyJ+=Io7^gGxP1CRO+blO;{f&W)j5vy{<5E)9M32>Q)mV`9<*35 zYe3pKX~mmz{kI$MgY$~!G_mzV+NGQ?PovQ2XA``U{N4cPsXd+Q0kY8^iOUK}SDD(u zksLR;wj8By0T=W6)ToLe=Q4RS>dYOs#R;x6r;5#CE!i zUKi$=Q69FJ4(bT-cIBpPJvt zigUg^v+_3)wRj|YysQ$`5pm-frP3=YlIP0_Tk>cBeA=&m)Nn*Wc<89iy;OrtDC;fT zlR?W3mQ2qW-|SNvcD(Oo6=WI%a42?$vMyCi8{F@Vg!&@&CO+s3n|s5w{_ zxO%}3zQ7qS<)ygn{A3j~^s`lhh)RH@vpM_&#Ncq}-nL8B5;lhVM}QK~-0t9?h^>7z z2vQkb_67Zoqbh1#3SCU>CL^^dRb{4U_E}^8|~>F{CJ4ND>N)HSD}qOT>|hmF6|HaNcHM{y(N;P+0*V@M{XTcmk_cE z>NDmwhVA6LrSVK_>Dsg&Mzm4F$yAfjyCWg*6G|qR7hY|12m#u`{vt)PoH*rvb!{u3 z9H$RE6`R>t#$(#mKD=!TzqM+ID4yCsx}W=hM@h9Ziu(DNxw{538!BF-Om1zhwaWmXg{9%fZ3S#NrbT3;Mfun z-R9`~8nX&u_kk*z7GpiT)8FU47O06@RIdX3C*nZ=wr@kOx^_gtWsJLd@boYbJSNXK z{l4?b;LGoNGx1bxh`z<%tlqP*Z^sdPM0||uv(Qd@`c=zX^=-lXlMnR7Z*hK}u!Azv z#a7avoXanbobd7GKmqoKio0CeJ0B*zd@c^(lGgYHF!fap$x?)oK$lLlsv*q%AWIII z*aX^9j1fD${NToCiCjfh>~4Uw8)uNVlF>eeySn4ND@9PthvN&o^<%tzu}HW2!vnLy z2QwIId5s-n+p)=JAcs0ct@8godD&T?WL>@F>V$=trWz?4xi@NiWi9d~m5Xe?`B@&G zX=aw7U5jE5atspsel~s?W(7Nn5iFbb`g{@d(svT)&735p?oHBf2eCMr58mBM0tk0& zy02T%R>i;=msFGJecq#2Uwwu4uUTJ$T%&^R-`x!!5BO?cu{VBG{M*MP@GrW%`!lv0 zbh}w{c>rL7dTy02awpz#`pV02b+4jO28>hS4?4eRyE1r|360hj!bT$T%4*SOuV-zP zLwe2r6D3;J&eYlJkVb?qDgK zO=+aeoFI#6cK@TFt*!-=W)f$Ox~0p#_*=34b^y%NH}l=2Vg=S9Zg6XMpOnO;=OW>p z+tIk;{F4nr+j=7Zxbo29by&jocW!s>Yh>)Sr+W&yYR{rcJVDTNsKZgukc#2v>S&Qw zGnig@g=gd1Vn=xsXL1UFC>*;|O$S&TVsNx-f&AmKv_tXfokmF+K(T$OZjyM}Y-|Tu zm^MgmA2~!D%sQ-*5b~7khfbW{-xXgeUu&w%9jzEZZ*1fY)7In5S?zl8%@C|D-^V|e z6D<~L*OIPA3=E3{$#09zO`%^k*hMhnx<|9~o|Wo_=1LNtm!3;?L_UNoO@MjBb83tH zV8luPEI;!l51YqiW%cC%Y~hNYtBm`(dmnGo?7%8;$g&?o>U8alaYpPWQY8YHu;YzU zbDqKiFZ))(j8$onjYKzZypA+)g?3-_%Z)uX$Lty)cq-9vVP7?yEked7Gl!Cw(1E17hT0 zhr&^MCZESiZu?y0*Abp`<6for7o=WwyKs_P+6q~1gqOX_I-D;mAg0~Z06y<19v6Ab zM3{Wz;^~kwF>iwHivMLc0t*Z+pb|R~g~9B*yqJq!GvK4dgRA4RB3471GF5s3Z-i8M zQu^ZEu;5mW=bP^$J`^qHEC%1(_>JDx%rmiG{cYWmyhkuVxHQ zlXJ9tOEICCXEPVyO?-5sSwO_y5kd2{Ryh_pq6ieHiExX<{RoD(THcJUEyK_EB6oyh z{H4SV*zD&s21M@%*Z^pVcxGYo3f-I0h-}^W77W=ex`%KZycqAUb1~rU$&XEuWGo5a zb$EdPbAp}yj{-Lz;E=K#ymrmTf_zK5+8Hsq$NNls6b&H(4KrvN{^tmBPke+FmziVP z0i%9_#&!s?)4o%`$L$20xM$B#s=p`8HB5}CaKT#)tN}na>eLdsqT_N(%4?JA3~+ce z^#>>X((GIOdw4!EBk0^B#F+-A?l3#0Y%#i=kxx@Su}S1ajn!vZIJz%^aUe$h(@w7Z z&C|aj4RWM=S4HrkqQsRVaiD0fr+{!F!E zgUcK{_U9$V(~a-Rlc2tsmdcY6u8y}4B%hfoxxH5<_t3c8pja+i2Ch@?1YFGl8uDiZ zp^Q{ku^Yw{Qx(lTFGl;AF0y4k_m2EB@*5b5jY#SE{bFoouE`0aIDdp z!}2wiDpg0(w=ueq-i3CT4%bf96uo&FVoYmqcp?ayP*Ua!FN=y(4zPWtiWlsX=c^CG z25O#)T(2Xwa$KnD=eklzsI%8_t_G;#Kyn@Cr{j1tL-YgclgOow_I2AO z9=A$HgCorwUe{3dHGo$VTxR@eF7%~e82gqxXb+Uo`_(M^_#|{fV>ez}3U3P|^*wXt zU;q`-3-JG>`N-SPCmJ1A+$@l0WFQtE+v;iw=z9;{!bYY!Ms<+^+f++L+a$VwRnm7j zzlv4XTi7+uPZi5JU0XQ5;55ByruPyoh^o?l7~M3#0Ez zuF&pF_zD~gm_7-Rg?G@To@x!Z=Ze7PXBx7+#slxX!<{3wMxL;QORf~BE>yz~`Dm}3 zxb6-QnA;27f9FbfBTNMDjpFl?)5y`(Qpro^UeY&D0n@CDUcaGpU+cvy2C^HO=ZD#TllA_?@W)w;-S9ZqWTI+w*Z+F8@u zuL%hQpR8_uZOP9=#8>)tK*?0V8`gp$e!AfaxwN3STgewzq@*WRy1y0s7SF`jRWvqENM=&Olk_ZGVLMu<{a4Pf z(YsQJ5(=Ug5lh<@d%xh*U<=pbSbbDVaQvRniq;{Y2|@4vQfa;seGC8d#2tdm&UboQ zZWhYL%X3N-5h`;vxBQqZRd+@FwgJCzUj3XTwnhjicAsn-F_F~CLH1Uhe6uvG$};1t z3+P!n3bmCcYRaSQ<#ca6T`3agwL26`Feda_msfzK=k3Wm=%V-HuCzp$a?EV@%amHEkPx>u~a zf}Z^JQSPwcacb%Irt?ZEGD$$#*xX6dS@#+gr(STN{vq-NoOcV`iSB@9Xn~LvU3SId z_fjzWi9VrzITo=NtK!AJRi}!>WO_x5s0Hn?>@r5x$?;0p^lHWP>+Jh(GS%sOM^!gc zYsDQam2OYM@^{0F5a$bKLD+Inzw*(S&6@`cwHizD7OX+WYZYn!{#Mv-b73mc5zE|W z`_DRksbr39URByR%^?y_m*{gR&euopul0#)2{P?)vJ9GenYVrUbF*X>XmsvyH(E48 z7TFdXGTM0!g&7x}@|)r{i)KlxKi~hd*=MTlK*O_s_g%Nl`4u8y21b|CxX{$JR?~l9 z9~X#P^tsm?=U1+4o$hCY%)&!b#uGGCo>tAQnlW=F$&G`Yt8Xd4Mq!}5di+)B`uf%f z{YqiyVuo%yL1vZ-XQooR+{>m>oQ>h4i?-)C5UXiK)tFYU~mU!L0coM zxYZwx#Oad)kn<}#r&xcux|dC!c|i5L_qD2#3bJQz139l!fX3zLf^`&tUnNc6zoRRu z1X)nCd`Y&9N$hPkcRd>p1TR!p;R{+>=(3%EGHo(||57#(F5!U5Tt7|?6L?{}0yVSi zA6WHBjAOmL24@ZM5-c-x?szC3%0x1fF*qNzv=2sjSZlmAO1vnz6cP{RX2ZO)=?3N| zCi87%HqA;a&yrS{zXpmN07DoKwpr><&{zbsNUoMBx6C8T@9QE#xD*$ELSutU;0;;} z?y$y>)BrMKdSixWtJw?QD>ydF)k8YvaGemuduvj*A>DX<{L79KpqO0z`dQ`f$MaRi znE&h4&AWrJy`}E$G!14wv6(G3`SMAzem_=8=}zdz_CsTB4>{-r*NKLzckFs=*Y_D| zUlip_M)^r3mfZNLhDIGoO3Eh1{tdM#!2WCG>%pph`t}fcb|h?$-75n+31IHmLyV;o zwXUlQp_wVvZ;bNdUBMhoYn9FdX}$9|>N3miQMhfN+n#?wD?#tO31>;?70XX2<2Ki} zKG16%b6Jc+7!Iz`$0o8ATXHPKS)TZckohzNQ0V=%`uKrC9J0G%HVQ2br|s=A+Hr}4 zPoqJ|UUp-WZA?;r+}7*!v2ebk#Qk}751gzs^|i=Ybs3ns@^t$ggnMT7bNVAGu)V z4pZp+eUJ^bgIq9;wThYB$VapX2LSssK_k{o#%pS8n6-7eFybIVAVX_G`w2s6oE?f? z=pKG~3;8IMoh%Q@BY+AmHQgT68tQo1(mD7#!hgo>+p99SGvJJpbT}CMCcSF}L*NjRy!Cp9m}r4UfJ`KN*u%o26N-{&m}%U4m2MWXhoq9ip37eibu25pQNf zdRwJIJp)14Gb#pq-2zB|5m16{524T?IYoYDhuggZM1OQ`;B zka7OKnI=8X;qWX!x1hpfZ`^mr9cTQP{5U!|>lc#cC^_bJxqw#DO@94Rz+1 zOS(asjV)jlz#L4DR?Et>qfw4gD1nF2me7)cYK_+edDWCI4!!z^YSqG9ClaqF#h8Zn zD18P%{}J|sal5mPFgko zcP&D+Z%VsRrVW9XR;{Ge!iGWTt)c+R%@#XZyH!n5YUj+AC? zqnC>OQth&miJr(;`#)WQ$}*5_LL)TuSlsn(yPbwPIzHYkj1aVH2i>QgCw_r|C0(?Z zt%(K*zh&NTn0cEiBXHtz_DR#p8o9GBO~c)nt;pUrQOS02M?3J4_LQA+a(ii{xn+kx=V!X^$%*> z*j3DM#goJOoalm1eK5l51@~KqhgDQqo*C#V?LNq<*U@~3&7Yy9RGv513+xQGlc<4k z2oAy1&%y%M-SD3uY(+m@d)bGd9UwY$X`|~IeYC#o^Pxwu=}(PzlQuvD88E#&NJ zzN%eS*0-n;iy=;!G_l&8u3z$H6H*y5-K(Qdcw;ll#nCO7goui@>MU&^DS>Ng zI!<}rPkFPZ2JN&O4SkWcQjWC9^Xl$jh6{pS%K{AmIukq3cDN9T3-#W2RwC#DCI+*w zc%gl>71rIr(ft0s#t5@g*mUbSAg4sC44DSNlee>ZGZZ?}awFs8gQ)(EAnV0`|JxA{zFalTPGVSM7O5kEDWp8b! zi?FVZ>Th*mJ1?xXy=;PJXd>rokJqX`WQ*=bdOR@hrakGNRJ3KLLTTuM?p0I-=bT!v zJ`M9c2;YXqbGQaJN5Su#w8>|v<87NWY!Ox5L2v>w9N0@$7!+ zvcSFTU+bRSz=ckEPgftu-Pb#cJHoDSUnQL@M@m%RJj&(YvSQ*{3*&CxwG>DdyKLfm z4fKZ;{?#8E1Q7GrUhJXG!`Ottk>cXkKP{p#2N#G##S`_@*gM6?ugYO@&YNB&C1M*d zNIZ(V1rE#_%6yo_NIYEJTQYUHSA08l zv5>oExsSmp+2LhIn&bqJ4+liHKn1O-UxwCTenv9y?}Jg4u-V0CD`4a} ze&f8Bpc|J1!`mpz_0~*+UCDqWAnpc7fgW!*V9(x1xZd0ygoHcXxG_>aS>N;K;>=v+ z!>P72V42czKpnr`;Gh3vq=%DdI;ow6#aWYOfRde2IVaVG(%LgCU65GU6jNh)0*Q16 zW270S%@E=!(Ed6OkllRo^S#ExO~C66d@l#V*>oVE?XX*0$jK(LfHgosc@-`^PvSyx**r*IDl&8sbID5^C=>;c-Wm~@)WuLv z8;p3Q`B(_ZOh^_8ycy?LJ4+XBejC){)8!;w6G$a|cg>%+&u#(!ndVs*a4h784VOvz zB$Qn5H->J3lqo-~o=we2{{xyO07TAiY3bOGW6klRR6Z#1YI{sfV9O6a=Ka9i!&My5kzc*quxiXx!nf@ zEv6S%FpuzMRdvzb48w=jt_NH5+>mJ9=D21N3g6^Gm0RJ>w-U|1dK`WKL~tvIaMn4i zLLu!1?i@fzEzAR@QJw+3`znz$xf17cCYbi|05 zG;ghqS#vO*$u|#dwZ&l;{h=p2Dhz|Iwo7T_3gf`eJ(;y;KiKo3c-|AI3#JV~*ew%G zhMN~10is7BMBq_VT05}m%Ctg`T*z)1u~?3=atRupTC0!P3cL6T#`yF$I93xTr7-w= zUZd}U4IhJ$#`?Bh1nTj-2&IAoCqVp-ezYjwcm;_I-Qigo!(G3PYNe5*6(#dKz(m=| zkjPo8zSfT&0hr^N^4wS3zNhAgwH4NO&H|q%6kp&UpR#_ez4RiWE9F_#L?qx}H5gCU z7dZ_F3-rN8D;Pdn-_wc=#LV9o&ez9kNCwv4q@Sj^VF-Jw1k(*Zp-c4$@B+^3n;Bn3 zr1yjZ!t+W*Q%A0h9P&$}IK#xXWmg3Vn6Y}1AhcpL1qoMI9Ia=;>b{f}IPi=<8PvBi zRal{CVc*`$Ik=M$8@9n7Xf;1I?{eRZy$l*u-CE2LDz6MS?;QJ{q!LmC{ufq8Ay8xK zH&%vhqMISqHp*pw*btKN4y)`EhHlRL%Bf3ubN+`De$$Iti8f)8t)_87E|99EMwj2* zldI>X1>v@>B-QV=lsTI0ugZLw4{qVeTQYl7+4Xi^x-yC{ayQ=etJY_^@1jxolDg#= zaXn4?vNG+K`za#A3wCx0`0SQa(dBk??Xq5W!j`0@8k_m`xm&|{<|mC*rqaUAN)or8 zy6@HvN>--{^imxOC!abVTH8V3b$MvP` zD=9keUnEv|sQfjT0TvR$azy>j&Aex1Y@#B}qMhx>YcOaMZ(;VxRoh`%s z+N!47QTD*X=qqi<;vx65NYiZq9QQ+BT|%(+Ie=P3o3)d?F{7R3#?FLsjO}<);4!Kk zVj3Z-9jG7^E{&m1@b1CD6Ao)XrcmE>hP9;FPlW#xM*Is$=!52SSi^386@dj(3ig7b zu@R#qz##SEIcuB$R$Y9@^5HR~S9>_k9XbF48H~PS?`h;5Yaao_pb__zvdYAb7#oyS9}TEes03q)hL)V2fpD&0 z;Lqc`kG-T%OXy5RFb>4u&b+KCg)E8UvNIR~g>hai$;VbjwsVU=80wgCX~GU2uh!x>J$c|8T#Hxg?N@m^#3 z047XO@P)>VP*um^a|qX08Z;dSfPgP)YPp#4-v2%GmqV*0xSg{-B!%Bi)vb5o&J|rD z`c_jj;l39ay}chBi-Jlvd20XO%p!C@vQ^ls1?y|hA@r0ydzVX@4bSxj;WsAtL-AO~ z|I*S9@<(&YP?RlUc-al#J;Tn)9c}kH^Z&&dJ12J>{wcYGxWy2E&O<~DO`Lh~55wp_ z`XvSZA;SnT8)W^2pGmFH5WbxoFJC=U)CVh z_~)FU&_Dc2xOh{ z#`C`<&7Gd3xlW1y8(gQ9*Oi562w;KQKa3vAbENq5KV+-CDHd^xR)(m|QMTxE{j*lC z=W7-Dr)yP#0FwIubE4jtp1=GU&=jZtG3C(5YpV@}c7-{{H%@nyF@KxLG@UayJdOX5 zDFu8|#Lt-i;y7oqLv<3Q02yfbAEzd*^Um;tKYYE4zaiBx1tDQ*M$rG5o$0R*p+MU) zeE63g!&Wr~k`ws(PlAJh%H98BJF{B82{}(d`E5Nw@ zpU$c5|J|OR-s1Zv0+%9V1e@sf?@)Sh9!d-TG?W5mu^brs)&AqVvK4%OwEpy> zDf{baR{nEQ#iBp|?N5(p0h+4Z4vEhLw5o?k^eF+OqP+h>tU#w;nI5%S553s`!<%YX z$~;Nq6EV0Q*nV%D&l_KywG|0dxRD3ZKq&95_2 z`)93X(Hkbn{|_m`F8FgT&iGJ*3P3IY#{`C2_>o{=R9+Ah?Nvz~*Zu8)muxBm|xt zPx=0TEYI;53AD= z$psA2gXCXz^|yTxHQV{liTuNzW1liflFe$qY_FJyZd>dnEH}!M8+r!NjZ z0iJHd5^N2KKYIjcnX9g%s_JXlvn-_%?UR!|?Ipk&RRp3oD%r}pjK--9ts{Wytr*8= zw_~aC3N0*`siNgXH|J&{1@OM(gTe@XZfyp5%5bS^ z_I$fK1R>zHfu@ymo2$9p`YNfV)$MpI;M4EE%HKaEh7w%1y~9aB4syp8EyhrehcjHi zUkA=P&Qn}<&H*h_H&14i1q>FHeO{1>7793R87L`o3eMTZUk!iU8b0s^y!KIpO24{EJ`NB-4Ki~9^|*yJIbqDmWs7 zGYLa?{`ac<0zG*VTsFPKsa|T1?(%ntpYx0V`nC$^1!AqIyin+cYvi$a#YhMG*OADl zjjg?4(42^tAK(Kd4<#UH(I!a2Z6*hl+7vhp2^)JhsBdEc*M(|%h-Gnm8CtK@kM7Qk z7a0aupZT=Ic^+eFz? zbK%P3g3dc~8F9)yTBSf9Kzr(}J8eCCYpyjL2rNo5#Vlun?xt;LgFi(dX#5ijFo!;U z>td=(2N;H3gnQr<6!koWt#HQB>e)FuX$dP`vj5vFpd+}ff2UX4O*aW4e-jGRU8!q$s-B%cMQGnW8$$6^1o%z1KHXQlDLNw$i6*w#3;ENWf&>&l{^z}foQ zsVwjrQa($!QwGg+mkwMgo0F3Sfx$@>$uD^OuPQuL9OFs;`%35y6$r_Bd8&^KT}xUa zruv6sbm6?8CH!+MNlFN)xJjV^jM38>D9)yR3EiZ2JNq27<_zQD<%deHUePL1Oic0SA>HRTpcb+d)HD^x*fw2=%pn!Iav^!+1$b}|2o0!w^=PUzG zaT?HWO$rcZ-ya-Qk99z@wP=U~IQMKY50X7e4-02ffql_r z7EbR6bJ&??XR`%!VRw5Gzl3WP@#Zq$e7}NyV5-gC2nLt&eA6GvO#%f`oXUkj88kWJ zh;E+DYCJYi>IjkGOzAlJuF_n#YeruwS87c31XyTQ%ChmSEmLs5P6X%Mk)|8a3>OJm zR`-rlxx0}1qNmGiB#qYT7bS>o+lSeNh0ajZASzhr2 zfPw*@qv{J_JgQu~!`C}%>aL?fAbAMHB1BnKA57H5h6p_WX)xtw<#Btp}^kd3Lr$_?;#dchS%Ae<1nZcrSg3C556cD!#Dw%_5bsQ`J&tXTHK zILbU-v8c#3MBF}b1>rcllcBc>L^c+^cCbzMH>y@?jROJOH;uJ=r>JD0FarewVY{6= zw<@E^b?XQVqYKb2fJsUmciomgD&f7ZVBdWEq+0ao`XN&u@6C)HMG`UOG5*9L0qdOq>*2M|7ih8HSJi6zruHQ`Zkg%Obd^8)FM(H2D zY0&3iSKPX{2|%Yh4UD(-Wp!Mb0Mq!<x!&x=6EC9N{_TUY4c%izV zz-JZcl=JCogx9LLR*1M|vN(w8I)G7abDEzu5VlnQA*3UqGAR~IVevC)YmSsZ1jye2 z{CEV5x^k{+jfUNN*H}#sV&}c*RRve$RPEUVv%W0Ph|h?>1HF$4ZR}QU^V%~l_l#8m z1WHVicEFl)#PYF(M!FPP=?><}%8rz){ST67fi<$`z_HQ02b}fX`A+wT?}mU#LT|kC zQlu>@{)SDMr^eh9z8Ep?c)*8O0f0A!3D<4^C`lbDy}##3zY`%TwD5Hs9i5h!2;A>f zMT4`i0@3gOk(3EstunLUEr0Jtvh&f(XAfp7U-aemtu>NFu=U|MX$N31N1^idu`UK(6Q#>{<|81Yp^w4}V^8{WhwsftXMnkv8n>@0 z!1ClGCLAgFh@IlLH=?36SmOaF*}ctc^VCCONXC+>q&qGGmlv%yv|ib^UYfQafX@3q zad^gBFyHLtUAUd{+9M6V^3KQYneL{~TQMiq+cbkkPvlv{2Vd8j@4(W+N{EKbM#4Gv z^q$c0FYF5y7U$7zi>O_}Jf&DXz$3y-#j0-r|ZwDpLmMzbeUpq;67{Q6XIwmBl z6U0QH?^c(G*Rp$fJiPk;^y9)EwuZ0H0IONXp}gs6cvD9Zt*J6U*#04|{H2yef<%&l zbMI><^Rq~HGW{u&v4#Gn1pqG1GRcUuXMfcee-h~o{F7*_JQo^Sd&27_1wkIJ*O%2- zx@kn^x1oTe<@c?XL$14d5J$Je0XQRUw-xVHj0`ocH?)c&l8vt;Q13a1paQE(NwJJC z(YG`W)Md_Kk0u}4V^67dcyDR)cFO3fIM5fao9DTFvIk@hZrr|Kvy_#M7LAx*n6%Ra zcBp6-bB_6&+qG9(s(?@14A7<4FK+r?3{bvVMxE-@b5qdlLj5z6vkuJPdFlBN?|QL3 zG;pLfMV5;HYNox!oPPD|SKh6ldnz9do`g>n&2cS(Ee8-{3OhicI8=|lA#S%O#3A;dJ`}JUNcR9P|8z&MDr{_pONRF+2+Urh7h;>Ckw6<^W73cr!n{cB{` zM^{2jTm5npzarObx;E|6lGr7;;Q9!bSYJI zOXY=^Evt9K$MI42wto0VZpS5ex3)vZElkx}j|5sa4zC_eg_=%SwXEzOl=3F7ZHT-* zy}#Bw6;KJ_0`qAX1@Hk?&dxl|Y+*H&1bR31B_zSB_KKR5TMXPN%|0!Fgy-pf)pvD0 zm|Du;;_KvW+(G^|KaLKX*7~fw-yN?o>G?r7QZEdQq9Uz8yfn2WU}^W|6u*38T_fpL zWS$h?y8bbA#;+QMX(VJ(b0q(hZ+j1&{VU|D$aKJF=NyKkp0T>g&+hScI4pK6_2p|% z7+~U4u+>xyVGNCDkn`x|uK;k2#OHY)*TI6Sc1a@N($*EBa?~g7ZN|V5F}`>!fBb{l zxp0>?G7Ev|@7QRSx?fr5`Jm?oS|dK4nYvx#SKC!5O(SJqo}wpp%J|owyLjvQxg4kG zAr?_J<+hai4-r7-I5|&Z6%~lOI5SlxwK4enNS6*s+nX@ z!*NP1OFD*o9tH5518X`w>O0RVbJfe`(VVseKAl(s4W)gQBhzCR+>6W^l?3xEJDJv?Pp?th0$6_oh zyGBhH@Wif%jwVZS^Ozk5)tfB{+B>T!g{=t`RZV)}mAVeZ#3qq`@U=908@%dGVevru zQyIpnQ^K}O-V0Gxy$MHsqhi^@I2BMLDS|)knY^}!rrCuL=N~Z-C2@+!1$Mbu31x&C z1KDTlVqiO4Q#Rz z99(sTfk(upl^z3pKy$!B$c> zjjtmf2+k0Y3%cg*n)T;ImCYks2u}`|eS5#Y!xZy#9Q`6slcE?-uu!E489~wj#Hs`w zA3ht!g6hF9nu`M&uvZ?3FglREw>hyYI{G{?Vay+>addBXkE3HGyk>i$bAT=OnrQfa zsc6n2#23#9`&lmrNa&O_<~P_Ui`ws3hV3*z^R7RmL|?5S9fDgs`IAV+sxy&3+5a!@ ztwHCG5~*z*u{VH72wKR?9`QV4fXr(1)~~JinDKlJ8BX0wGSFvr<^s~H=Qm&Juhb2J zq|$a`WvIBcsy~wbhnA{WZO6FeBU4a1-%X>tcBWDWIIpS6ontA*WY@se37`KaObh zH!G!M`sXX-)1VqykgLN?2r$eXDrjB z;uH&0{ay5u7H>p$_YD`338#fS!2*>pn)Xu(-(Ytfp(Ry#+ipoYdFia z!%)siS<=Lg#o=24Jh+hPCa%$=rtb{rshR-_ln$#Q9bQMEG|Fzwi8S5S&}bia8rd5D z2oO?*AGox1o_v*LEV$vlt5+8E*A7?#vg_EL7Ycr?^(_;Z0wi>(o*$L)H#7XVzUU25 zb#UjKt-q0w(p!rC7|S(X)`LZy%&iXlj%*Pgr5dfRt>8=0qp4rF85||nwC)f~Vlilu z5;ty-dGSbM!r4^Y_9`?NQNRgot&|iAx5aG$=|mANDxq@WSiIFTh04i{Sj&k#>EORE ze(>X<gT*GE0xtVr$OBhWOUY`386tB_NG9}gG;N@s+}vh z7qB=CSw*Kv`hX!w^dH+B8cyoGXllMnhXRioLI*u7u^X zIo!-kxpKS7_Gf`^)}d}+dophhRgV`amU~wcqWz=dgjCXW@6W|;l(3}Mg=#Lz7aOwZ z(_JdBb6F{@8lQ3EDFtOvo8QSAN@#ec!Y(O^GbhOke5g9{zyuo!jhDYv?cEvyB3i}M~Zbu)Gp-yU^` z87Fj>#)IKXJ|B<-4J)=x5#R^g95yxoaS)H^@Adw?wOTYgXkjaS@_4J2j<`Nm&~PDm zyk-F18cUQCj$MJx?m7&2&3wxYw20KiiW$}2Vd(|E=H7!A}bm_R1GeVTO~ zcpICqYSPX-!+;`8abu;e=@sFvL1x4j7Qt`S*IzmGzp|A76~tqrCGZO{LmTuLwTiB3 zYf6tekK?9UeL-j#>)J3N&LW2ZA+J7nZN;naO-sZZra6o=B5d(t33Ks;#MCA&qb#e1+waj!UHf#(iRCcfT^{CK{$yKNRNQHxwl z-H9uxF{Fl2jo>cG0Y)Iaf|mqM5>PvBl9v{j7<|kj;~)uliU{Jg_uD)UeJR70fzCG@ zPG=&tq7NKWL7>h`Of1q2t;J&jDwcASKLC<=J~{yw6a;T&(;}+OEILmIAS3wnJe`tR zheHdav!Cf;b*yaghbV_lk-Q(aXKRI3W7vyNwc+ie`X+_wvJ zA!eP7usQ3xdoRZv{eP*D{Vkcw@s1kc03$*jiHKXQY&11El>o81i)5Flq8i{3J|*t| z{s6V$dBapbXbuhO9o96Ef}=?SU#99p#snnc_CRN;&Yyh}bcp+XJSC?iJXBSI7tBN4 z@RSL+J#$ytKF5n>*J(AmB{@{->soGJbYbi4b$LKj@mZ5F5paxc7dn*CI&+~BOZp9d zQGj?>&f}7WS{rK}4VK9RrYg@>b#B4{zdh6E#UmW1d`iJe`dG=m`oQiVQ5hR0Kxn%e zC|d2d#dl3IU377uJ_GBKn&|3v&;0CUPqt{f@n9fs0^5y+r{#6#}tR0&|Uh_Rbb%)3(bO|czK*smwn5QwcJxCyYypGZxwWp za7~)0>l?OlLRaQmBUFlwgwxBX9BFkaKGnEcDqSPze9+nNKK$}=xrHWCPAJ`FS+=bT z-Me#WCxd_2yG?QEunZ4nWzC1;Lmx{0zd1augI1r(Y?J)?`~uyOTN*C)mCuoQm8l1b zt+Zb?8E;WXr*<`_1W1;TUVV2(y|aL_fJUx5QiiMYc*}8o=sN8fXw&x*sc_1;@S|W2 zls_()#aQwb`C{~Diwr5p@?m@Ot5tZ373^8b(5nF36=6k=oIJ8qAOJkfbwKopNOdEH z^9}A@0drQ}W>!{(yO^kfbBzhT+>ZtCRV$!Ha%Ircp6Nkp^g(3`=-IvKL~P^cEr%l< zd%Sb)^HA${OaSH*&D{_i$u$Y00nntkTc;eEaOj8~GHHt(gl(d#bJa?_+4{ea{*;Y; zpq1p$?xi2VE3ST+kTU5_f&0J{tx3kBd04|MqmuAuK{{EQ3Y_JSVE{3Db@vgm3;h3L?yaMuUc0w(#X?XN zDN#c4AV?~RFmy-=2tzkW3`lpENQWRWL#K3imm)coO1A<-4Iv;MzV~nh&-wno>$iNL z=bv}2S*($BnEBkb_rCYO_H{Mec_-xaE_9EQX5<*O2FJ^P^tsxVXPx*t;f4r}vv{Ev zapM~^B4lL+xZ4xLo3I0k8RY?gB}?l9?@G<8n*!+FwN_Clo(=@&JwI1+u8z(|4z)nd z%xnlPr<5|=lQ}i-REc+59F-5*&B&a!arVQey(uy-@Fr+*f5ebfHY#2M<+$e#+7gR1 zq7>{5sbv3?zQ5|2sv_?^hMufcuqxZmfgDh{*HE|ZpO(nvF(MX}HoHTu7`Y!=APK@M zTnpq@Fam9hfZ8>b>UogxFdjK)Cg{~^bJ6;{vX|lI4D5QI0$ObO$oAEUeynNGdV%{- zw`XRt&78R2(s3LzL<feQ;G6s78~810%9QpYv?r)b@m&tJyL^!;*;I@oxCZ z=WKvwF4upw=KJ;{f~Bd>=V|oDlUuil>Ykg6w?(C1$-+joNuHyllNGF+?GQeCAjC|R zl`6<0f9pzgfSBL9R!{Xnc{lHVTuEz5506_%>-e-PT4l0qYZzUUaL9d4Nk6SKOD4rf zzOC?f52*i$*~gKg;c^UBI`MPdKW{J@0|8bV(qbY=O^Lp6dcv*8FZs##;TkTO4iq2n zB)5=$-qt}FuB{X#W5F$l=cKQ+JI2X!mHaX064 zRg}`no$L+^LIu0awD3&>52AUy#Jdq)xHQbVLXpD@8^#8;&2nazHPdONti@@FdulG* z3*&04eA)Yu2xCAZmi8{7X8{K#;CWFFgcb8`q4%bQ;sw?ra=Q*W^i9PjB``8)UdkMv zqHb#ngicvFqJk{@l}0@!r;V6fCade7rG(K@WvXuLr7R$}mrW~*1KV)c15EB;>i9zV zcq}oGgv{~4!Sp@^smu#D?!^2WPps!vNsw%+6Svb8LWYG7|byz zOu@w<50h#MM|v`1zdG~#6*qtWK=V>rhg?;yk9V<#PUW@p{AZ3|cLMm82}r5Mu5YrN zI7C8=%ThtdP`eSPxy@v41N8D;j?ATz=%7%%Nk}IzrfJ~agv-n=jme1WwC9C;_xlB< zdwQI^gio&m0U0B6tGhpQ3KRn>yGZ<$Gb3-*1fiND>d84v+2NB;yo!3AvD*}`yC@~9 z`_`AMmx?>mE|9l!YwtR5EjZ)Z{Y4SIVSf)U~arm0V?#1AHT?4ar zH|Xm?BAPMlh3%^e6-l5o2`QmgVV2e$Nb*dW zcrHh?jP6 z0QCA1;KK6jRZ3>5#`p<@KD4^Ft%g32bxQ||u5{y9OI{!5mUM@Gv0B>F{^;`ssQEca z?!~bawn#2v0R!JgX7QL+F>A0qc~Q9?(vO|E zYD|E)Hbv8ImxxZSJooNwrcBCwy!}xR$EjO_kzFo^c5_xl5ZbQGzOBT{9 ztI}^UQG5gR`HP6EjIO!bktlY-VnPB5A5bxz-T&k$I7~uc)IT}@x!?=tE;6P=Ls?U; ze}S$BYapC_7=hK7C+G-D5P}cfk~K}6c^M`mpqw|Y)k z6%1vR$XmDY^@C@`V4f7FUJPB#LHBwEu2p#DSW5Zp$vF~Amk2_zhcU1Z9b;YrZ(I_^ zeo+&Z&~o>ml!C(w%Cv3nY0fK#F!jOF>9T8evlThe@(l)M9wAMRM-Q2GKL&Ry_7qI; zaZ;w7YnGxyMYt6>HUP4KM&wURq0iY`20pp8_1}D))_?4*O+TwRAm`a*%M$C~h}xd( zilwO&%-kp%Awbt6TSuQRFMUZ1+=)ufUt9A^u-}+{UaHa*nWs_`!M!Y>+!+m6sqlet z0rxj&FQScM))Gb`f=cpBPHIalt#Vj{1@5|DB*9Bdq>TaGTfXdT$N=h)Snh0winyhq zdkUhtdGRba-U#!#%~3A(`J3HXYlEzD1$`uq5)u!(%|20B`xD@0P+SAq8fK`XkFU|z zoC&#lO_1wn&i;OJ;9ovph8N?PRt!xDWkZPTNBDH0pT4&sKiLp>VvbGCv$vZ{`RXc_ zz6T-l;)VS&;-bN1>G53lmn#y{-YmOiwA<~AymnWS;#^XIC?NeZ0TrTrk(WzNbIi2A z7y(cFL~8Ir_MUxgHA8FI)fEs8vbG%^v(2*yyBqD^u=rKr+Mgx*d#@xns`kX`w5KH+L{2X4 zjm9ZEIsritaTGJX_-3g=4~6Re+<-itti^4W<&shL;BP8rMr@oQkw3%e$|hcmFU{7+Tccfy^#{48fUDW*=}@U5 z!K7LA*io<=G4Wig?7SI%zz@6SQQ@)n27w;n|7V&gqkjNdP-V5&2#BT%{srSpX6rA9 zHR@J>Sf++B*Nr{hcOunnc{e!eXs5vQ;ywR^mFi7&=4g?{mFj~!Cmw1Z=y%8wwrO`9 zWDn)%%Dz6&FtujGnLu^^Hd0syuY5ZEb@UHxWDfGL}#!K$fs+jz zS#;87H>EX)@ACa?4tJj2Aw?%CuG8V77J9t|tK>-?aSPl9l1+qh=YGWkXU;QR_F@Z_ zX?(!X!*u2hE8(-J0`guO4PochoX_XN{kN>9^5yS-#h5v1BD}Zv>C2o`SrC)lBKN=5UcAWzM2~uEVtVtxUdU_d42D3?9PPyPm`1wuQ+Z@ zuzJlYqpxv)l5&vBr0U62E)r}}WH)<{_rH9x7yq4H+fP7KtNn|h%EgA)-d5Q6&M3V8 z_2o?WF%Ic2ZjBrDrSdIo{^*w>a&(iZ;}OH2yk*?J?r^kAqDOmTE+IGQH?em;IGEbZrdaCPm$ zf|>UN6lZA(mMz6mHOB@btMg(piUJD=A>9WzM1RmOZw0uU64Sl{nQzwT(Jaxt2j7J{ z&>WYs?wt9buXf;HIbZ5sfdRf#6S#JATxY(h#;^bF?f&sv&ot(1wR`08V3CqW+kj+# zN32rrP8_C`&3tb~oD>VQe~;j2&kB5beWs=&U#)_P=z%O;ifdDT5B*(xq;8*GwZZLN zS0W!X#(#0O<38JYBSm_3aql2qLRU~p z)ubnn#qV?j<4Rxt?MnX_r*vvwu|X05omAanoCPID>H!VTKYApw=UCvroZ1~T<{w1&%PNRd0bfwalX znYK`w?bK<1g0k_2p~#m6zrXw;=DS0Hat1cgu55y~Se!rcFcwmnNCEK8FOi6a%}q96eq9F_%0L8s~^Qo3^p=oMY0K-Dgf z)21v>HVsE1M^R%|qrr_Fq&On;kq~?qA_nERAh9O^oGYBq{mAcrPwaNW(nq}?Do>jY z9iT-z)a}u+;7f$NbMK+q@MR{+l)iAfWVaP|JP%*%ra9W;w0-KrSf}qiSDq z7f6ytAP@C^M5moGv?&Hz44c(DQ@z0Y8}x(6oCL6tHM7pQ0ZkM<2@kc(x$!n!Z|RRmJpA%C_2^2jMny!mJv!oIp7_{# zzL7T&d7bXcbHAgDuxEd}Czgun6xw?}RxHkxr!g%P4JNGA#)OrkbS83!_!y9rtc-dR z|Jgl|p!P$ADn1DP;-w*5Y%I=vIWXCO0l}yik>EJ1!U;s=btg;!4U%YLGa;Z;oDV$6 zN`gxD8MHe{c`m7HBzJBGk?)Imk@${fVt&opqZh(nXU4a^T(8t=8+>!^1|Sy>#-rqw zv>*HY-eq{5qjTFZ%2usW%rjgl;kF=xPAP(sl+TU(d13^2A-F%=`@6ssfSfQ=3D!N~{6+L+1R{BALRNs4ju|P>KgeF)mJN=#D@bThm z?$OC;a;*|slR{}@{o|Bd4<3C0X-#G~wT<3-*L^R0zX5y-oG%C;t>qRnIt@|mkqajQ z&Rez1AlyXaptz^B6eIkS<7C9W&^r5iAc`5VJYRJZ!4P6Rth_G9rG?^*%FEH#z`j&j zlT?56xvghM3m=!Yi6{V7*4K_a(T0F4`Y~V=6uq!BZV*h@Z<*Slo{fkInSQ@b zsG?I&yH=%)Mr97{3*v>oTtF<3XVbx0A^r`6JHEy305!r{ERlCByNv@&!t;c z^()ciaP#y=IEbD|JE)VT2nP~h z#_e*IFK}~JIrOD;;a{!a&%Z&f)4}8gfB<(9v@)-80Phaa|0Dr`se)3wW%gi%E&hd8 z2owia{(fPo=p38zL|nFFmbf=gJX5aKQ4+AhUrG(-3_<=*CXIXT={2A}$GR{WU-NRl zFj;00-Ipa)fpb4D!hK7{t45i(l}UlQZi!{$jreH!k>E$sD29}Rw8=IK-5aMI^Y%R{B!BVHn9V7!lYn8xC4rgw;W|f9*zk+ON zcPG4N6Wcvk~SnBRfy@?^GZ&)g7JgHi!m&J4))_I^qh(u*dzFA1Nv1tzGk-nAxb z(*f0Tp=Ozt8a{ZC9j9jk?n!`xO@sku*qi=Y&AjeGj)ROhJ%9+R@v#zn86Ftsh18^=pI{E<* z+rfH=VhpD(9mww7rJ|&Ca81mv9zqEw_}W|r`lUVxh)kG$Fd|M)Yuye zG^)AjTGStnRM=Ajme`K3QkeCy*r98wwvTF%VVp-XEUpgbZ7o(a&;RIystWu-flj@8f()HGCBp zmIcLR8f$-N8sGn&2@=1)S@JFwa1mnsgu z0lX?~C1G>J$Q}IhvCB@N>~Kc+ZjnNuFKDGp1I;ioMuYj}3QI?a`wO7^Ed`TdQao46(mpvdG zhBm3hgjm)S??a9;imWBB%NF2;^Mfbdac9c*qB3 z5`aD#at)WY=5>qNPLt$MhXNWb<%#~+E-P2*AjW=>(nrUznTmJ=@PD@0!qzU3Vu2qT z*m^3NUE@1=ScFPS`m9Ozqh%hUAa=Xh&Z2P@nYIVx zL`cn+*g@X!>v7et1wmwx0P#pBQ#Bh`hD^ytS7d`DpxI38VBn3K+Fk%|fR6Xcej@UI zg;8zQuPu1*yrtvU+4y%#D1E%g4&QsN%$h0riXwfmF5ui0UiakzV`q%F`SPp<;#RP| zJle_;TxJd6_2L)!v?hyTxMjwXtReok4WpBTGAWwWM{lMlnH2p%&*+0}oO&P-#}UJ| z9iM5exe<$NGh$X?ovB)8p9SHDME`lT(oAN?h+S?J9iQwp79tH zyyIsJT$2E&+|Py`bkumlk`7E-KGTCG>rde^@NhnGo)E zizceaxL*;s>3tKNvMbi&O1}6pW(5Zr%&C8P!x*7(3$jj>d?qRf&vm$X@b%9l`_~K- zl;OE?$W8`f~t4^!*tcCWyX@J{w`ZW$_GyBuY%RokA{~(b z(aWTiYr1J61eJ-90c(_AosQl&YQasV#o^mE7^kh%!^LTaf?b6=BXsJx<{b2ZcNtL1 zepWgVxYZzyk&w(%o(pl{hz3$AKdMI8(mAyMk=3aReKmEl3qNsK-gl`XvgIN#nCdYd}d{vfCeQ{=er{a_>hIvf@`E{$%duLvfmOa;=iD#YzfVn8`BnS>efBe(Kv>5C&5 zQKr#*I04r02ii<5x3@-1(kjl?mjT5xdC<1BHydltz?f2J)!S^DeSP3~n}MKtHiURc z=$!kHkCcpsX?I!;foo;ij*MMv*{%JnpeIXV+-!ngQ-`+X%E8^MY9F&dodufUcQ=U| zWQ-0t${a?Gn%^!ifW!rj_S4RZ42p}WgH9(`Q?h%iuI?dnB+K0#cfR?y)$R-dXyZrMVuYXy<9X{&JxvZ>`l~#k zf+E!tgtE^41Z&RMde+~Cx=O+A2O`dCzjv!OtGrV;9pgB*SZf3n+tFB+bfS~hDm!xr zz+M3t8(EaEvNkEx6g*L+>&tX;!8O7N2UalshNPp1XIq`qX8x^BXfAOf(V6nG`n4AK zj*n>)kvKVDKUgIayU3NqK$+WxV3 zNunSTdAkr@^f&taNJLabW2$MUE&ws={#Q0iMO}=T)_UUf}bW8*YKnhZO`x+0y5|tr(sNBy8`+ zskYC~)=eoScTzrBxO+~SX`I|%QIWWAch*5joo%94mDburY7*shoymTzUQXWDh+@hH zFBKlhonbtZo5he1f;|>HmKtL7FR4Y`KuL@MKOzM&MhVbuE?QaDU22CDAkT80K5d$s zxuKw1aOl9}?BH;AKM%`&wpC{JN`6`mtr?Abj$P)2f7!*AkD|#yx8paPqg|A@Qk*N* zWARa1G`eQhOq@}*^evTC)OW2l?NP$2Rnf#6a&u1RCC`%!{wsd7dtbLXGsm~+z1M?s zv*cM);NMj6h>>=er+81&10JPvv;e#(qqc0pu#nLff}R!yA}jcbh2*pP>i(Nv5+Vz1Vh&@90HDueJR zFe5&yBFhNKUg$LtBbmk^BrZ`@@`)4H^}L4C0+wXmse7JeC3UqQj-4~A1?RG+&0LeZ za#r1o4=#>zu|NNsO0VcLPIT-l=+LpBTrNp>n}iEi3Hb(N?oVykZVj!&`R>e5@Q4oU zu}v%?Nmh9)iqSBi59$Sz3-y3>Je!w&m53P!rWmAJCk^TT&a+(_K^4;)bjutdYl{|x zx0xz*W@q9C?E^+3Z#7UlDJ^dnD3aq)aIs`=lc9~Kfe&#lwU2!CyW$>fk01GO?`IP> zVlp&fwQhXFibv-F`Jz(U*+Y<*!e%C`a~u@Y+_-(gpFCrEi_9nbP{&Ckv59X~arn?yK1^+HL+yRL;iDY$QucL2p1hu-RK}33rPU1AJ zP;#gI+fxf*a-5Cx+Ne2t*7%&Y)p?quRy;XvaVpQuP&*B(Xr|##_-KaHzcOI9X{B`d zDlJXJv==B?w0fd0Jhu)|su;XrVXfh^r2j2(1ELV~mrnk+%5@x60*`aMatMQSZj*Qp zxU+CCT78;k%x=6%6UV|%GJXFi&?$bvFuR%*MlBIwup;>p!5!JP_6+oJ(C0j&H{MBA zG6O)l@JDe9E>cX^JqhEb)^kjT-|E4wq`vj}Ea!okX63?W%>pam1{yXzZoi)kqSQ2K zJ~SDtC|1c1QV$p;_LfSdy`6Vj({3tGcjddRtyt67Xr>SH_I8N3VAfJx0g1cvjjZl?4ojB9sRbuBkNI`Q~tu>T4?4hm3;#K_)^=gC2` zFuf;u)E5Al>-9gtT+0mbI;K~?Rh8gBl-=O_tdlv|x)Y&h1|;X`ni+k@xvdxst#O=c zqtSu3OA0cm$L^rZZehZC6#A_ZvKFt~-aOZZyu~|*xE=Z75j>X7SidQ1*4jzOev?cW zz<42h3(#%gR=w><44gD4wqqvM6XJC%dSYb1KLC)e&8fhTSs(~vY2j&An7z3Xm)jCs z`*kfuZFtk@xjuCoLgdpTc(J~sSujDD_61^^0Wf6@3SdE>@0*UPj>t^=#tr)Gc=I1p8n=0=haAbj=Uxl|Igo0fCcc^~W`Mj(^a-5@Na_0@9 zWRrqP3zC!Bdj&+npNf3gt~mlSxcF+BO8{D}TG4HplL@x<3LObCk~4bVl^yq|dVpM- zziMX?EII7uqsOZ2Gx3+5YKKkz2%b+(pq+Sd)_b7F=gi#RXbb05)^T_dM zi3_`ZAOJr2AaQiCtFTo$3i8Kafad-6Z3-HaJVKy8q$xp+R*gyE|z+DPX=!q8)bF?_xK8>fnE29ZpG!pINQj^%Iy=jr;$rTfhY+ zs&a`d+ovg{r^nXf{92704AoJD!Gn<|&rETGM7h+Ux^-SIZ-O9*ZNV}2cMF< zrMHD`6aklXMc=1Y%bEhcpCA_}>@p-G)2t3;x%)t*;W(jQAzN8!RUjNVE8_?;d)!Jj ztEcpB3Rsj5`|QUuxB*2`6#(#4O*dEUY2ny~s(zl`^ZJ m)zhrk)>uU_ah3=92qa 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 0; i-- { - cleanupFuncs[i]() - } - }() - - if firstTime { - var err error - s.generator, err = tfgen.NewGenerator( - s.logger.Named("tfgen"), - s.runner, - s.topology, - &s.secrets, - s.workdir, - s.license, - ) - if err != nil { - return err - } - } else { - s.generator.SetTopology(s.topology) - } - cleanupFuncs = append(cleanupFuncs, func() { - // Log the error before the cleanup so you don't have to wait to see - // the cause. - if launchErr != nil { - s.logger.Error("fatal error during launch", "error", launchErr) - } - - _ = s.generator.DestroyAllQuietly() - }) - - if firstTime { - // The networking phase is special. We have to pick a random subnet and - // hope. Once we have this established once it is immutable for future - // runs. - if err := s.initNetworkingAndVolumes(); err != nil { - return fmt.Errorf("initNetworkingAndVolumes: %w", err) - } - } - - if err := s.assignIPAddresses(); err != nil { - return fmt.Errorf("assignIPAddresses: %w", err) - } - - // The previous terraform run should have made the special volume for us. - if err := s.initTLS(context.TODO()); err != nil { - return fmt.Errorf("initTLS: %w", err) - } - - if firstTime { - if err := s.createFirstTime(); err != nil { - return err - } - - s.generator.MarkLaunched() - } else { - if err := s.updateExisting(); err != nil { - return err - } - } - - if err := s.waitForPeeringEstablishment(); err != nil { - return fmt.Errorf("waitForPeeringEstablishment: %w", err) - } - - cleanupFuncs = nil // reset - - return nil -} - -func (s *Sprawl) Stop() error { - var merr error - if s.generator != nil { - if err := s.generator.DestroyAllQuietly(); err != nil { - merr = multierror.Append(merr, err) - } - } - return merr -} - -const dockerOutOfNetworksErrorMessage = `Unable to create network: Error response from daemon: Pool overlaps with other one on this address space` - -var ErrDockerNetworkCollision = errors.New("could not create one or more docker networks for use due to subnet collision") - -func (s *Sprawl) initNetworkingAndVolumes() error { - var lastErr error - for attempts := 0; attempts < 5; attempts++ { - err := s.generator.Generate(tfgen.StepNetworks) - if err != nil && strings.Contains(err.Error(), dockerOutOfNetworksErrorMessage) { - lastErr = ErrDockerNetworkCollision - s.logger.Warn(ErrDockerNetworkCollision.Error()+"; retrying", "attempt", attempts+1) - time.Sleep(1 * time.Second) - continue - } else if err != nil { - return fmt.Errorf("generator[networks]: %w", err) - } - return nil - } - - return lastErr -} - -func (s *Sprawl) assignIPAddresses() error { - // assign ips now that we have network ips known to us - for _, net := range s.topology.Networks { - if len(net.IPPool) == 0 { - return fmt.Errorf("network %q does not have any ip assignments", net.Name) - } - } - for _, cluster := range s.topology.Clusters { - for _, node := range cluster.Nodes { - for _, addr := range node.Addresses { - net, ok := s.topology.Networks[addr.Network] - if !ok { - return fmt.Errorf("unknown network %q", addr.Network) - } - addr.IPAddress = net.IPByIndex(node.Index) - } - } - } - - return nil -} - -func (s *Sprawl) initConsulServers() error { - if err := s.generator.Generate(tfgen.StepServers); err != nil { - return fmt.Errorf("generator[servers]: %w", err) - } - - // s.logger.Info("ALL", "t", jd(s.topology)) // TODO - - // Create token-less api clients first. - for _, cluster := range s.topology.Clusters { - node := cluster.FirstServer() - - var err error - s.clients[cluster.Name], err = util.ProxyAPIClient( - node.LocalProxyPort(), - node.LocalAddress(), - 8500, - "", /*no token yet*/ - ) - if err != nil { - return fmt.Errorf("error creating initial bootstrap client for cluster=%s: %w", cluster.Name, err) - } - } - - if err := s.rejoinAllConsulServers(); err != nil { - return err - } - - for _, cluster := range s.topology.Clusters { - err := s.bootstrapACLs(cluster.Name) - if err != nil { - return fmt.Errorf("bootstrap[%s]: %w", cluster.Name, err) - } - - mgmtToken := s.secrets.ReadGeneric(cluster.Name, secrets.BootstrapToken) - - // Reconfigure the clients to use a management token. - node := cluster.FirstServer() - s.clients[cluster.Name], err = util.ProxyAPIClient( - node.LocalProxyPort(), - node.LocalAddress(), - 8500, - mgmtToken, - ) - if err != nil { - return fmt.Errorf("error creating final client for cluster=%s: %v", cluster.Name, err) - } - - // For some reason the grpc resolver stuff for partitions takes some - // time to get ready. - s.waitForLocalWrites(cluster, mgmtToken) - - // Create tenancies so that the ACL tokens and clients have somewhere to go. - if cluster.Enterprise { - if err := s.initTenancies(cluster); err != nil { - return fmt.Errorf("initTenancies[%s]: %w", cluster.Name, err) - } - } - - if err := s.populateInitialConfigEntries(cluster); err != nil { - return fmt.Errorf("populateInitialConfigEntries[%s]: %w", cluster.Name, err) - } - - if err := s.createAnonymousToken(cluster); err != nil { - return fmt.Errorf("createAnonymousToken[%s]: %w", cluster.Name, err) - } - - // Create tokens for all of the agents to use for anti-entropy. - // - // NOTE: this will cause the servers to roll to pick up the change to - // the acl{tokens{agent=XXX}}} section. - if err := s.createAgentTokens(cluster); err != nil { - return fmt.Errorf("createAgentTokens[%s]: %w", cluster.Name, err) - } - } - - return nil -} - -func (s *Sprawl) createFirstTime() error { - if err := s.initConsulServers(); err != nil { - return fmt.Errorf("initConsulServers: %w", err) - } - - if err := s.generator.Generate(tfgen.StepAgents); err != nil { - return fmt.Errorf("generator[agents]: %w", err) - } - for _, cluster := range s.topology.Clusters { - if err := s.waitForClientAntiEntropyOnce(cluster); err != nil { - return fmt.Errorf("waitForClientAntiEntropyOnce[%s]: %w", cluster.Name, err) - } - } - - // Ideally we start services WITH a token initially, so we pre-create them - // before running terraform for them. - if err := s.createAllServiceTokens(); err != nil { - return fmt.Errorf("createAllServiceTokens: %w", err) - } - - if err := s.registerAllServicesForDataplaneInstances(); err != nil { - return fmt.Errorf("registerAllServicesForDataplaneInstances: %w", err) - } - - // We can do this ahead, because we've incrementally run terraform as - // we went. - if err := s.registerAllServicesToAgents(); err != nil { - return fmt.Errorf("registerAllServicesToAgents: %w", err) - } - - // NOTE: start services WITH token initially - if err := s.generator.Generate(tfgen.StepServices); err != nil { - return fmt.Errorf("generator[services]: %w", err) - } - - if err := s.initPeerings(); err != nil { - return fmt.Errorf("initPeerings: %w", err) - } - return nil -} - -func (s *Sprawl) updateExisting() error { - if err := s.preRegenTasks(); err != nil { - return fmt.Errorf("preRegenTasks: %w", err) - } - - // We save all of the terraform to the end. Some of the containers will - // be a little broken until we can do stuff like register services to - // new agents, which we cannot do until they come up. - if err := s.generator.Generate(tfgen.StepRelaunch); err != nil { - return fmt.Errorf("generator[relaunch]: %w", err) - } - - if err := s.postRegenTasks(); err != nil { - return fmt.Errorf("postRegenTasks: %w", err) - } - - // TODO: enforce that peering relationships cannot change - // TODO: include a fixup version of new peerings? - - return nil -} - -func (s *Sprawl) preRegenTasks() error { - for _, cluster := range s.topology.Clusters { - // Create tenancies so that the ACL tokens and clients have somewhere to go. - if cluster.Enterprise { - if err := s.initTenancies(cluster); err != nil { - return fmt.Errorf("initTenancies[%s]: %w", cluster.Name, err) - } - } - - if err := s.populateInitialConfigEntries(cluster); err != nil { - return fmt.Errorf("populateInitialConfigEntries[%s]: %w", cluster.Name, err) - } - - // Create tokens for all of the agents to use for anti-entropy. - if err := s.createAgentTokens(cluster); err != nil { - return fmt.Errorf("createAgentTokens[%s]: %w", cluster.Name, err) - } - } - - // Ideally we start services WITH a token initially, so we pre-create them - // before running terraform for them. - if err := s.createAllServiceTokens(); err != nil { - return fmt.Errorf("createAllServiceTokens: %w", err) - } - - if err := s.registerAllServicesForDataplaneInstances(); err != nil { - return fmt.Errorf("registerAllServicesForDataplaneInstances: %w", err) - } - - return nil -} - -func (s *Sprawl) postRegenTasks() error { - if err := s.rejoinAllConsulServers(); err != nil { - return err - } - - for _, cluster := range s.topology.Clusters { - var err error - - mgmtToken := s.secrets.ReadGeneric(cluster.Name, secrets.BootstrapToken) - - // Reconfigure the clients to use a management token. - node := cluster.FirstServer() - s.clients[cluster.Name], err = util.ProxyAPIClient( - node.LocalProxyPort(), - node.LocalAddress(), - 8500, - mgmtToken, - ) - if err != nil { - return fmt.Errorf("error creating final client for cluster=%s: %v", cluster.Name, err) - } - - s.waitForLeader(cluster) - - // For some reason the grpc resolver stuff for partitions takes some - // time to get ready. - s.waitForLocalWrites(cluster, mgmtToken) - } - - for _, cluster := range s.topology.Clusters { - if err := s.waitForClientAntiEntropyOnce(cluster); err != nil { - return fmt.Errorf("waitForClientAntiEntropyOnce[%s]: %w", cluster.Name, err) - } - } - - if err := s.registerAllServicesToAgents(); err != nil { - return fmt.Errorf("registerAllServicesToAgents: %w", err) - } - - return nil -} - -func (s *Sprawl) waitForLocalWrites(cluster *topology.Cluster, token string) { - var ( - client = s.clients[cluster.Name] - logger = s.logger.With("cluster", cluster.Name) - ) - tryKV := func() error { - _, err := client.KV().Put(&api.KVPair{ - Key: "local-test", - Value: []byte("payload-for-local-test-in-" + cluster.Name), - }, nil) - return err - } - tryAP := func() error { - if !cluster.Enterprise { - return nil - } - _, _, err := client.Partitions().Create(context.Background(), &api.Partition{ - Name: "placeholder", - }, &api.WriteOptions{Token: token}) - return err - } - - start := time.Now() - for attempts := 0; ; attempts++ { - if err := tryKV(); err != nil { - logger.Warn("local kv write failed; something is not ready yet", "error", err) - time.Sleep(500 * time.Millisecond) - continue - } else { - dur := time.Since(start) - logger.Info("local kv write success", "elapsed", dur, "retries", attempts) - } - - break - } - - if cluster.Enterprise { - start = time.Now() - for attempts := 0; ; attempts++ { - if err := tryAP(); err != nil { - logger.Warn("local partition write failed; something is not ready yet", "error", err) - time.Sleep(500 * time.Millisecond) - continue - } else { - dur := time.Since(start) - logger.Info("local partition write success", "elapsed", dur, "retries", attempts) - } - - break - } - } -} - -func (s *Sprawl) waitForClientAntiEntropyOnce(cluster *topology.Cluster) error { - var ( - client = s.clients[cluster.Name] - logger = s.logger.With("cluster", cluster.Name) - ) - - var ( - queryOptionList = cluster.PartitionQueryOptionsList() - start = time.Now() - cc = client.Catalog() - ) - for { - // Enumerate all of the nodes that are currently in the catalog. This - // will overmatch including things like fake nodes for agentless but - // that's ok. - current := make(map[topology.NodeID]*api.Node) - for _, queryOpts := range queryOptionList { - nodes, _, err := cc.Nodes(queryOpts) - if err != nil { - return err - } - for _, node := range nodes { - nid := topology.NewNodeID(node.Node, node.Partition) - current[nid] = node - } - } - - // See if we have them all. - var stragglers []topology.NodeID - for _, node := range cluster.Nodes { - if !node.IsAgent() || node.Disabled { - continue - } - nid := node.CatalogID() - - got, ok := current[nid] - if ok && len(got.TaggedAddresses) > 0 { - // this is a field that is not updated just due to serf reconcile - continue - } - - stragglers = append(stragglers, nid) - } - - if len(stragglers) == 0 { - dur := time.Since(start) - logger.Info("all nodes have posted node updates, so first anti-entropy has happened", "elapsed", dur) - return nil - } - logger.Info("not all client nodes have posted node updates yet", "nodes", stragglers) - - time.Sleep(1 * time.Second) - } -} - -func newGossipKey() (string, error) { - key := make([]byte, 16) - n, err := rand.Reader.Read(key) - if err != nil { - return "", fmt.Errorf("Error reading random data: %s", err) - } - if n != 16 { - return "", fmt.Errorf("Couldn't read enough entropy. Generate more entropy!") - } - return base64.StdEncoding.EncodeToString(key), nil -} diff --git a/testing/deployer/sprawl/catalog.go b/testing/deployer/sprawl/catalog.go deleted file mode 100644 index eb355739a6cf7..0000000000000 --- a/testing/deployer/sprawl/catalog.go +++ /dev/null @@ -1,428 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sprawl - -import ( - "fmt" - "net/http" - "time" - - "github.com/hashicorp/consul/api" - - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/consul/testing/deployer/util" -) - -func (s *Sprawl) registerAllServicesToAgents() error { - for _, cluster := range s.topology.Clusters { - if err := s.registerServicesToAgents(cluster); err != nil { - return fmt.Errorf("registerServicesToAgents[%s]: %w", cluster.Name, err) - } - } - return nil -} - -func (s *Sprawl) registerAllServicesForDataplaneInstances() error { - for _, cluster := range s.topology.Clusters { - if err := s.registerServicesForDataplaneInstances(cluster); err != nil { - return fmt.Errorf("registerServicesForDataplaneInstances[%s]: %w", cluster.Name, err) - } - } - return nil -} - -func (s *Sprawl) registerServicesToAgents(cluster *topology.Cluster) error { - for _, node := range cluster.Nodes { - if !node.RunsWorkloads() || len(node.Services) == 0 || node.Disabled { - continue - } - - if !node.IsAgent() { - continue - } - - agentClient, err := util.ProxyAPIClient( - node.LocalProxyPort(), - node.LocalAddress(), - 8500, - "", /*token will be in request*/ - ) - if err != nil { - return err - } - - for _, svc := range node.Services { - if err := s.registerAgentService(agentClient, cluster, node, svc); err != nil { - return err - } - } - } - - return nil -} - -func (s *Sprawl) registerAgentService( - agentClient *api.Client, - cluster *topology.Cluster, - node *topology.Node, - svc *topology.Service, -) error { - if !node.IsAgent() { - panic("called wrong method type") - } - - if svc.IsMeshGateway { - return nil // handled at startup time for agent-full, but won't be for agent-less - } - - var ( - logger = s.logger.With("cluster", cluster.Name) - ) - - reg := &api.AgentServiceRegistration{ - ID: svc.ID.Name, - Name: svc.ID.Name, - Port: svc.Port, - Meta: svc.Meta, - } - if cluster.Enterprise { - reg.Namespace = svc.ID.Namespace - reg.Partition = svc.ID.Partition - } - - if !svc.DisableServiceMesh { - var upstreams []api.Upstream - for _, u := range svc.Upstreams { - uAPI := api.Upstream{ - DestinationPeer: u.Peer, - DestinationName: u.ID.Name, - LocalBindAddress: u.LocalAddress, - LocalBindPort: u.LocalPort, - // Config map[string]interface{} `json:",omitempty" bexpr:"-"` - // MeshGateway MeshGatewayConfig `json:",omitempty"` - } - if cluster.Enterprise { - uAPI.DestinationNamespace = u.ID.Namespace - if u.Peer == "" { - uAPI.DestinationPartition = u.ID.Partition - } - } - upstreams = append(upstreams, uAPI) - } - reg.Connect = &api.AgentServiceConnect{ - SidecarService: &api.AgentServiceRegistration{ - Proxy: &api.AgentServiceConnectProxyConfig{ - Upstreams: upstreams, - }, - }, - } - } - - switch { - case svc.CheckTCP != "": - chk := &api.AgentServiceCheck{ - Name: "up", - TCP: svc.CheckTCP, - Interval: "5s", - Timeout: "1s", - } - reg.Checks = append(reg.Checks, chk) - case svc.CheckHTTP != "": - chk := &api.AgentServiceCheck{ - Name: "up", - HTTP: svc.CheckHTTP, - Method: "GET", - Interval: "5s", - Timeout: "1s", - } - reg.Checks = append(reg.Checks, chk) - } - - // Switch token for every request. - hdr := make(http.Header) - hdr.Set("X-Consul-Token", s.secrets.ReadServiceToken(cluster.Name, svc.ID)) - agentClient.SetHeaders(hdr) - -RETRY: - if err := agentClient.Agent().ServiceRegister(reg); err != nil { - if isACLNotFound(err) { - time.Sleep(50 * time.Millisecond) - goto RETRY - } - return fmt.Errorf("failed to register service %q to node %q: %w", svc.ID, node.ID(), err) - } - - logger.Info("registered service to client agent", - "service", svc.ID.Name, - "node", node.Name, - "namespace", svc.ID.Namespace, - "partition", svc.ID.Partition, - ) - - return nil -} - -func (s *Sprawl) registerServicesForDataplaneInstances(cluster *topology.Cluster) error { - for _, node := range cluster.Nodes { - if !node.RunsWorkloads() || len(node.Services) == 0 || node.Disabled { - continue - } - - if !node.IsDataplane() { - continue - } - - if err := s.registerCatalogNode(cluster, node); err != nil { - return fmt.Errorf("error registering virtual node: %w", err) - } - - for _, svc := range node.Services { - if err := s.registerCatalogService(cluster, node, svc); err != nil { - return fmt.Errorf("error registering service: %w", err) - } - if !svc.DisableServiceMesh { - if err := s.registerCatalogSidecarService(cluster, node, svc); err != nil { - return fmt.Errorf("error registering sidecar service: %w", err) - } - } - } - } - - return nil -} - -func (s *Sprawl) registerCatalogNode( - cluster *topology.Cluster, - node *topology.Node, -) error { - if !node.IsDataplane() { - panic("called wrong method type") - } - - var ( - client = s.clients[cluster.Name] - logger = s.logger.With("cluster", cluster.Name) - ) - - reg := &api.CatalogRegistration{ - Node: node.PodName(), - Address: node.LocalAddress(), - NodeMeta: map[string]string{ - "dataplane-faux": "1", - }, - } - if cluster.Enterprise { - reg.Partition = node.Partition - } - - // register synthetic node -RETRY: - if _, err := client.Catalog().Register(reg, nil); err != nil { - if isACLNotFound(err) { - time.Sleep(50 * time.Millisecond) - goto RETRY - } - return fmt.Errorf("error registering virtual node %s: %w", node.ID(), err) - } - - logger.Info("virtual node created", - "node", node.ID(), - ) - - return nil -} - -func (s *Sprawl) registerCatalogService( - cluster *topology.Cluster, - node *topology.Node, - svc *topology.Service, -) error { - if !node.IsDataplane() { - panic("called wrong method type") - } - - var ( - client = s.clients[cluster.Name] - logger = s.logger.With("cluster", cluster.Name) - ) - - reg := serviceToCatalogRegistration(cluster, node, svc) - -RETRY: - if _, err := client.Catalog().Register(reg, nil); err != nil { - if isACLNotFound(err) { - time.Sleep(50 * time.Millisecond) - goto RETRY - } - return fmt.Errorf("error registering service %s to node %s: %w", svc.ID, node.ID(), err) - } - - logger.Info("dataplane service created", - "service", svc.ID, - "node", node.ID(), - ) - - return nil -} - -func (s *Sprawl) registerCatalogSidecarService( - cluster *topology.Cluster, - node *topology.Node, - svc *topology.Service, -) error { - if !node.IsDataplane() { - panic("called wrong method type") - } - if svc.DisableServiceMesh { - panic("not valid") - } - - var ( - client = s.clients[cluster.Name] - logger = s.logger.With("cluster", cluster.Name) - ) - - pid, reg := serviceToSidecarCatalogRegistration(cluster, node, svc) -RETRY: - if _, err := client.Catalog().Register(reg, nil); err != nil { - if isACLNotFound(err) { - time.Sleep(50 * time.Millisecond) - goto RETRY - } - return fmt.Errorf("error registering service %s to node %s: %w", svc.ID, node.ID(), err) - } - - logger.Info("dataplane sidecar service created", - "service", pid, - "node", node.ID(), - ) - - return nil -} - -func serviceToCatalogRegistration( - cluster *topology.Cluster, - node *topology.Node, - svc *topology.Service, -) *api.CatalogRegistration { - reg := &api.CatalogRegistration{ - Node: node.PodName(), - SkipNodeUpdate: true, - Service: &api.AgentService{ - Kind: api.ServiceKindTypical, - ID: svc.ID.Name, - Service: svc.ID.Name, - Meta: svc.Meta, - Port: svc.Port, - Address: node.LocalAddress(), - }, - } - if node.HasPublicAddress() { - reg.TaggedAddresses = map[string]string{ - "lan": node.LocalAddress(), - "lan_ipv4": node.LocalAddress(), - "wan": node.PublicAddress(), - "wan_ipv4": node.PublicAddress(), - } - } - if cluster.Enterprise { - reg.Partition = svc.ID.Partition - reg.Service.Namespace = svc.ID.Namespace - reg.Service.Partition = svc.ID.Partition - } - - if svc.HasCheck() { - chk := &api.HealthCheck{ - Name: "external sync", - // Type: "external-sync", - Status: "passing", // TODO - ServiceID: svc.ID.Name, - ServiceName: svc.ID.Name, - Output: "", - } - if cluster.Enterprise { - chk.Namespace = svc.ID.Namespace - chk.Partition = svc.ID.Partition - } - switch { - case svc.CheckTCP != "": - chk.Definition.TCP = svc.CheckTCP - case svc.CheckHTTP != "": - chk.Definition.HTTP = svc.CheckHTTP - chk.Definition.Method = "GET" - } - reg.Checks = append(reg.Checks, chk) - } - return reg -} - -func serviceToSidecarCatalogRegistration( - cluster *topology.Cluster, - node *topology.Node, - svc *topology.Service, -) (topology.ServiceID, *api.CatalogRegistration) { - pid := svc.ID - pid.Name += "-sidecar-proxy" - reg := &api.CatalogRegistration{ - Node: node.PodName(), - SkipNodeUpdate: true, - Service: &api.AgentService{ - Kind: api.ServiceKindConnectProxy, - ID: pid.Name, - Service: pid.Name, - Meta: svc.Meta, - Port: svc.EnvoyPublicListenerPort, - Address: node.LocalAddress(), - Proxy: &api.AgentServiceConnectProxyConfig{ - DestinationServiceName: svc.ID.Name, - DestinationServiceID: svc.ID.Name, - LocalServicePort: svc.Port, - }, - }, - Checks: []*api.HealthCheck{{ - Name: "external sync", - // Type: "external-sync", - Status: "passing", // TODO - ServiceID: pid.Name, - ServiceName: pid.Name, - Definition: api.HealthCheckDefinition{ - TCP: fmt.Sprintf("%s:%d", node.LocalAddress(), svc.EnvoyPublicListenerPort), - }, - Output: "", - }}, - } - if node.HasPublicAddress() { - reg.TaggedAddresses = map[string]string{ - "lan": node.LocalAddress(), - "lan_ipv4": node.LocalAddress(), - "wan": node.PublicAddress(), - "wan_ipv4": node.PublicAddress(), - } - } - if cluster.Enterprise { - reg.Partition = pid.Partition - reg.Service.Namespace = pid.Namespace - reg.Service.Partition = pid.Partition - reg.Checks[0].Namespace = pid.Namespace - reg.Checks[0].Partition = pid.Partition - } - - for _, u := range svc.Upstreams { - pu := api.Upstream{ - DestinationName: u.ID.Name, - DestinationPeer: u.Peer, - LocalBindAddress: u.LocalAddress, - LocalBindPort: u.LocalPort, - } - if cluster.Enterprise { - pu.DestinationNamespace = u.ID.Namespace - if u.Peer == "" { - pu.DestinationPartition = u.ID.Partition - } - } - reg.Service.Proxy.Upstreams = append(reg.Service.Proxy.Upstreams, pu) - } - - return pid, reg -} diff --git a/testing/deployer/sprawl/configentries.go b/testing/deployer/sprawl/configentries.go deleted file mode 100644 index 90ca2bb4cda2e..0000000000000 --- a/testing/deployer/sprawl/configentries.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sprawl - -import ( - "fmt" - "strings" - "time" - - "github.com/hashicorp/consul/api" - - "github.com/hashicorp/consul/testing/deployer/topology" -) - -func (s *Sprawl) populateInitialConfigEntries(cluster *topology.Cluster) error { - if len(cluster.InitialConfigEntries) == 0 { - return nil - } - - var ( - client = s.clients[cluster.Name] - logger = s.logger.With("cluster", cluster.Name) - ) - - for _, ce := range cluster.InitialConfigEntries { - _, _, err := client.ConfigEntries().Set(ce, nil) - if err != nil { - if ce.GetKind() == api.ServiceIntentions && strings.Contains(err.Error(), intentionsMigrationError) { - logger.Warn("known error writing initial config entry; trying again", - "kind", ce.GetKind(), - "name", ce.GetName(), - "namespace", ce.GetNamespace(), - "partition", ce.GetPartition(), - "error", err, - ) - - time.Sleep(500 * time.Millisecond) - continue - } - return fmt.Errorf( - "error persisting config entry kind=%q name=%q namespace=%q partition=%q: %w", - ce.GetKind(), - ce.GetName(), - ce.GetNamespace(), - ce.GetPartition(), - err, - ) - } - logger.Info("wrote initial config entry", - "kind", ce.GetKind(), - "name", ce.GetName(), - "namespace", ce.GetNamespace(), - "partition", ce.GetPartition(), - ) - } - - return nil -} - -const intentionsMigrationError = `Intentions are read only while being upgraded to config entries` diff --git a/testing/deployer/sprawl/consul.go b/testing/deployer/sprawl/consul.go deleted file mode 100644 index e92fe218846e4..0000000000000 --- a/testing/deployer/sprawl/consul.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sprawl - -import ( - "errors" - "fmt" - "time" - - "github.com/hashicorp/consul/api" - - "github.com/hashicorp/consul/testing/deployer/sprawl/internal/secrets" - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/consul/testing/deployer/util" -) - -func getLeader(client *api.Client) (string, error) { - leaderAdd, err := client.Status().Leader() - if err != nil { - return "", fmt.Errorf("could not query leader: %w", err) - } - if leaderAdd == "" { - return "", errors.New("no leader available") - } - return leaderAdd, nil -} - -func (s *Sprawl) waitForLeader(cluster *topology.Cluster) { - var ( - client = s.clients[cluster.Name] - logger = s.logger.With("cluster", cluster.Name) - ) - for { - leader, err := client.Status().Leader() - if leader != "" && err == nil { - logger.Info("cluster has leader", "leader_addr", leader) - return - } - logger.Info("cluster has no leader yet", "error", err) - time.Sleep(500 * time.Millisecond) - } -} - -func (s *Sprawl) rejoinAllConsulServers() error { - // Join the servers together. - for _, cluster := range s.topology.Clusters { - if err := s.rejoinServers(cluster); err != nil { - return fmt.Errorf("rejoinServers[%s]: %w", cluster.Name, err) - } - s.waitForLeader(cluster) - } - return nil -} - -func (s *Sprawl) rejoinServers(cluster *topology.Cluster) error { - var ( - // client = s.clients[cluster.Name] - logger = s.logger.With("cluster", cluster.Name) - ) - - servers := cluster.ServerNodes() - - recoveryToken := s.secrets.ReadGeneric(cluster.Name, secrets.AgentRecovery) - - node0, rest := servers[0], servers[1:] - client, err := util.ProxyNotPooledAPIClient( - node0.LocalProxyPort(), - node0.LocalAddress(), - 8500, - recoveryToken, - ) - if err != nil { - return fmt.Errorf("could not get client for %q: %w", node0.ID(), err) - } - - logger.Info("joining servers together", - "from", node0.ID(), - "rest", nodeSliceToNodeIDSlice(rest), - ) - for _, node := range rest { - for { - err = client.Agent().Join(node.LocalAddress(), false) - if err == nil { - break - } - logger.Warn("could not join", "from", node0.ID(), "to", node.ID(), "error", err) - time.Sleep(500 * time.Millisecond) - } - } - - return nil -} - -func nodeSliceToNodeIDSlice(nodes []*topology.Node) []topology.NodeID { - var out []topology.NodeID - for _, node := range nodes { - out = append(out, node.ID()) - } - return out -} diff --git a/testing/deployer/sprawl/debug.go b/testing/deployer/sprawl/debug.go deleted file mode 100644 index df11f96c3c8b6..0000000000000 --- a/testing/deployer/sprawl/debug.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sprawl - -import "encoding/json" - -func jd(v any) string { - b, _ := json.MarshalIndent(v, "", " ") - return string(b) -} diff --git a/testing/deployer/sprawl/details.go b/testing/deployer/sprawl/details.go deleted file mode 100644 index 1c896598b4a9d..0000000000000 --- a/testing/deployer/sprawl/details.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sprawl - -import ( - "bytes" - "fmt" - "sort" - "strconv" - "strings" - "text/tabwriter" -) - -// PrintDetails will dump relevant addressing and naming data to the logger for -// human interaction purposes. -func (s *Sprawl) PrintDetails() error { - det := logDetails{ - TopologyID: s.topology.ID, - } - - for _, cluster := range s.topology.Clusters { - client := s.clients[cluster.Name] - - cfg, err := client.Operator().RaftGetConfiguration(nil) - if err != nil { - return fmt.Errorf("could not get raft config for cluster %q: %w", cluster.Name, err) - } - - var leaderNode string - for _, svr := range cfg.Servers { - if svr.Leader { - leaderNode = strings.TrimSuffix(svr.Node, "-pod") - } - } - - cd := clusterDetails{ - Name: cluster.Name, - Leader: leaderNode, - } - - for _, node := range cluster.Nodes { - if node.Disabled { - continue - } - - var addrs []string - for _, addr := range node.Addresses { - addrs = append(addrs, addr.Network+"="+addr.IPAddress) - } - sort.Strings(addrs) - - if node.IsServer() { - cd.Apps = append(cd.Apps, appDetail{ - Type: "server", - Container: node.DockerName(), - Addresses: addrs, - ExposedPort: node.ExposedPort(8500), - }) - } - - for _, svc := range node.Services { - if svc.IsMeshGateway { - cd.Apps = append(cd.Apps, appDetail{ - Type: "mesh-gateway", - Container: node.DockerName(), - ExposedPort: node.ExposedPort(svc.Port), - ExposedEnvoyAdminPort: node.ExposedPort(svc.EnvoyAdminPort), - Addresses: addrs, - Service: svc.ID.String(), - }) - } else { - cd.Apps = append(cd.Apps, appDetail{ - Type: "app", - Container: node.DockerName(), - ExposedPort: node.ExposedPort(svc.Port), - ExposedEnvoyAdminPort: node.ExposedPort(svc.EnvoyAdminPort), - Addresses: addrs, - Service: svc.ID.String(), - }) - } - } - } - - det.Clusters = append(det.Clusters, cd) - } - - var buf bytes.Buffer - w := tabwriter.NewWriter(&buf, 0, 0, 3, ' ', tabwriter.Debug) - - score := map[string]int{ - "server": 0, - "mesh-gateway": 1, - "app": 2, - } - - for _, cluster := range det.Clusters { - fmt.Fprintf(w, "CLUSTER\tTYPE\tCONTAINER\tNAME\tADDRS\tPORTS\t\n") - sort.Slice(cluster.Apps, func(i, j int) bool { - a := cluster.Apps[i] - b := cluster.Apps[j] - - asc := score[a.Type] - bsc := score[b.Type] - - if asc < bsc { - return true - } else if asc > bsc { - return false - } - - if a.Container < b.Container { - return true - } else if a.Container > b.Container { - return false - } - - if a.Service < b.Service { - return true - } else if a.Service > b.Service { - return false - } - - return a.ExposedPort < b.ExposedPort - }) - for _, d := range cluster.Apps { - if d.Type == "server" && d.Container == cluster.Leader { - d.Type = "leader" - } - portStr := "app=" + strconv.Itoa(d.ExposedPort) - if d.ExposedEnvoyAdminPort > 0 { - portStr += " envoy=" + strconv.Itoa(d.ExposedEnvoyAdminPort) - } - fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t\n", - cluster.Name, - d.Type, - d.Container, - d.Service, - strings.Join(d.Addresses, ", "), - portStr, - ) - } - fmt.Fprintf(w, "\t\t\t\t\t\n") - } - - w.Flush() - - s.logger.Info("CURRENT SPRAWL DETAILS", "details", buf.String()) - - return nil -} - -type logDetails struct { - TopologyID string - Clusters []clusterDetails -} - -type clusterDetails struct { - Name string - - Leader string - Apps []appDetail -} - -type appDetail struct { - Type string // server|mesh-gateway|app - Container string - Addresses []string - ExposedPort int `json:",omitempty"` - ExposedEnvoyAdminPort int `json:",omitempty"` - // just services - Service string `json:",omitempty"` -} diff --git a/testing/deployer/sprawl/ent.go b/testing/deployer/sprawl/ent.go deleted file mode 100644 index 8ec2925ef1638..0000000000000 --- a/testing/deployer/sprawl/ent.go +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sprawl - -import ( - "bytes" - "context" - "fmt" - "os" - "strings" - "time" - - "github.com/hashicorp/consul/api" - - "github.com/hashicorp/consul/testing/deployer/topology" -) - -func (s *Sprawl) ensureLicense() error { - if s.license != "" { - return nil - } - v, err := readLicense() - if err != nil { - return err - } - s.license = v - return nil -} - -func readLicense() (string, error) { - if license := os.Getenv("CONSUL_LICENSE"); license != "" { - return license, nil - } - - licensePath := os.Getenv("CONSUL_LICENSE_PATH") - if licensePath == "" { - return "", nil - } - - licenseBytes, err := os.ReadFile(licensePath) - if err != nil { - return "", err - } - return strings.TrimSpace(string(licenseBytes)), nil -} - -func (s *Sprawl) initTenancies(cluster *topology.Cluster) error { - var ( - client = s.clients[cluster.Name] - logger = s.logger.With("cluster", cluster.Name) - ) - - // TODO: change this to UPSERT - - var ( - partClient = client.Partitions() - nsClient = client.Namespaces() - - partitionNameList []string - ) - for _, ap := range cluster.Partitions { - if ap.Name != "default" { - old, _, err := partClient.Read(context.Background(), ap.Name, nil) - if err != nil { - return fmt.Errorf("error reading partition %q: %w", ap.Name, err) - } - if old == nil { - obj := &api.Partition{ - Name: ap.Name, - } - - _, _, err := partClient.Create(context.Background(), obj, nil) - if err != nil { - return fmt.Errorf("error creating partition %q: %w", ap.Name, err) - } - logger.Info("created partition", "partition", ap.Name) - } - - partitionNameList = append(partitionNameList, ap.Name) - } - - if err := s.createCrossNamespaceCatalogReadPolicies(cluster, ap.Name); err != nil { - return fmt.Errorf("createCrossNamespaceCatalogReadPolicies[%s]: %w", ap.Name, err) - } - - for _, ns := range ap.Namespaces { - old, _, err := nsClient.Read(ns, &api.QueryOptions{Partition: ap.Name}) - if err != nil { - return err - } - - if old == nil { - obj := &api.Namespace{ - Partition: ap.Name, - Name: ns, - ACLs: &api.NamespaceACLConfig{ - PolicyDefaults: []api.ACLLink{ - {Name: "cross-ns-catalog-read"}, - }, - }, - } - if ns == "default" { - _, _, err := nsClient.Update(obj, nil) - if err != nil { - return err - } - logger.Info("updated namespace", "namespace", ns, "partition", ap.Name) - } else { - _, _, err := nsClient.Create(obj, nil) - if err != nil { - return err - } - logger.Info("created namespace", "namespace", ns, "partition", ap.Name) - } - } - } - } - - if err := s.waitUntilPartitionedSerfIsReady(context.TODO(), cluster, partitionNameList); err != nil { - return fmt.Errorf("waitUntilPartitionedSerfIsReady: %w", err) - } - - return nil -} - -func (s *Sprawl) waitUntilPartitionedSerfIsReady(ctx context.Context, cluster *topology.Cluster, partitions []string) error { - var ( - logger = s.logger.With("cluster", cluster.Name) - ) - - readyLogs := make(map[string]string) - for _, partition := range partitions { - readyLogs[partition] = `agent.server: Added serf partition to gossip network: partition=` + partition - } - - start := time.Now() - logger.Info("waiting for partitioned serf to be ready on all servers", "partitions", partitions) - for _, node := range cluster.Nodes { - if !node.IsServer() || node.Disabled { - continue - } - - var buf bytes.Buffer - for { - buf.Reset() - - err := s.runner.DockerExec(ctx, []string{ - "logs", node.DockerName(), - }, &buf, nil) - if err != nil { - return fmt.Errorf("could not fetch docker logs from node %q: %w", node.ID(), err) - } - - var ( - body = buf.String() - found []string - ) - - for partition, readyLog := range readyLogs { - if strings.Contains(body, readyLog) { - found = append(found, partition) - } - } - - if len(found) == len(readyLogs) { - break - } - } - - time.Sleep(500 * time.Millisecond) - } - - logger.Info("partitioned serf is ready on all servers", "partitions", partitions, "elapsed", time.Since(start)) - - return nil -} diff --git a/testing/deployer/sprawl/helpers.go b/testing/deployer/sprawl/helpers.go deleted file mode 100644 index 941311a1c1183..0000000000000 --- a/testing/deployer/sprawl/helpers.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sprawl - -// Deprecated: remove -func TruncateSquidError(err error) error { - return err -} - -// Deprecated: remove -func IsSquid503(err error) bool { - return false -} diff --git a/testing/deployer/sprawl/internal/build/docker.go b/testing/deployer/sprawl/internal/build/docker.go deleted file mode 100644 index 7007d44c844ae..0000000000000 --- a/testing/deployer/sprawl/internal/build/docker.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package build - -import ( - "context" - "strings" - - "github.com/hashicorp/go-hclog" - - "github.com/hashicorp/consul/testing/deployer/sprawl/internal/runner" - "github.com/hashicorp/consul/testing/deployer/topology" -) - -const dockerfileEnvoy = ` -ARG CONSUL_IMAGE -ARG ENVOY_IMAGE -FROM ${CONSUL_IMAGE} -FROM ${ENVOY_IMAGE} -COPY --from=0 /bin/consul /bin/consul -` - -// FROM hashicorp/consul-dataplane:latest -// COPY --from=busybox:uclibc /bin/sh /bin/sh -const dockerfileDataplane = ` -ARG DATAPLANE_IMAGE -FROM busybox:latest -FROM ${DATAPLANE_IMAGE} -COPY --from=0 /bin/busybox /bin/busybox -USER 0:0 -RUN ["busybox", "--install", "/bin", "-s"] -USER 100:0 -ENTRYPOINT [] -` - -func DockerImages( - logger hclog.Logger, - run *runner.Runner, - t *topology.Topology, -) error { - logw := logger.Named("docker").StandardWriter(&hclog.StandardLoggerOptions{ForceLevel: hclog.Info}) - - built := make(map[string]struct{}) - for _, c := range t.Clusters { - for _, n := range c.Nodes { - joint := n.Images.EnvoyConsulImage() - if _, ok := built[joint]; joint != "" && !ok { - logger.Info("building image", "image", joint) - err := run.DockerExec(context.TODO(), []string{ - "build", - "--build-arg", - "CONSUL_IMAGE=" + n.Images.Consul, - "--build-arg", - "ENVOY_IMAGE=" + n.Images.Envoy, - "-t", joint, - "-", - }, logw, strings.NewReader(dockerfileEnvoy)) - if err != nil { - return err - } - - built[joint] = struct{}{} - } - - cdp := n.Images.LocalDataplaneImage() - if _, ok := built[cdp]; cdp != "" && !ok { - logger.Info("building image", "image", cdp) - err := run.DockerExec(context.TODO(), []string{ - "build", - "--build-arg", - "DATAPLANE_IMAGE=" + n.Images.Dataplane, - "-t", cdp, - "-", - }, logw, strings.NewReader(dockerfileDataplane)) - if err != nil { - return err - } - - built[cdp] = struct{}{} - } - } - } - - return nil -} diff --git a/testing/deployer/sprawl/internal/runner/exec.go b/testing/deployer/sprawl/internal/runner/exec.go deleted file mode 100644 index 1c2a8a1d311b4..0000000000000 --- a/testing/deployer/sprawl/internal/runner/exec.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package runner - -import ( - "bytes" - "context" - "errors" - "fmt" - "io" - "os" - "os/exec" - - "github.com/hashicorp/go-hclog" -) - -type Runner struct { - logger hclog.Logger - - tfBin string - dockerBin string -} - -func Load(logger hclog.Logger) (*Runner, error) { - r := &Runner{ - logger: logger, - } - - type item struct { - name string - dest *string - warn string // optional - } - lookup := []item{ - {"docker", &r.dockerBin, ""}, - {"terraform", &r.tfBin, ""}, - } - - var ( - bins []string - err error - ) - for _, i := range lookup { - *i.dest, err = exec.LookPath(i.name) - if err != nil { - if errors.Is(err, exec.ErrNotFound) { - if i.warn != "" { - return nil, fmt.Errorf("Could not find %q on path (%s): %w", i.name, i.warn, err) - } else { - return nil, fmt.Errorf("Could not find %q on path: %w", i.name, err) - } - } - return nil, fmt.Errorf("Unexpected failure looking for %q on path: %w", i.name, err) - } - bins = append(bins, *i.dest) - } - r.logger.Trace("using binaries", "paths", bins) - - return r, nil -} - -func (r *Runner) DockerExec(ctx context.Context, args []string, stdout io.Writer, stdin io.Reader) error { - return cmdExec(ctx, "docker", r.dockerBin, args, stdout, nil, stdin, "") -} - -func (r *Runner) DockerExecWithStderr(ctx context.Context, args []string, stdout, stderr io.Writer, stdin io.Reader) error { - return cmdExec(ctx, "docker", r.dockerBin, args, stdout, stderr, stdin, "") -} - -func (r *Runner) TerraformExec(ctx context.Context, args []string, stdout io.Writer, workdir string) error { - return cmdExec(ctx, "terraform", r.tfBin, args, stdout, nil, nil, workdir) -} - -func cmdExec(ctx context.Context, name, binary string, args []string, stdout, stderr io.Writer, stdin io.Reader, dir string) error { - if binary == "" { - panic("binary named " + name + " was not detected") - } - var errWriter bytes.Buffer - - if stdout == nil { - stdout = os.Stdout // TODO: wrap logs - } - - cmd := exec.CommandContext(ctx, binary, args...) - if dir != "" { - cmd.Dir = dir - } - cmd.Stdout = stdout - cmd.Stderr = &errWriter - if stderr != nil { - cmd.Stderr = io.MultiWriter(stderr, cmd.Stderr) - } - cmd.Stdin = stdin - if err := cmd.Run(); err != nil { - return &ExecError{ - BinaryName: name, - Err: err, - ErrorOutput: errWriter.String(), - } - } - - return nil -} - -type ExecError struct { - BinaryName string - ErrorOutput string - Err error -} - -func (e *ExecError) Unwrap() error { - return e.Err -} - -func (e *ExecError) Error() string { - return fmt.Sprintf( - "could not invoke %q: %v : %s", - e.BinaryName, - e.Err, - e.ErrorOutput, - ) -} diff --git a/testing/deployer/sprawl/internal/secrets/store.go b/testing/deployer/sprawl/internal/secrets/store.go deleted file mode 100644 index 0cacf88b256eb..0000000000000 --- a/testing/deployer/sprawl/internal/secrets/store.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package secrets - -import ( - "net/url" - "strings" - - "github.com/hashicorp/consul/testing/deployer/topology" -) - -type Store struct { - m map[string]string -} - -const ( - GossipKey = "gossip" - BootstrapToken = "bootstrap-token" - AgentRecovery = "agent-recovery" -) - -func (s *Store) SaveGeneric(cluster, name, value string) { - s.save(encode(cluster, "generic", name), value) -} - -func (s *Store) ReadGeneric(cluster, name string) string { - return s.read(encode(cluster, "generic", name)) -} - -func (s *Store) SaveAgentToken(cluster string, nid topology.NodeID, value string) { - s.save(encode(cluster, "agent", nid.String()), value) -} - -func (s *Store) ReadAgentToken(cluster string, nid topology.NodeID) string { - return s.read(encode(cluster, "agent", nid.String())) -} - -func (s *Store) SaveServiceToken(cluster string, sid topology.ServiceID, value string) { - s.save(encode(cluster, "service", sid.String()), value) -} - -func (s *Store) ReadServiceToken(cluster string, sid topology.ServiceID) string { - return s.read(encode(cluster, "service", sid.String())) -} - -func (s *Store) save(key, value string) { - if s.m == nil { - s.m = make(map[string]string) - } - - s.m[key] = value -} - -func (s *Store) read(key string) string { - if s.m == nil { - return "" - } - - v, ok := s.m[key] - if !ok { - return "" - } - return v -} - -func encode(parts ...string) string { - var out []string - for _, p := range parts { - out = append(out, url.QueryEscape(p)) - } - return strings.Join(out, "/") -} diff --git a/testing/deployer/sprawl/internal/tfgen/agent.go b/testing/deployer/sprawl/internal/tfgen/agent.go deleted file mode 100644 index d884d200d2e92..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/agent.go +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tfgen - -import ( - "fmt" - "strings" - - "github.com/hashicorp/hcl/v2/hclwrite" - - "github.com/hashicorp/consul/testing/deployer/sprawl/internal/secrets" - "github.com/hashicorp/consul/testing/deployer/topology" -) - -func (g *Generator) generateAgentHCL(node *topology.Node) (string, error) { - if !node.IsAgent() { - return "", fmt.Errorf("not an agent") - } - - cluster, ok := g.topology.Clusters[node.Cluster] - if !ok { - return "", fmt.Errorf("no such cluster: %s", node.Cluster) - } - - var b HCLBuilder - - b.add("server", node.IsServer()) - b.add("bind_addr", "0.0.0.0") - b.add("client_addr", "0.0.0.0") - b.add("advertise_addr", `{{ GetInterfaceIP "eth0" }}`) - b.add("datacenter", node.Datacenter) - b.add("disable_update_check", true) - b.add("log_level", "trace") - b.add("enable_debug", true) - b.add("use_streaming_backend", true) - - // speed up leaves - b.addBlock("performance", func() { - b.add("leave_drain_time", "50ms") - }) - - b.add("primary_datacenter", node.Datacenter) - - // Using retry_join here is bad because changing server membership will - // destroy and recreate all of the servers - // if !node.IsServer() { - b.addSlice("retry_join", []string{"server." + node.Cluster + "-consulcluster.lan"}) - b.add("retry_interval", "1s") - // } - - if node.IsServer() { - b.addBlock("peering", func() { - b.add("enabled", true) - }) - } - - b.addBlock("ui_config", func() { - b.add("enabled", true) - }) - - b.addBlock("telemetry", func() { - b.add("disable_hostname", true) - b.add("prometheus_retention_time", "168h") - }) - - b.add("encrypt", g.sec.ReadGeneric(node.Cluster, secrets.GossipKey)) - - { - var ( - root = "/consul/config/certs" - caFile = root + "/consul-agent-ca.pem" - certFile = root + "/" + node.TLSCertPrefix + ".pem" - certKey = root + "/" + node.TLSCertPrefix + "-key.pem" - ) - - b.addBlock("tls", func() { - b.addBlock("internal_rpc", func() { - b.add("ca_file", caFile) - b.add("cert_file", certFile) - b.add("key_file", certKey) - b.add("verify_incoming", true) - b.add("verify_server_hostname", true) - b.add("verify_outgoing", true) - }) - // if cfg.EncryptionTLSAPI { - // b.addBlock("https", func() { - // b.add("ca_file", caFile) - // b.add("cert_file", certFile) - // b.add("key_file", certKey) - // // b.add("verify_incoming", true) - // }) - // } - if node.IsServer() { - b.addBlock("grpc", func() { - b.add("ca_file", caFile) - b.add("cert_file", certFile) - b.add("key_file", certKey) - // b.add("verify_incoming", true) - }) - } - }) - } - - b.addBlock("ports", func() { - if node.IsServer() { - b.add("grpc_tls", 8503) - b.add("grpc", -1) - } else { - b.add("grpc", 8502) - b.add("grpc_tls", -1) - } - b.add("http", 8500) - b.add("dns", 8600) - }) - - b.addSlice("recursors", []string{"8.8.8.8"}) - - b.addBlock("acl", func() { - b.add("enabled", true) - b.add("default_policy", "deny") - b.add("down_policy", "extend-cache") - b.add("enable_token_persistence", true) - b.addBlock("tokens", func() { - if node.IsServer() { - b.add("initial_management", g.sec.ReadGeneric(node.Cluster, secrets.BootstrapToken)) - } - b.add("agent_recovery", g.sec.ReadGeneric(node.Cluster, secrets.AgentRecovery)) - b.add("agent", g.sec.ReadAgentToken(node.Cluster, node.ID())) - }) - }) - - if node.IsServer() { - b.add("bootstrap_expect", len(cluster.ServerNodes())) - // b.add("translate_wan_addrs", true) - b.addBlock("rpc", func() { - b.add("enable_streaming", true) - }) - if node.HasPublicAddress() { - b.add("advertise_addr_wan", `{{ GetInterfaceIP "eth1" }}`) // note: can't use 'node.PublicAddress()' b/c we don't know that yet - } - - // Exercise config entry bootstrap - // b.addBlock("config_entries", func() { - // b.addBlock("bootstrap", func() { - // b.add("kind", "service-defaults") - // b.add("name", "placeholder") - // b.add("protocol", "grpc") - // }) - // b.addBlock("bootstrap", func() { - // b.add("kind", "service-intentions") - // b.add("name", "placeholder") - // b.addBlock("sources", func() { - // b.add("name", "placeholder-client") - // b.add("action", "allow") - // }) - // }) - // }) - - b.addBlock("connect", func() { - b.add("enabled", true) - }) - - } else { - if cluster.Enterprise { - b.add("partition", node.Partition) - } - } - - return b.String(), nil -} - -type HCLBuilder struct { - parts []string -} - -func (b *HCLBuilder) format(s string, a ...any) { - if len(a) == 0 { - b.parts = append(b.parts, s) - } else { - b.parts = append(b.parts, fmt.Sprintf(s, a...)) - } -} - -func (b *HCLBuilder) add(k string, v any) { - switch x := v.(type) { - case string: - if x != "" { - b.format("%s = %q", k, x) - } - case int: - b.format("%s = %d", k, x) - case bool: - b.format("%s = %v", k, x) - default: - panic(fmt.Sprintf("unexpected type %T", v)) - } -} - -func (b *HCLBuilder) addBlock(block string, fn func()) { - b.format(block + "{") - fn() - b.format("}") -} - -func (b *HCLBuilder) addSlice(name string, vals []string) { - b.format(name + " = [") - for _, v := range vals { - b.format("%q,", v) - } - b.format("]") -} - -func (b *HCLBuilder) String() string { - joined := strings.Join(b.parts, "\n") - // Ensure it looks tidy - return string(hclwrite.Format([]byte(joined))) -} diff --git a/testing/deployer/sprawl/internal/tfgen/digest.go b/testing/deployer/sprawl/internal/tfgen/digest.go deleted file mode 100644 index e840f91ee67b5..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/digest.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tfgen - -import ( - "fmt" -) - -// digestOutputs takes the data extracted from terraform output variables and -// updates various fields on the topology.Topology with that data. -func (g *Generator) digestOutputs(out *Outputs) error { - for clusterName, nodeMap := range out.Nodes { - cluster, ok := g.topology.Clusters[clusterName] - if !ok { - return fmt.Errorf("found output cluster that does not exist: %s", clusterName) - } - for nid, nodeOut := range nodeMap { - node := cluster.NodeByID(nid) - if node == nil { - return fmt.Errorf("found output node that does not exist in cluster %q: %s", nid, clusterName) - } - - if node.DigestExposedPorts(nodeOut.Ports) { - g.logger.Info("discovered exposed port mappings", - "cluster", clusterName, - "node", nid.String(), - "ports", nodeOut.Ports, - ) - } - } - } - - for netName, proxyPort := range out.ProxyPorts { - changed, err := g.topology.DigestExposedProxyPort(netName, proxyPort) - if err != nil { - return err - } - if changed { - g.logger.Info("discovered exposed forward proxy port", - "network", netName, - "port", proxyPort, - ) - } - } - - return nil -} diff --git a/testing/deployer/sprawl/internal/tfgen/dns.go b/testing/deployer/sprawl/internal/tfgen/dns.go deleted file mode 100644 index 6c3e5ca624696..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/dns.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tfgen - -import ( - "bytes" - "fmt" - "os" - "path/filepath" - "strings" - "text/template" - - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/consul/testing/deployer/util" -) - -func (g *Generator) getCoreDNSContainer( - net *topology.Network, - ipAddress string, - hashes []string, -) Resource { - var env []string - for i, hv := range hashes { - env = append(env, fmt.Sprintf("HASH_FILE_%d_VALUE=%s", i, hv)) - } - coredns := struct { - Name string - DockerNetworkName string - IPAddress string - HashValues string - Env []string - }{ - Name: net.Name, - DockerNetworkName: net.DockerName, - IPAddress: ipAddress, - Env: env, - } - return Eval(tfCorednsT, &coredns) -} - -func (g *Generator) writeCoreDNSFiles(net *topology.Network, dnsIPAddress string) (bool, []string, error) { - if net.IsPublic() { - return false, nil, fmt.Errorf("coredns only runs on local networks") - } - - rootdir := filepath.Join(g.workdir, "terraform", "coredns-config-"+net.Name) - if err := os.MkdirAll(rootdir, 0755); err != nil { - return false, nil, err - } - - for _, cluster := range g.topology.Clusters { - if cluster.NetworkName != net.Name { - continue - } - var addrs []string - for _, node := range cluster.SortedNodes() { - if node.Kind != topology.NodeKindServer || node.Disabled { - continue - } - addr := node.AddressByNetwork(net.Name) - if addr.IPAddress != "" { - addrs = append(addrs, addr.IPAddress) - } - } - - var ( - clusterDNSName = cluster.Name + "-consulcluster.lan" - ) - - corefilePath := filepath.Join(rootdir, "Corefile") - zonefilePath := filepath.Join(rootdir, "servers") - - _, err := UpdateFileIfDifferent( - g.logger, - generateCoreDNSConfigFile( - clusterDNSName, - addrs, - ), - corefilePath, - 0644, - ) - if err != nil { - return false, nil, fmt.Errorf("error writing %q: %w", corefilePath, err) - } - corefileHash, err := util.HashFile(corefilePath) - if err != nil { - return false, nil, fmt.Errorf("error hashing %q: %w", corefilePath, err) - } - - _, err = UpdateFileIfDifferent( - g.logger, - generateCoreDNSZoneFile( - dnsIPAddress, - clusterDNSName, - addrs, - ), - zonefilePath, - 0644, - ) - if err != nil { - return false, nil, fmt.Errorf("error writing %q: %w", zonefilePath, err) - } - zonefileHash, err := util.HashFile(zonefilePath) - if err != nil { - return false, nil, fmt.Errorf("error hashing %q: %w", zonefilePath, err) - } - - return true, []string{corefileHash, zonefileHash}, nil - } - - return false, nil, nil -} - -func generateCoreDNSConfigFile( - clusterDNSName string, - addrs []string, -) []byte { - serverPart := "" - if len(addrs) > 0 { - var servers []string - for _, addr := range addrs { - servers = append(servers, addr+":8600") - } - serverPart = fmt.Sprintf(` -consul:53 { - forward . %s - log - errors - whoami -} -`, strings.Join(servers, " ")) - } - - return []byte(fmt.Sprintf(` -%[1]s:53 { - file /config/servers %[1]s - log - errors - whoami -} - -%[2]s - -.:53 { - forward . 8.8.8.8:53 - log - errors - whoami -} -`, clusterDNSName, serverPart)) -} - -func generateCoreDNSZoneFile( - dnsIPAddress string, - clusterDNSName string, - addrs []string, -) []byte { - var buf bytes.Buffer - buf.WriteString(fmt.Sprintf(` -$TTL 60 -$ORIGIN %[1]s. -@ IN SOA ns.%[1]s. webmaster.%[1]s. ( - 2017042745 ; serial - 7200 ; refresh (2 hours) - 3600 ; retry (1 hour) - 1209600 ; expire (2 weeks) - 3600 ; minimum (1 hour) - ) -@ IN NS ns.%[1]s. ; Name server -ns IN A %[2]s ; self -`, clusterDNSName, dnsIPAddress)) - - for _, addr := range addrs { - buf.WriteString(fmt.Sprintf(` -server IN A %s ; Consul server -`, addr)) - } - - return buf.Bytes() -} - -var tfCorednsT = template.Must(template.ParseFS(content, "templates/container-coredns.tf.tmpl")) diff --git a/testing/deployer/sprawl/internal/tfgen/docker.go b/testing/deployer/sprawl/internal/tfgen/docker.go deleted file mode 100644 index bc8bd657563df..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/docker.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tfgen - -import ( - "fmt" - "regexp" -) - -var invalidResourceName = regexp.MustCompile(`[^a-z0-9-]+`) - -func DockerImageResourceName(image string) string { - return invalidResourceName.ReplaceAllLiteralString(image, "-") -} - -func DockerNetwork(name, subnet string) Resource { - return Text(fmt.Sprintf(` -resource "docker_network" %[1]q { - name = %[1]q - attachable = true - ipam_config { - subnet = %[2]q - } -} -`, name, subnet)) -} - -func DockerVolume(name string) Resource { - return Text(fmt.Sprintf(` -resource "docker_volume" %[1]q { - name = %[1]q -}`, name)) -} - -func DockerImage(name, image string) Resource { - return Text(fmt.Sprintf(` -resource "docker_image" %[1]q { - name = %[2]q - keep_locally = true -}`, name, image)) -} diff --git a/testing/deployer/sprawl/internal/tfgen/docker_test.go b/testing/deployer/sprawl/internal/tfgen/docker_test.go deleted file mode 100644 index 942b87189fca5..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/docker_test.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tfgen - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestDockerImageResourceName(t *testing.T) { - fn := DockerImageResourceName - - assert.Equal(t, "", fn("")) - assert.Equal(t, "abcdefghijklmnopqrstuvwxyz0123456789-", fn("abcdefghijklmnopqrstuvwxyz0123456789-")) - assert.Equal(t, "hashicorp-consul-1-15-0", fn("hashicorp/consul:1.15.0")) -} diff --git a/testing/deployer/sprawl/internal/tfgen/gen.go b/testing/deployer/sprawl/internal/tfgen/gen.go deleted file mode 100644 index b576f2c93e59a..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/gen.go +++ /dev/null @@ -1,478 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tfgen - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/hashicorp/go-hclog" - - "github.com/hashicorp/consul/testing/deployer/sprawl/internal/runner" - "github.com/hashicorp/consul/testing/deployer/sprawl/internal/secrets" - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/consul/testing/deployer/util" -) - -type Generator struct { - logger hclog.Logger - runner *runner.Runner - topology *topology.Topology - sec *secrets.Store - workdir string - license string - - tfLogger io.Writer - - // set during network phase - remainingSubnets map[string]struct{} - - launched bool -} - -func NewGenerator( - logger hclog.Logger, - runner *runner.Runner, - topo *topology.Topology, - sec *secrets.Store, - workdir string, - license string, -) (*Generator, error) { - if logger == nil { - panic("logger is required") - } - if runner == nil { - panic("runner is required") - } - if topo == nil { - panic("topology is required") - } - if sec == nil { - panic("secrets store is required") - } - if workdir == "" { - panic("workdir is required") - } - - g := &Generator{ - logger: logger, - runner: runner, - sec: sec, - workdir: workdir, - license: license, - - tfLogger: logger.Named("terraform").StandardWriter(&hclog.StandardLoggerOptions{ - ForceLevel: hclog.Info, - }), - } - g.SetTopology(topo) - - _ = g.terraformDestroy(context.Background(), true) // cleanup prior run - - return g, nil -} - -func (g *Generator) MarkLaunched() { - g.launched = true -} - -func (g *Generator) SetTopology(topo *topology.Topology) { - if topo == nil { - panic("topology is required") - } - g.topology = topo -} - -type Step int - -const ( - StepAll Step = 0 - StepNetworks Step = 1 - StepServers Step = 2 - StepAgents Step = 3 - StepServices Step = 4 - // StepPeering Step = XXX5 - StepRelaunch Step = 5 -) - -func (s Step) String() string { - switch s { - case StepAll: - return "all" - case StepNetworks: - return "networks" - case StepServers: - return "servers" - case StepAgents: - return "agents" - case StepServices: - return "services" - case StepRelaunch: - return "relaunch" - // case StepPeering: - // return "peering" - default: - return "UNKNOWN--" + strconv.Itoa(int(s)) - } -} - -func (s Step) StartServers() bool { return s >= StepServers } -func (s Step) StartAgents() bool { return s >= StepAgents } -func (s Step) StartServices() bool { return s >= StepServices } - -// func (s Step) InitiatePeering() bool { return s >= StepPeering } - -func (g *Generator) Regenerate() error { - return g.Generate(StepRelaunch) -} - -func (g *Generator) Generate(step Step) error { - if g.launched && step != StepRelaunch { - return fmt.Errorf("cannot use step %q after successful launch; see Regenerate()", step) - } - - g.logger.Info("generating and creating resources", "step", step.String()) - var ( - networks []Resource - volumes []Resource - images []Resource - containers []Resource - - imageNames = make(map[string]string) - ) - - addVolume := func(name string) { - volumes = append(volumes, DockerVolume(name)) - } - addImage := func(name, image string) { - if image == "" { - return - } - if _, ok := imageNames[image]; ok { - return - } - - if name == "" { - name = DockerImageResourceName(image) - } - - imageNames[image] = name - - g.logger.Info("registering image", "resource", name, "image", image) - - images = append(images, DockerImage(name, image)) - } - - if g.remainingSubnets == nil { - g.remainingSubnets = util.GetPossibleDockerNetworkSubnets() - } - if len(g.remainingSubnets) == 0 { - return fmt.Errorf("exhausted all docker networks") - } - - addImage("nginx", "nginx:latest") - addImage("coredns", "coredns/coredns:latest") - for _, net := range g.topology.SortedNetworks() { - if net.Subnet == "" { - // Because this harness runs on a linux or macos host, we can't - // directly invoke the moby libnetwork calls to check for free - // subnets as it would have to cross into the docker desktop vm on - // mac. - // - // Instead rely on map iteration order being random to avoid - // collisions, but detect the terraform failure and retry until - // success. - - var ipnet string - for ipnet = range g.remainingSubnets { - } - if ipnet == "" { - return fmt.Errorf("could not get a free docker network") - } - delete(g.remainingSubnets, ipnet) - - if _, err := net.SetSubnet(ipnet); err != nil { - return fmt.Errorf("assigned subnet is invalid %q: %w", ipnet, err) - } - } - networks = append(networks, DockerNetwork(net.DockerName, net.Subnet)) - - var ( - // We always ask for a /24, so just blindly pick x.x.x.252 as our - // proxy address. There's an offset of 2 in the list of available - // addresses here because we removed x.x.x.0 and x.x.x.1 from the - // pool. - proxyIPAddress = net.IPByIndex(250) - // Grab x.x.x.253 for the dns server - dnsIPAddress = net.IPByIndex(251) - ) - - { - // wrote, hashes, err := g.write - } - - { // nginx forward proxy - _, hash, err := g.writeNginxConfig(net) - if err != nil { - return fmt.Errorf("writeNginxConfig[%s]: %w", net.Name, err) - } - - containers = append(containers, g.getForwardProxyContainer(net, proxyIPAddress, hash)) - - } - - net.ProxyAddress = proxyIPAddress - net.DNSAddress = "" - - if net.IsLocal() { - wrote, hashes, err := g.writeCoreDNSFiles(net, dnsIPAddress) - if err != nil { - return fmt.Errorf("writeCoreDNSFiles[%s]: %w", net.Name, err) - } - if wrote { - net.DNSAddress = dnsIPAddress - containers = append(containers, g.getCoreDNSContainer(net, dnsIPAddress, hashes)) - } - } - } - - for _, c := range g.topology.SortedClusters() { - if c.TLSVolumeName == "" { - c.TLSVolumeName = c.Name + "-tls-material-" + g.topology.ID - } - addVolume(c.TLSVolumeName) - } - - addImage("pause", "registry.k8s.io/pause:3.3") - - if step.StartServers() { - for _, c := range g.topology.SortedClusters() { - for _, node := range c.SortedNodes() { - if node.Disabled { - continue - } - addImage("", node.Images.Consul) - addImage("", node.Images.EnvoyConsulImage()) - addImage("", node.Images.LocalDataplaneImage()) - - if node.IsAgent() { - addVolume(node.DockerName()) - } - - for _, svc := range node.Services { - addImage("", svc.Image) - } - - myContainers, err := g.generateNodeContainers(step, c, node) - if err != nil { - return err - } - - containers = append(containers, myContainers...) - } - } - } - - tfpath := func(p string) string { - return filepath.Join(g.workdir, "terraform", p) - } - - if _, err := WriteHCLResourceFile(g.logger, []Resource{Text(terraformPrelude)}, tfpath("init.tf"), 0644); err != nil { - return err - } - if netResult, err := WriteHCLResourceFile(g.logger, networks, tfpath("networks.tf"), 0644); err != nil { - return err - } else if netResult == UpdateResultModified { - if step != StepNetworks { - return fmt.Errorf("cannot change networking details after they are established") - } - } - if _, err := WriteHCLResourceFile(g.logger, volumes, tfpath("volumes.tf"), 0644); err != nil { - return err - } - if _, err := WriteHCLResourceFile(g.logger, images, tfpath("images.tf"), 0644); err != nil { - return err - } - if _, err := WriteHCLResourceFile(g.logger, containers, tfpath("containers.tf"), 0644); err != nil { - return err - } - - if err := g.terraformApply(context.TODO()); err != nil { - return err - } - - out, err := g.terraformOutputs(context.TODO()) - if err != nil { - return err - } - - return g.digestOutputs(out) -} - -func (g *Generator) DestroyAll() error { - return g.terraformDestroy(context.TODO(), false) -} - -func (g *Generator) DestroyAllQuietly() error { - return g.terraformDestroy(context.TODO(), true) -} - -func (g *Generator) terraformApply(ctx context.Context) error { - tfdir := filepath.Join(g.workdir, "terraform") - - if _, err := os.Stat(filepath.Join(tfdir, ".terraform")); err != nil { - if !os.IsNotExist(err) { - return err - } - - // On the fly init - g.logger.Info("Running 'terraform init'...") - if err := g.runner.TerraformExec(ctx, []string{"init", "-input=false"}, g.tfLogger, tfdir); err != nil { - return err - } - } - - g.logger.Info("Running 'terraform apply'...") - return g.runner.TerraformExec(ctx, []string{"apply", "-input=false", "-auto-approve"}, g.tfLogger, tfdir) -} - -func (g *Generator) terraformDestroy(ctx context.Context, quiet bool) error { - g.logger.Info("Running 'terraform destroy'...") - - var out io.Writer - if quiet { - out = io.Discard - } else { - out = g.tfLogger - } - - tfdir := filepath.Join(g.workdir, "terraform") - return g.runner.TerraformExec(ctx, []string{ - "destroy", "-input=false", "-auto-approve", "-refresh=false", - }, out, tfdir) -} - -func (g *Generator) terraformOutputs(ctx context.Context) (*Outputs, error) { - tfdir := filepath.Join(g.workdir, "terraform") - - var buf bytes.Buffer - err := g.runner.TerraformExec(ctx, []string{ - "output", "-json", - }, &buf, tfdir) - if err != nil { - return nil, err - } - - type outputVar struct { - // may be map[string]any - Value any `json:"value"` - } - - raw := make(map[string]*outputVar) - dec := json.NewDecoder(&buf) - if err := dec.Decode(&raw); err != nil { - return nil, err - } - - out := &Outputs{} - - for key, rv := range raw { - switch { - case strings.HasPrefix(key, "ports_"): - cluster, nid, ok := extractNodeOutputKey("ports_", key) - if !ok { - return nil, fmt.Errorf("unexpected output var: %s", key) - } - - ports := make(map[int]int) - for k, v := range rv.Value.(map[string]any) { - ki, err := strconv.Atoi(k) - if err != nil { - return nil, fmt.Errorf("unexpected port value %q: %w", k, err) - } - ports[ki] = int(v.(float64)) - } - out.SetNodePorts(cluster, nid, ports) - case strings.HasPrefix(key, "forwardproxyport_"): - netname := strings.TrimPrefix(key, "forwardproxyport_") - - found := rv.Value.(map[string]any) - if len(found) != 1 { - return nil, fmt.Errorf("found unexpected ports: %v", found) - } - got, ok := found[strconv.Itoa(proxyInternalPort)] - if !ok { - return nil, fmt.Errorf("found unexpected ports: %v", found) - } - - out.SetProxyPort(netname, int(got.(float64))) - } - } - - return out, nil -} - -func extractNodeOutputKey(prefix, key string) (string, topology.NodeID, bool) { - clusterNode := strings.TrimPrefix(key, prefix) - - cluster, nodeid, ok := strings.Cut(clusterNode, "_") - if !ok { - return "", topology.NodeID{}, false - } - - partition, node, ok := strings.Cut(nodeid, "_") - if !ok { - return "", topology.NodeID{}, false - } - - nid := topology.NewNodeID(node, partition) - return cluster, nid, true -} - -type Outputs struct { - ProxyPorts map[string]int // net -> exposed port - Nodes map[string]map[topology.NodeID]*NodeOutput // clusterID -> node -> stuff -} - -func (o *Outputs) SetNodePorts(cluster string, nid topology.NodeID, ports map[int]int) { - nodeOut := o.getNode(cluster, nid) - nodeOut.Ports = ports -} - -func (o *Outputs) SetProxyPort(net string, port int) { - if o.ProxyPorts == nil { - o.ProxyPorts = make(map[string]int) - } - o.ProxyPorts[net] = port -} - -func (o *Outputs) getNode(cluster string, nid topology.NodeID) *NodeOutput { - if o.Nodes == nil { - o.Nodes = make(map[string]map[topology.NodeID]*NodeOutput) - } - cnodes, ok := o.Nodes[cluster] - if !ok { - cnodes = make(map[topology.NodeID]*NodeOutput) - o.Nodes[cluster] = cnodes - } - - nodeOut, ok := cnodes[nid] - if !ok { - nodeOut = &NodeOutput{} - cnodes[nid] = nodeOut - } - - return nodeOut -} - -type NodeOutput struct { - Ports map[int]int `json:",omitempty"` -} diff --git a/testing/deployer/sprawl/internal/tfgen/io.go b/testing/deployer/sprawl/internal/tfgen/io.go deleted file mode 100644 index 160e85be316ba..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/io.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tfgen - -import ( - "bytes" - "os" - "strings" - - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/hcl/v2/hclwrite" - "github.com/rboyer/safeio" -) - -func WriteHCLResourceFile( - logger hclog.Logger, - res []Resource, - path string, - perm os.FileMode, -) (UpdateResult, error) { - var text []string - for _, r := range res { - val, err := r.Render() - if err != nil { - return UpdateResultNone, err - } - text = append(text, strings.TrimSpace(val)) - } - - body := strings.Join(text, "\n\n") - - // Ensure it looks tidy - out := hclwrite.Format(bytes.TrimSpace([]byte(body))) - - return UpdateFileIfDifferent(logger, out, path, perm) -} - -type UpdateResult int - -const ( - UpdateResultNone UpdateResult = iota - UpdateResultCreated - UpdateResultModified -) - -func UpdateFileIfDifferent( - logger hclog.Logger, - body []byte, - path string, - perm os.FileMode, -) (UpdateResult, error) { - prev, err := os.ReadFile(path) - - result := UpdateResultNone - if err != nil { - if !os.IsNotExist(err) { - return result, err - } - logger.Info("writing new file", "path", path) - result = UpdateResultCreated - } else { - // loaded - if bytes.Equal(body, prev) { - return result, nil - } - logger.Info("file has changed", "path", path) - result = UpdateResultModified - } - - _, err = safeio.WriteToFile(bytes.NewReader(body), path, perm) - return result, err -} diff --git a/testing/deployer/sprawl/internal/tfgen/nodes.go b/testing/deployer/sprawl/internal/tfgen/nodes.go deleted file mode 100644 index 7b7addfb207b3..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/nodes.go +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tfgen - -import ( - "fmt" - "sort" - "strconv" - "text/template" - - "github.com/hashicorp/consul/testing/deployer/topology" -) - -type terraformPod struct { - PodName string - Node *topology.Node - Ports []int - Labels map[string]string - TLSVolumeName string - DNSAddress string - DockerNetworkName string -} - -type terraformConsulAgent struct { - terraformPod - ImageResource string - HCL string - EnterpriseLicense string - Env []string -} - -type terraformMeshGatewayService struct { - terraformPod - EnvoyImageResource string - Service *topology.Service - Command []string -} - -type terraformService struct { - terraformPod - AppImageResource string - EnvoyImageResource string // agentful - DataplaneImageResource string // agentless - Service *topology.Service - Env []string - Command []string - EnvoyCommand []string // agentful -} - -func (g *Generator) generateNodeContainers( - step Step, - cluster *topology.Cluster, - node *topology.Node, -) ([]Resource, error) { - if node.Disabled { - return nil, fmt.Errorf("cannot generate containers for a disabled node") - } - - pod := terraformPod{ - PodName: node.PodName(), - Node: node, - Labels: map[string]string{ - "consulcluster-topology-id": g.topology.ID, - "consulcluster-cluster-name": node.Cluster, - }, - TLSVolumeName: cluster.TLSVolumeName, - DNSAddress: "8.8.8.8", - } - - cluster, ok := g.topology.Clusters[node.Cluster] - if !ok { - return nil, fmt.Errorf("no such cluster: %s", node.Cluster) - } - - net, ok := g.topology.Networks[cluster.NetworkName] - if !ok { - return nil, fmt.Errorf("no local network: %s", cluster.NetworkName) - } - if net.DNSAddress != "" { - pod.DNSAddress = net.DNSAddress - } - pod.DockerNetworkName = net.DockerName - - var ( - containers []Resource - ) - - if node.IsAgent() { - agentHCL, err := g.generateAgentHCL(node) - if err != nil { - return nil, err - } - - agent := terraformConsulAgent{ - terraformPod: pod, - ImageResource: DockerImageResourceName(node.Images.Consul), - HCL: agentHCL, - EnterpriseLicense: g.license, - Env: node.AgentEnv, - } - - switch { - case node.IsServer() && step.StartServers(), - !node.IsServer() && step.StartAgents(): - containers = append(containers, Eval(tfConsulT, &agent)) - } - } - - for _, svc := range node.SortedServices() { - if svc.IsMeshGateway { - if node.Kind == topology.NodeKindDataplane { - panic("NOT READY YET") - } - gw := terraformMeshGatewayService{ - terraformPod: pod, - EnvoyImageResource: DockerImageResourceName(node.Images.EnvoyConsulImage()), - Service: svc, - Command: []string{ - "consul", "connect", "envoy", - "-register", - "-mesh-gateway", - }, - } - if token := g.sec.ReadServiceToken(node.Cluster, svc.ID); token != "" { - gw.Command = append(gw.Command, "-token", token) - } - if cluster.Enterprise { - gw.Command = append(gw.Command, - "-partition", - svc.ID.Partition, - ) - } - gw.Command = append(gw.Command, - "-address", - `{{ GetInterfaceIP \"eth0\" }}:`+strconv.Itoa(svc.Port), - "-wan-address", - `{{ GetInterfaceIP \"eth1\" }}:`+strconv.Itoa(svc.Port), - ) - gw.Command = append(gw.Command, - "-grpc-addr", "http://127.0.0.1:8502", - "-admin-bind", - // for demo purposes - "0.0.0.0:"+strconv.Itoa(svc.EnvoyAdminPort), - "--", - "-l", - "trace", - ) - if step.StartServices() { - containers = append(containers, Eval(tfMeshGatewayT, &gw)) - } - } else { - tfsvc := terraformService{ - terraformPod: pod, - AppImageResource: DockerImageResourceName(svc.Image), - Service: svc, - Command: svc.Command, - } - tfsvc.Env = append(tfsvc.Env, svc.Env...) - if step.StartServices() { - containers = append(containers, Eval(tfAppT, &tfsvc)) - } - - setenv := func(k, v string) { - tfsvc.Env = append(tfsvc.Env, k+"="+v) - } - - if !svc.DisableServiceMesh { - if node.IsDataplane() { - tfsvc.DataplaneImageResource = DockerImageResourceName(node.Images.LocalDataplaneImage()) - tfsvc.EnvoyImageResource = "" - tfsvc.EnvoyCommand = nil - // --- REQUIRED --- - setenv("DP_CONSUL_ADDRESSES", "server."+node.Cluster+"-consulcluster.lan") - setenv("DP_SERVICE_NODE_NAME", node.PodName()) - setenv("DP_PROXY_SERVICE_ID", svc.ID.Name+"-sidecar-proxy") - } else { - tfsvc.DataplaneImageResource = "" - tfsvc.EnvoyImageResource = DockerImageResourceName(node.Images.EnvoyConsulImage()) - tfsvc.EnvoyCommand = []string{ - "consul", "connect", "envoy", - "-sidecar-for", svc.ID.Name, - } - } - if cluster.Enterprise { - if node.IsDataplane() { - setenv("DP_SERVICE_NAMESPACE", svc.ID.Namespace) - setenv("DP_SERVICE_PARTITION", svc.ID.Partition) - } else { - tfsvc.EnvoyCommand = append(tfsvc.EnvoyCommand, - "-partition", - svc.ID.Partition, - "-namespace", - svc.ID.Namespace, - ) - } - } - if token := g.sec.ReadServiceToken(node.Cluster, svc.ID); token != "" { - if node.IsDataplane() { - setenv("DP_CREDENTIAL_TYPE", "static") - setenv("DP_CREDENTIAL_STATIC_TOKEN", token) - } else { - tfsvc.EnvoyCommand = append(tfsvc.EnvoyCommand, "-token", token) - } - } - if node.IsDataplane() { - setenv("DP_ENVOY_ADMIN_BIND_ADDRESS", "0.0.0.0") // for demo purposes - setenv("DP_ENVOY_ADMIN_BIND_PORT", "19000") - setenv("DP_LOG_LEVEL", "trace") - - setenv("DP_CA_CERTS", "/consul/config/certs/consul-agent-ca.pem") - setenv("DP_CONSUL_GRPC_PORT", "8503") - setenv("DP_TLS_SERVER_NAME", "server."+node.Datacenter+".consul") - } else { - tfsvc.EnvoyCommand = append(tfsvc.EnvoyCommand, - "-grpc-addr", "http://127.0.0.1:8502", - "-admin-bind", - // for demo purposes - "0.0.0.0:"+strconv.Itoa(svc.EnvoyAdminPort), - "--", - "-l", - "trace", - ) - } - if step.StartServices() { - sort.Strings(tfsvc.Env) - - if node.IsDataplane() { - containers = append(containers, Eval(tfAppDataplaneT, &tfsvc)) - } else { - containers = append(containers, Eval(tfAppSidecarT, &tfsvc)) - } - } - } - } - } - - // Wait until the very end to render the pod so we know all of the ports. - pod.Ports = node.SortedPorts() - - // pod placeholder container - containers = append(containers, Eval(tfPauseT, &pod)) - - return containers, nil -} - -var tfPauseT = template.Must(template.ParseFS(content, "templates/container-pause.tf.tmpl")) -var tfConsulT = template.Must(template.ParseFS(content, "templates/container-consul.tf.tmpl")) -var tfMeshGatewayT = template.Must(template.ParseFS(content, "templates/container-mgw.tf.tmpl")) -var tfAppT = template.Must(template.ParseFS(content, "templates/container-app.tf.tmpl")) -var tfAppSidecarT = template.Must(template.ParseFS(content, "templates/container-app-sidecar.tf.tmpl")) -var tfAppDataplaneT = template.Must(template.ParseFS(content, "templates/container-app-dataplane.tf.tmpl")) diff --git a/testing/deployer/sprawl/internal/tfgen/prelude.go b/testing/deployer/sprawl/internal/tfgen/prelude.go deleted file mode 100644 index 2e9a01cb08058..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/prelude.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tfgen - -const terraformPrelude = `provider "docker" { - host = "unix:///var/run/docker.sock" -} - -terraform { - required_providers { - docker = { - source = "kreuzwerker/docker" - version = "~> 2.0" - } - } - required_version = ">= 0.13" -} -` diff --git a/testing/deployer/sprawl/internal/tfgen/proxy.go b/testing/deployer/sprawl/internal/tfgen/proxy.go deleted file mode 100644 index 0fafa9b925e9e..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/proxy.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tfgen - -import ( - "fmt" - "os" - "path/filepath" - "text/template" - - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/consul/testing/deployer/util" -) - -const proxyInternalPort = 80 - -func (g *Generator) writeNginxConfig(net *topology.Network) (bool, string, error) { - rootdir := filepath.Join(g.workdir, "terraform", "nginx-config-"+net.Name) - if err := os.MkdirAll(rootdir, 0755); err != nil { - return false, "", err - } - - configFile := filepath.Join(rootdir, "nginx.conf") - - body := fmt.Sprintf(` -server { - listen %d; - - location / { - resolver 8.8.8.8; - ############## - # Relevant config knobs are here: https://nginx.org/en/docs/http/ngx_http_proxy_module.html - ############## - proxy_pass http://$http_host$uri$is_args$args; - proxy_cache off; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_connect_timeout 5s; - proxy_read_timeout 5s; - proxy_send_timeout 5s; - proxy_request_buffering off; - proxy_buffering off; - } -} -`, proxyInternalPort) - - _, err := UpdateFileIfDifferent( - g.logger, - []byte(body), - configFile, - 0644, - ) - if err != nil { - return false, "", fmt.Errorf("error writing %q: %w", configFile, err) - } - - hash, err := util.HashFile(configFile) - if err != nil { - return false, "", fmt.Errorf("error hashing %q: %w", configFile, err) - } - - return true, hash, err -} - -func (g *Generator) getForwardProxyContainer( - net *topology.Network, - ipAddress string, - hash string, -) Resource { - env := []string{"HASH_FILE_VALUE=" + hash} - proxy := struct { - Name string - DockerNetworkName string - InternalPort int - IPAddress string - Env []string - }{ - Name: net.Name, - DockerNetworkName: net.DockerName, - InternalPort: proxyInternalPort, - IPAddress: ipAddress, - Env: env, - } - - return Eval(tfForwardProxyT, &proxy) -} - -var tfForwardProxyT = template.Must(template.ParseFS(content, "templates/container-proxy.tf.tmpl")) diff --git a/testing/deployer/sprawl/internal/tfgen/res.go b/testing/deployer/sprawl/internal/tfgen/res.go deleted file mode 100644 index a45c460793d22..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/res.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tfgen - -import ( - "bytes" - "text/template" - - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/hcl/v2/hclwrite" -) - -type FileResource struct { - name string - res Resource -} - -func (r *FileResource) Name() string { return r.name } - -func (r *FileResource) Commit(logger hclog.Logger) error { - val, err := r.res.Render() - if err != nil { - return err - } - _, err = UpdateFileIfDifferent(logger, []byte(val), r.name, 0644) - return err -} - -func File(name string, res Resource) *FileResource { - return &FileResource{name: name, res: res} -} - -func Text(s string) Resource { - return &textResource{text: s} -} - -func Embed(name string) Resource { - return &embedResource{name: name} -} - -func Eval(t *template.Template, data any) Resource { - return &evalResource{template: t, data: data, hcl: false} -} - -func HCL(t *template.Template, data any) Resource { - return &evalResource{template: t, data: data, hcl: true} -} - -type Resource interface { - Render() (string, error) -} - -type embedResource struct { - name string -} - -func (r *embedResource) Render() (string, error) { - val, err := content.ReadFile(r.name) - if err != nil { - return "", err - } - return string(val), nil -} - -type textResource struct { - text string -} - -func (r *textResource) Render() (string, error) { - return r.text, nil -} - -type evalResource struct { - template *template.Template - data any - hcl bool -} - -func (r *evalResource) Render() (string, error) { - out, err := StringTemplate(r.template, r.data) - if err != nil { - return "", err - } - - if r.hcl { - return string(hclwrite.Format([]byte(out))), nil - } - return out, nil -} - -func StringTemplate(t *template.Template, data any) (string, error) { - var res bytes.Buffer - if err := t.Execute(&res, data); err != nil { - return "", err - } - return res.String(), nil -} diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-app-dataplane.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-app-dataplane.tf.tmpl deleted file mode 100644 index bfb0705e6df8e..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-app-dataplane.tf.tmpl +++ /dev/null @@ -1,29 +0,0 @@ -resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}-sidecar" { - name = "{{.Node.DockerName}}-{{.Service.ID.TFString}}-sidecar" - network_mode = "container:${docker_container.{{.PodName}}.id}" - image = docker_image.{{.DataplaneImageResource}}.latest - restart = "on-failure" - -{{- range $k, $v := .Labels }} - labels { - label = "{{ $k }}" - value = "{{ $v }}" - } -{{- end }} - - volumes { - volume_name = "{{.TLSVolumeName}}" - container_path = "/consul/config/certs" - read_only = true - } - - env = [ -{{- range .Env }} - "{{.}}", -{{- end}} - ] - - command = [ - "/usr/local/bin/consul-dataplane", - ] -} diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-app-sidecar.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-app-sidecar.tf.tmpl deleted file mode 100644 index 6abb397c25341..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-app-sidecar.tf.tmpl +++ /dev/null @@ -1,31 +0,0 @@ -resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}-sidecar" { - name = "{{.Node.DockerName}}-{{.Service.ID.TFString}}-sidecar" - network_mode = "container:${docker_container.{{.PodName}}.id}" - image = docker_image.{{.EnvoyImageResource}}.latest - restart = "on-failure" - -{{- range $k, $v := .Labels }} - labels { - label = "{{ $k }}" - value = "{{ $v }}" - } -{{- end }} - - volumes { - volume_name = "{{.TLSVolumeName}}" - container_path = "/consul/config/certs" - read_only = true - } - - env = [ -{{- range .Env }} - "{{.}}", -{{- end}} - ] - - command = [ -{{- range .EnvoyCommand }} - "{{.}}", -{{- end }} - ] -} diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-app.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-app.tf.tmpl deleted file mode 100644 index b1b390f0f16c4..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-app.tf.tmpl +++ /dev/null @@ -1,25 +0,0 @@ -resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}" { - name = "{{.Node.DockerName}}-{{.Service.ID.TFString}}" - network_mode = "container:${docker_container.{{.PodName}}.id}" - image = docker_image.{{.AppImageResource}}.latest - restart = "on-failure" - -{{- range $k, $v := .Labels }} - labels { - label = "{{ $k }}" - value = "{{ $v }}" - } -{{- end }} - - env = [ -{{- range .Env }} - "{{.}}", -{{- end}} - ] - - command = [ -{{- range .Command }} - "{{.}}", -{{- end }} - ] -} diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-consul.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-consul.tf.tmpl deleted file mode 100644 index 01f7f3fb4d7dd..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-consul.tf.tmpl +++ /dev/null @@ -1,40 +0,0 @@ -resource "docker_container" "{{.Node.DockerName}}" { - name = "{{.Node.DockerName}}" - network_mode = "container:${docker_container.{{.PodName}}.id}" - image = docker_image.{{.ImageResource}}.latest - restart = "always" - - env = [ - "CONSUL_UID=0", - "CONSUL_GID=0", - "CONSUL_LICENSE={{.EnterpriseLicense}}", -{{- range .Env }} - "{{.}}", -{{- end}} - ] - -{{- range $k, $v := .Labels }} - labels { - label = "{{ $k }}" - value = "{{ $v }}" - } -{{- end }} - - command = [ - "agent", - "-hcl", - <<-EOT -{{ .HCL }} -EOT - ] - - volumes { - volume_name = "{{.Node.DockerName}}" - container_path = "/consul/data" - } - - volumes { - volume_name = "{{.TLSVolumeName}}" - container_path = "/consul/config/certs" - } -} diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-coredns.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-coredns.tf.tmpl deleted file mode 100644 index 7789376a98f10..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-coredns.tf.tmpl +++ /dev/null @@ -1,28 +0,0 @@ -resource "docker_container" "{{.DockerNetworkName}}-coredns" { - name = "{{.DockerNetworkName}}-coredns" - image = docker_image.coredns.latest - restart = "always" - dns = ["8.8.8.8"] - - networks_advanced { - name = docker_network.{{.DockerNetworkName}}.name - ipv4_address = "{{.IPAddress}}" - } - - env = [ -{{- range .Env }} - "{{.}}", -{{- end}} - ] - - volumes { - host_path = abspath("coredns-config-{{.Name}}") - container_path = "/config" - read_only = true - } - - command = [ - "-conf", - "/config/Corefile", - ] -} diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-mgw.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-mgw.tf.tmpl deleted file mode 100644 index ec25665f3ed87..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-mgw.tf.tmpl +++ /dev/null @@ -1,25 +0,0 @@ -resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}" { - name = "{{.Node.DockerName}}-{{.Service.ID.TFString}}" - network_mode = "container:${docker_container.{{.PodName}}.id}" - image = docker_image.{{.EnvoyImageResource}}.latest - restart = "on-failure" - -{{- range $k, $v := .Labels }} - labels { - label = "{{ $k }}" - value = "{{ $v }}" - } -{{- end }} - - volumes { - volume_name = "{{.TLSVolumeName}}" - container_path = "/consul/config/certs" - read_only = true - } - - command = [ -{{- range .Command }} - "{{.}}", -{{- end }} - ] -} diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-pause.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-pause.tf.tmpl deleted file mode 100644 index 1f1627b0719bd..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-pause.tf.tmpl +++ /dev/null @@ -1,38 +0,0 @@ -resource "docker_container" "{{.PodName}}" { - name = "{{.PodName}}" - image = docker_image.pause.latest - hostname = "{{.PodName}}" - restart = "always" - dns = ["{{.DNSAddress}}"] - -{{- range $k, $v := .Labels }} - labels { - label = "{{ $k }}" - value = "{{ $v }}" - } -{{- end }} - -depends_on = [ - docker_container.{{.DockerNetworkName}}-coredns, - docker_container.{{.DockerNetworkName}}-forwardproxy, -] - -{{- range .Ports }} -ports { - internal = {{.}} -} -{{- end }} - -{{- range .Node.Addresses }} -networks_advanced { - name = docker_network.{{.DockerNetworkName}}.name - ipv4_address = "{{.IPAddress}}" -} -{{- end }} -} - -output "ports_{{.Node.Cluster}}_{{.Node.Partition}}_{{.Node.Name}}" { - value = { - for port in docker_container.{{.PodName}}.ports : port.internal => port.external - } -} diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-proxy.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-proxy.tf.tmpl deleted file mode 100644 index ed44d8343fe8b..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-proxy.tf.tmpl +++ /dev/null @@ -1,33 +0,0 @@ -resource "docker_container" "{{.DockerNetworkName}}-forwardproxy" { - name = "{{.DockerNetworkName}}-forwardproxy" - image = docker_image.nginx.latest - restart = "always" - dns = ["8.8.8.8"] - - ports { - internal = {{.InternalPort}} - } - - networks_advanced { - name = docker_network.{{.DockerNetworkName}}.name - ipv4_address = "{{.IPAddress}}" - } - - env = [ -{{- range .Env }} - "{{.}}", -{{- end}} - ] - - volumes { - host_path = abspath("nginx-config-{{.Name}}/nginx.conf") - container_path = "/etc/nginx/conf.d/default.conf" - read_only = true - } -} - -output "forwardproxyport_{{.Name}}" { - value = { - for port in docker_container.{{.DockerNetworkName}}-forwardproxy.ports : port.internal => port.external - } -} diff --git a/testing/deployer/sprawl/internal/tfgen/tfgen.go b/testing/deployer/sprawl/internal/tfgen/tfgen.go deleted file mode 100644 index e752528ef1619..0000000000000 --- a/testing/deployer/sprawl/internal/tfgen/tfgen.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tfgen - -import ( - "embed" -) - -//go:embed templates/container-app-dataplane.tf.tmpl -//go:embed templates/container-app-sidecar.tf.tmpl -//go:embed templates/container-app.tf.tmpl -//go:embed templates/container-consul.tf.tmpl -//go:embed templates/container-mgw.tf.tmpl -//go:embed templates/container-pause.tf.tmpl -//go:embed templates/container-proxy.tf.tmpl -//go:embed templates/container-coredns.tf.tmpl -var content embed.FS diff --git a/testing/deployer/sprawl/peering.go b/testing/deployer/sprawl/peering.go deleted file mode 100644 index 5275161cfd9a3..0000000000000 --- a/testing/deployer/sprawl/peering.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sprawl - -import ( - "context" - "fmt" - "strings" - "time" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/go-hclog" - - "github.com/hashicorp/consul/testing/deployer/topology" -) - -// TODO: this is definitely a grpc resolver/balancer issue to look into -const grpcWeirdError = `transport: Error while dialing failed to find Consul server for global address` - -func isWeirdGRPCError(err error) bool { - if err == nil { - return false - } - return strings.Contains(err.Error(), grpcWeirdError) -} - -func (s *Sprawl) initPeerings() error { - // TODO: wait until services are healthy? wait until mesh gateways work? - // if err := s.generator.Generate(tfgen.StepPeering); err != nil { - // return fmt.Errorf("generator[peering]: %w", err) - // } - - var ( - logger = s.logger.Named("peering") - _ = logger - ) - - for _, peering := range s.topology.Peerings { - dialingCluster, ok := s.topology.Clusters[peering.Dialing.Name] - if !ok { - return fmt.Errorf("peering references dialing cluster that does not exist: %s", peering.String()) - } - acceptingCluster, ok := s.topology.Clusters[peering.Accepting.Name] - if !ok { - return fmt.Errorf("peering references accepting cluster that does not exist: %s", peering.String()) - } - - var ( - dialingClient = s.clients[dialingCluster.Name] - acceptingClient = s.clients[acceptingCluster.Name] - ) - - // TODO: allow for use of ServerExternalAddresses - - req1 := api.PeeringGenerateTokenRequest{ - PeerName: peering.Accepting.PeerName, - } - if acceptingCluster.Enterprise { - req1.Partition = peering.Accepting.Partition - } - - GENTOKEN: - resp, _, err := acceptingClient.Peerings().GenerateToken(context.Background(), req1, nil) - if err != nil { - if isWeirdGRPCError(err) { - time.Sleep(50 * time.Millisecond) - goto GENTOKEN - } - return fmt.Errorf("error generating peering token for %q: %w", peering.String(), err) - } - - peeringToken := resp.PeeringToken - logger.Info("generated peering token", "peering", peering.String()) - - req2 := api.PeeringEstablishRequest{ - PeerName: peering.Dialing.PeerName, - PeeringToken: peeringToken, - } - if dialingCluster.Enterprise { - req2.Partition = peering.Dialing.Partition - } - - logger.Info("establishing peering with token", "peering", peering.String()) - ESTABLISH: - _, _, err = dialingClient.Peerings().Establish(context.Background(), req2, nil) - if err != nil { - if isWeirdGRPCError(err) { - time.Sleep(50 * time.Millisecond) - goto ESTABLISH - } - return fmt.Errorf("error establishing peering with token for %q: %w", peering.String(), err) - } - - logger.Info("peering established", "peering", peering.String()) - } - - return nil -} - -func (s *Sprawl) waitForPeeringEstablishment() error { - var ( - logger = s.logger.Named("peering") - ) - - for _, peering := range s.topology.Peerings { - dialingCluster, ok := s.topology.Clusters[peering.Dialing.Name] - if !ok { - return fmt.Errorf("peering references dialing cluster that does not exist: %s", peering.String()) - } - acceptingCluster, ok := s.topology.Clusters[peering.Accepting.Name] - if !ok { - return fmt.Errorf("peering references accepting cluster that does not exist: %s", peering.String()) - } - - var ( - dialingClient = s.clients[dialingCluster.Name] - acceptingClient = s.clients[acceptingCluster.Name] - - dialingLogger = logger.With( - "cluster", dialingCluster.Name, - "peering", peering.String(), - ) - acceptingLogger = logger.With( - "cluster", acceptingCluster.Name, - "peering", peering.String(), - ) - ) - - s.checkPeeringDirection(dialingLogger, dialingClient, peering.Dialing, dialingCluster.Enterprise) - s.checkPeeringDirection(acceptingLogger, acceptingClient, peering.Accepting, acceptingCluster.Enterprise) - } - return nil -} - -func (s *Sprawl) checkPeeringDirection(logger hclog.Logger, client *api.Client, pc topology.PeerCluster, enterprise bool) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - for { - opts := &api.QueryOptions{} - if enterprise { - opts.Partition = pc.Partition - } - res, _, err := client.Peerings().Read(ctx, pc.PeerName, opts) - if isWeirdGRPCError(err) { - time.Sleep(50 * time.Millisecond) - continue - } - if err != nil { - logger.Info("error looking up peering", "error", err) - time.Sleep(100 * time.Millisecond) - continue - } - if res == nil { - logger.Info("peering not found") - time.Sleep(100 * time.Millisecond) - continue - } - - if res.State == api.PeeringStateActive { - logger.Info("peering is active") - return - } - logger.Info("peering not active yet", "state", res.State) - time.Sleep(500 * time.Millisecond) - } -} diff --git a/testing/deployer/sprawl/sprawl.go b/testing/deployer/sprawl/sprawl.go deleted file mode 100644 index a4b27597626e9..0000000000000 --- a/testing/deployer/sprawl/sprawl.go +++ /dev/null @@ -1,467 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sprawl - -import ( - "bufio" - "bytes" - "context" - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "strings" - "time" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-multierror" - "github.com/mitchellh/copystructure" - - "github.com/hashicorp/consul/testing/deployer/sprawl/internal/runner" - "github.com/hashicorp/consul/testing/deployer/sprawl/internal/secrets" - "github.com/hashicorp/consul/testing/deployer/sprawl/internal/tfgen" - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/consul/testing/deployer/util" -) - -// TODO: manage workdir externally without chdir - -// Sprawl is the definition of a complete running Consul deployment topology. -type Sprawl struct { - logger hclog.Logger - runner *runner.Runner - license string - secrets secrets.Store - - workdir string - - // set during Run - config *topology.Config - topology *topology.Topology - generator *tfgen.Generator - - clients map[string]*api.Client // one per cluster -} - -// Topology allows access to the topology that defines the resources. Do not -// write to any of these fields. -func (s *Sprawl) Topology() *topology.Topology { - return s.topology -} - -func (s *Sprawl) Config() *topology.Config { - c2, err := copyConfig(s.config) - if err != nil { - panic(err) - } - return c2 -} - -func (s *Sprawl) HTTPClientForCluster(clusterName string) (*http.Client, error) { - cluster, ok := s.topology.Clusters[clusterName] - if !ok { - return nil, fmt.Errorf("no such cluster: %s", clusterName) - } - - // grab the local network for the cluster - network, ok := s.topology.Networks[cluster.NetworkName] - if !ok { - return nil, fmt.Errorf("no such network: %s", cluster.NetworkName) - } - - transport, err := util.ProxyHTTPTransport(network.ProxyPort) - if err != nil { - return nil, err - } - - return &http.Client{Transport: transport}, nil -} - -// APIClientForNode gets a pooled api.Client connected to the agent running on -// the provided node. -// -// Passing an empty token will assume the bootstrap token. If you want to -// actually use the anonymous token say "-". -func (s *Sprawl) APIClientForNode(clusterName string, nid topology.NodeID, token string) (*api.Client, error) { - cluster, ok := s.topology.Clusters[clusterName] - if !ok { - return nil, fmt.Errorf("no such cluster: %s", clusterName) - } - - nid.Normalize() - - node := cluster.NodeByID(nid) - if !node.IsAgent() { - return nil, fmt.Errorf("node is not an agent") - } - - switch token { - case "": - token = s.secrets.ReadGeneric(clusterName, secrets.BootstrapToken) - case "-": - token = "" - } - - return util.ProxyAPIClient( - node.LocalProxyPort(), - node.LocalAddress(), - 8500, - token, - ) -} - -func copyConfig(cfg *topology.Config) (*topology.Config, error) { - dup, err := copystructure.Copy(cfg) - if err != nil { - return nil, err - } - return dup.(*topology.Config), nil -} - -// Launch will create the topology defined by the provided configuration and -// bring up all of the relevant clusters. Once created the Stop method must be -// called to destroy everything. -func Launch( - logger hclog.Logger, - workdir string, - cfg *topology.Config, -) (*Sprawl, error) { - if logger == nil { - panic("logger is required") - } - if workdir == "" { - panic("workdir is required") - } - - if err := os.MkdirAll(filepath.Join(workdir, "terraform"), 0755); err != nil { - return nil, err - } - - runner, err := runner.Load(logger) - if err != nil { - return nil, err - } - - // Copy this to avoid leakage. - cfg, err = copyConfig(cfg) - if err != nil { - return nil, err - } - - s := &Sprawl{ - logger: logger, - runner: runner, - workdir: workdir, - clients: make(map[string]*api.Client), - } - - if err := s.ensureLicense(); err != nil { - return nil, err - } - - // Copy this AGAIN, BEFORE compiling so we capture the original definition, without denorms. - s.config, err = copyConfig(cfg) - if err != nil { - return nil, err - } - - s.topology, err = topology.Compile(logger.Named("compile"), cfg) - if err != nil { - return nil, fmt.Errorf("topology.Compile: %w", err) - } - - s.logger.Info("compiled topology", "ct", jd(s.topology)) // TODO - - start := time.Now() - if err := s.launch(); err != nil { - return nil, err - } - s.logger.Info("topology is ready for use", "elapsed", time.Since(start)) - - if err := s.PrintDetails(); err != nil { - return nil, fmt.Errorf("error gathering diagnostic details: %w", err) - } - - return s, nil -} - -func (s *Sprawl) Relaunch( - cfg *topology.Config, -) error { - // Copy this BEFORE compiling so we capture the original definition, without denorms. - var err error - s.config, err = copyConfig(cfg) - if err != nil { - return err - } - - newTopology, err := topology.Recompile(s.logger.Named("recompile"), cfg, s.topology) - if err != nil { - return fmt.Errorf("topology.Compile: %w", err) - } - - s.topology = newTopology - - s.logger.Info("compiled replacement topology", "ct", jd(s.topology)) // TODO - - start := time.Now() - if err := s.relaunch(); err != nil { - return err - } - s.logger.Info("topology is ready for use", "elapsed", time.Since(start)) - - if err := s.PrintDetails(); err != nil { - return fmt.Errorf("error gathering diagnostic details: %w", err) - } - - return nil -} - -// Leader returns the cluster leader agent, or an error if no leader is -// available. -func (s *Sprawl) Leader(clusterName string) (*topology.Node, error) { - cluster, ok := s.topology.Clusters[clusterName] - if !ok { - return nil, fmt.Errorf("no such cluster: %s", clusterName) - } - - var ( - client = s.clients[cluster.Name] - // logger = s.logger.With("cluster", cluster.Name) - ) - - leaderAddr, err := getLeader(client) - if err != nil { - return nil, err - } - - for _, node := range cluster.Nodes { - if !node.IsServer() || node.Disabled { - continue - } - if strings.HasPrefix(leaderAddr, node.LocalAddress()+":") { - return node, nil - } - } - - return nil, fmt.Errorf("leader not found") -} - -// Followers returns the cluster following servers. -func (s *Sprawl) Followers(clusterName string) ([]*topology.Node, error) { - cluster, ok := s.topology.Clusters[clusterName] - if !ok { - return nil, fmt.Errorf("no such cluster: %s", clusterName) - } - - leaderNode, err := s.Leader(clusterName) - if err != nil { - return nil, fmt.Errorf("could not determine leader: %w", err) - } - - var followers []*topology.Node - - for _, node := range cluster.Nodes { - if !node.IsServer() || node.Disabled { - continue - } - if node.ID() != leaderNode.ID() { - followers = append(followers, node) - } - } - - return followers, nil -} - -func (s *Sprawl) DisabledServers(clusterName string) ([]*topology.Node, error) { - cluster, ok := s.topology.Clusters[clusterName] - if !ok { - return nil, fmt.Errorf("no such cluster: %s", clusterName) - } - - var servers []*topology.Node - - for _, node := range cluster.Nodes { - if !node.IsServer() || !node.Disabled { - continue - } - servers = append(servers, node) - } - - return servers, nil -} - -func (s *Sprawl) StopContainer(ctx context.Context, containerName string) error { - return s.runner.DockerExec(ctx, []string{"stop", containerName}, nil, nil) -} - -func (s *Sprawl) SnapshotEnvoy(ctx context.Context) error { - snapDir := filepath.Join(s.workdir, "envoy-snapshots") - if err := os.MkdirAll(snapDir, 0755); err != nil { - return fmt.Errorf("could not create envoy snapshot output dir %s: %w", snapDir, err) - } - - targets := map[string]string{ - "config_dump.json": "config_dump", - "clusters.json": "clusters?format=json", - "stats.txt": "stats", - "stats_prometheus.txt": "stats/prometheus", - } - - var merr error - for _, c := range s.topology.Clusters { - client, err := s.HTTPClientForCluster(c.Name) - if err != nil { - return fmt.Errorf("could not get http client for cluster %q: %w", c.Name, err) - } - - for _, n := range c.Nodes { - if n.Disabled { - continue - } - for _, s := range n.Services { - if s.Disabled || s.EnvoyAdminPort <= 0 { - continue - } - prefix := fmt.Sprintf("http://%s:%d", n.LocalAddress(), s.EnvoyAdminPort) - - for fn, target := range targets { - u := prefix + "/" + target - - body, err := scrapeURL(client, u) - if err != nil { - merr = multierror.Append(merr, fmt.Errorf("could not scrape %q for %s on %s: %w", - target, s.ID.String(), n.ID().String(), err, - )) - continue - } - - outFn := filepath.Join(snapDir, n.DockerName()+"--"+s.ID.TFString()+"."+fn) - - if err := os.WriteFile(outFn+".tmp", body, 0644); err != nil { - merr = multierror.Append(merr, fmt.Errorf("could not write output %q for %s on %s: %w", - target, s.ID.String(), n.ID().String(), err, - )) - continue - } - - if err := os.Rename(outFn+".tmp", outFn); err != nil { - merr = multierror.Append(merr, fmt.Errorf("could not write output %q for %s on %s: %w", - target, s.ID.String(), n.ID().String(), err, - )) - continue - } - } - } - } - } - return merr -} - -func scrapeURL(client *http.Client, url string) ([]byte, error) { - res, err := client.Get(url) - if err != nil { - return nil, err - } - defer res.Body.Close() - - body, err := io.ReadAll(res.Body) - if err != nil { - return nil, err - } - return body, nil -} - -func (s *Sprawl) CaptureLogs(ctx context.Context) error { - logDir := filepath.Join(s.workdir, "logs") - if err := os.MkdirAll(logDir, 0755); err != nil { - return fmt.Errorf("could not create log output dir %s: %w", logDir, err) - } - - containers, err := s.listContainers(ctx) - if err != nil { - return err - } - - s.logger.Info("Capturing logs") - - var merr error - for _, container := range containers { - if err := s.dumpContainerLogs(ctx, container, logDir); err != nil { - merr = multierror.Append(merr, fmt.Errorf("could not dump logs for container %s: %w", container, err)) - } - } - - return merr -} - -// Dump known containers out of terraform state file. -func (s *Sprawl) listContainers(ctx context.Context) ([]string, error) { - tfdir := filepath.Join(s.workdir, "terraform") - - var buf bytes.Buffer - if err := s.runner.TerraformExec(ctx, []string{"state", "list"}, &buf, tfdir); err != nil { - return nil, fmt.Errorf("error listing containers in terraform state file: %w", err) - } - - var ( - scan = bufio.NewScanner(&buf) - containers []string - ) - for scan.Scan() { - line := strings.TrimSpace(scan.Text()) - - name := strings.TrimPrefix(line, "docker_container.") - if name != line { - containers = append(containers, name) - continue - } - } - if err := scan.Err(); err != nil { - return nil, err - } - - return containers, nil -} - -func (s *Sprawl) dumpContainerLogs(ctx context.Context, containerName, outputRoot string) error { - path := filepath.Join(outputRoot, containerName+".log") - - f, err := os.Create(path + ".tmp") - if err != nil { - return err - } - keep := false - defer func() { - _ = f.Close() - if !keep { - _ = os.Remove(path + ".tmp") - _ = os.Remove(path) - } - }() - - err = s.runner.DockerExecWithStderr( - ctx, - []string{"logs", containerName}, - f, - f, - nil, - ) - if err != nil { - return err - } - - if err := f.Close(); err != nil { - return err - } - - if err := os.Rename(path+".tmp", path); err != nil { - return err - } - - keep = true - return nil -} diff --git a/testing/deployer/sprawl/sprawltest/sprawltest.go b/testing/deployer/sprawl/sprawltest/sprawltest.go deleted file mode 100644 index 2fe10537459c0..0000000000000 --- a/testing/deployer/sprawl/sprawltest/sprawltest.go +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sprawltest - -import ( - "context" - "fmt" - "io" - "os" - "os/exec" - "path/filepath" - "sync" - "testing" - - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-multierror" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/testing/deployer/sprawl" - "github.com/hashicorp/consul/testing/deployer/sprawl/internal/runner" - "github.com/hashicorp/consul/testing/deployer/topology" -) - -// TODO(rb): move comments to doc.go - -var ( - // set SPRAWL_WORKDIR_ROOT in the environment to have the test output - // coalesced in here. By default it uses a directory called "workdir" in - // each package. - workdirRoot string - - // set SPRAWL_KEEP_WORKDIR=1 in the environment to keep the workdir output - // intact. Files are all destroyed by default. - keepWorkdirOnFail bool - - // set SPRAWL_KEEP_RUNNING=1 in the environment to keep the workdir output - // intact and also refrain from tearing anything down. Things are all - // destroyed by default. - // - // SPRAWL_KEEP_RUNNING=1 implies SPRAWL_KEEP_WORKDIR=1 - keepRunningOnFail bool - - // set SPRAWL_SKIP_OLD_CLEANUP to prevent the library from tearing down and - // removing anything found in the working directory at init time. The - // default behavior is to do this. - skipOldCleanup bool -) - -var cleanupPriorRunOnce sync.Once - -func init() { - if root := os.Getenv("SPRAWL_WORKDIR_ROOT"); root != "" { - fmt.Fprintf(os.Stdout, "INFO: sprawltest: SPRAWL_WORKDIR_ROOT set; using %q as output root\n", root) - workdirRoot = root - } else { - workdirRoot = "workdir" - } - - if os.Getenv("SPRAWL_KEEP_WORKDIR") == "1" { - keepWorkdirOnFail = true - fmt.Fprintf(os.Stdout, "INFO: sprawltest: SPRAWL_KEEP_WORKDIR set; not destroying workdir on failure\n") - } - - if os.Getenv("SPRAWL_KEEP_RUNNING") == "1" { - keepRunningOnFail = true - keepWorkdirOnFail = true - fmt.Fprintf(os.Stdout, "INFO: sprawltest: SPRAWL_KEEP_RUNNING set; not tearing down resources on failure\n") - } - - if os.Getenv("SPRAWL_SKIP_OLD_CLEANUP") == "1" { - skipOldCleanup = true - fmt.Fprintf(os.Stdout, "INFO: sprawltest: SPRAWL_SKIP_OLD_CLEANUP set; not cleaning up anything found in %q\n", workdirRoot) - } - - if !skipOldCleanup { - cleanupPriorRunOnce.Do(func() { - fmt.Fprintf(os.Stdout, "INFO: sprawltest: triggering cleanup of any prior test runs\n") - CleanupWorkingDirectories() - }) - } -} - -// Launch will create the topology defined by the provided configuration and -// bring up all of the relevant clusters. -// -// - Logs will be routed to (*testing.T).Logf. -// -// - By default everything will be stopped and removed via -// (*testing.T).Cleanup. For failed tests, this can be skipped by setting the -// environment variable SKIP_TEARDOWN=1. -func Launch(t *testing.T, cfg *topology.Config) *sprawl.Sprawl { - SkipIfTerraformNotPresent(t) - sp, err := sprawl.Launch( - testutil.Logger(t), - initWorkingDirectory(t), - cfg, - ) - require.NoError(t, err) - stopOnCleanup(t, sp) - return sp -} - -func initWorkingDirectory(t *testing.T) string { - // TODO(rb): figure out how to get the calling package which we can put in - // the middle here, which is likely 2 call frames away so maybe - // runtime.Callers can help - scratchDir := filepath.Join(workdirRoot, t.Name()) - _ = os.RemoveAll(scratchDir) // cleanup prior runs - if err := os.MkdirAll(scratchDir, 0755); err != nil { - t.Fatalf("error: %v", err) - } - - t.Cleanup(func() { - if t.Failed() && keepWorkdirOnFail { - t.Logf("test failed; leaving sprawl terraform definitions in: %s", scratchDir) - } else { - _ = os.RemoveAll(scratchDir) - } - }) - - return scratchDir -} - -func stopOnCleanup(t *testing.T, sp *sprawl.Sprawl) { - t.Cleanup(func() { - if t.Failed() && keepWorkdirOnFail { - // It's only worth it to capture the logs if we aren't going to - // immediately discard them. - if err := sp.CaptureLogs(context.Background()); err != nil { - t.Logf("log capture encountered failures: %v", err) - } - if err := sp.SnapshotEnvoy(context.Background()); err != nil { - t.Logf("envoy snapshot capture encountered failures: %v", err) - } - } - - if t.Failed() && keepRunningOnFail { - t.Log("test failed; leaving sprawl running") - } else { - //nolint:errcheck - sp.Stop() - } - }) -} - -// CleanupWorkingDirectories is meant to run in an init() once at the start of -// any tests. -func CleanupWorkingDirectories() { - fi, err := os.ReadDir(workdirRoot) - if os.IsNotExist(err) { - return - } else if err != nil { - fmt.Fprintf(os.Stderr, "WARN: sprawltest: unable to scan 'workdir' for prior runs to cleanup\n") - return - } else if len(fi) == 0 { - fmt.Fprintf(os.Stdout, "INFO: sprawltest: no prior tests to clean up\n") - return - } - - r, err := runner.Load(hclog.NewNullLogger()) - if err != nil { - fmt.Fprintf(os.Stderr, "WARN: sprawltest: unable to look for 'terraform' and 'docker' binaries\n") - return - } - - ctx := context.Background() - - for _, d := range fi { - if !d.IsDir() { - continue - } - path := filepath.Join(workdirRoot, d.Name(), "terraform") - - fmt.Fprintf(os.Stdout, "INFO: sprawltest: cleaning up failed prior run in: %s\n", path) - - err := r.TerraformExec(ctx, []string{ - "init", "-input=false", - }, io.Discard, path) - - err2 := r.TerraformExec(ctx, []string{ - "destroy", "-input=false", "-auto-approve", "-refresh=false", - }, io.Discard, path) - - if err2 != nil { - err = multierror.Append(err, err2) - } - - if err != nil { - fmt.Fprintf(os.Stderr, "WARN: sprawltest: could not clean up failed prior run in: %s: %v\n", path, err) - } else { - _ = os.RemoveAll(path) - } - } -} - -func SkipIfTerraformNotPresent(t *testing.T) { - const terraformBinaryName = "terraform" - - path, err := exec.LookPath(terraformBinaryName) - if err != nil || path == "" { - t.Skipf("%q not found on $PATH - download and install to run this test", terraformBinaryName) - } -} diff --git a/testing/deployer/sprawl/sprawltest/test_test.go b/testing/deployer/sprawl/sprawltest/test_test.go deleted file mode 100644 index 1bb69ea77efee..0000000000000 --- a/testing/deployer/sprawl/sprawltest/test_test.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sprawltest_test - -import ( - "strconv" - "testing" - - "github.com/hashicorp/consul/api" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest" - "github.com/hashicorp/consul/testing/deployer/topology" -) - -func TestSprawl(t *testing.T) { - serversDC1 := newTopologyServerSet("dc1-server", 3, []string{"dc1", "wan"}, nil) - serversDC2 := newTopologyServerSet("dc2-server", 3, []string{"dc2", "wan"}, nil) - - cfg := &topology.Config{ - Networks: []*topology.Network{ - {Name: "dc1"}, - {Name: "dc2"}, - {Name: "wan", Type: "wan"}, - }, - Clusters: []*topology.Cluster{ - { - Name: "dc1", - Nodes: topology.MergeSlices(serversDC1, []*topology.Node{ - { - Kind: topology.NodeKindClient, - Name: "dc1-client1", - Services: []*topology.Service{ - { - ID: topology.ServiceID{Name: "mesh-gateway"}, - Port: 8443, - EnvoyAdminPort: 19000, - IsMeshGateway: true, - }, - }, - }, - { - Kind: topology.NodeKindClient, - Name: "dc1-client2", - Services: []*topology.Service{ - { - ID: topology.ServiceID{Name: "ping"}, - Image: "rboyer/pingpong:latest", - Port: 8080, - EnvoyAdminPort: 19000, - Command: []string{ - "-bind", "0.0.0.0:8080", - "-dial", "127.0.0.1:9090", - "-pong-chaos", - "-dialfreq", "250ms", - "-name", "ping", - }, - Upstreams: []*topology.Upstream{{ - ID: topology.ServiceID{Name: "pong"}, - LocalPort: 9090, - Peer: "peer-dc2-default", - }}, - }, - }, - }, - }), - InitialConfigEntries: []api.ConfigEntry{ - &api.ExportedServicesConfigEntry{ - Name: "default", - Services: []api.ExportedService{{ - Name: "ping", - Consumers: []api.ServiceConsumer{{ - Peer: "peer-dc2-default", - }}, - }}, - }, - }, - }, - { - Name: "dc2", - Nodes: topology.MergeSlices(serversDC2, []*topology.Node{ - { - Kind: topology.NodeKindClient, - Name: "dc2-client1", - Services: []*topology.Service{ - { - ID: topology.ServiceID{Name: "mesh-gateway"}, - Port: 8443, - EnvoyAdminPort: 19000, - IsMeshGateway: true, - }, - }, - }, - { - Kind: topology.NodeKindDataplane, - Name: "dc2-client2", - Services: []*topology.Service{ - { - ID: topology.ServiceID{Name: "pong"}, - Image: "rboyer/pingpong:latest", - Port: 8080, - EnvoyAdminPort: 19000, - Command: []string{ - "-bind", "0.0.0.0:8080", - "-dial", "127.0.0.1:9090", - "-pong-chaos", - "-dialfreq", "250ms", - "-name", "pong", - }, - Upstreams: []*topology.Upstream{{ - ID: topology.ServiceID{Name: "ping"}, - LocalPort: 9090, - Peer: "peer-dc1-default", - }}, - }, - }, - }, - }), - InitialConfigEntries: []api.ConfigEntry{ - &api.ExportedServicesConfigEntry{ - Name: "default", - Services: []api.ExportedService{{ - Name: "ping", - Consumers: []api.ServiceConsumer{{ - Peer: "peer-dc2-default", - }}, - }}, - }, - }, - }, - }, - Peerings: []*topology.Peering{{ - Dialing: topology.PeerCluster{ - Name: "dc1", - }, - Accepting: topology.PeerCluster{ - Name: "dc2", - }, - }}, - } - - sp := sprawltest.Launch(t, cfg) - - for _, cluster := range sp.Topology().Clusters { - leader, err := sp.Leader(cluster.Name) - require.NoError(t, err) - t.Logf("%s: leader = %s", cluster.Name, leader.ID()) - - followers, err := sp.Followers(cluster.Name) - require.NoError(t, err) - for _, f := range followers { - t.Logf("%s: follower = %s", cluster.Name, f.ID()) - } - } -} - -func newTopologyServerSet( - namePrefix string, - num int, - networks []string, - mutateFn func(i int, node *topology.Node), -) []*topology.Node { - var out []*topology.Node - for i := 1; i <= num; i++ { - name := namePrefix + strconv.Itoa(i) - - node := &topology.Node{ - Kind: topology.NodeKindServer, - Name: name, - } - for _, net := range networks { - node.Addresses = append(node.Addresses, &topology.Address{Network: net}) - } - - if mutateFn != nil { - mutateFn(i, node) - } - - out = append(out, node) - } - return out -} diff --git a/testing/deployer/sprawl/tls.go b/testing/deployer/sprawl/tls.go deleted file mode 100644 index 4ba26432f1e14..0000000000000 --- a/testing/deployer/sprawl/tls.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sprawl - -import ( - "bytes" - "context" - "fmt" - "io" - - "github.com/hashicorp/consul/testing/deployer/topology" -) - -const ( - consulUID = "100" - consulGID = "1000" - consulUserArg = consulUID + ":" + consulGID -) - -func tlsPrefixFromNode(node *topology.Node) string { - switch node.Kind { - case topology.NodeKindServer: - return node.Partition + "." + node.Name + ".server" - case topology.NodeKindClient: - return node.Partition + "." + node.Name + ".client" - default: - return "" - } -} - -func tlsCertCreateCommand(node *topology.Node) string { - if node.IsServer() { - return fmt.Sprintf(`consul tls cert create -server -dc=%s -node=%s`, node.Datacenter, node.PodName()) - } else { - return fmt.Sprintf(`consul tls cert create -client -dc=%s`, node.Datacenter) - } -} - -func (s *Sprawl) initTLS(ctx context.Context) error { - for _, cluster := range s.topology.Clusters { - - var buf bytes.Buffer - - // Create the CA if not already done, and proceed to do all of the - // consul CLI calls inside of a throwaway temp directory. - buf.WriteString(` -if [[ ! -f consul-agent-ca-key.pem || ! -f consul-agent-ca.pem ]]; then - consul tls ca create -fi -rm -rf tmp -mkdir -p tmp -cp -a consul-agent-ca-key.pem consul-agent-ca.pem tmp -cd tmp -`) - - for _, node := range cluster.Nodes { - if !node.IsAgent() || node.Disabled { - continue - } - - node.TLSCertPrefix = tlsPrefixFromNode(node) - if node.TLSCertPrefix == "" { - continue - } - - expectPrefix := cluster.Datacenter + "-" + string(node.Kind) + "-consul-0" - - // Conditionally generate these in isolation and rename them to - // not rely upon the numerical indexing. - buf.WriteString(fmt.Sprintf(` -if [[ ! -f %[1]s || ! -f %[2]s ]]; then - rm -f %[3]s %[4]s - %[5]s - mv -f %[3]s %[1]s - mv -f %[4]s %[2]s -fi -`, - "../"+node.TLSCertPrefix+"-key.pem", "../"+node.TLSCertPrefix+".pem", - expectPrefix+"-key.pem", expectPrefix+".pem", - tlsCertCreateCommand(node), - )) - } - - err := s.runner.DockerExec(ctx, []string{ - "run", - "--rm", - "-i", - "--net=none", - "-v", cluster.TLSVolumeName + ":/data", - "busybox:latest", - "sh", "-c", - // Need this so the permissions stick; docker seems to treat unused volumes differently. - `touch /data/VOLUME_PLACEHOLDER && chown -R ` + consulUserArg + ` /data`, - }, io.Discard, nil) - if err != nil { - return fmt.Errorf("could not initialize docker volume for cert data %q: %w", cluster.TLSVolumeName, err) - } - - err = s.runner.DockerExec(ctx, []string{"run", - "--rm", - "-i", - "--net=none", - "-u", consulUserArg, - "-v", cluster.TLSVolumeName + ":/data", - "-w", "/data", - "--entrypoint", "", - cluster.Images.Consul, - "/bin/sh", "-ec", buf.String(), - }, io.Discard, nil) - if err != nil { - return fmt.Errorf("could not create all necessary TLS certificates in docker volume: %v", err) - } - } - - return nil -} diff --git a/testing/deployer/topology/compile.go b/testing/deployer/topology/compile.go deleted file mode 100644 index 78ee5843c1b23..0000000000000 --- a/testing/deployer/topology/compile.go +++ /dev/null @@ -1,674 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package topology - -import ( - crand "crypto/rand" - "encoding/hex" - "errors" - "fmt" - "reflect" - "regexp" - "sort" - - "github.com/google/go-cmp/cmp" - "github.com/hashicorp/go-hclog" -) - -const DockerPrefix = "consulcluster" - -func Compile(logger hclog.Logger, raw *Config) (*Topology, error) { - return compile(logger, raw, nil) -} - -func Recompile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error) { - if prev == nil { - return nil, errors.New("missing previous topology") - } - return compile(logger, raw, prev) -} - -func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error) { - var id string - if prev == nil { - var err error - id, err = newTopologyID() - if err != nil { - return nil, err - } - } else { - id = prev.ID - } - - images := DefaultImages().OverrideWith(raw.Images) - if images.Consul != "" { - return nil, fmt.Errorf("topology.images.consul cannot be set at this level") - } - - if len(raw.Networks) == 0 { - return nil, fmt.Errorf("topology.networks is empty") - } - - networks := make(map[string]*Network) - for _, net := range raw.Networks { - if net.DockerName != "" { - return nil, fmt.Errorf("network %q should not specify DockerName", net.Name) - } - if !IsValidLabel(net.Name) { - return nil, fmt.Errorf("network name is not valid: %s", net.Name) - } - if _, exists := networks[net.Name]; exists { - return nil, fmt.Errorf("cannot have two networks with the same name %q", net.Name) - } - - switch net.Type { - case "": - net.Type = "lan" - case "wan", "lan": - default: - return nil, fmt.Errorf("network %q has unknown type %q", net.Name, net.Type) - } - - networks[net.Name] = net - net.DockerName = DockerPrefix + "-" + net.Name + "-" + id - } - - if len(raw.Clusters) == 0 { - return nil, fmt.Errorf("topology.clusters is empty") - } - - var ( - clusters = make(map[string]*Cluster) - nextIndex int // use a global index so any shared networks work properly with assignments - ) - - foundPeerNames := make(map[string]map[string]struct{}) - for _, c := range raw.Clusters { - if c.Name == "" { - return nil, fmt.Errorf("cluster has no name") - } - - foundPeerNames[c.Name] = make(map[string]struct{}) - - if !IsValidLabel(c.Name) { - return nil, fmt.Errorf("cluster name is not valid: %s", c.Name) - } - - if _, exists := clusters[c.Name]; exists { - return nil, fmt.Errorf("cannot have two clusters with the same name %q; use unique names and override the Datacenter field if that's what you want", c.Name) - } - - if c.Datacenter == "" { - c.Datacenter = c.Name - } else { - if !IsValidLabel(c.Datacenter) { - return nil, fmt.Errorf("datacenter name is not valid: %s", c.Datacenter) - } - } - - clusters[c.Name] = c - if c.NetworkName == "" { - c.NetworkName = c.Name - } - - c.Images = images.OverrideWith(c.Images).ChooseConsul(c.Enterprise) - - if _, ok := networks[c.NetworkName]; !ok { - return nil, fmt.Errorf("cluster %q uses network name %q that does not exist", c.Name, c.NetworkName) - } - - if len(c.Nodes) == 0 { - return nil, fmt.Errorf("cluster %q has no nodes", c.Name) - } - - if c.TLSVolumeName != "" { - return nil, fmt.Errorf("user cannot specify the TLSVolumeName field") - } - - tenancies := make(map[string]map[string]struct{}) - addTenancy := func(partition, namespace string) { - partition = PartitionOrDefault(partition) - namespace = NamespaceOrDefault(namespace) - m, ok := tenancies[partition] - if !ok { - m = make(map[string]struct{}) - tenancies[partition] = m - } - m[namespace] = struct{}{} - } - - for _, ap := range c.Partitions { - addTenancy(ap.Name, "default") - for _, ns := range ap.Namespaces { - addTenancy(ap.Name, ns) - } - } - - for _, ce := range c.InitialConfigEntries { - addTenancy(ce.GetPartition(), ce.GetNamespace()) - } - - seenNodes := make(map[NodeID]struct{}) - for _, n := range c.Nodes { - if n.Name == "" { - return nil, fmt.Errorf("cluster %q node has no name", c.Name) - } - if !IsValidLabel(n.Name) { - return nil, fmt.Errorf("node name is not valid: %s", n.Name) - } - - switch n.Kind { - case NodeKindServer, NodeKindClient, NodeKindDataplane: - default: - return nil, fmt.Errorf("cluster %q node %q has invalid kind: %s", c.Name, n.Name, n.Kind) - } - - n.Partition = PartitionOrDefault(n.Partition) - if !IsValidLabel(n.Partition) { - return nil, fmt.Errorf("node partition is not valid: %s", n.Partition) - } - addTenancy(n.Partition, "default") - - if _, exists := seenNodes[n.ID()]; exists { - return nil, fmt.Errorf("cannot have two nodes in the same cluster %q with the same name %q", c.Name, n.ID()) - } - seenNodes[n.ID()] = struct{}{} - - if len(n.usedPorts) != 0 { - return nil, fmt.Errorf("user cannot specify the usedPorts field") - } - n.usedPorts = make(map[int]int) - exposePort := func(v int) bool { - if _, ok := n.usedPorts[v]; ok { - return false - } - n.usedPorts[v] = 0 - return true - } - - if n.IsAgent() { - // TODO: the ux here is awful; we should be able to examine the topology to guess properly - exposePort(8500) - if n.IsServer() { - exposePort(8503) - } else { - exposePort(8502) - } - } - - if n.Index != 0 { - return nil, fmt.Errorf("user cannot specify the node index") - } - n.Index = nextIndex - nextIndex++ - - n.Images = c.Images.OverrideWith(n.Images).ChooseNode(n.Kind) - - n.Cluster = c.Name - n.Datacenter = c.Datacenter - n.dockerName = DockerPrefix + "-" + n.Name + "-" + id - - if len(n.Addresses) == 0 { - n.Addresses = append(n.Addresses, &Address{Network: c.NetworkName}) - } - var ( - numPublic int - numLocal int - ) - for _, addr := range n.Addresses { - if addr.Network == "" { - return nil, fmt.Errorf("cluster %q node %q has invalid address", c.Name, n.Name) - } - - if addr.Type != "" { - return nil, fmt.Errorf("user cannot specify the address type directly") - } - - net, ok := networks[addr.Network] - if !ok { - return nil, fmt.Errorf("cluster %q node %q uses network name %q that does not exist", c.Name, n.Name, addr.Network) - } - - if net.IsPublic() { - numPublic++ - } else if net.IsLocal() { - numLocal++ - } - addr.Type = net.Type - - addr.DockerNetworkName = net.DockerName - } - - if numLocal == 0 { - return nil, fmt.Errorf("cluster %q node %q has no local addresses", c.Name, n.Name) - } - if numPublic > 1 { - return nil, fmt.Errorf("cluster %q node %q has more than one public address", c.Name, n.Name) - } - - seenServices := make(map[ServiceID]struct{}) - for _, svc := range n.Services { - if n.IsAgent() { - // Default to that of the enclosing node. - svc.ID.Partition = n.Partition - } - svc.ID.Normalize() - - // Denormalize - svc.Node = n - - if !IsValidLabel(svc.ID.Partition) { - return nil, fmt.Errorf("service partition is not valid: %s", svc.ID.Partition) - } - if !IsValidLabel(svc.ID.Namespace) { - return nil, fmt.Errorf("service namespace is not valid: %s", svc.ID.Namespace) - } - if !IsValidLabel(svc.ID.Name) { - return nil, fmt.Errorf("service name is not valid: %s", svc.ID.Name) - } - addTenancy(svc.ID.Partition, svc.ID.Namespace) - - if _, exists := seenServices[svc.ID]; exists { - return nil, fmt.Errorf("cannot have two services on the same node %q in the same cluster %q with the same name %q", n.ID(), c.Name, svc.ID) - } - seenServices[svc.ID] = struct{}{} - - if !svc.DisableServiceMesh && n.IsDataplane() { - if svc.EnvoyPublicListenerPort <= 0 { - if _, ok := n.usedPorts[20000]; !ok { - // For convenience the FIRST service on a node can get 20000 for free. - svc.EnvoyPublicListenerPort = 20000 - } else { - return nil, fmt.Errorf("envoy public listener port is required") - } - } - } - - // add all of the service ports - for _, port := range svc.ports() { - if ok := exposePort(port); !ok { - return nil, fmt.Errorf("port used more than once on cluster %q node %q: %d", c.Name, n.ID(), port) - } - } - - // TODO(rb): re-expose? - // switch svc.Protocol { - // case "": - // svc.Protocol = "tcp" - // fallthrough - // case "tcp": - // if svc.CheckHTTP != "" { - // return nil, fmt.Errorf("cannot set CheckHTTP for tcp service") - // } - // case "http": - // if svc.CheckTCP != "" { - // return nil, fmt.Errorf("cannot set CheckTCP for tcp service") - // } - // default: - // return nil, fmt.Errorf("service has invalid protocol: %s", svc.Protocol) - // } - - for _, u := range svc.Upstreams { - // Default to that of the enclosing service. - if u.Peer == "" { - if u.ID.Partition == "" { - u.ID.Partition = svc.ID.Partition - } - if u.ID.Namespace == "" { - u.ID.Namespace = svc.ID.Namespace - } - } else { - if u.ID.Partition != "" { - u.ID.Partition = "" // irrelevant here; we'll set it to the value of the OTHER side for plumbing purposes in tests - } - u.ID.Namespace = NamespaceOrDefault(u.ID.Namespace) - foundPeerNames[c.Name][u.Peer] = struct{}{} - } - - if u.ID.Name == "" { - return nil, fmt.Errorf("upstream service name is required") - } - addTenancy(u.ID.Partition, u.ID.Namespace) - } - - if err := svc.Validate(); err != nil { - return nil, fmt.Errorf("cluster %q node %q service %q is not valid: %w", c.Name, n.Name, svc.ID.String(), err) - } - } - } - - // Explode this into the explicit list based on stray references made. - c.Partitions = nil - for ap, nsMap := range tenancies { - p := &Partition{ - Name: ap, - } - for ns := range nsMap { - p.Namespaces = append(p.Namespaces, ns) - } - sort.Strings(p.Namespaces) - c.Partitions = append(c.Partitions, p) - } - sort.Slice(c.Partitions, func(i, j int) bool { - return c.Partitions[i].Name < c.Partitions[j].Name - }) - - if !c.Enterprise { - expect := []*Partition{{Name: "default", Namespaces: []string{"default"}}} - if !reflect.DeepEqual(c.Partitions, expect) { - return nil, fmt.Errorf("cluster %q references non-default partitions or namespaces but is CE", c.Name) - } - } - } - - clusteredPeerings := make(map[string]map[string]*PeerCluster) // local-cluster -> local-peer -> info - addPeerMapEntry := func(pc PeerCluster) { - pm, ok := clusteredPeerings[pc.Name] - if !ok { - pm = make(map[string]*PeerCluster) - clusteredPeerings[pc.Name] = pm - } - pm[pc.PeerName] = &pc - } - for _, p := range raw.Peerings { - dialingCluster, ok := clusters[p.Dialing.Name] - if !ok { - return nil, fmt.Errorf("peering references a dialing cluster that does not exist: %s", p.Dialing.Name) - } - acceptingCluster, ok := clusters[p.Accepting.Name] - if !ok { - return nil, fmt.Errorf("peering references an accepting cluster that does not exist: %s", p.Accepting.Name) - } - if p.Dialing.Name == p.Accepting.Name { - return nil, fmt.Errorf("self peerings are not allowed: %s", p.Dialing.Name) - } - - p.Dialing.Partition = PartitionOrDefault(p.Dialing.Partition) - p.Accepting.Partition = PartitionOrDefault(p.Accepting.Partition) - - if dialingCluster.Enterprise { - if !dialingCluster.hasPartition(p.Dialing.Partition) { - return nil, fmt.Errorf("dialing side of peering cannot reference a partition that does not exist: %s", p.Dialing.Partition) - } - } else { - if p.Dialing.Partition != "default" { - return nil, fmt.Errorf("dialing side of peering cannot reference a partition when CE") - } - } - if acceptingCluster.Enterprise { - if !acceptingCluster.hasPartition(p.Accepting.Partition) { - return nil, fmt.Errorf("accepting side of peering cannot reference a partition that does not exist: %s", p.Accepting.Partition) - } - } else { - if p.Accepting.Partition != "default" { - return nil, fmt.Errorf("accepting side of peering cannot reference a partition when CE") - } - } - - if p.Dialing.PeerName == "" { - p.Dialing.PeerName = "peer-" + p.Accepting.Name + "-" + p.Accepting.Partition - } - if p.Accepting.PeerName == "" { - p.Accepting.PeerName = "peer-" + p.Dialing.Name + "-" + p.Dialing.Partition - } - - { // Ensure the link fields do not have recursive links. - p.Dialing.Link = nil - p.Accepting.Link = nil - - // Copy the un-linked data before setting the link - pa := p.Accepting - pd := p.Dialing - - p.Accepting.Link = &pd - p.Dialing.Link = &pa - } - - addPeerMapEntry(p.Accepting) - addPeerMapEntry(p.Dialing) - - delete(foundPeerNames[p.Accepting.Name], p.Accepting.PeerName) - delete(foundPeerNames[p.Dialing.Name], p.Dialing.PeerName) - } - - for cluster, peers := range foundPeerNames { - if len(peers) > 0 { - var pretty []string - for name := range peers { - pretty = append(pretty, name) - } - sort.Strings(pretty) - return nil, fmt.Errorf("cluster[%s] found topology references to peerings that do not exist: %v", cluster, pretty) - } - } - - // after we decoded the peering stuff, we can fill in some computed data in the upstreams - for _, c := range clusters { - c.Peerings = clusteredPeerings[c.Name] - for _, n := range c.Nodes { - for _, svc := range n.Services { - for _, u := range svc.Upstreams { - if u.Peer == "" { - u.Cluster = c.Name - u.Peering = nil - continue - } - remotePeer, ok := c.Peerings[u.Peer] - if !ok { - return nil, fmt.Errorf("not possible") - } - u.Cluster = remotePeer.Link.Name - u.Peering = remotePeer.Link - // this helps in generating fortio assertions; otherwise field is ignored - u.ID.Partition = remotePeer.Link.Partition - } - } - } - } - - t := &Topology{ - ID: id, - Networks: networks, - Clusters: clusters, - Images: images, - Peerings: raw.Peerings, - } - - if prev != nil { - // networks cannot change - if !sameKeys(prev.Networks, t.Networks) { - return nil, fmt.Errorf("cannot create or destroy networks") - } - - for _, newNetwork := range t.Networks { - oldNetwork := prev.Networks[newNetwork.Name] - - // Carryover - newNetwork.inheritFromExisting(oldNetwork) - - if err := isSame(oldNetwork, newNetwork); err != nil { - return nil, fmt.Errorf("networks cannot change: %w", err) - } - - } - - // cannot add or remove an entire cluster - if !sameKeys(prev.Clusters, t.Clusters) { - return nil, fmt.Errorf("cannot create or destroy clusters") - } - - for _, newCluster := range t.Clusters { - oldCluster := prev.Clusters[newCluster.Name] - - // Carryover - newCluster.inheritFromExisting(oldCluster) - - if newCluster.Name != oldCluster.Name || - newCluster.NetworkName != oldCluster.NetworkName || - newCluster.Datacenter != oldCluster.Datacenter || - newCluster.Enterprise != oldCluster.Enterprise { - return nil, fmt.Errorf("cannot edit some cluster fields for %q", newCluster.Name) - } - - // WARN on presence of some things. - if len(newCluster.InitialConfigEntries) > 0 { - logger.Warn("initial config entries were provided, but are skipped on recompile") - } - - // Check NODES - if err := inheritAndValidateNodes(oldCluster.Nodes, newCluster.Nodes); err != nil { - return nil, fmt.Errorf("some immutable aspects of nodes were changed in cluster %q: %w", newCluster.Name, err) - } - } - } - - return t, nil -} - -const permutedWarning = "use the disabled node kind if you want to ignore a node" - -func inheritAndValidateNodes( - prev, curr []*Node, -) error { - nodeMap := mapifyNodes(curr) - - for prevIdx, node := range prev { - currNode, ok := nodeMap[node.ID()] - if !ok { - return fmt.Errorf("node %q has vanished; "+permutedWarning, node.ID()) - } - // Ensure it hasn't been permuted. - if currNode.Pos != prevIdx { - return fmt.Errorf( - "node %q has been shuffled %d -> %d; "+permutedWarning, - node.ID(), - prevIdx, - currNode.Pos, - ) - } - - if currNode.Node.Kind != node.Kind || - currNode.Node.Partition != node.Partition || - currNode.Node.Name != node.Name || - currNode.Node.Index != node.Index || - len(currNode.Node.Addresses) != len(node.Addresses) || - !sameKeys(currNode.Node.usedPorts, node.usedPorts) { - return fmt.Errorf("cannot edit some node fields for %q", node.ID()) - } - - currNode.Node.inheritFromExisting(node) - - for i := 0; i < len(currNode.Node.Addresses); i++ { - prevAddr := node.Addresses[i] - currAddr := currNode.Node.Addresses[i] - - if prevAddr.Network != currAddr.Network { - return fmt.Errorf("addresses were shuffled for node %q", node.ID()) - } - - if prevAddr.Type != currAddr.Type { - return fmt.Errorf("cannot edit some address fields for %q", node.ID()) - } - - currAddr.inheritFromExisting(prevAddr) - } - - svcMap := mapifyServices(currNode.Node.Services) - - for _, svc := range node.Services { - currSvc, ok := svcMap[svc.ID] - if !ok { - continue // service has vanished, this is ok - } - // don't care about index permutation - - if currSvc.ID != svc.ID || - currSvc.Port != svc.Port || - currSvc.EnvoyAdminPort != svc.EnvoyAdminPort || - currSvc.EnvoyPublicListenerPort != svc.EnvoyPublicListenerPort || - isSame(currSvc.Command, svc.Command) != nil || - isSame(currSvc.Env, svc.Env) != nil { - return fmt.Errorf("cannot edit some address fields for %q", svc.ID) - } - - currSvc.inheritFromExisting(svc) - } - } - return nil -} - -func newTopologyID() (string, error) { - const n = 16 - id := make([]byte, n) - if _, err := crand.Read(id[:]); err != nil { - return "", err - } - return hex.EncodeToString(id)[:n], nil -} - -// matches valid DNS labels according to RFC 1123, should be at most 63 -// characters according to the RFC -var validLabel = regexp.MustCompile(`^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?$`) - -// IsValidLabel returns true if the string given is a valid DNS label (RFC 1123). -// Note: the only difference between RFC 1035 and RFC 1123 labels is that in -// RFC 1123 labels can begin with a number. -func IsValidLabel(name string) bool { - return validLabel.MatchString(name) -} - -// ValidateLabel is similar to IsValidLabel except it returns an error -// instead of false when name is not a valid DNS label. The error will contain -// reference to what constitutes a valid DNS label. -func ValidateLabel(name string) error { - if !IsValidLabel(name) { - return errors.New("a valid DNS label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character") - } - return nil -} - -func isSame(x, y any) error { - diff := cmp.Diff(x, y) - if diff != "" { - return fmt.Errorf("values are not equal\n--- expected\n+++ actual\n%v", diff) - } - return nil -} - -func sameKeys[K comparable, V any](x, y map[K]V) bool { - if len(x) != len(y) { - return false - } - - for kx := range x { - if _, ok := y[kx]; !ok { - return false - } - } - return true -} - -func mapifyNodes(nodes []*Node) map[NodeID]nodeWithPosition { - m := make(map[NodeID]nodeWithPosition) - for i, node := range nodes { - m[node.ID()] = nodeWithPosition{ - Pos: i, - Node: node, - } - } - return m -} - -type nodeWithPosition struct { - Pos int - Node *Node -} - -func mapifyServices(services []*Service) map[ServiceID]*Service { - m := make(map[ServiceID]*Service) - for _, svc := range services { - m[svc.ID] = svc - } - return m -} diff --git a/testing/deployer/topology/default_cdp.go b/testing/deployer/topology/default_cdp.go deleted file mode 100644 index 22424d2dd1211..0000000000000 --- a/testing/deployer/topology/default_cdp.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package topology - -const DefaultDataplaneImage = "hashicorp/consul-dataplane:1.1.0" diff --git a/testing/deployer/topology/default_consul.go b/testing/deployer/topology/default_consul.go deleted file mode 100644 index f9542f16643d6..0000000000000 --- a/testing/deployer/topology/default_consul.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package topology - -const DefaultConsulImage = "hashicorp/consul:1.15.2" -const DefaultConsulEnterpriseImage = "hashicorp/consul-enterprise:1.15.2-ent" diff --git a/testing/deployer/topology/default_envoy.go b/testing/deployer/topology/default_envoy.go deleted file mode 100644 index c557a318a17fd..0000000000000 --- a/testing/deployer/topology/default_envoy.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package topology - -const DefaultEnvoyImage = "envoyproxy/envoy:v1.25.1" diff --git a/testing/deployer/topology/ids.go b/testing/deployer/topology/ids.go deleted file mode 100644 index 3f964b12548e6..0000000000000 --- a/testing/deployer/topology/ids.go +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package topology - -import ( - "fmt" - - "github.com/hashicorp/consul/api" -) - -type NodeServiceID struct { - Node string - Service string `json:",omitempty"` - Namespace string `json:",omitempty"` - Partition string `json:",omitempty"` -} - -func NewNodeServiceID(node, service, namespace, partition string) NodeServiceID { - id := NodeServiceID{ - Node: node, - Service: service, - Namespace: namespace, - Partition: partition, - } - id.Normalize() - return id -} - -func (id NodeServiceID) NodeID() NodeID { - return NewNodeID(id.Node, id.Partition) -} - -func (id NodeServiceID) ServiceID() ServiceID { - return NewServiceID(id.Service, id.Namespace, id.Partition) -} - -func (id *NodeServiceID) Normalize() { - id.Namespace = NamespaceOrDefault(id.Namespace) - id.Partition = PartitionOrDefault(id.Partition) -} - -func (id NodeServiceID) String() string { - return fmt.Sprintf("%s/%s/%s/%s", id.Partition, id.Node, id.Namespace, id.Service) -} - -type NodeID struct { - Name string `json:",omitempty"` - Partition string `json:",omitempty"` -} - -func NewNodeID(name, partition string) NodeID { - id := NodeID{ - Name: name, - Partition: partition, - } - id.Normalize() - return id -} - -func (id *NodeID) Normalize() { - id.Partition = PartitionOrDefault(id.Partition) -} - -func (id NodeID) String() string { - return fmt.Sprintf("%s/%s", id.Partition, id.Name) -} - -func (id NodeID) ACLString() string { - return fmt.Sprintf("%s--%s", id.Partition, id.Name) -} -func (id NodeID) TFString() string { - return id.ACLString() -} - -type ServiceID struct { - Name string `json:",omitempty"` - Namespace string `json:",omitempty"` - Partition string `json:",omitempty"` -} - -func NewServiceID(name, namespace, partition string) ServiceID { - id := ServiceID{ - Name: name, - Namespace: namespace, - Partition: partition, - } - id.Normalize() - return id -} - -func (id ServiceID) Less(other ServiceID) bool { - if id.Partition != other.Partition { - return id.Partition < other.Partition - } - if id.Namespace != other.Namespace { - return id.Namespace < other.Namespace - } - return id.Name < other.Name -} - -func (id *ServiceID) Normalize() { - id.Namespace = NamespaceOrDefault(id.Namespace) - id.Partition = PartitionOrDefault(id.Partition) -} - -func (id ServiceID) String() string { - return fmt.Sprintf("%s/%s/%s", id.Partition, id.Namespace, id.Name) -} - -func (id ServiceID) ACLString() string { - return fmt.Sprintf("%s--%s--%s", id.Partition, id.Namespace, id.Name) -} -func (id ServiceID) TFString() string { - return id.ACLString() -} - -func PartitionOrDefault(name string) string { - if name == "" { - return "default" - } - return name -} -func NamespaceOrDefault(name string) string { - if name == "" { - return "default" - } - return name -} - -func DefaultToEmpty(name string) string { - if name == "default" { - return "" - } - return name -} - -// PartitionQueryOptions returns an *api.QueryOptions with the given partition -// field set only if the partition is non-default. This helps when writing -// tests for joint use in CE and ENT. -func PartitionQueryOptions(partition string) *api.QueryOptions { - return &api.QueryOptions{ - Partition: DefaultToEmpty(partition), - } -} diff --git a/testing/deployer/topology/images.go b/testing/deployer/topology/images.go deleted file mode 100644 index d58d7a1213dee..0000000000000 --- a/testing/deployer/topology/images.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package topology - -import ( - "strings" -) - -type Images struct { - Consul string `json:",omitempty"` - ConsulCE string `json:",omitempty"` - ConsulEnterprise string `json:",omitempty"` - Envoy string - Dataplane string -} - -func (i Images) LocalDataplaneImage() string { - if i.Dataplane == "" { - return "" - } - - img, tag, ok := strings.Cut(i.Dataplane, ":") - if !ok { - tag = "latest" - } - - repo, name, ok := strings.Cut(img, "/") - if ok { - name = repo + "-" + name - } - - // ex: local/hashicorp-consul-dataplane:1.1.0 - return "local/" + name + ":" + tag -} - -func (i Images) EnvoyConsulImage() string { - if i.Consul == "" || i.Envoy == "" { - return "" - } - - img1, tag1, ok1 := strings.Cut(i.Consul, ":") - img2, tag2, ok2 := strings.Cut(i.Envoy, ":") - if !ok1 { - tag1 = "latest" - } - if !ok2 { - tag2 = "latest" - } - - repo1, name1, ok1 := strings.Cut(img1, "/") - repo2, name2, ok2 := strings.Cut(img2, "/") - - if ok1 { - name1 = repo1 + "-" + name1 - } else { - name1 = repo1 - } - if ok2 { - name2 = repo2 + "-" + name2 - } else { - name2 = repo2 - } - - // ex: local/hashicorp-consul-and-envoyproxy-envoy:1.15.0-with-v1.26.2 - return "local/" + name1 + "-and-" + name2 + ":" + tag1 + "-with-" + tag2 -} - -func (i Images) ChooseNode(kind NodeKind) Images { - switch kind { - case NodeKindServer: - i.Envoy = "" - i.Dataplane = "" - case NodeKindClient: - i.Dataplane = "" - case NodeKindDataplane: - i.Envoy = "" - default: - // do nothing - } - return i -} - -func (i Images) ChooseConsul(enterprise bool) Images { - if enterprise { - i.Consul = i.ConsulEnterprise - } else { - i.Consul = i.ConsulCE - } - i.ConsulEnterprise = "" - i.ConsulCE = "" - return i -} - -func (i Images) OverrideWith(i2 Images) Images { - if i2.Consul != "" { - i.Consul = i2.Consul - } - if i2.ConsulCE != "" { - i.ConsulCE = i2.ConsulCE - } - if i2.ConsulEnterprise != "" { - i.ConsulEnterprise = i2.ConsulEnterprise - } - if i2.Envoy != "" { - i.Envoy = i2.Envoy - } - if i2.Dataplane != "" { - i.Dataplane = i2.Dataplane - } - return i -} - -// DefaultImages controls which specific docker images are used as default -// values for topology components that do not specify values. -// -// These can be bulk-updated using the make target 'make update-defaults' -func DefaultImages() Images { - return Images{ - Consul: "", - ConsulCE: DefaultConsulImage, - ConsulEnterprise: DefaultConsulEnterpriseImage, - Envoy: DefaultEnvoyImage, - Dataplane: DefaultDataplaneImage, - } -} diff --git a/testing/deployer/topology/images_test.go b/testing/deployer/topology/images_test.go deleted file mode 100644 index d3ea2136e260c..0000000000000 --- a/testing/deployer/topology/images_test.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package topology - -import ( - "strconv" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestImages_EnvoyConsulImage(t *testing.T) { - type testcase struct { - consul, envoy string - expect string - } - - run := func(t *testing.T, tc testcase) { - i := Images{Consul: tc.consul, Envoy: tc.envoy} - j := i.EnvoyConsulImage() - require.Equal(t, tc.expect, j) - } - - cases := []testcase{ - { - consul: "", - envoy: "", - expect: "", - }, - { - consul: "consul", - envoy: "", - expect: "", - }, - { - consul: "", - envoy: "envoy", - expect: "", - }, - { - consul: "consul", - envoy: "envoy", - expect: "local/consul-and-envoy:latest-with-latest", - }, - // repos - { - consul: "hashicorp/consul", - envoy: "envoy", - expect: "local/hashicorp-consul-and-envoy:latest-with-latest", - }, - { - consul: "consul", - envoy: "envoyproxy/envoy", - expect: "local/consul-and-envoyproxy-envoy:latest-with-latest", - }, - { - consul: "hashicorp/consul", - envoy: "envoyproxy/envoy", - expect: "local/hashicorp-consul-and-envoyproxy-envoy:latest-with-latest", - }, - // tags - { - consul: "consul:1.15.0", - envoy: "envoy", - expect: "local/consul-and-envoy:1.15.0-with-latest", - }, - { - consul: "consul", - envoy: "envoy:v1.26.1", - expect: "local/consul-and-envoy:latest-with-v1.26.1", - }, - { - consul: "consul:1.15.0", - envoy: "envoy:v1.26.1", - expect: "local/consul-and-envoy:1.15.0-with-v1.26.1", - }, - // repos+tags - { - consul: "hashicorp/consul:1.15.0", - envoy: "envoy:v1.26.1", - expect: "local/hashicorp-consul-and-envoy:1.15.0-with-v1.26.1", - }, - { - consul: "consul:1.15.0", - envoy: "envoyproxy/envoy:v1.26.1", - expect: "local/consul-and-envoyproxy-envoy:1.15.0-with-v1.26.1", - }, - { - consul: "hashicorp/consul:1.15.0", - envoy: "envoyproxy/envoy:v1.26.1", - expect: "local/hashicorp-consul-and-envoyproxy-envoy:1.15.0-with-v1.26.1", - }, - } - - for i, tc := range cases { - t.Run(strconv.Itoa(i), func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/testing/deployer/topology/topology.go b/testing/deployer/topology/topology.go deleted file mode 100644 index b485436612688..0000000000000 --- a/testing/deployer/topology/topology.go +++ /dev/null @@ -1,790 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package topology - -import ( - "errors" - "fmt" - "net" - "net/netip" - "reflect" - "sort" - - "github.com/hashicorp/consul/api" -) - -type Topology struct { - ID string - - // Images controls which specific docker images are used when running this - // node. Non-empty fields here override non-empty fields inherited from the - // general default values from DefaultImages(). - Images Images - - // Networks is the list of networks to create for this set of clusters. - Networks map[string]*Network - - // Clusters defines the list of Consul clusters that should be created, and - // their associated workloads. - Clusters map[string]*Cluster - - // Peerings defines the list of pairwise peerings that should be established - // between clusters. - Peerings []*Peering `json:",omitempty"` -} - -func (t *Topology) DigestExposedProxyPort(netName string, proxyPort int) (bool, error) { - net, ok := t.Networks[netName] - if !ok { - return false, fmt.Errorf("found output network that does not exist: %s", netName) - } - if net.ProxyPort == proxyPort { - return false, nil - } - - net.ProxyPort = proxyPort - - // Denormalize for UX. - for _, cluster := range t.Clusters { - for _, node := range cluster.Nodes { - for _, addr := range node.Addresses { - if addr.Network == netName { - addr.ProxyPort = proxyPort - } - } - } - } - - return true, nil -} - -func (t *Topology) SortedNetworks() []*Network { - var out []*Network - for _, n := range t.Networks { - out = append(out, n) - } - sort.Slice(out, func(i, j int) bool { - return out[i].Name < out[j].Name - }) - return out -} - -func (t *Topology) SortedClusters() []*Cluster { - var out []*Cluster - for _, c := range t.Clusters { - out = append(out, c) - } - sort.Slice(out, func(i, j int) bool { - return out[i].Name < out[j].Name - }) - return out -} - -type Config struct { - // Images controls which specific docker images are used when running this - // node. Non-empty fields here override non-empty fields inherited from the - // general default values from DefaultImages(). - Images Images - - // Networks is the list of networks to create for this set of clusters. - Networks []*Network - - // Clusters defines the list of Consul clusters that should be created, and - // their associated workloads. - Clusters []*Cluster - - // Peerings defines the list of pairwise peerings that should be established - // between clusters. - Peerings []*Peering -} - -func (c *Config) Cluster(name string) *Cluster { - for _, cluster := range c.Clusters { - if cluster.Name == name { - return cluster - } - } - return nil -} - -type Network struct { - Type string // lan/wan ; empty means lan - Name string // logical name - - // computed at topology compile - DockerName string - // generated during network-and-tls - Subnet string - IPPool []string `json:"-"` - // generated during network-and-tls - ProxyAddress string `json:",omitempty"` - DNSAddress string `json:",omitempty"` - // filled in from terraform outputs after network-and-tls - ProxyPort int `json:",omitempty"` -} - -func (n *Network) IsLocal() bool { - return n.Type == "" || n.Type == "lan" -} - -func (n *Network) IsPublic() bool { - return n.Type == "wan" -} - -func (n *Network) inheritFromExisting(existing *Network) { - n.Subnet = existing.Subnet - n.IPPool = existing.IPPool - n.ProxyAddress = existing.ProxyAddress - n.DNSAddress = existing.DNSAddress - n.ProxyPort = existing.ProxyPort -} - -func (n *Network) IPByIndex(index int) string { - if index >= len(n.IPPool) { - panic(fmt.Sprintf( - "not enough ips on this network to assign index %d: %d", - len(n.IPPool), index, - )) - } - return n.IPPool[index] -} - -func (n *Network) SetSubnet(subnet string) (bool, error) { - if n.Subnet == subnet { - return false, nil - } - - p, err := netip.ParsePrefix(subnet) - if err != nil { - return false, err - } - if !p.IsValid() { - return false, errors.New("not valid") - } - p = p.Masked() - - var ipPool []string - - addr := p.Addr() - for { - if !p.Contains(addr) { - break - } - ipPool = append(ipPool, addr.String()) - addr = addr.Next() - } - - ipPool = ipPool[2:] // skip the x.x.x.{0,1} - - n.Subnet = subnet - n.IPPool = ipPool - return true, nil -} - -// Cluster represents a single standalone install of Consul. This is the unit -// of what is peered when using cluster peering. Older consul installs would -// call this a datacenter. -type Cluster struct { - Name string - NetworkName string // empty assumes same as Name - - // Images controls which specific docker images are used when running this - // cluster. Non-empty fields here override non-empty fields inherited from - // the enclosing Topology. - Images Images - - // Enterprise marks this cluster as desiring to run Consul Enterprise - // components. - Enterprise bool `json:",omitempty"` - - // Nodes is the definition of the nodes (agent-less and agent-ful). - Nodes []*Node - - // Partitions is a list of tenancy configurations that should be created - // after the servers come up but before the clients and the rest of the - // topology starts. - // - // Enterprise Only. - Partitions []*Partition `json:",omitempty"` - - // Datacenter defaults to "Name" if left unspecified. It lets you possibly - // create multiple peer clusters with identical datacenter names. - Datacenter string - - // InitialConfigEntries is a convenience function to have some config - // entries created after the servers start up but before the rest of the - // topology comes up. - InitialConfigEntries []api.ConfigEntry `json:",omitempty"` - - // TLSVolumeName is the docker volume name containing the various certs - // generated by 'consul tls cert create' - // - // This is generated during the networking phase and is not user specified. - TLSVolumeName string `json:",omitempty"` - - // Peerings is a map of peering names to information about that peering in this cluster - // - // Denormalized during compile. - Peerings map[string]*PeerCluster `json:",omitempty"` -} - -func (c *Cluster) inheritFromExisting(existing *Cluster) { - c.TLSVolumeName = existing.TLSVolumeName -} - -type Partition struct { - Name string - Namespaces []string -} - -func (c *Cluster) hasPartition(p string) bool { - for _, partition := range c.Partitions { - if partition.Name == p { - return true - } - } - return false -} - -func (c *Cluster) PartitionQueryOptionsList() []*api.QueryOptions { - if !c.Enterprise { - return []*api.QueryOptions{{}} - } - - var out []*api.QueryOptions - for _, p := range c.Partitions { - out = append(out, &api.QueryOptions{Partition: p.Name}) - } - return out -} - -func (c *Cluster) ServerNodes() []*Node { - var out []*Node - for _, node := range c.SortedNodes() { - if node.Kind != NodeKindServer || node.Disabled { - continue - } - out = append(out, node) - } - return out -} - -func (c *Cluster) ServerByAddr(addr string) *Node { - expect, _, err := net.SplitHostPort(addr) - if err != nil { - return nil - } - - for _, node := range c.Nodes { - if node.Kind != NodeKindServer || node.Disabled { - continue - } - if node.LocalAddress() == expect { - return node - } - } - - return nil -} - -func (c *Cluster) FirstServer() *Node { - for _, node := range c.Nodes { - if node.IsServer() && !node.Disabled && node.ExposedPort(8500) > 0 { - return node - } - } - return nil -} - -func (c *Cluster) FirstClient() *Node { - for _, node := range c.Nodes { - if node.Kind != NodeKindClient || node.Disabled { - continue - } - return node - } - return nil -} - -func (c *Cluster) ActiveNodes() []*Node { - var out []*Node - for _, node := range c.Nodes { - if !node.Disabled { - out = append(out, node) - } - } - return out -} - -func (c *Cluster) SortedNodes() []*Node { - var out []*Node - out = append(out, c.Nodes...) - - kindOrder := map[NodeKind]int{ - NodeKindServer: 1, - NodeKindClient: 2, - NodeKindDataplane: 2, - } - sort.Slice(out, func(i, j int) bool { - ni, nj := out[i], out[j] - - // servers before clients/dataplanes - ki, kj := kindOrder[ni.Kind], kindOrder[nj.Kind] - if ki < kj { - return true - } else if ki > kj { - return false - } - - // lex sort by partition - if ni.Partition < nj.Partition { - return true - } else if ni.Partition > nj.Partition { - return false - } - - // lex sort by name - return ni.Name < nj.Name - }) - return out -} - -func (c *Cluster) FindService(id NodeServiceID) *Service { - id.Normalize() - - nid := id.NodeID() - sid := id.ServiceID() - return c.ServiceByID(nid, sid) -} - -func (c *Cluster) ServiceByID(nid NodeID, sid ServiceID) *Service { - return c.NodeByID(nid).ServiceByID(sid) -} - -func (c *Cluster) ServicesByID(sid ServiceID) []*Service { - sid.Normalize() - - var out []*Service - for _, n := range c.Nodes { - for _, svc := range n.Services { - if svc.ID == sid { - out = append(out, svc) - } - } - } - return out -} - -func (c *Cluster) NodeByID(nid NodeID) *Node { - nid.Normalize() - for _, n := range c.Nodes { - if n.ID() == nid { - return n - } - } - panic("node not found: " + nid.String()) -} - -type Address struct { - Network string - - // denormalized at topology compile - Type string - // denormalized at topology compile - DockerNetworkName string - // generated after network-and-tls - IPAddress string - // denormalized from terraform outputs stored in the Network - ProxyPort int `json:",omitempty"` -} - -func (a *Address) inheritFromExisting(existing *Address) { - a.IPAddress = existing.IPAddress - a.ProxyPort = existing.ProxyPort -} - -func (a Address) IsLocal() bool { - return a.Type == "" || a.Type == "lan" -} - -func (a Address) IsPublic() bool { - return a.Type == "wan" -} - -type NodeKind string - -const ( - NodeKindUnknown NodeKind = "" - NodeKindServer NodeKind = "server" - NodeKindClient NodeKind = "client" - NodeKindDataplane NodeKind = "dataplane" -) - -// TODO: rename pod -type Node struct { - Kind NodeKind - Partition string // will be not empty - Name string // logical name - - // Images controls which specific docker images are used when running this - // node. Non-empty fields here override non-empty fields inherited from - // the enclosing Cluster. - Images Images - - // AgentEnv contains optional environment variables to attach to Consul agents. - AgentEnv []string - - Disabled bool `json:",omitempty"` - - Addresses []*Address - Services []*Service - - // denormalized at topology compile - Cluster string - Datacenter string - - // computed at topology compile - Index int - - // generated during network-and-tls - TLSCertPrefix string `json:",omitempty"` - - // dockerName is computed at topology compile - dockerName string - - // usedPorts has keys that are computed at topology compile (internal - // ports) and values initialized to zero until terraform creates the pods - // and extracts the exposed port values from output variables. - usedPorts map[int]int // keys are from compile / values are from terraform output vars -} - -func (n *Node) DockerName() string { - return n.dockerName -} - -func (n *Node) ExposedPort(internalPort int) int { - return n.usedPorts[internalPort] -} - -func (n *Node) SortedPorts() []int { - var out []int - for internalPort := range n.usedPorts { - out = append(out, internalPort) - } - sort.Ints(out) - return out -} - -func (n *Node) inheritFromExisting(existing *Node) { - n.TLSCertPrefix = existing.TLSCertPrefix - - merged := existing.usedPorts - for k, vNew := range n.usedPorts { - if _, present := merged[k]; !present { - merged[k] = vNew - } - } - n.usedPorts = merged -} - -func (n *Node) String() string { - return n.ID().String() -} - -func (n *Node) ID() NodeID { - return NewNodeID(n.Name, n.Partition) -} - -func (n *Node) CatalogID() NodeID { - return NewNodeID(n.PodName(), n.Partition) -} - -func (n *Node) PodName() string { - return n.dockerName + "-pod" -} - -func (n *Node) AddressByNetwork(name string) *Address { - for _, a := range n.Addresses { - if a.Network == name { - return a - } - } - return nil -} - -func (n *Node) LocalAddress() string { - for _, a := range n.Addresses { - if a.IsLocal() { - if a.IPAddress == "" { - panic("node has no assigned local address") - } - return a.IPAddress - } - } - panic("node has no local network") -} - -func (n *Node) HasPublicAddress() bool { - for _, a := range n.Addresses { - if a.IsPublic() { - return true - } - } - return false -} - -func (n *Node) LocalProxyPort() int { - for _, a := range n.Addresses { - if a.IsLocal() { - if a.ProxyPort > 0 { - return a.ProxyPort - } - panic("node has no assigned local address") - } - } - panic("node has no local network") -} - -func (n *Node) PublicAddress() string { - for _, a := range n.Addresses { - if a.IsPublic() { - if a.IPAddress == "" { - panic("node has no assigned public address") - } - return a.IPAddress - } - } - panic("node has no public network") -} - -func (n *Node) PublicProxyPort() int { - for _, a := range n.Addresses { - if a.IsPublic() { - if a.ProxyPort > 0 { - return a.ProxyPort - } - panic("node has no assigned public address") - } - } - panic("node has no public network") -} - -func (n *Node) IsServer() bool { - return n.Kind == NodeKindServer -} - -func (n *Node) IsAgent() bool { - return n.Kind == NodeKindServer || n.Kind == NodeKindClient -} - -func (n *Node) RunsWorkloads() bool { - return n.IsAgent() || n.IsDataplane() -} - -func (n *Node) IsDataplane() bool { - return n.Kind == NodeKindDataplane -} - -func (n *Node) SortedServices() []*Service { - var out []*Service - out = append(out, n.Services...) - sort.Slice(out, func(i, j int) bool { - mi := out[i].IsMeshGateway - mj := out[j].IsMeshGateway - if mi && !mi { - return false - } else if !mi && mj { - return true - } - return out[i].ID.Less(out[j].ID) - }) - return out -} - -// DigestExposedPorts returns true if it was changed. -func (n *Node) DigestExposedPorts(ports map[int]int) bool { - if reflect.DeepEqual(n.usedPorts, ports) { - return false - } - for internalPort := range n.usedPorts { - if v, ok := ports[internalPort]; ok { - n.usedPorts[internalPort] = v - } else { - panic(fmt.Sprintf( - "cluster %q node %q port %d not found in exposed list", - n.Cluster, - n.ID(), - internalPort, - )) - } - } - for _, svc := range n.Services { - svc.DigestExposedPorts(ports) - } - - return true -} - -func (n *Node) ServiceByID(sid ServiceID) *Service { - sid.Normalize() - for _, svc := range n.Services { - if svc.ID == sid { - return svc - } - } - panic("service not found: " + sid.String()) -} - -type ServiceAndNode struct { - Service *Service - Node *Node -} - -type Service struct { - ID ServiceID - Image string - Port int - ExposedPort int `json:",omitempty"` - - Disabled bool `json:",omitempty"` // TODO - - // TODO: expose extra port here? - - Meta map[string]string `json:",omitempty"` - - // TODO(rb): re-expose this perhaps? Protocol string `json:",omitempty"` // tcp|http (empty == tcp) - CheckHTTP string `json:",omitempty"` // url; will do a GET - CheckTCP string `json:",omitempty"` // addr; will do a socket open/close - - EnvoyAdminPort int - ExposedEnvoyAdminPort int `json:",omitempty"` - EnvoyPublicListenerPort int `json:",omitempty"` // agentless - - Command []string `json:",omitempty"` // optional - Env []string `json:",omitempty"` // optional - - DisableServiceMesh bool `json:",omitempty"` - IsMeshGateway bool `json:",omitempty"` - Upstreams []*Upstream - - // denormalized at topology compile - Node *Node `json:"-"` -} - -func (s *Service) inheritFromExisting(existing *Service) { - s.ExposedPort = existing.ExposedPort - s.ExposedEnvoyAdminPort = existing.ExposedEnvoyAdminPort -} - -func (s *Service) ports() []int { - var out []int - if s.Port > 0 { - out = append(out, s.Port) - } - if s.EnvoyAdminPort > 0 { - out = append(out, s.EnvoyAdminPort) - } - if s.EnvoyPublicListenerPort > 0 { - out = append(out, s.EnvoyPublicListenerPort) - } - for _, u := range s.Upstreams { - if u.LocalPort > 0 { - out = append(out, u.LocalPort) - } - } - return out -} - -func (s *Service) HasCheck() bool { - return s.CheckTCP != "" || s.CheckHTTP != "" -} - -func (s *Service) DigestExposedPorts(ports map[int]int) { - s.ExposedPort = ports[s.Port] - if s.EnvoyAdminPort > 0 { - s.ExposedEnvoyAdminPort = ports[s.EnvoyAdminPort] - } else { - s.ExposedEnvoyAdminPort = 0 - } -} - -func (s *Service) Validate() error { - if s.ID.Name == "" { - return fmt.Errorf("service name is required") - } - if s.Image == "" && !s.IsMeshGateway { - return fmt.Errorf("service image is required") - } - if s.Port <= 0 { - return fmt.Errorf("service has invalid port") - } - if s.DisableServiceMesh && s.IsMeshGateway { - return fmt.Errorf("cannot disable service mesh and still run a mesh gateway") - } - if s.DisableServiceMesh && len(s.Upstreams) > 0 { - return fmt.Errorf("cannot disable service mesh and configure upstreams") - } - - if s.DisableServiceMesh { - if s.EnvoyAdminPort != 0 { - return fmt.Errorf("cannot use envoy admin port without a service mesh") - } - } else { - if s.EnvoyAdminPort <= 0 { - return fmt.Errorf("envoy admin port is required") - } - } - - for _, u := range s.Upstreams { - if u.ID.Name == "" { - return fmt.Errorf("upstream service name is required") - } - if u.LocalPort <= 0 { - return fmt.Errorf("upstream local port is required") - } - - if u.LocalAddress != "" { - ip := net.ParseIP(u.LocalAddress) - if ip == nil { - return fmt.Errorf("upstream local address is invalid: %s", u.LocalAddress) - } - } - } - - return nil -} - -type Upstream struct { - ID ServiceID - LocalAddress string `json:",omitempty"` // defaults to 127.0.0.1 - LocalPort int - Peer string `json:",omitempty"` - // TODO: what about mesh gateway mode overrides? - - // computed at topology compile - Cluster string `json:",omitempty"` - Peering *PeerCluster `json:",omitempty"` // this will have Link!=nil -} - -type Peering struct { - Dialing PeerCluster - Accepting PeerCluster -} - -type PeerCluster struct { - Name string - Partition string - PeerName string // name to call it on this side; defaults if not specified - - // computed at topology compile (pointer so it can be empty in json) - Link *PeerCluster `json:",omitempty"` -} - -func (c PeerCluster) String() string { - return c.Name + ":" + c.Partition -} - -func (p *Peering) String() string { - return "(" + p.Dialing.String() + ")->(" + p.Accepting.String() + ")" -} diff --git a/testing/deployer/topology/util.go b/testing/deployer/topology/util.go deleted file mode 100644 index a6d6670c2655c..0000000000000 --- a/testing/deployer/topology/util.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package topology - -func MergeSlices[V any](x, y []V) []V { - switch { - case len(x) == 0 && len(y) == 0: - return nil - case len(x) == 0: - return y - case len(y) == 0: - return x - } - - out := make([]V, 0, len(x)+len(y)) - out = append(out, x...) - out = append(out, y...) - return out -} diff --git a/testing/deployer/topology/util_test.go b/testing/deployer/topology/util_test.go deleted file mode 100644 index a858a4e698149..0000000000000 --- a/testing/deployer/topology/util_test.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package topology - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestMergeSlices(t *testing.T) { - require.Nil(t, MergeSlices[int](nil, nil)) -} diff --git a/testing/deployer/util/consul.go b/testing/deployer/util/consul.go deleted file mode 100644 index d3ebc037a9fed..0000000000000 --- a/testing/deployer/util/consul.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package util - -import ( - "fmt" - "net/http" - "net/url" - "strconv" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/go-cleanhttp" -) - -func ProxyNotPooledAPIClient(proxyPort int, containerIP string, containerPort int, token string) (*api.Client, error) { - return proxyAPIClient(cleanhttp.DefaultTransport(), proxyPort, containerIP, containerPort, token) -} - -func ProxyAPIClient(proxyPort int, containerIP string, containerPort int, token string) (*api.Client, error) { - return proxyAPIClient(cleanhttp.DefaultPooledTransport(), proxyPort, containerIP, containerPort, token) -} - -func proxyAPIClient(baseTransport *http.Transport, proxyPort int, containerIP string, containerPort int, token string) (*api.Client, error) { - if proxyPort <= 0 { - return nil, fmt.Errorf("cannot use an http proxy on port %d", proxyPort) - } - if containerIP == "" { - return nil, fmt.Errorf("container IP is required") - } - if containerPort <= 0 { - return nil, fmt.Errorf("cannot dial api client on port %d", containerPort) - } - - proxyURL, err := url.Parse("http://127.0.0.1:" + strconv.Itoa(proxyPort)) - if err != nil { - return nil, err - } - - cfg := api.DefaultConfig() - cfg.Transport = baseTransport - cfg.Transport.Proxy = http.ProxyURL(proxyURL) - cfg.Address = fmt.Sprintf("http://%s:%d", containerIP, containerPort) - cfg.Token = token - return api.NewClient(cfg) -} - -func ProxyNotPooledHTTPTransport(proxyPort int) (*http.Transport, error) { - return proxyHTTPTransport(cleanhttp.DefaultTransport(), proxyPort) -} - -func ProxyHTTPTransport(proxyPort int) (*http.Transport, error) { - return proxyHTTPTransport(cleanhttp.DefaultPooledTransport(), proxyPort) -} - -func proxyHTTPTransport(baseTransport *http.Transport, proxyPort int) (*http.Transport, error) { - if proxyPort <= 0 { - return nil, fmt.Errorf("cannot use an http proxy on port %d", proxyPort) - } - proxyURL, err := url.Parse("http://127.0.0.1:" + strconv.Itoa(proxyPort)) - if err != nil { - return nil, err - } - baseTransport.Proxy = http.ProxyURL(proxyURL) - return baseTransport, nil -} diff --git a/testing/deployer/util/files.go b/testing/deployer/util/files.go deleted file mode 100644 index 5929f227e501a..0000000000000 --- a/testing/deployer/util/files.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package util - -import ( - "fmt" - "io" - "os" - "path/filepath" - - "golang.org/x/crypto/blake2b" -) - -func FilesExist(parent string, paths ...string) (bool, error) { - for _, p := range paths { - ok, err := FileExists(filepath.Join(parent, p)) - if err != nil { - return false, err - } - if !ok { - return false, nil - } - } - return true, nil -} - -func FileExists(path string) (bool, error) { - _, err := os.Stat(path) - if os.IsNotExist(err) { - return false, nil - } else if err != nil { - return false, err - } else { - return true, nil - } -} - -func HashFile(path string) (string, error) { - hash, err := blake2b.New256(nil) - if err != nil { - return "", err - } - - if err := AddFileToHash(path, hash); err != nil { - return "", err - } - - return fmt.Sprintf("%x", hash.Sum(nil)), nil -} - -func AddFileToHash(path string, w io.Writer) error { - f, err := os.Open(path) - if err != nil { - return err - } - defer f.Close() - _, err = io.Copy(w, f) - return err -} diff --git a/testing/deployer/util/internal/ipamutils/doc.go b/testing/deployer/util/internal/ipamutils/doc.go deleted file mode 100644 index 7820e3776201b..0000000000000 --- a/testing/deployer/util/internal/ipamutils/doc.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2015 Docker Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Originally from: -// https://github.com/moby/moby/blob/7489b51f610104ab5acc43f4e77142927e7b522e/libnetwork/ipamutils -// -// The only changes were to remove dead code from the package that we did not -// need, and to edit the tests to use github.com/stretchr/testify to avoid an -// extra dependency. -package ipamutils diff --git a/testing/deployer/util/internal/ipamutils/utils.go b/testing/deployer/util/internal/ipamutils/utils.go deleted file mode 100644 index 11367cc176bbf..0000000000000 --- a/testing/deployer/util/internal/ipamutils/utils.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// Package ipamutils provides utility functions for ipam management -package ipamutils - -import ( - "fmt" - "net" - "sync" -) - -var ( - // predefinedLocalScopeDefaultNetworks contains a list of 31 IPv4 private networks with host size 16 and 12 - // (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGlobalScopeDefaultNetworks` - predefinedLocalScopeDefaultNetworks []*net.IPNet - // predefinedGlobalScopeDefaultNetworks contains a list of 64K IPv4 private networks with host size 8 - // (10.x.x.x/24) which do not overlap with the networks in `PredefinedLocalScopeDefaultNetworks` - predefinedGlobalScopeDefaultNetworks []*net.IPNet - mutex sync.Mutex - localScopeDefaultNetworks = []*NetworkToSplit{{"172.17.0.0/16", 16}, {"172.18.0.0/16", 16}, {"172.19.0.0/16", 16}, - {"172.20.0.0/14", 16}, {"172.24.0.0/14", 16}, {"172.28.0.0/14", 16}, - {"192.168.0.0/16", 20}} - globalScopeDefaultNetworks = []*NetworkToSplit{{"10.0.0.0/8", 24}} -) - -// NetworkToSplit represent a network that has to be split in chunks with mask length Size. -// Each subnet in the set is derived from the Base pool. Base is to be passed -// in CIDR format. -// Example: a Base "10.10.0.0/16 with Size 24 will define the set of 256 -// 10.10.[0-255].0/24 address pools -type NetworkToSplit struct { - Base string `json:"base"` - Size int `json:"size"` -} - -func init() { - var err error - if predefinedGlobalScopeDefaultNetworks, err = SplitNetworks(globalScopeDefaultNetworks); err != nil { - panic("failed to initialize the global scope default address pool: " + err.Error()) - } - - if predefinedLocalScopeDefaultNetworks, err = SplitNetworks(localScopeDefaultNetworks); err != nil { - panic("failed to initialize the local scope default address pool: " + err.Error()) - } -} - -// ConfigGlobalScopeDefaultNetworks configures global default pool. -// Ideally this will be called from SwarmKit as part of swarm init -func ConfigGlobalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error { - if defaultAddressPool == nil { - return nil - } - mutex.Lock() - defer mutex.Unlock() - defaultNetworks, err := SplitNetworks(defaultAddressPool) - if err != nil { - return err - } - predefinedGlobalScopeDefaultNetworks = defaultNetworks - return nil -} - -// GetGlobalScopeDefaultNetworks returns a copy of the global-sopce network list. -func GetGlobalScopeDefaultNetworks() []*net.IPNet { - mutex.Lock() - defer mutex.Unlock() - return append([]*net.IPNet(nil), predefinedGlobalScopeDefaultNetworks...) -} - -// GetLocalScopeDefaultNetworks returns a copy of the default local-scope network list. -func GetLocalScopeDefaultNetworks() []*net.IPNet { - return append([]*net.IPNet(nil), predefinedLocalScopeDefaultNetworks...) -} - -// SplitNetworks takes a slice of networks, split them accordingly and returns them -func SplitNetworks(list []*NetworkToSplit) ([]*net.IPNet, error) { - localPools := make([]*net.IPNet, 0, len(list)) - - for _, p := range list { - _, b, err := net.ParseCIDR(p.Base) - if err != nil { - return nil, fmt.Errorf("invalid base pool %q: %v", p.Base, err) - } - ones, _ := b.Mask.Size() - if p.Size <= 0 || p.Size < ones { - return nil, fmt.Errorf("invalid pools size: %d", p.Size) - } - localPools = append(localPools, splitNetwork(p.Size, b)...) - } - return localPools, nil -} - -func splitNetwork(size int, base *net.IPNet) []*net.IPNet { - one, bits := base.Mask.Size() - mask := net.CIDRMask(size, bits) - n := 1 << uint(size-one) - s := uint(bits - size) - list := make([]*net.IPNet, 0, n) - - for i := 0; i < n; i++ { - ip := copyIP(base.IP) - addIntToIP(ip, uint(i<= 0; i-- { - array[i] |= (byte)(ordinal & 0xff) - ordinal >>= 8 - } -} diff --git a/testing/deployer/util/internal/ipamutils/utils_test.go b/testing/deployer/util/internal/ipamutils/utils_test.go deleted file mode 100644 index e91ae258cb913..0000000000000 --- a/testing/deployer/util/internal/ipamutils/utils_test.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package ipamutils - -import ( - "net" - "testing" - - "github.com/stretchr/testify/assert" -) - -func initBroadPredefinedNetworks() []*net.IPNet { - pl := make([]*net.IPNet, 0, 31) - mask := []byte{255, 255, 0, 0} - for i := 17; i < 32; i++ { - pl = append(pl, &net.IPNet{IP: []byte{172, byte(i), 0, 0}, Mask: mask}) - } - mask20 := []byte{255, 255, 240, 0} - for i := 0; i < 16; i++ { - pl = append(pl, &net.IPNet{IP: []byte{192, 168, byte(i << 4), 0}, Mask: mask20}) - } - return pl -} - -func initGranularPredefinedNetworks() []*net.IPNet { - pl := make([]*net.IPNet, 0, 256*256) - mask := []byte{255, 255, 255, 0} - for i := 0; i < 256; i++ { - for j := 0; j < 256; j++ { - pl = append(pl, &net.IPNet{IP: []byte{10, byte(i), byte(j), 0}, Mask: mask}) - } - } - return pl -} - -func initGlobalScopeNetworks() []*net.IPNet { - pl := make([]*net.IPNet, 0, 256*256) - mask := []byte{255, 255, 255, 0} - for i := 0; i < 256; i++ { - for j := 0; j < 256; j++ { - pl = append(pl, &net.IPNet{IP: []byte{30, byte(i), byte(j), 0}, Mask: mask}) - } - } - return pl -} - -func TestDefaultNetwork(t *testing.T) { - for _, nw := range GetGlobalScopeDefaultNetworks() { - if ones, bits := nw.Mask.Size(); bits != 32 || ones != 24 { - t.Fatalf("Unexpected size for network in granular list: %v", nw) - } - } - - for _, nw := range GetLocalScopeDefaultNetworks() { - if ones, bits := nw.Mask.Size(); bits != 32 || (ones != 20 && ones != 16) { - t.Fatalf("Unexpected size for network in broad list: %v", nw) - } - } - - originalBroadNets := initBroadPredefinedNetworks() - m := make(map[string]bool) - for _, v := range originalBroadNets { - m[v.String()] = true - } - for _, nw := range GetLocalScopeDefaultNetworks() { - _, ok := m[nw.String()] - assert.True(t, ok) - delete(m, nw.String()) - } - - assert.Empty(t, m) - - originalGranularNets := initGranularPredefinedNetworks() - - m = make(map[string]bool) - for _, v := range originalGranularNets { - m[v.String()] = true - } - for _, nw := range GetGlobalScopeDefaultNetworks() { - _, ok := m[nw.String()] - assert.True(t, ok) - delete(m, nw.String()) - } - - assert.Empty(t, m) -} - -func TestConfigGlobalScopeDefaultNetworks(t *testing.T) { - err := ConfigGlobalScopeDefaultNetworks([]*NetworkToSplit{{"30.0.0.0/8", 24}}) - assert.NoError(t, err) - - originalGlobalScopeNetworks := initGlobalScopeNetworks() - m := make(map[string]bool) - for _, v := range originalGlobalScopeNetworks { - m[v.String()] = true - } - for _, nw := range GetGlobalScopeDefaultNetworks() { - _, ok := m[nw.String()] - assert.True(t, ok) - delete(m, nw.String()) - } - - assert.Empty(t, m) -} diff --git a/testing/deployer/util/net.go b/testing/deployer/util/net.go deleted file mode 100644 index 83ca01761b48c..0000000000000 --- a/testing/deployer/util/net.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package util - -import ( - "github.com/hashicorp/consul/testing/deployer/util/internal/ipamutils" -) - -// GetPossibleDockerNetworkSubnets returns a copy of the global-scope network list. -func GetPossibleDockerNetworkSubnets() map[string]struct{} { - list := ipamutils.GetGlobalScopeDefaultNetworks() - - out := make(map[string]struct{}) - for _, ipnet := range list { - subnet := ipnet.String() - out[subnet] = struct{}{} - } - return out -} diff --git a/testrpc/wait.go b/testrpc/wait.go index ca315d28539e4..acd9524d78f30 100644 --- a/testrpc/wait.go +++ b/testrpc/wait.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package testrpc diff --git a/tlsutil/config.go b/tlsutil/config.go index 5cba2597f19d7..5cdaf7633eca5 100644 --- a/tlsutil/config.go +++ b/tlsutil/config.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tlsutil @@ -857,23 +857,10 @@ func (c *Configurator) IncomingHTTPSConfig() *tls.Config { return config } -// OutgoingTLSConfigForCheck creates a client *tls.Config for executing checks. -// It is RECOMMENDED that the serverName be left unspecified. The crypto/tls -// client will deduce the ServerName (for SNI) from the check address unless -// it's an IP (RFC 6066, Section 3). However, there are two instances where -// supplying a serverName is useful: -// -// 1. When the check address is an IP, a serverName can be supplied for SNI. -// Note: setting serverName will also override the hostname used to verify -// the certificate presented by the server being checked. -// -// 2. When the hostname in the check address won't be present in the SAN -// (Subject Alternative Name) field of the certificate presented by the -// server being checked. Note: setting serverName will also override the -// ServerName used for SNI. -// -// Setting skipVerify will disable verification of the server's certificate -// chain and hostname, which is generally not suitable for production use. +// OutgoingTLSConfigForCheck generates a *tls.Config for outgoing TLS connections +// for checks. This function is separated because there is an extra flag to +// consider for checks. EnableAgentTLSForChecks and InsecureSkipVerify has to +// be checked for checks. func (c *Configurator) OutgoingTLSConfigForCheck(skipVerify bool, serverName string) *tls.Config { c.log("OutgoingTLSConfigForCheck") @@ -888,9 +875,13 @@ func (c *Configurator) OutgoingTLSConfigForCheck(skipVerify bool, serverName str } } + if serverName == "" { + serverName = c.serverNameOrNodeName() + } config := c.internalRPCTLSConfig(false) config.InsecureSkipVerify = skipVerify config.ServerName = serverName + return config } diff --git a/tlsutil/config_test.go b/tlsutil/config_test.go index 8054b08ecd92e..30ebd62c206b7 100644 --- a/tlsutil/config_test.go +++ b/tlsutil/config_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 //go:build !fips // +build !fips @@ -1376,7 +1376,7 @@ func TestConfigurator_OutgoingTLSConfigForCheck(t *testing.T) { }, }, { - name: "agent tls, default consul server name, no override", + name: "agent tls, default server name", conf: func() (*Configurator, error) { return NewConfigurator(Config{ InternalRPC: ProtocolConfig{ @@ -1389,11 +1389,11 @@ func TestConfigurator_OutgoingTLSConfigForCheck(t *testing.T) { }, expected: &tls.Config{ MinVersion: tls.VersionTLS12, - ServerName: "", + ServerName: "servername", }, }, { - name: "agent tls, skip verify, consul node name for server name, no override", + name: "agent tls, skip verify, node name for server name", conf: func() (*Configurator, error) { return NewConfigurator(Config{ InternalRPC: ProtocolConfig{ @@ -1407,7 +1407,7 @@ func TestConfigurator_OutgoingTLSConfigForCheck(t *testing.T) { expected: &tls.Config{ InsecureSkipVerify: true, MinVersion: tls.VersionTLS12, - ServerName: "", + ServerName: "nodename", }, }, { diff --git a/tlsutil/generate.go b/tlsutil/generate.go index 907d7ba99694f..a92f76f9201c8 100644 --- a/tlsutil/generate.go +++ b/tlsutil/generate.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tlsutil diff --git a/tlsutil/generate_test.go b/tlsutil/generate_test.go index da3fd29af1f9c..ddceefe2cd5ae 100644 --- a/tlsutil/generate_test.go +++ b/tlsutil/generate_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package tlsutil diff --git a/tools/internal-grpc-proxy/main.go b/tools/internal-grpc-proxy/main.go index 5a4218e8fa466..fda3d2f044464 100644 --- a/tools/internal-grpc-proxy/main.go +++ b/tools/internal-grpc-proxy/main.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package main diff --git a/troubleshoot/proxy/certs.go b/troubleshoot/proxy/certs.go index 8f0c09b0293e9..083f1873b528f 100644 --- a/troubleshoot/proxy/certs.go +++ b/troubleshoot/proxy/certs.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package troubleshoot diff --git a/troubleshoot/proxy/certs_test.go b/troubleshoot/proxy/certs_test.go index e3db4dc009c5a..ec3ead7e02275 100644 --- a/troubleshoot/proxy/certs_test.go +++ b/troubleshoot/proxy/certs_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package troubleshoot diff --git a/troubleshoot/proxy/stats.go b/troubleshoot/proxy/stats.go index 249dce07db040..0ae4f68c8d102 100644 --- a/troubleshoot/proxy/stats.go +++ b/troubleshoot/proxy/stats.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package troubleshoot diff --git a/troubleshoot/proxy/troubleshoot_proxy.go b/troubleshoot/proxy/troubleshoot_proxy.go index 4cd422b0d4b89..5dac26752e439 100644 --- a/troubleshoot/proxy/troubleshoot_proxy.go +++ b/troubleshoot/proxy/troubleshoot_proxy.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package troubleshoot diff --git a/troubleshoot/proxy/upstreams.go b/troubleshoot/proxy/upstreams.go index 62f08572059a3..c42f6b9716650 100644 --- a/troubleshoot/proxy/upstreams.go +++ b/troubleshoot/proxy/upstreams.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package troubleshoot diff --git a/troubleshoot/proxy/upstreams_test.go b/troubleshoot/proxy/upstreams_test.go index a2f0bf60b08e0..a000738acde0b 100644 --- a/troubleshoot/proxy/upstreams_test.go +++ b/troubleshoot/proxy/upstreams_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package troubleshoot diff --git a/troubleshoot/proxy/utils.go b/troubleshoot/proxy/utils.go index 78fadaed119e2..b812272942c69 100644 --- a/troubleshoot/proxy/utils.go +++ b/troubleshoot/proxy/utils.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package troubleshoot diff --git a/troubleshoot/proxy/validateupstream.go b/troubleshoot/proxy/validateupstream.go index 02c355f40e705..64be9d02e1723 100644 --- a/troubleshoot/proxy/validateupstream.go +++ b/troubleshoot/proxy/validateupstream.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package troubleshoot diff --git a/troubleshoot/proxy/validateupstream_test.go b/troubleshoot/proxy/validateupstream_test.go index ddeca9b1cd72a..8709c42d9212c 100644 --- a/troubleshoot/proxy/validateupstream_test.go +++ b/troubleshoot/proxy/validateupstream_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package troubleshoot diff --git a/troubleshoot/validate/validate.go b/troubleshoot/validate/validate.go index 93d26bb42ed12..f7c6299f99848 100644 --- a/troubleshoot/validate/validate.go +++ b/troubleshoot/validate/validate.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package validate diff --git a/troubleshoot/validate/validate_test.go b/troubleshoot/validate/validate_test.go index b9e2aeed611f5..9d779c48f466e 100644 --- a/troubleshoot/validate/validate_test.go +++ b/troubleshoot/validate/validate_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package validate diff --git a/types/area.go b/types/area.go index 7cd0af35fb5c0..30207cd2c388d 100644 --- a/types/area.go +++ b/types/area.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/types/checks.go b/types/checks.go index d119319f413e7..172330267db6d 100644 --- a/types/checks.go +++ b/types/checks.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/types/node_id.go b/types/node_id.go index 868dbf52a9a0d..c404b02bea353 100644 --- a/types/node_id.go +++ b/types/node_id.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/types/tls.go b/types/tls.go index e4788819b8c3a..b113c29030a7c 100644 --- a/types/tls.go +++ b/types/tls.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/types/tls_test.go b/types/tls_test.go index a988cfbc9fb7c..a41817af32cd3 100644 --- a/types/tls_test.go +++ b/types/tls_test.go @@ -1,5 +1,5 @@ // Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MPL-2.0 package types diff --git a/ui/packages/consul-acls/app/components/consul/acl/selector/index.hbs b/ui/packages/consul-acls/app/components/consul/acl/selector/index.hbs index a13efa37c19d4..afee0962633f4 100644 --- a/ui/packages/consul-acls/app/components/consul/acl/selector/index.hbs +++ b/ui/packages/consul-acls/app/components/consul/acl/selector/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}

    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 diff --git a/test/integration/consul-container/test/util/test_debug_resume_program.png b/test/integration/consul-container/test/util/test_debug_resume_program.png deleted file mode 100644 index 99c2899019bb54c55fe29d26a4939dbaf2684f74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51972 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

  • routes({ diff --git a/ui/packages/consul-acls/vendor/consul-acls/services.js b/ui/packages/consul-acls/vendor/consul-acls/services.js index 1654b41eeea71..74e67ac3a2b82 100644 --- a/ui/packages/consul-acls/vendor/consul-acls/services.js +++ b/ui/packages/consul-acls/vendor/consul-acls/services.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ (services => services({ diff --git a/ui/packages/consul-hcp/app/components/consul/hcp/home/index.hbs b/ui/packages/consul-hcp/app/components/consul/hcp/home/index.hbs index bb5a1fc32a983..55c6531d2be47 100644 --- a/ui/packages/consul-hcp/app/components/consul/hcp/home/index.hbs +++ b/ui/packages/consul-hcp/app/components/consul/hcp/home/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
    routes({ diff --git a/ui/packages/consul-hcp/vendor/consul-hcp/services.js b/ui/packages/consul-hcp/vendor/consul-hcp/services.js index d1c7820f7da51..c95daf828c763 100644 --- a/ui/packages/consul-hcp/vendor/consul-hcp/services.js +++ b/ui/packages/consul-hcp/vendor/consul-hcp/services.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ (services => services({ diff --git a/ui/packages/consul-lock-sessions/app/components/consul/lock-session/form/index.hbs b/ui/packages/consul-lock-sessions/app/components/consul/lock-session/form/index.hbs index d84292c72fba9..f7cffddd8b771 100644 --- a/ui/packages/consul-lock-sessions/app/components/consul/lock-session/form/index.hbs +++ b/ui/packages/consul-lock-sessions/app/components/consul/lock-session/form/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
    li:not(:first-child) { diff --git a/ui/packages/consul-lock-sessions/app/components/consul/lock-session/notifications/index.hbs b/ui/packages/consul-lock-sessions/app/components/consul/lock-session/notifications/index.hbs index 12c1391161b92..5f2847d11f014 100644 --- a/ui/packages/consul-lock-sessions/app/components/consul/lock-session/notifications/index.hbs +++ b/ui/packages/consul-lock-sessions/app/components/consul/lock-session/notifications/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} {{#if (eq @type 'remove')}} diff --git a/ui/packages/consul-lock-sessions/app/templates/dc/nodes/show/sessions.hbs b/ui/packages/consul-lock-sessions/app/templates/dc/nodes/show/sessions.hbs index 61c679aa2f1f9..6f18f84b2885d 100644 --- a/ui/packages/consul-lock-sessions/app/templates/dc/nodes/show/sessions.hbs +++ b/ui/packages/consul-lock-sessions/app/templates/dc/nodes/show/sessions.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} routes({ diff --git a/ui/packages/consul-lock-sessions/vendor/consul-lock-sessions/services.js b/ui/packages/consul-lock-sessions/vendor/consul-lock-sessions/services.js index 1654b41eeea71..74e67ac3a2b82 100644 --- a/ui/packages/consul-lock-sessions/vendor/consul-lock-sessions/services.js +++ b/ui/packages/consul-lock-sessions/vendor/consul-lock-sessions/services.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ (services => services({ diff --git a/ui/packages/consul-nspaces/app/components/consul/nspace/form/index.hbs b/ui/packages/consul-nspaces/app/components/consul/nspace/form/index.hbs index 52b39bd9df59f..6621cf73f8eaf 100644 --- a/ui/packages/consul-nspaces/app/components/consul/nspace/form/index.hbs +++ b/ui/packages/consul-nspaces/app/components/consul/nspace/form/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
    diff --git a/ui/packages/consul-nspaces/app/components/consul/nspace/form/index.js b/ui/packages/consul-nspaces/app/components/consul/nspace/form/index.js index df8978572e59b..42fb75ecdbd90 100644 --- a/ui/packages/consul-nspaces/app/components/consul/nspace/form/index.js +++ b/ui/packages/consul-nspaces/app/components/consul/nspace/form/index.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Component from "@glimmer/component"; diff --git a/ui/packages/consul-nspaces/app/components/consul/nspace/list/index.hbs b/ui/packages/consul-nspaces/app/components/consul/nspace/list/index.hbs index b503aefa0efd3..b1677012e108b 100644 --- a/ui/packages/consul-nspaces/app/components/consul/nspace/list/index.hbs +++ b/ui/packages/consul-nspaces/app/components/consul/nspace/list/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} () => { diff --git a/ui/packages/consul-nspaces/app/components/consul/nspace/notifications/index.hbs b/ui/packages/consul-nspaces/app/components/consul/nspace/notifications/index.hbs index 67d44210f2073..4f8269aa52a54 100644 --- a/ui/packages/consul-nspaces/app/components/consul/nspace/notifications/index.hbs +++ b/ui/packages/consul-nspaces/app/components/consul/nspace/notifications/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} {{#if (eq @type 'remove')}} diff --git a/ui/packages/consul-nspaces/app/components/consul/nspace/search-bar/index.hbs b/ui/packages/consul-nspaces/app/components/consul/nspace/search-bar/index.hbs index f438d18dce2a2..49819ebb9b91d 100644 --- a/ui/packages/consul-nspaces/app/components/consul/nspace/search-bar/index.hbs +++ b/ui/packages/consul-nspaces/app/components/consul/nspace/search-bar/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} routes({ diff --git a/ui/packages/consul-nspaces/vendor/consul-nspaces/services.js b/ui/packages/consul-nspaces/vendor/consul-nspaces/services.js index 1654b41eeea71..74e67ac3a2b82 100644 --- a/ui/packages/consul-nspaces/vendor/consul-nspaces/services.js +++ b/ui/packages/consul-nspaces/vendor/consul-nspaces/services.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ (services => services({ diff --git a/ui/packages/consul-partitions/app/components/consul/partition/form/index.hbs b/ui/packages/consul-partitions/app/components/consul/partition/form/index.hbs index 03119b64106dd..b9e16298a014c 100644 --- a/ui/packages/consul-partitions/app/components/consul/partition/form/index.hbs +++ b/ui/packages/consul-partitions/app/components/consul/partition/form/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
    ({ diff --git a/ui/packages/consul-partitions/app/components/consul/partition/notifications/index.hbs b/ui/packages/consul-partitions/app/components/consul/partition/notifications/index.hbs index d97ff184f965e..082fcf652cfb7 100644 --- a/ui/packages/consul-partitions/app/components/consul/partition/notifications/index.hbs +++ b/ui/packages/consul-partitions/app/components/consul/partition/notifications/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} {{#if (eq @type 'remove')}} diff --git a/ui/packages/consul-partitions/app/components/consul/partition/search-bar/index.hbs b/ui/packages/consul-partitions/app/components/consul/partition/search-bar/index.hbs index 56fa44084a7b8..77e4d6b27d215 100644 --- a/ui/packages/consul-partitions/app/components/consul/partition/search-bar/index.hbs +++ b/ui/packages/consul-partitions/app/components/consul/partition/search-bar/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} routes({ diff --git a/ui/packages/consul-partitions/vendor/consul-partitions/services.js b/ui/packages/consul-partitions/vendor/consul-partitions/services.js index 1cf59ee066ca7..8c9440bce3cd1 100644 --- a/ui/packages/consul-partitions/vendor/consul-partitions/services.js +++ b/ui/packages/consul-partitions/vendor/consul-partitions/services.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ (services => services({ diff --git a/ui/packages/consul-peerings/app/components/consul/peer/address/list/index.hbs b/ui/packages/consul-peerings/app/components/consul/peer/address/list/index.hbs index bc6294e015f0a..eccac17174b64 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/address/list/index.hbs +++ b/ui/packages/consul-peerings/app/components/consul/peer/address/list/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} diff --git a/ui/packages/consul-peerings/app/components/consul/peer/address/list/index.scss b/ui/packages/consul-peerings/app/components/consul/peer/address/list/index.scss index 6816f4934f59c..3c4951829bc0b 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/address/list/index.scss +++ b/ui/packages/consul-peerings/app/components/consul/peer/address/list/index.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ .border-bottom-primary { diff --git a/ui/packages/consul-peerings/app/components/consul/peer/bento-box/index.hbs b/ui/packages/consul-peerings/app/components/consul/peer/bento-box/index.hbs index b0f633718ec23..b949548612b35 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/bento-box/index.hbs +++ b/ui/packages/consul-peerings/app/components/consul/peer/bento-box/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} diff --git a/ui/packages/consul-peerings/app/components/consul/peer/components.scss b/ui/packages/consul-peerings/app/components/consul/peer/components.scss index ad5f5cd296917..1e20d8b236fe6 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/components.scss +++ b/ui/packages/consul-peerings/app/components/consul/peer/components.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ %pill-pending::before, diff --git a/ui/packages/consul-peerings/app/components/consul/peer/form/chart.xstate.js b/ui/packages/consul-peerings/app/components/consul/peer/form/chart.xstate.js index 2380c523b4cee..af8a7570225a3 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/form/chart.xstate.js +++ b/ui/packages/consul-peerings/app/components/consul/peer/form/chart.xstate.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ export default { diff --git a/ui/packages/consul-peerings/app/components/consul/peer/form/generate/actions/index.hbs b/ui/packages/consul-peerings/app/components/consul/peer/form/generate/actions/index.hbs index 1c16d1d533dc3..f5f66960bb486 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/form/generate/actions/index.hbs +++ b/ui/packages/consul-peerings/app/components/consul/peer/form/generate/actions/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} diff --git a/ui/packages/consul-peerings/app/components/consul/peer/form/generate/fieldsets/index.js b/ui/packages/consul-peerings/app/components/consul/peer/form/generate/fieldsets/index.js index a037015d1d85d..708b52fd8b114 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/form/generate/fieldsets/index.js +++ b/ui/packages/consul-peerings/app/components/consul/peer/form/generate/fieldsets/index.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Component from '@glimmer/component'; diff --git a/ui/packages/consul-peerings/app/components/consul/peer/form/generate/index.hbs b/ui/packages/consul-peerings/app/components/consul/peer/form/generate/index.hbs index d6493c895c6d0..217818abd2a30 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/form/generate/index.hbs +++ b/ui/packages/consul-peerings/app/components/consul/peer/form/generate/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
    diff --git a/ui/packages/consul-peerings/app/components/consul/peer/form/index.hbs b/ui/packages/consul-peerings/app/components/consul/peer/form/index.hbs index 031ffead3ccca..a0e151f2f64e2 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/form/index.hbs +++ b/ui/packages/consul-peerings/app/components/consul/peer/form/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
    diff --git a/ui/packages/consul-peerings/app/components/consul/peer/form/index.scss b/ui/packages/consul-peerings/app/components/consul/peer/form/index.scss index 830cced098ae0..bca9acedd661a 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/form/index.scss +++ b/ui/packages/consul-peerings/app/components/consul/peer/form/index.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ .consul-peer-form { diff --git a/ui/packages/consul-peerings/app/components/consul/peer/form/initiate/actions/index.hbs b/ui/packages/consul-peerings/app/components/consul/peer/form/initiate/actions/index.hbs index f5f4c4864f4b4..2aba71c1a0b00 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/form/initiate/actions/index.hbs +++ b/ui/packages/consul-peerings/app/components/consul/peer/form/initiate/actions/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} diff --git a/ui/packages/consul-peerings/app/components/consul/peer/form/token/actions/index.hbs b/ui/packages/consul-peerings/app/components/consul/peer/form/token/actions/index.hbs index feb85bf4a25ea..b3f455833a4ec 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/form/token/actions/index.hbs +++ b/ui/packages/consul-peerings/app/components/consul/peer/form/token/actions/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
  • Switch to the peer
    - Someone on your team should log into the Datacenter (Community) or Admin Partition (Enterprise) that you want this one to connect with. + Someone on your team should log into the Datacenter (CE) or Admin Partition (Enterprise) that you want this one to connect with.
  • Initiate the peering
    diff --git a/ui/packages/consul-peerings/app/components/consul/peer/index.scss b/ui/packages/consul-peerings/app/components/consul/peer/index.scss index c7e6b20eaf06e..db9d677688a4a 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/index.scss +++ b/ui/packages/consul-peerings/app/components/consul/peer/index.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ @import './components'; diff --git a/ui/packages/consul-peerings/app/components/consul/peer/list/index.hbs b/ui/packages/consul-peerings/app/components/consul/peer/list/index.hbs index b0d10e1f8a741..a1af71ce11eb4 100644 --- a/ui/packages/consul-peerings/app/components/consul/peer/list/index.hbs +++ b/ui/packages/consul-peerings/app/components/consul/peer/list/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} diff --git a/ui/packages/consul-peerings/app/templates/dc/peers/show.hbs b/ui/packages/consul-peerings/app/templates/dc/peers/show.hbs index 843c54adf8ef4..93df6f79c7a14 100644 --- a/ui/packages/consul-peerings/app/templates/dc/peers/show.hbs +++ b/ui/packages/consul-peerings/app/templates/dc/peers/show.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} diff --git a/ui/packages/consul-peerings/app/templates/dc/peers/show/addresses.hbs b/ui/packages/consul-peerings/app/templates/dc/peers/show/addresses.hbs index 5845f97f5456e..a8d46aeee7dd5 100644 --- a/ui/packages/consul-peerings/app/templates/dc/peers/show/addresses.hbs +++ b/ui/packages/consul-peerings/app/templates/dc/peers/show/addresses.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} diff --git a/ui/packages/consul-peerings/app/templates/dc/peers/show/exported.hbs b/ui/packages/consul-peerings/app/templates/dc/peers/show/exported.hbs index 35198bfe8df3b..b25af6128fd6a 100644 --- a/ui/packages/consul-peerings/app/templates/dc/peers/show/exported.hbs +++ b/ui/packages/consul-peerings/app/templates/dc/peers/show/exported.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} diff --git a/ui/packages/consul-peerings/app/templates/dc/peers/show/imported.hbs b/ui/packages/consul-peerings/app/templates/dc/peers/show/imported.hbs index c7d32b3b16dba..05832b1c5480e 100644 --- a/ui/packages/consul-peerings/app/templates/dc/peers/show/imported.hbs +++ b/ui/packages/consul-peerings/app/templates/dc/peers/show/imported.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} diff --git a/ui/packages/consul-peerings/app/templates/dc/peers/show/index.hbs b/ui/packages/consul-peerings/app/templates/dc/peers/show/index.hbs index 9a077304e400a..acdf7641c14aa 100644 --- a/ui/packages/consul-peerings/app/templates/dc/peers/show/index.hbs +++ b/ui/packages/consul-peerings/app/templates/dc/peers/show/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} diff --git a/ui/packages/consul-peerings/vendor/consul-peerings/routes.js b/ui/packages/consul-peerings/vendor/consul-peerings/routes.js index 4ce314ba540db..a8748cec3a3e3 100644 --- a/ui/packages/consul-peerings/vendor/consul-peerings/routes.js +++ b/ui/packages/consul-peerings/vendor/consul-peerings/routes.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ ((routes) => diff --git a/ui/packages/consul-peerings/vendor/consul-peerings/services.js b/ui/packages/consul-peerings/vendor/consul-peerings/services.js index afad1c0e84462..2601489b0bcf5 100644 --- a/ui/packages/consul-peerings/vendor/consul-peerings/services.js +++ b/ui/packages/consul-peerings/vendor/consul-peerings/services.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ (services => services({ diff --git a/ui/packages/consul-ui/.docfy-config.js b/ui/packages/consul-ui/.docfy-config.js index 65bfd7401ff5d..c8308a5854c21 100644 --- a/ui/packages/consul-ui/.docfy-config.js +++ b/ui/packages/consul-ui/.docfy-config.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ const path = require('path'); diff --git a/ui/packages/consul-ui/.eslintrc.js b/ui/packages/consul-ui/.eslintrc.js index 114ea2c2f7d37..c8397263b5eaf 100644 --- a/ui/packages/consul-ui/.eslintrc.js +++ b/ui/packages/consul-ui/.eslintrc.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ module.exports = { diff --git a/ui/packages/consul-ui/.istanbul.yml b/ui/packages/consul-ui/.istanbul.yml index 636bf0e77b0a6..45e59c85a1076 100644 --- a/ui/packages/consul-ui/.istanbul.yml +++ b/ui/packages/consul-ui/.istanbul.yml @@ -1,5 +1,5 @@ # Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 +# SPDX-License-Identifier: MPL-2.0 instrumentation: excludes: [ diff --git a/ui/packages/consul-ui/.prettierrc.js b/ui/packages/consul-ui/.prettierrc.js index 4833e3531de51..cd0cb10db33aa 100644 --- a/ui/packages/consul-ui/.prettierrc.js +++ b/ui/packages/consul-ui/.prettierrc.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ 'use strict'; diff --git a/ui/packages/consul-ui/.template-lintrc.js b/ui/packages/consul-ui/.template-lintrc.js index 868e880ed35a8..2acbc36ee99fb 100644 --- a/ui/packages/consul-ui/.template-lintrc.js +++ b/ui/packages/consul-ui/.template-lintrc.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ 'use strict'; diff --git a/ui/packages/consul-ui/app/abilities/acl.js b/ui/packages/consul-ui/app/abilities/acl.js index 32701965184f5..c8667d6e72d01 100644 --- a/ui/packages/consul-ui/app/abilities/acl.js +++ b/ui/packages/consul-ui/app/abilities/acl.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/auth-method.js b/ui/packages/consul-ui/app/abilities/auth-method.js index de92c39c259dd..92e805cc7d262 100644 --- a/ui/packages/consul-ui/app/abilities/auth-method.js +++ b/ui/packages/consul-ui/app/abilities/auth-method.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/base.js b/ui/packages/consul-ui/app/abilities/base.js index c2f58ab7b4851..663b107d63926 100644 --- a/ui/packages/consul-ui/app/abilities/base.js +++ b/ui/packages/consul-ui/app/abilities/base.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import { inject as service } from '@ember/service'; diff --git a/ui/packages/consul-ui/app/abilities/intention.js b/ui/packages/consul-ui/app/abilities/intention.js index 27c7dc50c3e73..0ae68551b9227 100644 --- a/ui/packages/consul-ui/app/abilities/intention.js +++ b/ui/packages/consul-ui/app/abilities/intention.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/kv.js b/ui/packages/consul-ui/app/abilities/kv.js index bfcaca43fd9a2..7b32d1b4d9ca0 100644 --- a/ui/packages/consul-ui/app/abilities/kv.js +++ b/ui/packages/consul-ui/app/abilities/kv.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility, { ACCESS_LIST } from './base'; diff --git a/ui/packages/consul-ui/app/abilities/license.js b/ui/packages/consul-ui/app/abilities/license.js index 82affe7cff2c5..a1cd4f96982a4 100644 --- a/ui/packages/consul-ui/app/abilities/license.js +++ b/ui/packages/consul-ui/app/abilities/license.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/node.js b/ui/packages/consul-ui/app/abilities/node.js index 51b92aa131f2c..aaf63243d52f9 100644 --- a/ui/packages/consul-ui/app/abilities/node.js +++ b/ui/packages/consul-ui/app/abilities/node.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/nspace.js b/ui/packages/consul-ui/app/abilities/nspace.js index 994b51f41de32..b561700b18db2 100644 --- a/ui/packages/consul-ui/app/abilities/nspace.js +++ b/ui/packages/consul-ui/app/abilities/nspace.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/overview.js b/ui/packages/consul-ui/app/abilities/overview.js index 4381ecf537aef..cbd6ecd8606a0 100644 --- a/ui/packages/consul-ui/app/abilities/overview.js +++ b/ui/packages/consul-ui/app/abilities/overview.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/partition.js b/ui/packages/consul-ui/app/abilities/partition.js index b884e058498a3..3dade71b77148 100644 --- a/ui/packages/consul-ui/app/abilities/partition.js +++ b/ui/packages/consul-ui/app/abilities/partition.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from 'consul-ui/abilities/base'; diff --git a/ui/packages/consul-ui/app/abilities/peer.js b/ui/packages/consul-ui/app/abilities/peer.js index 7a52ed4300919..b564c731d5b60 100644 --- a/ui/packages/consul-ui/app/abilities/peer.js +++ b/ui/packages/consul-ui/app/abilities/peer.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from 'consul-ui/abilities/base'; diff --git a/ui/packages/consul-ui/app/abilities/permission.js b/ui/packages/consul-ui/app/abilities/permission.js index 41b2e5a7076ff..8856b4c1bc195 100644 --- a/ui/packages/consul-ui/app/abilities/permission.js +++ b/ui/packages/consul-ui/app/abilities/permission.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/policy.js b/ui/packages/consul-ui/app/abilities/policy.js index 4c7ee5a32d9f3..38c15963ed873 100644 --- a/ui/packages/consul-ui/app/abilities/policy.js +++ b/ui/packages/consul-ui/app/abilities/policy.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/role.js b/ui/packages/consul-ui/app/abilities/role.js index 457fb1bea9cc5..19ab731169ac1 100644 --- a/ui/packages/consul-ui/app/abilities/role.js +++ b/ui/packages/consul-ui/app/abilities/role.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/server.js b/ui/packages/consul-ui/app/abilities/server.js index b6acef100cc7d..55cee3bbd04c5 100644 --- a/ui/packages/consul-ui/app/abilities/server.js +++ b/ui/packages/consul-ui/app/abilities/server.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/service-instance.js b/ui/packages/consul-ui/app/abilities/service-instance.js index 2f00b9857fcbf..e424bb608f744 100644 --- a/ui/packages/consul-ui/app/abilities/service-instance.js +++ b/ui/packages/consul-ui/app/abilities/service-instance.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility, { ACCESS_READ, ACCESS_WRITE } from './base'; diff --git a/ui/packages/consul-ui/app/abilities/session.js b/ui/packages/consul-ui/app/abilities/session.js index dd505eea2d06b..6a9554ae902b2 100644 --- a/ui/packages/consul-ui/app/abilities/session.js +++ b/ui/packages/consul-ui/app/abilities/session.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/token.js b/ui/packages/consul-ui/app/abilities/token.js index e8880daf6c439..d09692e42f5fb 100644 --- a/ui/packages/consul-ui/app/abilities/token.js +++ b/ui/packages/consul-ui/app/abilities/token.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/upstream.js b/ui/packages/consul-ui/app/abilities/upstream.js index 55cf1d0d0ebc8..d8e5090b505c0 100644 --- a/ui/packages/consul-ui/app/abilities/upstream.js +++ b/ui/packages/consul-ui/app/abilities/upstream.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/zervice.js b/ui/packages/consul-ui/app/abilities/zervice.js index 0fadbcb7c6e7a..0b143c5b8fbc8 100644 --- a/ui/packages/consul-ui/app/abilities/zervice.js +++ b/ui/packages/consul-ui/app/abilities/zervice.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/abilities/zone.js b/ui/packages/consul-ui/app/abilities/zone.js index 3f141319f9117..18a1bf4d71b99 100644 --- a/ui/packages/consul-ui/app/abilities/zone.js +++ b/ui/packages/consul-ui/app/abilities/zone.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import BaseAbility from './base'; diff --git a/ui/packages/consul-ui/app/adapters/application.js b/ui/packages/consul-ui/app/adapters/application.js index d0010c784b3aa..1154b24732786 100644 --- a/ui/packages/consul-ui/app/adapters/application.js +++ b/ui/packages/consul-ui/app/adapters/application.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './http'; diff --git a/ui/packages/consul-ui/app/adapters/auth-method.js b/ui/packages/consul-ui/app/adapters/auth-method.js index 97153a3fcbe8f..6d3fbfeb2bf81 100644 --- a/ui/packages/consul-ui/app/adapters/auth-method.js +++ b/ui/packages/consul-ui/app/adapters/auth-method.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/binding-rule.js b/ui/packages/consul-ui/app/adapters/binding-rule.js index 49029ce7a7240..026674c7584c0 100644 --- a/ui/packages/consul-ui/app/adapters/binding-rule.js +++ b/ui/packages/consul-ui/app/adapters/binding-rule.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/coordinate.js b/ui/packages/consul-ui/app/adapters/coordinate.js index fc5eba788cc73..a7a0b286c862e 100644 --- a/ui/packages/consul-ui/app/adapters/coordinate.js +++ b/ui/packages/consul-ui/app/adapters/coordinate.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/discovery-chain.js b/ui/packages/consul-ui/app/adapters/discovery-chain.js index 6ce0020c6e85a..37879323b20c9 100644 --- a/ui/packages/consul-ui/app/adapters/discovery-chain.js +++ b/ui/packages/consul-ui/app/adapters/discovery-chain.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/http.js b/ui/packages/consul-ui/app/adapters/http.js index 5e9acc62fec87..89b7f11da4b7a 100644 --- a/ui/packages/consul-ui/app/adapters/http.js +++ b/ui/packages/consul-ui/app/adapters/http.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import { inject as service } from '@ember/service'; diff --git a/ui/packages/consul-ui/app/adapters/intention.js b/ui/packages/consul-ui/app/adapters/intention.js index b47d179b84462..3ea6925470ae2 100644 --- a/ui/packages/consul-ui/app/adapters/intention.js +++ b/ui/packages/consul-ui/app/adapters/intention.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/kv.js b/ui/packages/consul-ui/app/adapters/kv.js index bb29fff4d9698..e512723702e52 100644 --- a/ui/packages/consul-ui/app/adapters/kv.js +++ b/ui/packages/consul-ui/app/adapters/kv.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/node.js b/ui/packages/consul-ui/app/adapters/node.js index 5ac1a936005a6..be0799a10d6d9 100644 --- a/ui/packages/consul-ui/app/adapters/node.js +++ b/ui/packages/consul-ui/app/adapters/node.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/nspace.js b/ui/packages/consul-ui/app/adapters/nspace.js index 6e9f27dde0a72..3636a363c6551 100644 --- a/ui/packages/consul-ui/app/adapters/nspace.js +++ b/ui/packages/consul-ui/app/adapters/nspace.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/oidc-provider.js b/ui/packages/consul-ui/app/adapters/oidc-provider.js index 6fafe51a85695..c758a49dcd0ac 100644 --- a/ui/packages/consul-ui/app/adapters/oidc-provider.js +++ b/ui/packages/consul-ui/app/adapters/oidc-provider.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/partition.js b/ui/packages/consul-ui/app/adapters/partition.js index b2ec2178de14c..4ba23078afb6f 100644 --- a/ui/packages/consul-ui/app/adapters/partition.js +++ b/ui/packages/consul-ui/app/adapters/partition.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/permission.js b/ui/packages/consul-ui/app/adapters/permission.js index 806ed5a3c3043..23b5a2725075c 100644 --- a/ui/packages/consul-ui/app/adapters/permission.js +++ b/ui/packages/consul-ui/app/adapters/permission.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/policy.js b/ui/packages/consul-ui/app/adapters/policy.js index 6c959df2d8a4d..9d1415f3a3499 100644 --- a/ui/packages/consul-ui/app/adapters/policy.js +++ b/ui/packages/consul-ui/app/adapters/policy.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/proxy.js b/ui/packages/consul-ui/app/adapters/proxy.js index 6f37be6540119..782c9e1b7db95 100644 --- a/ui/packages/consul-ui/app/adapters/proxy.js +++ b/ui/packages/consul-ui/app/adapters/proxy.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/role.js b/ui/packages/consul-ui/app/adapters/role.js index 8773fddeac174..a64d3db366d26 100644 --- a/ui/packages/consul-ui/app/adapters/role.js +++ b/ui/packages/consul-ui/app/adapters/role.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/service-instance.js b/ui/packages/consul-ui/app/adapters/service-instance.js index e61efc8188032..d02295d898de8 100644 --- a/ui/packages/consul-ui/app/adapters/service-instance.js +++ b/ui/packages/consul-ui/app/adapters/service-instance.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/service.js b/ui/packages/consul-ui/app/adapters/service.js index c8e6adf82698e..c3acb927e0ddc 100644 --- a/ui/packages/consul-ui/app/adapters/service.js +++ b/ui/packages/consul-ui/app/adapters/service.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/session.js b/ui/packages/consul-ui/app/adapters/session.js index 3f42ac4bb97c7..c0c2c5437c8a5 100644 --- a/ui/packages/consul-ui/app/adapters/session.js +++ b/ui/packages/consul-ui/app/adapters/session.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/token.js b/ui/packages/consul-ui/app/adapters/token.js index 7e8e46dacb1b3..555b334e5e5b7 100644 --- a/ui/packages/consul-ui/app/adapters/token.js +++ b/ui/packages/consul-ui/app/adapters/token.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/adapters/topology.js b/ui/packages/consul-ui/app/adapters/topology.js index 8ed49fea40fd7..b12ffc3f9dbf3 100644 --- a/ui/packages/consul-ui/app/adapters/topology.js +++ b/ui/packages/consul-ui/app/adapters/topology.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Adapter from './application'; diff --git a/ui/packages/consul-ui/app/app.js b/ui/packages/consul-ui/app/app.js index 43db29bdd35e5..de6711919bb83 100644 --- a/ui/packages/consul-ui/app/app.js +++ b/ui/packages/consul-ui/app/app.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Application from '@ember/application'; diff --git a/ui/packages/consul-ui/app/components/action/index.hbs b/ui/packages/consul-ui/app/components/action/index.hbs index ad405278bfc7e..97119fdd477a2 100644 --- a/ui/packages/consul-ui/app/components/action/index.hbs +++ b/ui/packages/consul-ui/app/components/action/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} {{#if @for~}} diff --git a/ui/packages/consul-ui/app/components/anchors/index.scss b/ui/packages/consul-ui/app/components/anchors/index.scss index 0de89716dbe15..9fe7e5079d42f 100644 --- a/ui/packages/consul-ui/app/components/anchors/index.scss +++ b/ui/packages/consul-ui/app/components/anchors/index.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ @import './skin'; diff --git a/ui/packages/consul-ui/app/components/anchors/skin.scss b/ui/packages/consul-ui/app/components/anchors/skin.scss index 53fb0d94617ab..a34e5becc9e44 100644 --- a/ui/packages/consul-ui/app/components/anchors/skin.scss +++ b/ui/packages/consul-ui/app/components/anchors/skin.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ %anchor-decoration, diff --git a/ui/packages/consul-ui/app/components/anonymous/index.hbs b/ui/packages/consul-ui/app/components/anonymous/index.hbs index 8709fc4b8b770..0566ddf99b461 100644 --- a/ui/packages/consul-ui/app/components/anonymous/index.hbs +++ b/ui/packages/consul-ui/app/components/anonymous/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} {{yield}} \ No newline at end of file diff --git a/ui/packages/consul-ui/app/components/anonymous/index.js b/ui/packages/consul-ui/app/components/anonymous/index.js index d99599ac30397..8f027b69f0e03 100644 --- a/ui/packages/consul-ui/app/components/anonymous/index.js +++ b/ui/packages/consul-ui/app/components/anonymous/index.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Component from '@ember/component'; diff --git a/ui/packages/consul-ui/app/components/app-error/index.hbs b/ui/packages/consul-ui/app/components/app-error/index.hbs index ca65502f59392..0c087cdd4d979 100644 --- a/ui/packages/consul-ui/app/components/app-error/index.hbs +++ b/ui/packages/consul-ui/app/components/app-error/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} diff --git a/ui/packages/consul-ui/app/components/app-view/index.hbs b/ui/packages/consul-ui/app/components/app-view/index.hbs index 3b6ebb26e1383..53cf7113b247a 100644 --- a/ui/packages/consul-ui/app/components/app-view/index.hbs +++ b/ui/packages/consul-ui/app/components/app-view/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
    diff --git a/ui/packages/consul-ui/app/components/auth-form/index.js b/ui/packages/consul-ui/app/components/auth-form/index.js index 0cd05cc4c29b2..4c861ad527cb0 100644 --- a/ui/packages/consul-ui/app/components/auth-form/index.js +++ b/ui/packages/consul-ui/app/components/auth-form/index.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Component from '@glimmer/component'; diff --git a/ui/packages/consul-ui/app/components/auth-form/index.scss b/ui/packages/consul-ui/app/components/auth-form/index.scss index 1a5c5afff9884..49051008b08db 100644 --- a/ui/packages/consul-ui/app/components/auth-form/index.scss +++ b/ui/packages/consul-ui/app/components/auth-form/index.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ @import './skin'; diff --git a/ui/packages/consul-ui/app/components/auth-form/layout.scss b/ui/packages/consul-ui/app/components/auth-form/layout.scss index 60ea16642b5a0..2889b700d09d3 100644 --- a/ui/packages/consul-ui/app/components/auth-form/layout.scss +++ b/ui/packages/consul-ui/app/components/auth-form/layout.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ %auth-form { diff --git a/ui/packages/consul-ui/app/components/auth-form/pageobject.js b/ui/packages/consul-ui/app/components/auth-form/pageobject.js index f3812d638f900..3ad553f2ad10d 100644 --- a/ui/packages/consul-ui/app/components/auth-form/pageobject.js +++ b/ui/packages/consul-ui/app/components/auth-form/pageobject.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ export default (submitable, clickable, attribute) => diff --git a/ui/packages/consul-ui/app/components/auth-form/skin.scss b/ui/packages/consul-ui/app/components/auth-form/skin.scss index 341c0928fc8c8..18ff35fead26d 100644 --- a/ui/packages/consul-ui/app/components/auth-form/skin.scss +++ b/ui/packages/consul-ui/app/components/auth-form/skin.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ %auth-form em { diff --git a/ui/packages/consul-ui/app/components/auth-form/tabs.xstate.js b/ui/packages/consul-ui/app/components/auth-form/tabs.xstate.js index e25cc0d3e7196..c0fcf889a92c8 100644 --- a/ui/packages/consul-ui/app/components/auth-form/tabs.xstate.js +++ b/ui/packages/consul-ui/app/components/auth-form/tabs.xstate.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ export default { diff --git a/ui/packages/consul-ui/app/components/auth-modal/index.scss b/ui/packages/consul-ui/app/components/auth-modal/index.scss index 24f3ba363a488..c9d0eac524602 100644 --- a/ui/packages/consul-ui/app/components/auth-modal/index.scss +++ b/ui/packages/consul-ui/app/components/auth-modal/index.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ /*TODO: This is a different style of modal dialog */ diff --git a/ui/packages/consul-ui/app/components/auth-modal/layout.scss b/ui/packages/consul-ui/app/components/auth-modal/layout.scss index 0f38371bbaa28..dcdcede010720 100644 --- a/ui/packages/consul-ui/app/components/auth-modal/layout.scss +++ b/ui/packages/consul-ui/app/components/auth-modal/layout.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ %auth-modal footer { diff --git a/ui/packages/consul-ui/app/components/auth-modal/skin.scss b/ui/packages/consul-ui/app/components/auth-modal/skin.scss index ac930a2dd6193..b88fad1e54c60 100644 --- a/ui/packages/consul-ui/app/components/auth-modal/skin.scss +++ b/ui/packages/consul-ui/app/components/auth-modal/skin.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ %auth-modal footer button::after { diff --git a/ui/packages/consul-ui/app/components/auth-profile/index.hbs b/ui/packages/consul-ui/app/components/auth-profile/index.hbs index 324a657bbe433..3a7f4e5256b6d 100644 --- a/ui/packages/consul-ui/app/components/auth-profile/index.hbs +++ b/ui/packages/consul-ui/app/components/auth-profile/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
    diff --git a/ui/packages/consul-ui/app/components/code-editor/index.js b/ui/packages/consul-ui/app/components/code-editor/index.js index 72e3abf8eb8a0..52203ac22a0e8 100644 --- a/ui/packages/consul-ui/app/components/code-editor/index.js +++ b/ui/packages/consul-ui/app/components/code-editor/index.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Component from '@ember/component'; diff --git a/ui/packages/consul-ui/app/components/code-editor/index.scss b/ui/packages/consul-ui/app/components/code-editor/index.scss index 58c7c66596cc4..559533e42a849 100644 --- a/ui/packages/consul-ui/app/components/code-editor/index.scss +++ b/ui/packages/consul-ui/app/components/code-editor/index.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ @import './skin'; diff --git a/ui/packages/consul-ui/app/components/code-editor/layout.scss b/ui/packages/consul-ui/app/components/code-editor/layout.scss index b8194d850bc94..285fda57a35f6 100644 --- a/ui/packages/consul-ui/app/components/code-editor/layout.scss +++ b/ui/packages/consul-ui/app/components/code-editor/layout.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ %code-editor { diff --git a/ui/packages/consul-ui/app/components/code-editor/skin.scss b/ui/packages/consul-ui/app/components/code-editor/skin.scss index 0a8dafc65dde5..db0f52bc0d297 100644 --- a/ui/packages/consul-ui/app/components/code-editor/skin.scss +++ b/ui/packages/consul-ui/app/components/code-editor/skin.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ $syntax-consul: #69499a; diff --git a/ui/packages/consul-ui/app/components/composite-row/index.scss b/ui/packages/consul-ui/app/components/composite-row/index.scss index e9db145da19d9..255a2a67c6ca6 100644 --- a/ui/packages/consul-ui/app/components/composite-row/index.scss +++ b/ui/packages/consul-ui/app/components/composite-row/index.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ @import './layout'; diff --git a/ui/packages/consul-ui/app/components/composite-row/layout.scss b/ui/packages/consul-ui/app/components/composite-row/layout.scss index 819c41f9504f0..dfc3860b501fc 100644 --- a/ui/packages/consul-ui/app/components/composite-row/layout.scss +++ b/ui/packages/consul-ui/app/components/composite-row/layout.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ %composite-row { diff --git a/ui/packages/consul-ui/app/components/confirmation-alert/index.hbs b/ui/packages/consul-ui/app/components/confirmation-alert/index.hbs index 95f243a89233e..cf5a0c403c674 100644 --- a/ui/packages/consul-ui/app/components/confirmation-alert/index.hbs +++ b/ui/packages/consul-ui/app/components/confirmation-alert/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} {{yield}} diff --git a/ui/packages/consul-ui/app/components/confirmation-alert/index.js b/ui/packages/consul-ui/app/components/confirmation-alert/index.js index d99599ac30397..8f027b69f0e03 100644 --- a/ui/packages/consul-ui/app/components/confirmation-alert/index.js +++ b/ui/packages/consul-ui/app/components/confirmation-alert/index.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Component from '@ember/component'; diff --git a/ui/packages/consul-ui/app/components/confirmation-dialog/index.hbs b/ui/packages/consul-ui/app/components/confirmation-dialog/index.hbs index da4c7660efbf4..07826204afe45 100644 --- a/ui/packages/consul-ui/app/components/confirmation-dialog/index.hbs +++ b/ui/packages/consul-ui/app/components/confirmation-dialog/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
    diff --git a/ui/packages/consul-ui/app/components/confirmation-dialog/index.js b/ui/packages/consul-ui/app/components/confirmation-dialog/index.js index e10782f579d44..b60850d50a264 100644 --- a/ui/packages/consul-ui/app/components/confirmation-dialog/index.js +++ b/ui/packages/consul-ui/app/components/confirmation-dialog/index.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ /*eslint ember/closure-actions: "warn"*/ diff --git a/ui/packages/consul-ui/app/components/confirmation-dialog/index.scss b/ui/packages/consul-ui/app/components/confirmation-dialog/index.scss index 65914fb025766..67ae530a98eaa 100644 --- a/ui/packages/consul-ui/app/components/confirmation-dialog/index.scss +++ b/ui/packages/consul-ui/app/components/confirmation-dialog/index.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ @import './skin'; diff --git a/ui/packages/consul-ui/app/components/confirmation-dialog/layout.scss b/ui/packages/consul-ui/app/components/confirmation-dialog/layout.scss index 9538794833b1a..82773a342339e 100644 --- a/ui/packages/consul-ui/app/components/confirmation-dialog/layout.scss +++ b/ui/packages/consul-ui/app/components/confirmation-dialog/layout.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ %confirmation-dialog { diff --git a/ui/packages/consul-ui/app/components/confirmation-dialog/skin.scss b/ui/packages/consul-ui/app/components/confirmation-dialog/skin.scss index 4509c4b3fdc52..248c7c9950e7d 100644 --- a/ui/packages/consul-ui/app/components/confirmation-dialog/skin.scss +++ b/ui/packages/consul-ui/app/components/confirmation-dialog/skin.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ table div.with-confirmation.confirming { diff --git a/ui/packages/consul-ui/app/components/consul/acl/disabled/index.hbs b/ui/packages/consul-ui/app/components/consul/acl/disabled/index.hbs index 23e6271820d2f..77e8dba8fecc1 100644 --- a/ui/packages/consul-ui/app/components/consul/acl/disabled/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/acl/disabled/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} diff --git a/ui/packages/consul-ui/app/components/consul/auth-method/binding-list/index.hbs b/ui/packages/consul-ui/app/components/consul/auth-method/binding-list/index.hbs index 44e351e452844..d0ab9b8ae62a1 100644 --- a/ui/packages/consul-ui/app/components/consul/auth-method/binding-list/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/auth-method/binding-list/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
    diff --git a/ui/packages/consul-ui/app/components/consul/auth-method/index.scss b/ui/packages/consul-ui/app/components/consul/auth-method/index.scss index 7e6ffe2de8c03..266174687f49a 100644 --- a/ui/packages/consul-ui/app/components/consul/auth-method/index.scss +++ b/ui/packages/consul-ui/app/components/consul/auth-method/index.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ // List diff --git a/ui/packages/consul-ui/app/components/consul/auth-method/list/index.hbs b/ui/packages/consul-ui/app/components/consul/auth-method/list/index.hbs index 160e38bd9ce5c..2f15936b42cfb 100644 --- a/ui/packages/consul-ui/app/components/consul/auth-method/list/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/auth-method/list/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} () => { diff --git a/ui/packages/consul-ui/app/components/consul/auth-method/nspace-list/index.hbs b/ui/packages/consul-ui/app/components/consul/auth-method/nspace-list/index.hbs index cb617ad0660f2..ec47712ec380a 100644 --- a/ui/packages/consul-ui/app/components/consul/auth-method/nspace-list/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/auth-method/nspace-list/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
    diff --git a/ui/packages/consul-ui/app/components/consul/auth-method/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/auth-method/search-bar/index.hbs index 63e9f11be2f68..5a0a5949a571e 100644 --- a/ui/packages/consul-ui/app/components/consul/auth-method/search-bar/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/auth-method/search-bar/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} diff --git a/ui/packages/consul-ui/app/components/consul/auth-method/type/index.hbs b/ui/packages/consul-ui/app/components/consul/auth-method/type/index.hbs index a21db4f39264a..b28adf8460540 100644 --- a/ui/packages/consul-ui/app/components/consul/auth-method/type/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/auth-method/type/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} {{#let (icon-mapping @item.Type) as |flightIcon|}} diff --git a/ui/packages/consul-ui/app/components/consul/auth-method/view/index.hbs b/ui/packages/consul-ui/app/components/consul/auth-method/view/index.hbs index eab0fa48399c2..00b0169679fc6 100644 --- a/ui/packages/consul-ui/app/components/consul/auth-method/view/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/auth-method/view/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
    diff --git a/ui/packages/consul-ui/app/components/consul/bucket/list/index.hbs b/ui/packages/consul-ui/app/components/consul/bucket/list/index.hbs index 21d598d64ff5f..0c82141ca5b07 100644 --- a/ui/packages/consul-ui/app/components/consul/bucket/list/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/bucket/list/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }} {{#if this.itemsToDisplay.length}} diff --git a/ui/packages/consul-ui/app/components/consul/bucket/list/index.js b/ui/packages/consul-ui/app/components/consul/bucket/list/index.js index 0268cb6d22efd..387d04f1721f4 100644 --- a/ui/packages/consul-ui/app/components/consul/bucket/list/index.js +++ b/ui/packages/consul-ui/app/components/consul/bucket/list/index.js @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ import Component from '@glimmer/component'; diff --git a/ui/packages/consul-ui/app/components/consul/bucket/list/index.scss b/ui/packages/consul-ui/app/components/consul/bucket/list/index.scss index 996323841f587..710f6a3593bf4 100644 --- a/ui/packages/consul-ui/app/components/consul/bucket/list/index.scss +++ b/ui/packages/consul-ui/app/components/consul/bucket/list/index.scss @@ -1,6 +1,6 @@ /** * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 + * SPDX-License-Identifier: MPL-2.0 */ %consul-bucket-list { diff --git a/ui/packages/consul-ui/app/components/consul/datacenter/selector/index.hbs b/ui/packages/consul-ui/app/components/consul/datacenter/selector/index.hbs index 767422e4b9b13..ecc4f51f1a6b1 100644 --- a/ui/packages/consul-ui/app/components/consul/datacenter/selector/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/datacenter/selector/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}
  • diff --git a/ui/packages/consul-ui/app/components/consul/discovery-chain/index.hbs b/ui/packages/consul-ui/app/components/consul/discovery-chain/index.hbs index e25096f849cd2..59d5846061744 100644 --- a/ui/packages/consul-ui/app/components/consul/discovery-chain/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/discovery-chain/index.hbs @@ -1,6 +1,6 @@ {{! Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 + SPDX-License-Identifier: MPL-2.0 }}