From 20e223f971efe96cc738844603817faa7e881fe6 Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Mon, 26 Feb 2024 15:38:40 +0000 Subject: [PATCH] backport of commit 4b8bc716b4e28027752ffed9cc6b54a6fea9072f --- .changelog/2962.txt | 2 +- .changelog/3000.txt | 36 - .changelog/{3116.txt => 3118.txt} | 0 .changelog/3184.txt | 3 - .changelog/3418.txt | 2 +- .changelog/3668.txt | 4 +- .changelog/3675.txt | 3 - .github/pull_request_template.md | 11 +- .github/workflows/build.yml | 91 +- ...1.yml => nightly-acceptance-1-3-0-rc1.yml} | 14 +- ...1-4-x.yml => weekly-acceptance-0-49-x.yml} | 8 +- ...-1-3-x.yml => weekly-acceptance-1-0-x.yml} | 9 +- .github/workflows/weekly-acceptance-1-1-x.yml | 4 +- .github/workflows/weekly-acceptance-1-2-x.yml | 5 +- CHANGELOG.md | 181 -- Makefile | 31 +- README.md | 2 +- .../aks_acceptance_test_packages.yaml | 2 +- .../eks_acceptance_test_packages.yaml | 2 +- .../gke_acceptance_test_packages.yaml | 2 +- acceptance/ci-inputs/kind-inputs.yaml | 4 +- .../kind_acceptance_test_packages.yaml | 4 +- acceptance/framework/cli/cli.go | 4 +- acceptance/framework/config/config.go | 6 - .../framework/connhelper/connect_helper.go | 4 +- acceptance/framework/consul/cli_cluster.go | 5 +- acceptance/framework/consul/helm_cluster.go | 78 +- .../framework/consul/helm_cluster_test.go | 7 +- .../framework/environment/environment.go | 30 +- acceptance/framework/helpers/helpers.go | 10 +- acceptance/framework/k8s/deploy.go | 2 +- acceptance/framework/k8s/helpers.go | 14 +- acceptance/framework/k8s/kubectl.go | 7 +- acceptance/framework/logger/logger.go | 25 +- .../framework/portforward/port_forward.go | 3 +- acceptance/framework/resource/helpers.go | 94 - acceptance/framework/vault/vault_cluster.go | 13 +- acceptance/go.mod | 34 +- acceptance/go.sum | 55 +- .../api_gateway_kitchen_sink_test.go | 232 -- .../api-gateway_v2/api_gateway_v2_test.go | 186 -- acceptance/tests/api-gateway_v2/helpers.go | 123 -- acceptance/tests/api-gateway_v2/main_test.go | 24 - acceptance/tests/cli/cli_install_test.go | 4 +- acceptance/tests/cloud/observability_test.go | 6 +- .../config_entries_namespaces_test.go | 2 +- .../config-entries/config_entries_test.go | 12 +- .../connect/connect_proxy_lifecycle_test.go | 23 +- .../tests/connect/local_rate_limit_test.go | 4 +- .../tests/consul-dns/consul_dns_test.go | 2 +- acceptance/tests/example/main_test.go | 1 - .../bases/api-gateway-v2/apigateway.yaml | 16 - .../bases/api-gateway-v2/certificate.yaml | 11 - .../bases/api-gateway-v2/gatewayclass.yaml | 13 - .../api-gateway-v2/gatewayclassconfig.yaml | 7 - .../bases/api-gateway-v2/kustomization.yaml | 8 - .../bases/api-gateway-v2/tcproute.yaml | 10 - .../bases/cloud/hcp-mock/deployment.yaml | 2 +- .../kitchen-sink-ent/api-gateway.yaml | 25 - .../kitchen-sink-ent/external-ref.yaml | 16 - .../kitchen-sink-ent/filters.yaml | 25 - .../kitchen-sink-ent/gateway-policy.yaml | 25 - .../kitchen-sink-ent/gatewayclassconfig.yaml | 12 - .../kitchen-sink-ent/httproute.yaml | 45 - .../kitchen-sink-ent/jwt-provider.yaml | 12 - .../kitchen-sink-ent/jwt-route-filter.yaml | 15 - .../kitchen-sink-ent/kustomization.yaml | 18 - .../kitchen-sink/api-gateway.yaml | 25 - .../kitchen-sink/external-ref.yaml | 16 - .../api-gateways/kitchen-sink/filters.yaml | 25 - .../kitchen-sink/gateway-policy.yaml | 25 - .../kitchen-sink/gatewayclassconfig.yaml | 12 - .../api-gateways/kitchen-sink/httproute.yaml | 40 - .../kitchen-sink/kustomization.yaml | 15 - acceptance/tests/mesh_v2/mesh_inject_test.go | 1 + acceptance/tests/metrics/metrics_test.go | 2 +- acceptance/tests/partitions/main_test.go | 2 +- .../peering_connect_namespaces_test.go | 2 +- .../tests/peering/peering_connect_test.go | 2 +- .../tests/peering/peering_gateway_test.go | 2 +- acceptance/tests/sameness/sameness_test.go | 16 +- acceptance/tests/server/main_test.go | 18 - acceptance/tests/server/server_test.go | 91 - .../snapshot_agent_k8s_secret_test.go | 4 +- .../snapshot_agent_vault_test.go | 4 +- acceptance/tests/sync/sync_catalog_test.go | 6 +- acceptance/tests/tenancy_v2/main_test.go | 30 - acceptance/tests/tenancy_v2/namespace_test.go | 62 - acceptance/tests/tenancy_v2/partition_test.go | 91 - acceptance/tests/vault/vault_wan_fed_test.go | 4 +- .../wan-federation/wan_federation_test.go | 4 +- charts/consul/Chart.yaml | 10 +- charts/consul/README.md | 2 +- charts/consul/templates/_helpers.tpl | 34 +- .../templates/connect-inject-clusterrole.yaml | 34 - .../templates/connect-inject-deployment.yaml | 3 - charts/consul/templates/crd-apigateways.yaml | 302 --- .../templates/crd-exportedservices-v1.yaml | 139 -- .../templates/crd-exportedservices.yaml | 51 +- .../templates/crd-gatewayclassconfigs-v1.yaml | 201 -- .../templates/crd-gatewayclassconfigs.yaml | 1883 ++--------------- .../crd-gatewayclasses-external.yaml | 9 +- .../consul/templates/crd-gatewayclasses.yaml | 122 -- .../templates/crd-gateways-external.yaml | 9 +- .../templates/crd-grpcroutes-external.yaml | 9 +- charts/consul/templates/crd-grpcroutes.yaml | 23 +- .../templates/crd-httproutes-external.yaml | 9 +- charts/consul/templates/crd-httproutes.yaml | 23 +- .../templates/crd-meshconfigurations.yaml | 100 - charts/consul/templates/crd-meshgateways.yaml | 134 -- .../templates/crd-proxyconfigurations.yaml | 20 +- .../crd-referencegrants-external.yaml | 9 +- .../templates/crd-routetimeoutfilters.yaml | 2 - .../consul/templates/crd-servicerouters.yaml | 4 +- .../templates/crd-tcproutes-external.yaml | 9 +- charts/consul/templates/crd-tcproutes.yaml | 23 +- .../templates/crd-tlsroutes-external.yaml | 9 +- .../templates/crd-trafficpermissions.yaml | 72 +- .../templates/crd-udproutes-external.yaml | 9 +- .../gateway-cleanup-clusterrole.yaml | 9 - .../consul/templates/gateway-cleanup-job.yaml | 8 - .../gateway-resources-clusterrole.yaml | 10 - .../gateway-resources-configmap.yaml | 178 +- .../templates/gateway-resources-job.yaml | 2 +- .../templates/mesh-gateway-clusterrole.yaml | 2 - .../mesh-gateway-clusterrolebinding.yaml | 2 - .../templates/mesh-gateway-deployment.yaml | 2 - .../mesh-gateway-podsecuritypolicy.yaml | 2 - .../templates/mesh-gateway-service.yaml | 2 - .../mesh-gateway-serviceaccount.yaml | 2 - .../consul/templates/partition-init-job.yaml | 3 - .../templates/server-config-configmap.yaml | 7 +- .../templates/server-disruptionbudget.yaml | 2 +- .../consul/templates/server-statefulset.yaml | 13 +- .../test/unit/connect-inject-clusterrole.bats | 25 - .../test/unit/connect-inject-deployment.bats | 30 +- .../unit/gateway-resources-configmap.bats | 439 +--- charts/consul/test/unit/helpers.bats | 16 +- .../consul/test/unit/partition-init-job.bats | 25 +- .../test/unit/server-config-configmap.bats | 60 +- .../test/unit/server-disruptionbudget.bats | 28 +- .../consul/test/unit/server-statefulset.bats | 6 +- charts/consul/values.yaml | 26 +- cli/cmd/proxy/list/command.go | 1 - cli/go.mod | 6 +- cli/go.sum | 12 +- cli/version/version.go | 2 +- control-plane/Dockerfile.dev | 11 - control-plane/api-gateway/cache/consul.go | 23 +- control-plane/api-gateway/gatekeeper/init.go | 7 +- .../auth/v2beta1/traffic_permissions_types.go | 5 + .../v2beta1/traffic_permissions_types_test.go | 144 +- .../v2beta1/trafficpermissions_webhook.go | 10 +- control-plane/api/common/common.go | 23 +- .../{consul_resource.go => meshconfig.go} | 2 +- ...ource_webhook.go => meshconfig_webhook.go} | 42 +- ...ook_test.go => meshconfig_webhook_test.go} | 142 +- .../api/mesh/v2beta1/api_gateway_types.go | 205 -- .../v2beta1/gateway_class_config_types.go | 171 -- .../api/mesh/v2beta1/gateway_class_types.go | 63 - .../api/mesh/v2beta1/grpc_route_types.go | 9 +- .../api/mesh/v2beta1/grpc_route_types_test.go | 8 + .../api/mesh/v2beta1/grpc_route_webhook.go | 10 +- .../api/mesh/v2beta1/http_route_types.go | 9 +- .../api/mesh/v2beta1/http_route_types_test.go | 8 + .../api/mesh/v2beta1/http_route_webhook.go | 10 +- .../mesh/v2beta1/mesh_configuration_types.go | 145 -- .../api/mesh/v2beta1/mesh_gateway_types.go | 199 -- .../proxy_configuration_route_webhook.go | 10 +- .../mesh/v2beta1/proxy_configuration_types.go | 9 +- .../v2beta1/proxy_configuration_types_test.go | 8 + .../api/mesh/v2beta1/tcp_route_types.go | 9 +- .../api/mesh/v2beta1/tcp_route_types_test.go | 13 + .../api/mesh/v2beta1/tcp_route_webhook.go | 10 +- .../api/mesh/v2beta1/zz_generated.deepcopy.go | 714 ------- .../v2/exported_services_types.go | 147 -- .../v2/multicluster_groupversion_info.go | 27 - .../api/multicluster/v2/shared_types.go | 14 - control-plane/api/multicluster/v2/status.go | 93 - .../multicluster/v2/zz_generated.deepcopy.go | 136 -- .../build-support/functions/10-util.sh | 55 +- .../scripts/consul-enterprise-version.sh | 6 +- control-plane/cni/go.mod | 18 +- control-plane/cni/go.sum | 50 +- .../controllers}/configentry_controller.go | 6 +- .../configentry_controller_ent_test.go | 4 +- .../configentry_controller_test.go | 2 +- .../controlplanerequestlimit_controller.go | 2 +- .../exportedservices_controller.go | 2 +- .../exportedservices_controller_ent_test.go | 20 +- .../controllers}/finalizer_patch.go | 4 +- .../controllers}/finalizer_patch_test.go | 2 +- .../controllers}/ingressgateway_controller.go | 2 +- .../controllers}/jwtprovider_controller.go | 2 +- .../controllers}/mesh_controller.go | 2 +- .../controllers}/proxydefaults_controller.go | 2 +- .../controllers}/samenessgroups_controller.go | 2 +- .../servicedefaults_controller.go | 2 +- .../serviceintentions_controller.go | 2 +- .../serviceresolver_controller.go | 2 +- .../controllers}/servicerouter_controller.go | 2 +- .../servicesplitter_controller.go | 2 +- .../terminatinggateway_controller.go | 2 +- .../controllersv2}/grpc_route_controller.go | 10 +- .../controllersv2}/http_route_controller.go | 10 +- .../controllersv2/meshconfig_controller.go} | 106 +- .../meshconfig_controller_test.go} | 183 +- .../proxy_configuration_controller.go | 10 +- .../controllersv2}/tcp_route_controller.go | 10 +- .../traffic_permissions_controller.go | 10 +- ...nsul.hashicorp.com_trafficpermissions.yaml | 72 +- .../consul.hashicorp.com_servicerouters.yaml | 4 +- ...mesh.consul.hashicorp.com_apigateways.yaml | 297 --- ...sul.hashicorp.com_gatewayclassconfigs.yaml | 1821 ---------------- ...h.consul.hashicorp.com_gatewayclasses.yaml | 117 - .../mesh.consul.hashicorp.com_grpcroutes.yaml | 23 +- .../mesh.consul.hashicorp.com_httproutes.yaml | 23 +- ...nsul.hashicorp.com_meshconfigurations.yaml | 95 - ...esh.consul.hashicorp.com_meshgateways.yaml | 129 -- ...sul.hashicorp.com_proxyconfigurations.yaml | 20 +- .../mesh.consul.hashicorp.com_tcproutes.yaml | 23 +- ...consul.hashicorp.com_exportedservices.yaml | 103 - control-plane/config/rbac/role.yaml | 100 - control-plane/config/webhook/manifests.yaml | 152 +- .../common/annotation_processor.go | 4 +- .../common/annotation_processor_test.go | 27 + control-plane/connect-inject/common/common.go | 26 +- .../connect-inject/common/common_test.go | 53 +- .../connect-inject/constants/constants.go | 17 - .../endpointsv2/endpoints_controller.go | 10 +- .../endpointsv2/endpoints_controller_test.go | 51 +- .../controllers/pod/pod_controller.go | 44 +- .../pod/pod_controller_ent_test.go | 54 +- .../controllers/pod/pod_controller_test.go | 273 ++- .../serviceaccount_controller.go | 3 + .../serviceaccount_controller_test.go | 15 +- .../connect-inject/webhook/container_init.go | 6 +- .../webhookv2/container_init.go | 6 +- .../connect-inject/webhookv2/mesh_webhook.go | 11 - .../webhookv2/mesh_webhook_test.go | 109 - control-plane/consul/dataplane_client_test.go | 2 + control-plane/consul/resource_client_test.go | 1 + .../resources/api-gateway-controller.go | 85 - .../resources/api-gateway-controller_test.go | 194 -- .../consul_resource_controller_ent_test.go | 188 -- .../resources/exported_services_controller.go | 45 - .../gateway_class_config_controller.go | 45 - .../resources/gateway_class_controller.go | 45 - .../resources/gateway_controller_crud.go | 211 -- .../resources/gateway_controller_setup.go | 106 - .../controllers/resources/gateway_indices.go | 75 - .../mesh_configuration_controller.go | 43 - .../resources/mesh_gateway_controller.go | 85 - .../resources/mesh_gateway_controller_test.go | 601 ------ control-plane/gateways/builder.go | 38 - control-plane/gateways/constants.go | 32 - control-plane/gateways/deployment.go | 208 -- .../deployment_dataplane_container.go | 199 -- .../gateways/deployment_init_container.go | 193 -- control-plane/gateways/deployment_test.go | 1262 ----------- control-plane/gateways/gateway_config.go | 58 - control-plane/gateways/metadata.go | 169 -- control-plane/gateways/metadata_test.go | 341 --- control-plane/gateways/role.go | 45 - control-plane/gateways/service.go | 63 - control-plane/gateways/service_test.go | 358 ---- control-plane/gateways/serviceaccount.go | 24 - control-plane/gateways/serviceaccount_test.go | 34 - control-plane/go.mod | 22 +- control-plane/go.sum | 28 +- control-plane/helper/test/test_util.go | 102 +- .../create-federation-secret/command_test.go | 2 +- control-plane/subcommand/flags/consul.go | 14 +- control-plane/subcommand/flags/consul_test.go | 11 +- .../subcommand/gateway-cleanup/command.go | 179 +- .../gateway-cleanup/command_test.go | 166 -- .../subcommand/gateway-resources/command.go | 269 +-- .../gateway-resources/command_test.go | 400 +--- .../subcommand/inject-connect/command.go | 20 +- .../subcommand/inject-connect/command_test.go | 9 - .../inject-connect/v1controllers.go | 2 +- .../inject-connect/v2controllers.go | 191 +- control-plane/subcommand/mesh-init/command.go | 13 +- .../subcommand/mesh-init/command_ent_test.go | 7 +- .../subcommand/mesh-init/command_test.go | 31 +- .../subcommand/partition-init/command.go | 163 +- .../partition-init/command_ent_test.go | 288 +-- .../server-acl-init/command_ent_test.go | 2 + .../subcommand/sync-catalog/command_test.go | 4 +- control-plane/tenancy/namespace/namespace.go | 117 - .../tenancy/namespace/namespace_controller.go | 95 - .../namespace_controller_ent_test.go | 35 - .../namespace/namespace_controller_test.go | 301 --- control-plane/version/version.go | 2 +- hack/copy-crds-to-chart/main.go | 17 +- 295 files changed, 2080 insertions(+), 18179 deletions(-) delete mode 100644 .changelog/3000.txt rename .changelog/{3116.txt => 3118.txt} (100%) delete mode 100644 .changelog/3184.txt delete mode 100644 .changelog/3675.txt rename .github/workflows/{weekly-acceptance-1-4-0-rc1.yml => nightly-acceptance-1-3-0-rc1.yml} (67%) rename .github/workflows/{weekly-acceptance-1-4-x.yml => weekly-acceptance-0-49-x.yml} (86%) rename .github/workflows/{weekly-acceptance-1-3-x.yml => weekly-acceptance-1-0-x.yml} (86%) delete mode 100644 acceptance/framework/resource/helpers.go delete mode 100644 acceptance/tests/api-gateway/api_gateway_kitchen_sink_test.go delete mode 100644 acceptance/tests/api-gateway_v2/api_gateway_v2_test.go delete mode 100644 acceptance/tests/api-gateway_v2/helpers.go delete mode 100644 acceptance/tests/api-gateway_v2/main_test.go delete mode 100644 acceptance/tests/fixtures/bases/api-gateway-v2/apigateway.yaml delete mode 100644 acceptance/tests/fixtures/bases/api-gateway-v2/certificate.yaml delete mode 100644 acceptance/tests/fixtures/bases/api-gateway-v2/gatewayclass.yaml delete mode 100644 acceptance/tests/fixtures/bases/api-gateway-v2/gatewayclassconfig.yaml delete mode 100644 acceptance/tests/fixtures/bases/api-gateway-v2/kustomization.yaml delete mode 100644 acceptance/tests/fixtures/bases/api-gateway-v2/tcproute.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/api-gateway.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/external-ref.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/filters.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/gateway-policy.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/gatewayclassconfig.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/httproute.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/jwt-provider.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/jwt-route-filter.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/kustomization.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/api-gateway.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/external-ref.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/filters.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/gateway-policy.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/gatewayclassconfig.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/httproute.yaml delete mode 100644 acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/kustomization.yaml delete mode 100644 acceptance/tests/server/main_test.go delete mode 100644 acceptance/tests/server/server_test.go delete mode 100644 acceptance/tests/tenancy_v2/main_test.go delete mode 100644 acceptance/tests/tenancy_v2/namespace_test.go delete mode 100644 acceptance/tests/tenancy_v2/partition_test.go delete mode 100644 charts/consul/templates/crd-apigateways.yaml delete mode 100644 charts/consul/templates/crd-exportedservices-v1.yaml delete mode 100644 charts/consul/templates/crd-gatewayclassconfigs-v1.yaml delete mode 100644 charts/consul/templates/crd-gatewayclasses.yaml delete mode 100644 charts/consul/templates/crd-meshconfigurations.yaml delete mode 100644 charts/consul/templates/crd-meshgateways.yaml delete mode 100644 control-plane/Dockerfile.dev rename control-plane/api/common/{consul_resource.go => meshconfig.go} (98%) rename control-plane/api/common/{consul_resource_webhook.go => meshconfig_webhook.go} (62%) rename control-plane/api/common/{consul_resource_webhook_test.go => meshconfig_webhook_test.go} (50%) delete mode 100644 control-plane/api/mesh/v2beta1/api_gateway_types.go delete mode 100644 control-plane/api/mesh/v2beta1/gateway_class_config_types.go delete mode 100644 control-plane/api/mesh/v2beta1/gateway_class_types.go delete mode 100644 control-plane/api/mesh/v2beta1/mesh_configuration_types.go delete mode 100644 control-plane/api/mesh/v2beta1/mesh_gateway_types.go delete mode 100644 control-plane/api/multicluster/v2/exported_services_types.go delete mode 100644 control-plane/api/multicluster/v2/multicluster_groupversion_info.go delete mode 100644 control-plane/api/multicluster/v2/shared_types.go delete mode 100644 control-plane/api/multicluster/v2/status.go delete mode 100644 control-plane/api/multicluster/v2/zz_generated.deepcopy.go rename control-plane/{controllers/configentries => config-entries/controllers}/configentry_controller.go (99%) rename control-plane/{controllers/configentries => config-entries/controllers}/configentry_controller_ent_test.go (99%) rename control-plane/{controllers/configentries => config-entries/controllers}/configentry_controller_test.go (99%) rename control-plane/{controllers/configentries => config-entries/controllers}/controlplanerequestlimit_controller.go (98%) rename control-plane/{controllers/configentries => config-entries/controllers}/exportedservices_controller.go (98%) rename control-plane/{controllers/configentries => config-entries/controllers}/exportedservices_controller_ent_test.go (95%) rename control-plane/{controllers/configentries => config-entries/controllers}/finalizer_patch.go (95%) rename control-plane/{controllers/configentries => config-entries/controllers}/finalizer_patch_test.go (99%) rename control-plane/{controllers/configentries => config-entries/controllers}/ingressgateway_controller.go (98%) rename control-plane/{controllers/configentries => config-entries/controllers}/jwtprovider_controller.go (98%) rename control-plane/{controllers/configentries => config-entries/controllers}/mesh_controller.go (98%) rename control-plane/{controllers/configentries => config-entries/controllers}/proxydefaults_controller.go (98%) rename control-plane/{controllers/configentries => config-entries/controllers}/samenessgroups_controller.go (98%) rename control-plane/{controllers/configentries => config-entries/controllers}/servicedefaults_controller.go (98%) rename control-plane/{controllers/configentries => config-entries/controllers}/serviceintentions_controller.go (98%) rename control-plane/{controllers/configentries => config-entries/controllers}/serviceresolver_controller.go (98%) rename control-plane/{controllers/configentries => config-entries/controllers}/servicerouter_controller.go (98%) rename control-plane/{controllers/configentries => config-entries/controllers}/servicesplitter_controller.go (98%) rename control-plane/{controllers/configentries => config-entries/controllers}/terminatinggateway_controller.go (98%) rename control-plane/{controllers/resources => config-entries/controllersv2}/grpc_route_controller.go (84%) rename control-plane/{controllers/resources => config-entries/controllersv2}/http_route_controller.go (84%) rename control-plane/{controllers/resources/consul_resource_controller.go => config-entries/controllersv2/meshconfig_controller.go} (71%) rename control-plane/{controllers/resources/consul_resource_controller_test.go => config-entries/controllersv2/meshconfig_controller_test.go} (78%) rename control-plane/{controllers/resources => config-entries/controllersv2}/proxy_configuration_controller.go (85%) rename control-plane/{controllers/resources => config-entries/controllersv2}/tcp_route_controller.go (84%) rename control-plane/{controllers/resources => config-entries/controllersv2}/traffic_permissions_controller.go (84%) delete mode 100644 control-plane/config/crd/bases/mesh.consul.hashicorp.com_apigateways.yaml delete mode 100644 control-plane/config/crd/bases/mesh.consul.hashicorp.com_gatewayclassconfigs.yaml delete mode 100644 control-plane/config/crd/bases/mesh.consul.hashicorp.com_gatewayclasses.yaml delete mode 100644 control-plane/config/crd/bases/mesh.consul.hashicorp.com_meshconfigurations.yaml delete mode 100644 control-plane/config/crd/bases/mesh.consul.hashicorp.com_meshgateways.yaml delete mode 100644 control-plane/config/crd/bases/multicluster.consul.hashicorp.com_exportedservices.yaml delete mode 100644 control-plane/controllers/resources/api-gateway-controller.go delete mode 100644 control-plane/controllers/resources/api-gateway-controller_test.go delete mode 100644 control-plane/controllers/resources/consul_resource_controller_ent_test.go delete mode 100644 control-plane/controllers/resources/exported_services_controller.go delete mode 100644 control-plane/controllers/resources/gateway_class_config_controller.go delete mode 100644 control-plane/controllers/resources/gateway_class_controller.go delete mode 100644 control-plane/controllers/resources/gateway_controller_crud.go delete mode 100644 control-plane/controllers/resources/gateway_controller_setup.go delete mode 100644 control-plane/controllers/resources/gateway_indices.go delete mode 100644 control-plane/controllers/resources/mesh_configuration_controller.go delete mode 100644 control-plane/controllers/resources/mesh_gateway_controller.go delete mode 100644 control-plane/controllers/resources/mesh_gateway_controller_test.go delete mode 100644 control-plane/gateways/builder.go delete mode 100644 control-plane/gateways/constants.go delete mode 100644 control-plane/gateways/deployment.go delete mode 100644 control-plane/gateways/deployment_dataplane_container.go delete mode 100644 control-plane/gateways/deployment_init_container.go delete mode 100644 control-plane/gateways/deployment_test.go delete mode 100644 control-plane/gateways/gateway_config.go delete mode 100644 control-plane/gateways/metadata.go delete mode 100644 control-plane/gateways/metadata_test.go delete mode 100644 control-plane/gateways/role.go delete mode 100644 control-plane/gateways/service.go delete mode 100644 control-plane/gateways/service_test.go delete mode 100644 control-plane/gateways/serviceaccount.go delete mode 100644 control-plane/gateways/serviceaccount_test.go delete mode 100644 control-plane/tenancy/namespace/namespace.go delete mode 100644 control-plane/tenancy/namespace/namespace_controller.go delete mode 100644 control-plane/tenancy/namespace/namespace_controller_ent_test.go delete mode 100644 control-plane/tenancy/namespace/namespace_controller_test.go diff --git a/.changelog/2962.txt b/.changelog/2962.txt index f4550c2781..f707e4828f 100644 --- a/.changelog/2962.txt +++ b/.changelog/2962.txt @@ -1,3 +1,3 @@ -```release-note:feature +```releast-note:feature api-gateway: (Consul Enterprise) Add JWT authentication and authorization for API Gateway and HTTPRoutes. ``` diff --git a/.changelog/3000.txt b/.changelog/3000.txt deleted file mode 100644 index 1e6be21f78..0000000000 --- a/.changelog/3000.txt +++ /dev/null @@ -1,36 +0,0 @@ -```release-note:breaking-change -server: set `leave_on_terminate` to `true` and set the server pod disruption budget `maxUnavailable` to `1`. - -This change makes server rollouts faster and more reliable. However, there is now a potential for reduced reliability if users accidentally -scale the statefulset down. Now servers will leave the raft pool when they are stopped gracefully which reduces the fault -tolerance. For example, with 5 servers, you can tolerate a loss of 2 servers' data as raft guarantees data is replicated to -a majority of nodes (3). However, if you accidentally scale the statefulset down to 3, then the raft quorum will now be 2, and -if you lose 2 servers, you may lose data. Before this change, the quorum would have remained at 3. - -During a regular rollout, the number of servers will be reduced by 1 at a time, which doesn't affect quorum when running -an odd number of servers, e.g. quorum for 5 servers is 3, and quorum for 4 servers is also 3. That's why the pod disruption -budget is being set to 1 now. - -If a server is stopped ungracefully, e.g. due to a node loss, it will not leave the raft pool, and so fault tolerance won't be affected. - -For the vast majority of users, this change will be beneficial, however if you wish to remain with the old settings you -can set: - - server: - extraConfig: | - {"leave_on_terminate": false} - disruptionBudget: - maxUnavailable: - -``` - -```release-note:breaking-change -server: set `autopilot.min_quorum` to the correct quorum value to ensure autopilot doesn't prune servers needed for quorum. Also set `autopilot. disable_upgrade_migration` to `true` as that setting is meant for blue/green deploys, not rolling deploys. - -This setting makes sense for most use-cases, however if you had a specific reason to use the old settings you can use the following config to keep them: - - server: - extraConfig: | - {"autopilot": {"min_quorum": 0, "disable_upgrade_migration": false}} - -``` diff --git a/.changelog/3116.txt b/.changelog/3118.txt similarity index 100% rename from .changelog/3116.txt rename to .changelog/3118.txt diff --git a/.changelog/3184.txt b/.changelog/3184.txt deleted file mode 100644 index 4e1abf0f35..0000000000 --- a/.changelog/3184.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -consul-telemetry-collector: fix args to consul-dataplane when global.acls.manageSystemACLs -``` \ No newline at end of file diff --git a/.changelog/3418.txt b/.changelog/3418.txt index 032356f989..ea38dea8ff 100644 --- a/.changelog/3418.txt +++ b/.changelog/3418.txt @@ -1,3 +1,3 @@ ```release-note:security -Upgrade OpenShift container images to use `ubi9-minimal:9.3` as the base image. +Upgrade OpenShift container images to use `ubi-minimal:9.3` as the base image. ``` diff --git a/.changelog/3668.txt b/.changelog/3668.txt index 797590f713..25b12b0d18 100644 --- a/.changelog/3668.txt +++ b/.changelog/3668.txt @@ -1,3 +1,3 @@ ```release-note:improvement -control-plane: publish `consul-k8s-control-plane` and `consul-k8s-control-plane-fips` images to official HashiCorp AWS ECR. -``` + control-plane: publish `consul-k8s-control-plane` and `consul-k8s-control-plane-fips` images to official HashiCorp AWS ECR. + ``` diff --git a/.changelog/3675.txt b/.changelog/3675.txt deleted file mode 100644 index 987370cfa4..0000000000 --- a/.changelog/3675.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -helm: Kubernetes v1.29 is now supported. Minimum tested version of Kubernetes is now v1.26. -``` \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index e863abf7c5..f5d211b137 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,13 +1,14 @@ -### Changes proposed in this PR ### +Changes proposed in this PR: - - -### How I've tested this PR ### +How I've tested this PR: +How I expect reviewers to test this PR: -### How I expect reviewers to test this PR ### - -### Checklist ### +Checklist: - [ ] Tests added - [ ] [CHANGELOG entry added](https://github.com/hashicorp/consul-k8s/blob/main/CONTRIBUTING.md#adding-a-changelog-entry) + + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b372abc0d6..54a69d7a1c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -106,7 +106,6 @@ jobs: - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni", gotags: "fips", env: "CGO_ENABLED=1 GOEXPERIMENT=boringcrypto CC=aarch64-linux-gnu-gcc", fips: "+fips1402", pkg_suffix: "-fips" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "amd64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni.exe", gotags: "fips", env: "CGO_ENABLED=1 GOEXPERIMENT=cngcrypto", fips: "+fips1402" } - fail-fast: true name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} ${{ matrix.component }} ${{ matrix.fips }} build @@ -328,8 +327,8 @@ jobs: extra_build_args: | GOLANG_VERSION=${{ needs.get-go-version.outputs.go-version }} - build-docker-ubi: - name: Docker ${{ matrix.arch }} ${{ matrix.fips }} UBI builds + build-docker-ubi-redhat-registry: + name: Docker ${{ matrix.arch }} ${{ matrix.fips }} UBI build for RedHat Registry needs: [get-product-version, get-go-version, build] runs-on: ubuntu-latest strategy: @@ -352,6 +351,78 @@ jobs: run: | cd "${ZIP_LOCATION}" unzip -j *.zip + - name: Copy LICENSE + run: + cp LICENSE ./control-plane + - name: Docker Build (Action) + if: ${{ !matrix.fips }} + uses: hashicorp/actions-docker-build@76d2fc91532d816ca2660d8f3139e432ac3700fd + with: + smoke_test: | + TEST_VERSION="$(docker run "${IMAGE_NAME}" consul-k8s-control-plane version | awk '{print $2}')" + if [ "${TEST_VERSION}" != "v${version}" ]; then + echo "Test FAILED" + exit 1 + fi + echo "Test PASSED" + version: ${{ env.version }} + target: ubi + arch: ${{ matrix.arch }} + pkg_name: consul-k8s-control-plane_${{ env.version }} + bin_name: consul-k8s-control-plane + workdir: control-plane + tags: | + public.ecr.aws/hashicorp/${{ env.repo }}-control-plane:${{ env.version }}-ubi + redhat_tag: quay.io/redhat-isv-containers/611ca2f89a9b407267837100:${{env.version}}-ubi + extra_build_args: | + GOLANG_VERSION=${{ needs.get-go-version.outputs.go-version }} + + - name: Docker FIPS Build (Action) + if: ${{ matrix.fips }} + uses: hashicorp/actions-docker-build@76d2fc91532d816ca2660d8f3139e432ac3700fd + with: + smoke_test: | + TEST_VERSION="$(docker run "${IMAGE_NAME}" consul-k8s-control-plane version | awk '{print $2}')" + if [ "${TEST_VERSION}" != "v${version}" ]; then + echo "Test FAILED" + exit 1 + fi + echo "Test PASSED" + version: ${{ env.version }} + target: ubi-fips # duplicate target to distinguish FIPS builds in CRT machinery + arch: ${{ matrix.arch }} + pkg_name: consul-k8s-control-plane_${{ env.version }} + bin_name: consul-k8s-control-plane + workdir: control-plane + tags: | + public.ecr.aws/hashicorp/${{ env.repo }}-control-plane-fips:${{ env.version }}-ubi + redhat_tag: quay.io/redhat-isv-containers/6486b1beabfc4e51588c0416:${{env.version}}-ubi # this is different than the non-FIPS one + extra_build_args: | + GOLANG_VERSION=${{ needs.get-go-version.outputs.go-version }} + + build-docker-ubi-dockerhub: + name: Docker ${{ matrix.arch }} ${{ matrix.fips }} UBI build for DockerHub + needs: [ get-product-version, get-go-version, build ] + runs-on: ubuntu-latest + strategy: + matrix: + arch: [ "amd64" ] + fips: [ "+fips1402", "" ] + env: + repo: ${{ github.event.repository.name }} + version: ${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }} + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: consul-cni_${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }}_linux_${{ matrix.arch }}.zip + path: control-plane/dist/cni/linux/${{ matrix.arch }} + - name: extract consul-cni zip + env: + ZIP_LOCATION: control-plane/dist/cni/linux/${{ matrix.arch }} + run: | + cd ${ZIP_LOCATION} + unzip -j *.zip - name: Copy LICENSE run: cp LICENSE ./control-plane @@ -365,8 +436,8 @@ jobs: echo "minor_dev_tag=$(echo ${{ env.version }}| sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+(-[0-9a-zA-Z\+\.]+)?$/\1\2/')" >> $GITHUB_ENV - name: Docker Build (Action) - if: ${{ !matrix.fips }} uses: hashicorp/actions-docker-build@76d2fc91532d816ca2660d8f3139e432ac3700fd + if: ${{ !matrix.fips }} with: smoke_test: | TEST_VERSION="$(docker run "${IMAGE_NAME}" consul-k8s-control-plane version | awk '{print $2}')" @@ -383,19 +454,17 @@ jobs: workdir: control-plane tags: | docker.io/hashicorp/${{ env.repo }}-control-plane:${{ env.version }}-ubi - public.ecr.aws/hashicorp/${{ env.repo }}-control-plane:${{ env.version }}-ubi dev_tags: | docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.full_dev_tag }}-ubi docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.full_dev_tag }}-ubi-${{ github.sha }} docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.minor_dev_tag }}-ubi docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.minor_dev_tag }}-ubi-${{ github.sha }} - redhat_tag: quay.io/redhat-isv-containers/611ca2f89a9b407267837100:${{env.version}}-ubi extra_build_args: | GOLANG_VERSION=${{ needs.get-go-version.outputs.go-version }} - name: Docker FIPS Build (Action) - if: ${{ matrix.fips }} uses: hashicorp/actions-docker-build@76d2fc91532d816ca2660d8f3139e432ac3700fd + if: ${{ matrix.fips }} with: smoke_test: | TEST_VERSION="$(docker run "${IMAGE_NAME}" consul-k8s-control-plane version | awk '{print $2}')" @@ -411,7 +480,11 @@ jobs: bin_name: consul-k8s-control-plane workdir: control-plane tags: | - public.ecr.aws/hashicorp/${{ env.repo }}-control-plane-fips:${{ env.version }}-ubi - redhat_tag: quay.io/redhat-isv-containers/6486b1beabfc4e51588c0416:${{env.version}}-ubi # this is different than the non-FIPS one + docker.io/hashicorp/${{ env.repo }}-control-plane-fips:${{ env.version }}-ubi + dev_tags: | + docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.full_dev_tag }}-ubi + docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.full_dev_tag }}-ubi-${{ github.sha }} + docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.minor_dev_tag }}-ubi + docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.minor_dev_tag }}-ubi-${{ github.sha }} extra_build_args: | GOLANG_VERSION=${{ needs.get-go-version.outputs.go-version }} diff --git a/.github/workflows/weekly-acceptance-1-4-0-rc1.yml b/.github/workflows/nightly-acceptance-1-3-0-rc1.yml similarity index 67% rename from .github/workflows/weekly-acceptance-1-4-0-rc1.yml rename to .github/workflows/nightly-acceptance-1-3-0-rc1.yml index e74a44ea70..ad2b373ca4 100644 --- a/.github/workflows/weekly-acceptance-1-4-0-rc1.yml +++ b/.github/workflows/nightly-acceptance-1-3-0-rc1.yml @@ -1,17 +1,15 @@ -# Dispatch to the consul-k8s-workflows with a weekly cron -# -# A separate file is needed for each release because the cron schedules are different for each release. -name: weekly-acceptance-1-4-0-rc1 +# Dispatch to the consul-k8s-workflows with a nightly cron +name: nightly-acceptance on: schedule: # * is a special character in YAML so you have to quote this string - # Run weekly on Friday at 3AM UTC/11PM EST/8PM PST - - cron: '0 3 * * 5' + # Run nightly at 12AM UTC/8PM EST/5PM PST + - cron: '0 0 * * *' # these should be the only settings that you will ever need to change env: - BRANCH: "release/1.4.0-rc1" - CONTEXT: "weekly" + BRANCH: "release/1.3.0-rc1" + CONTEXT: "nightly" jobs: cloud: diff --git a/.github/workflows/weekly-acceptance-1-4-x.yml b/.github/workflows/weekly-acceptance-0-49-x.yml similarity index 86% rename from .github/workflows/weekly-acceptance-1-4-x.yml rename to .github/workflows/weekly-acceptance-0-49-x.yml index a6bbe05e6b..5e1c17f3c7 100644 --- a/.github/workflows/weekly-acceptance-1-4-x.yml +++ b/.github/workflows/weekly-acceptance-0-49-x.yml @@ -1,16 +1,16 @@ # Dispatch to the consul-k8s-workflows with a weekly cron # # A separate file is needed for each release because the cron schedules are different for each release. -name: weekly-acceptance-1-4-x +name: weekly-acceptance-0-49-x on: schedule: # * is a special character in YAML so you have to quote this string - # Run weekly on Thursday at 3AM UTC/11PM EST/8PM PST - - cron: '0 3 * * 4' + # Run weekly on Monday at 3AM UTC/11PM EST/8PM PST + - cron: '0 3 * * 1' # these should be the only settings that you will ever need to change env: - BRANCH: "release/1.4.x" + BRANCH: "release/0.49.x" CONTEXT: "weekly" jobs: diff --git a/.github/workflows/weekly-acceptance-1-3-x.yml b/.github/workflows/weekly-acceptance-1-0-x.yml similarity index 86% rename from .github/workflows/weekly-acceptance-1-3-x.yml rename to .github/workflows/weekly-acceptance-1-0-x.yml index 9d1a2d65a6..11dda52bed 100644 --- a/.github/workflows/weekly-acceptance-1-3-x.yml +++ b/.github/workflows/weekly-acceptance-1-0-x.yml @@ -1,16 +1,17 @@ # Dispatch to the consul-k8s-workflows with a weekly cron # # A separate file is needed for each release because the cron schedules are different for each release. -name: weekly-acceptance-1-3-x +name: weekly-acceptance-1-0-x on: schedule: # * is a special character in YAML so you have to quote this string - # Run weekly on Wednesday at 3AM UTC/11PM EST/8PM PST - - cron: '0 3 * * 3' + # Run weekly on Tuesday at 3AM UTC/11PM EST/8PM PST + - cron: '0 3 * * 2' + # these should be the only settings that you will ever need to change env: - BRANCH: "release/1.3.x" + BRANCH: "release/1.0.x" CONTEXT: "weekly" jobs: diff --git a/.github/workflows/weekly-acceptance-1-1-x.yml b/.github/workflows/weekly-acceptance-1-1-x.yml index c3c39fef32..86153587b0 100644 --- a/.github/workflows/weekly-acceptance-1-1-x.yml +++ b/.github/workflows/weekly-acceptance-1-1-x.yml @@ -5,8 +5,8 @@ name: weekly-acceptance-1-1-x on: schedule: # * is a special character in YAML so you have to quote this string - # Run weekly on Monday at 3AM UTC/11PM EST/8PM PST - - cron: '0 3 * * 1' + # Run weekly on Wednesday at 3AM UTC/11PM EST/8PM PST + - cron: '0 3 * * 3' # these should be the only settings that you will ever need to change diff --git a/.github/workflows/weekly-acceptance-1-2-x.yml b/.github/workflows/weekly-acceptance-1-2-x.yml index 3dac6c8755..353a086f16 100644 --- a/.github/workflows/weekly-acceptance-1-2-x.yml +++ b/.github/workflows/weekly-acceptance-1-2-x.yml @@ -5,8 +5,9 @@ name: weekly-acceptance-1-2-x on: schedule: # * is a special character in YAML so you have to quote this string - # Run weekly on Tuesday at 3AM UTC/11PM EST/8PM PST - - cron: '0 3 * * 2' + # Run weekly on Wednesday at 3AM UTC/11PM EST/8PM PST + # - cron: '0 3 * * 3' + - cron: '0 0 * * *' # Temporarily nightly until 1.2.0 GA # these should be the only settings that you will ever need to change diff --git a/CHANGELOG.md b/CHANGELOG.md index ebbcde7f64..32a32bbf09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,51 +29,6 @@ BUG FIXES: Adds NET_BIND_SERVICE to capabilities.add Adds ALL to capabilities.drop unless .Values.meshGateway.hostNetwork is true [[GH-3549](https://github.com/hashicorp/consul-k8s/issues/3549)] -## 1.2.6 (February 15, 2024) - -FEATURES: - -* helm: introduces `global.metrics.datadog` overrides to streamline consul-k8s datadog integration. -helm: introduces `server.enableAgentDebug` to expose agent [`enable_debug`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#enable_debug) configuration. -helm: introduces `global.metrics.disableAgentHostName` to expose agent [`telemetry.disable_hostname`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#telemetry-disable_hostname) configuration. -helm: introduces `global.metrics.enableHostMetrics` to expose agent [`telemetry.enable_host_metrics`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#telemetry-enable_host_metrics) configuration. -helm: introduces `global.metrics.prefixFilter` to expose agent [`telemetry.prefix_filter`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#telemetry-prefix_filter) configuration. -helm: introduces `global.metrics.datadog.dogstatsd.dogstatsdAddr` to expose agent [`telemetry.dogstatsd_addr`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#telemetry-dogstatsd_addr) configuration. -helm: introduces `global.metrics.datadog.dogstatsd.dogstatsdTags` to expose agent [`telemetry.dogstatsd_tags`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#telemetry-dogstatsd_tags) configuration. -helm: introduces required `ad.datadoghq.com/` annotations and `tags.datadoghq.com/` labels for integration with [Datadog Autodiscovery](https://docs.datadoghq.com/integrations/consul/?tab=containerized) and [Datadog Unified Service Tagging](https://docs.datadoghq.com/getting_started/tagging/unified_service_tagging/?tab=kubernetes#serverless-environment) for Consul. -helm: introduces automated unix domain socket hostPath mounting for containerized integration with datadog within consul-server statefulset. -helm: introduces `global.metrics.datadog.otlp` override options to allow OTLP metrics forwarding to Datadog Agent. -control-plane: adds `server-acl-init` datadog agent token creation for datadog integration. [[GH-3407](https://github.com/hashicorp/consul-k8s/issues/3407)] - -IMPROVEMENTS: - -* Upgrade to use Go 1.21.7. [[GH-3591](https://github.com/hashicorp/consul-k8s/issues/3591)] -* api-gateway: Apply `connectInject.initContainer.resources` to the init container for API gateway Pods. [[GH-3531](https://github.com/hashicorp/consul-k8s/issues/3531)] -* cni: When CNI is enabled, set ReadOnlyRootFilesystem=true and AllowPrivilegeEscalation=false for mesh pod init containers and AllowPrivilegeEscalation=false for consul-dataplane containers (ReadOnlyRootFilesystem was already true for consul-dataplane containers). [[GH-3498](https://github.com/hashicorp/consul-k8s/issues/3498)] -* control-plane: Changed the container ordering in connect-inject to insert consul-dataplane container first if lifecycle is enabled. Container ordering is unchanged if lifecycle is disabled. [[GH-2743](https://github.com/hashicorp/consul-k8s/issues/2743)] -* helm: Change `/bin/sh -ec ""` to `/bin/sh -ec "exec "` in helm deployments [[GH-3548](https://github.com/hashicorp/consul-k8s/issues/3548)] - -BUG FIXES: - -* api-gateway: fix issue where external annotations and labels are being incorrectly deleted on services controlled by the API Gateway [[GH-3597](https://github.com/hashicorp/consul-k8s/issues/3597)] -* mesh-gw: update capabilities on the security context needed for the dataplane container. -Adds NET_BIND_SERVICE to capabilities.add -Adds ALL to capabilities.drop unless .Values.meshGateway.hostNetwork is true [[GH-3549](https://github.com/hashicorp/consul-k8s/issues/3549)] - -## 1.1.10 (February 15, 2024) - -IMPROVEMENTS: - -* Upgrade to use Go 1.21.7. [[GH-3591](https://github.com/hashicorp/consul-k8s/issues/3591)] -* cni: When CNI is enabled, set ReadOnlyRootFilesystem=true and AllowPrivilegeEscalation=false for mesh pod init containers and AllowPrivilegeEscalation=false for consul-dataplane containers (ReadOnlyRootFilesystem was already true for consul-dataplane containers). [[GH-3498](https://github.com/hashicorp/consul-k8s/issues/3498)] -* helm: Change `/bin/sh -ec ""` to `/bin/sh -ec "exec "` in helm deployments [[GH-3548](https://github.com/hashicorp/consul-k8s/issues/3548)] - -BUG FIXES: - -* mesh-gw: update capabilities on the security context needed for the dataplane container. -Adds NET_BIND_SERVICE to capabilities.add -Adds ALL to capabilities.drop unless .Values.meshGateway.hostNetwork is true [[GH-3549](https://github.com/hashicorp/consul-k8s/issues/3549)] - ## 1.3.2 (Jan 25, 2024) SECURITY: @@ -91,36 +46,6 @@ BUG FIXES: * api-gateway: fix issue where deleting an http-route in a non-default namespace would not remove the route from Consul. [[GH-3440](https://github.com/hashicorp/consul-k8s/issues/3440)] -## 1.2.5 (Jan 25, 2024) - -SECURITY: - -* Update `golang.org/x/crypto` to v0.17.0 to address [CVE-2023-48795](https://nvd.nist.gov/vuln/detail/CVE-2023-48795). [[GH-3442](https://github.com/hashicorp/consul-k8s/issues/3442)] -* Upgrade to use `ubi-minimal:9.3` for OpenShift container images. [[GH-3418](https://github.com/hashicorp/consul-k8s/issues/3418)] - -IMPROVEMENTS: - -* Upgrade to use Go 1.21.6. [[GH-3478](https://github.com/hashicorp/consul-k8s/issues/3478)] -* control-plane: Add new `consul.hashicorp.com/sidecar-proxy-startup-failure-seconds` and `consul.hashicorp.com/sidecar-proxy-liveness-failure-seconds` annotations that allow users to manually configure startup and liveness probes for Envoy sidecar proxies. [[GH-3450](https://github.com/hashicorp/consul-k8s/issues/3450)] -* control-plane: reduce Consul Catalog API requests required for endpoints reconcile in large clusters [[GH-3322](https://github.com/hashicorp/consul-k8s/issues/3322)] - -BUG FIXES: - -* api-gateway: fix issue where deleting an http-route in a non-default namespace would not remove the route from Consul. [[GH-3440](https://github.com/hashicorp/consul-k8s/issues/3440)] - -## 1.1.9 (Jan 25, 2024) - -SECURITY: - -* Update `golang.org/x/crypto` to v0.17.0 to address [CVE-2023-48795](https://nvd.nist.gov/vuln/detail/CVE-2023-48795). [[GH-3442](https://github.com/hashicorp/consul-k8s/issues/3442)] -* Upgrade to use `ubi-minimal:9.3` for OpenShift container images. [[GH-3418](https://github.com/hashicorp/consul-k8s/issues/3418)] - -IMPROVEMENTS: - -* Upgrade to use Go 1.21.6. [[GH-3478](https://github.com/hashicorp/consul-k8s/issues/3478)] -* control-plane: Add new `consul.hashicorp.com/sidecar-proxy-startup-failure-seconds` and `consul.hashicorp.com/sidecar-proxy-liveness-failure-seconds` annotations that allow users to manually configure startup and liveness probes for Envoy sidecar proxies. [[GH-3450](https://github.com/hashicorp/consul-k8s/issues/3450)] -* control-plane: reduce Consul Catalog API requests required for endpoints reconcile in large clusters [[GH-3322](https://github.com/hashicorp/consul-k8s/issues/3322)] - ## 1.3.1 (December 19, 2023) SECURITY: @@ -160,73 +85,6 @@ BUG FIXES: * control-plane: Remove virtual nodes in the Consul Catalog when they do not have any services listed. [[GH-3307](https://github.com/hashicorp/consul-k8s/issues/3307)] * mesh: prevent extra-config from being loaded twice (and erroring for segment config) on clients and servers. [[GH-3337](https://github.com/hashicorp/consul-k8s/issues/3337)] -## 1.2.4 (December 19, 2023) - -SECURITY: - -* Update `github.com/golang-jwt/jwt/v4` to v4.5.0 to address [PRISMA-2022-0270](https://github.com/golang-jwt/jwt/issues/258). [[GH-3237](https://github.com/hashicorp/consul-k8s/issues/3237)] -* Upgrade to use Go 1.20.12. This resolves CVEs -[CVE-2023-45283](https://nvd.nist.gov/vuln/detail/CVE-2023-45283): (`path/filepath`) recognize \??\ as a Root Local Device path prefix (Windows) -[CVE-2023-45284](https://nvd.nist.gov/vuln/detail/CVE-2023-45285): recognize device names with trailing spaces and superscripts (Windows) -[CVE-2023-39326](https://nvd.nist.gov/vuln/detail/CVE-2023-39326): (`net/http`) limit chunked data overhead -[CVE-2023-45285](https://nvd.nist.gov/vuln/detail/CVE-2023-45285): (`cmd/go`) go get may unexpectedly fallback to insecure git [[GH-3312](https://github.com/hashicorp/consul-k8s/issues/3312)] - -FEATURES: - -* crd: adds the [`retryOn`](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-router#routes-destination-retryon) field to the ServiceRouter CRD. [[GH-3308](https://github.com/hashicorp/consul-k8s/issues/3308)] -* helm: add persistentVolumeClaimRetentionPolicy variable for managing Statefulsets PVC retain policy when deleting or downsizing the statefulset. [[GH-3180](https://github.com/hashicorp/consul-k8s/issues/3180)] - -IMPROVEMENTS: - -* cli: Add -o json (-output-format json) to `consul-k8s proxy list` command that returns the result in json format. [[GH-3221](https://github.com/hashicorp/consul-k8s/issues/3221)] -* cli: Add consul-k8s proxy stats command line interface that outputs the localhost:19000/stats of envoy in the pod [[GH-3158](https://github.com/hashicorp/consul-k8s/issues/3158)] -* control-plane: Add new `consul.hashicorp.com/proxy-config-map` annotation that allows for setting values in the opaque config map for proxy service registrations. [[GH-3347](https://github.com/hashicorp/consul-k8s/issues/3347)] -* helm: add validation that global.cloud.enabled is not set with externalServers.hosts set to HCP-managed clusters [[GH-3315](https://github.com/hashicorp/consul-k8s/issues/3315)] - -BUG FIXES: - -* consul-telemetry-collector: add telemetryCollector.cloud.resourceId that works even when not global.cloud.enabled [[GH-3219](https://github.com/hashicorp/consul-k8s/issues/3219)] -* consul-telemetry-collector: fix deployments to non-default namespaces when global.enableConsulNamespaces [[GH-3215](https://github.com/hashicorp/consul-k8s/issues/3215)] -* consul-telemetry-collector: fix args to consul-dataplane when global.acls.manageSystemACLs [[GH-3184](https://github.com/hashicorp/consul-k8s/issues/3215)] -* control-plane: Only delete ACL tokens matched Pod UID in Service Registration metadata [[GH-3210](https://github.com/hashicorp/consul-k8s/issues/3210)] -* control-plane: fixes an issue with the server-acl-init job where the job would fail on upgrades due to consul server ip address changes. [[GH-3137](https://github.com/hashicorp/consul-k8s/issues/3137)] -* control-plane: normalize the `partition` and `namespace` fields in V1 CRDs when comparing with saved version of the config-entry. [[GH-3284](https://github.com/hashicorp/consul-k8s/issues/3284)] -* control-plane: Remove virtual nodes in the Consul Catalog when they do not have any services listed. [[GH-3307](https://github.com/hashicorp/consul-k8s/issues/3307)] -* mesh: prevent extra-config from being loaded twice (and erroring for segment config) on clients and servers. [[GH-3337](https://github.com/hashicorp/consul-k8s/issues/3337)] - -## 1.1.8 (December 19, 2023) - -SECURITY: - -* Update `github.com/golang-jwt/jwt/v4` to v4.5.0 to address [PRISMA-2022-0270](https://github.com/golang-jwt/jwt/issues/258). [[GH-3237](https://github.com/hashicorp/consul-k8s/issues/3237)] -* Upgrade to use Go 1.20.12. This resolves CVEs -[CVE-2023-45283](https://nvd.nist.gov/vuln/detail/CVE-2023-45283): (`path/filepath`) recognize \??\ as a Root Local Device path prefix (Windows) -[CVE-2023-45284](https://nvd.nist.gov/vuln/detail/CVE-2023-45285): recognize device names with trailing spaces and superscripts (Windows) -[CVE-2023-39326](https://nvd.nist.gov/vuln/detail/CVE-2023-39326): (`net/http`) limit chunked data overhead -[CVE-2023-45285](https://nvd.nist.gov/vuln/detail/CVE-2023-45285): (`cmd/go`) go get may unexpectedly fallback to insecure git [[GH-3312](https://github.com/hashicorp/consul-k8s/issues/3312)] - -FEATURES: - -* crd: adds the [`retryOn`](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-router#routes-destination-retryon) field to the ServiceRouter CRD. [[GH-3308](https://github.com/hashicorp/consul-k8s/issues/3308)] -* helm: add persistentVolumeClaimRetentionPolicy variable for managing Statefulsets PVC retain policy when deleting or downsizing the statefulset. [[GH-3180](https://github.com/hashicorp/consul-k8s/issues/3180)] - -IMPROVEMENTS: - -* cli: Add -o json (-output-format json) to `consul-k8s proxy list` command that returns the result in json format. [[GH-3221](https://github.com/hashicorp/consul-k8s/issues/3221)] -* cli: Add consul-k8s proxy stats command line interface that outputs the localhost:19000/stats of envoy in the pod [[GH-3158](https://github.com/hashicorp/consul-k8s/issues/3158)] -* control-plane: Add new `consul.hashicorp.com/proxy-config-map` annotation that allows for setting values in the opaque config map for proxy service registrations. [[GH-3347](https://github.com/hashicorp/consul-k8s/issues/3347)] -* helm: add validation that global.cloud.enabled is not set with externalServers.hosts set to HCP-managed clusters [[GH-3315](https://github.com/hashicorp/consul-k8s/issues/3315)] - -BUG FIXES: - -* consul-telemetry-collector: add telemetryCollector.cloud.resourceId that works even when not global.cloud.enabled [[GH-3219](https://github.com/hashicorp/consul-k8s/issues/3219)] -* consul-telemetry-collector: fix deployments to non-default namespaces when global.enableConsulNamespaces [[GH-3215](https://github.com/hashicorp/consul-k8s/issues/3215)] -* consul-telemetry-collector: fix args to consul-dataplane when global.acls.manageSystemACLs [[GH-3184](https://github.com/hashicorp/consul-k8s/issues/3184)] -* control-plane: Only delete ACL tokens matched Pod UID in Service Registration metadata [[GH-3210](https://github.com/hashicorp/consul-k8s/issues/3210)] -* control-plane: fixes an issue with the server-acl-init job where the job would fail on upgrades due to consul server ip address changes. [[GH-3137](https://github.com/hashicorp/consul-k8s/issues/3137)] -* control-plane: Remove virtual nodes in the Consul Catalog when they do not have any services listed. [[GH-3137](https://github.com/hashicorp/consul-k8s/issues/3137)] -* mesh: prevent extra-config from being loaded twice (and erroring for segment config) on clients and servers. [[GH-3337](https://github.com/hashicorp/consul-k8s/issues/3337)] - ## 1.3.0 (November 8, 2023) SECURITY: @@ -270,45 +128,6 @@ BUG FIXES: * control-plane: remove extraneous error log in v2 pod controller when a pod is scheduled, but not yet allocated an IP. [[GH-3162](https://github.com/hashicorp/consul-k8s/issues/3162)] * control-plane: remove extraneous error log in v2 pod controller when attempting to delete ACL tokens. [[GH-3172](https://github.com/hashicorp/consul-k8s/issues/3172)] -## 1.2.3 (November 2, 2023) - -SECURITY: - -* Update Envoy version to 1.25.11 to address [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76) [[GH-3119](https://github.com/hashicorp/consul-k8s/issues/3119)] -* Upgrade `google.golang.org/grpc` to 1.56.3. -This resolves vulnerability [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487). [[GH-3139](https://github.com/hashicorp/consul-k8s/issues/3139)] -* Upgrade to use Go 1.20.10 and `x/net` 0.17.0. -This resolves [CVE-2023-39325](https://nvd.nist.gov/vuln/detail/CVE-2023-39325) -/ [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487). [[GH-3085](https://github.com/hashicorp/consul-k8s/issues/3085)] - -BUG FIXES: - -* api-gateway: fix issue where missing `NET_BIND_SERVICE` capability prevented api-gateway `Pod` from starting up when deployed to OpenShift [[GH-3070](https://github.com/hashicorp/consul-k8s/issues/3070)] -* control-plane: only alert on valid errors, not timeouts in gateway [[GH-3128](https://github.com/hashicorp/consul-k8s/issues/3128)] -* crd: fix misspelling of preparedQuery field in ControlPlaneRequestLimit CRD [[GH-3001](https://github.com/hashicorp/consul-k8s/issues/3001)] - -## 1.1.7 (November 2, 2023) - -SECURITY: - -* Update Envoy version to 1.25.11 to address [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76) [[GH-3120](https://github.com/hashicorp/consul-k8s/issues/3120)] -* Upgrade `google.golang.org/grpc` to 1.56.3. -This resolves vulnerability [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487). [[GH-3139](https://github.com/hashicorp/consul-k8s/issues/3139)] -* Upgrade to use Go 1.20.10 and `x/net` 0.17.0. -This resolves [CVE-2023-39325](https://nvd.nist.gov/vuln/detail/CVE-2023-39325) -/ [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487). [[GH-3085](https://github.com/hashicorp/consul-k8s/issues/3085)] - -## 1.0.11 (November 2, 2023) - -SECURITY: - -* Update Envoy version to 1.24.12 to address [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76) [[GH-3121](https://github.com/hashicorp/consul-k8s/issues/3121)] -* Upgrade `google.golang.org/grpc` to 1.56.3. -This resolves vulnerability [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487). [[GH-3139](https://github.com/hashicorp/consul-k8s/issues/3139)] -* Upgrade to use Go 1.20.10 and `x/net` 0.17.0. -This resolves [CVE-2023-39325](https://nvd.nist.gov/vuln/detail/CVE-2023-39325) -/ [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487). [[GH-3085](https://github.com/hashicorp/consul-k8s/issues/3085)] - ## 1.2.2 (September 21, 2023) SECURITY: diff --git a/Makefile b/Makefile index bb665fc5e7..06dd41b9db 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ bats-tests: ## Run Helm chart bats tests. .PHONY: control-plane-dev control-plane-dev: ## Build consul-k8s-control-plane binary. - @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh --os linux --arch amd64 + @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh -o linux -a amd64 .PHONY: dev-docker dev-docker: control-plane-dev-docker ## build dev local dev docker image @@ -44,7 +44,7 @@ dev-docker: control-plane-dev-docker ## build dev local dev docker image .PHONY: control-plane-dev-docker control-plane-dev-docker: ## Build consul-k8s-control-plane dev Docker image. - @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh --os linux --arch $(GOARCH) + @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh -o linux -a $(GOARCH) @docker build -t '$(DEV_IMAGE)' \ --target=dev \ --build-arg 'GOLANG_VERSION=$(GOLANG_VERSION)' \ @@ -57,7 +57,7 @@ control-plane-dev-docker: ## Build consul-k8s-control-plane dev Docker image. .PHONY: control-plane-dev-skaffold # DANGER: this target is experimental and could be modified/removed at any time. control-plane-dev-skaffold: ## Build consul-k8s-control-plane dev Docker image for use with skaffold or local development. - @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh --os linux --arch $(GOARCH) + @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh -o linux -a $(GOARCH) @docker build -t '$(DEV_IMAGE)' \ --build-arg 'GOLANG_VERSION=$(GOLANG_VERSION)' \ --build-arg 'TARGETARCH=$(GOARCH)' \ @@ -71,7 +71,7 @@ endif .PHONY: control-plane-dev-docker-multi-arch control-plane-dev-docker-multi-arch: check-remote-dev-image-env ## Build consul-k8s-control-plane dev multi-arch Docker image. - @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh --os linux --arch "arm64 amd64" + @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh -o linux -a "arm64 amd64" @docker buildx create --use && docker buildx build -t '$(REMOTE_DEV_IMAGE)' \ --platform linux/amd64,linux/arm64 \ --target=dev \ @@ -84,7 +84,7 @@ control-plane-dev-docker-multi-arch: check-remote-dev-image-env ## Build consul- .PHONY: control-plane-fips-dev-docker control-plane-fips-dev-docker: ## Build consul-k8s-control-plane FIPS dev Docker image. - @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh --os linux --arch $(GOARCH) --fips + @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh -o linux -a $(GOARCH) --fips @docker build -t '$(DEV_IMAGE)' \ --target=dev \ --build-arg 'GOLANG_VERSION=$(GOLANG_VERSION)' \ @@ -190,17 +190,12 @@ kind-cni: kind-delete ## Helper target for doing local cni acceptance testing make kind-cni-calico .PHONY: kind -kind: kind-delete ## Helper target for doing local acceptance testing (works in all cases) +kind: kind-delete ## Helper target for doing local acceptance testing kind create cluster --name dc1 --image $(KIND_NODE_IMAGE) kind create cluster --name dc2 --image $(KIND_NODE_IMAGE) kind create cluster --name dc3 --image $(KIND_NODE_IMAGE) kind create cluster --name dc4 --image $(KIND_NODE_IMAGE) -.PHONY: kind-small -kind-small: kind-delete ## Helper target for doing local acceptance testing (when you only need two clusters) - kind create cluster --name dc1 --image $(KIND_NODE_IMAGE) - kind create cluster --name dc2 --image $(KIND_NODE_IMAGE) - .PHONY: kind-load kind-load: ## Helper target for loading local dev images (run with `DEV_IMAGE=...` to load non-k8s images) kind load docker-image --name dc1 $(DEV_IMAGE) @@ -244,13 +239,13 @@ ensure-controller-gen-version: ## Ensure controller-gen version is v0.12.1. ifeq (, $(shell which $(CONTROLLER_GEN))) @echo "You don't have $(CONTROLLER_GEN), please install it first." else -ifeq (, $(shell $(CONTROLLER_GEN) --version | grep v0.12.1)) - @echo "controller-gen version is not v0.12.1, uninstall the binary and install the correct version with 'make get-controller-gen'." - @echo "Found version: $(shell $(CONTROLLER_GEN) --version)" - @exit 1 -else - @echo "Found correct version: $(shell $(CONTROLLER_GEN) --version)" -endif + ifeq (, $(shell $(CONTROLLER_GEN) --version | grep v0.12.1)) + @echo "controller-gen version is not v0.12.1, uninstall the binary and install the correct version with 'make get-controller-gen'." + @echo "Found version: $(shell $(CONTROLLER_GEN) --version)" + @exit 1 + else + @echo "Found correct version: $(shell $(CONTROLLER_GEN) --version)" + endif endif .PHONY: add-copyright-header diff --git a/README.md b/README.md index e59e5b8577..52e909741b 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ by contacting us at [security@hashicorp.com](mailto:security@hashicorp.com). The following pre-requisites must be met before installing Consul on Kubernetes. - * **Kubernetes 1.26.x - 1.29.x** - This represents the earliest versions of Kubernetes tested. + * **Kubernetes 1.25.x - 1.28.x** - This represents the earliest versions of Kubernetes tested. It is possible that this chart works with earlier versions, but it is untested. * Helm install diff --git a/acceptance/ci-inputs/aks_acceptance_test_packages.yaml b/acceptance/ci-inputs/aks_acceptance_test_packages.yaml index b2874fd373..9b36143c6b 100644 --- a/acceptance/ci-inputs/aks_acceptance_test_packages.yaml +++ b/acceptance/ci-inputs/aks_acceptance_test_packages.yaml @@ -4,4 +4,4 @@ # Cloud package is not included in test suite as it is triggered from a non consul-k8s repo and requires HCP credentials - {runner: 0, test-packages: "connect peering snapshot-agent wan-federation"} - {runner: 1, test-packages: "consul-dns example partitions metrics sync"} -- {runner: 2, test-packages: "basic cli config-entries api-gateway ingress-gateway terminating-gateway vault server"} \ No newline at end of file +- {runner: 2, test-packages: "basic cli config-entries api-gateway ingress-gateway terminating-gateway vault"} \ No newline at end of file diff --git a/acceptance/ci-inputs/eks_acceptance_test_packages.yaml b/acceptance/ci-inputs/eks_acceptance_test_packages.yaml index b2874fd373..9b36143c6b 100644 --- a/acceptance/ci-inputs/eks_acceptance_test_packages.yaml +++ b/acceptance/ci-inputs/eks_acceptance_test_packages.yaml @@ -4,4 +4,4 @@ # Cloud package is not included in test suite as it is triggered from a non consul-k8s repo and requires HCP credentials - {runner: 0, test-packages: "connect peering snapshot-agent wan-federation"} - {runner: 1, test-packages: "consul-dns example partitions metrics sync"} -- {runner: 2, test-packages: "basic cli config-entries api-gateway ingress-gateway terminating-gateway vault server"} \ No newline at end of file +- {runner: 2, test-packages: "basic cli config-entries api-gateway ingress-gateway terminating-gateway vault"} \ No newline at end of file diff --git a/acceptance/ci-inputs/gke_acceptance_test_packages.yaml b/acceptance/ci-inputs/gke_acceptance_test_packages.yaml index b2874fd373..9b36143c6b 100644 --- a/acceptance/ci-inputs/gke_acceptance_test_packages.yaml +++ b/acceptance/ci-inputs/gke_acceptance_test_packages.yaml @@ -4,4 +4,4 @@ # Cloud package is not included in test suite as it is triggered from a non consul-k8s repo and requires HCP credentials - {runner: 0, test-packages: "connect peering snapshot-agent wan-federation"} - {runner: 1, test-packages: "consul-dns example partitions metrics sync"} -- {runner: 2, test-packages: "basic cli config-entries api-gateway ingress-gateway terminating-gateway vault server"} \ No newline at end of file +- {runner: 2, test-packages: "basic cli config-entries api-gateway ingress-gateway terminating-gateway vault"} \ No newline at end of file diff --git a/acceptance/ci-inputs/kind-inputs.yaml b/acceptance/ci-inputs/kind-inputs.yaml index 5271ee68ba..9b047bdac6 100644 --- a/acceptance/ci-inputs/kind-inputs.yaml +++ b/acceptance/ci-inputs/kind-inputs.yaml @@ -1,6 +1,6 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: MPL-2.0 -kindVersion: v0.22.0 -kindNodeImage: kindest/node:v1.29.2@sha256:51a1434a5397193442f0be2a297b488b6c919ce8a3931be0ce822606ea5ca245 +kindVersion: v0.19.0 +kindNodeImage: kindest/node:v1.28.0@sha256:dad5a6238c5e41d7cac405fae3b5eda2ad1de6f1190fa8bfc64ff5bb86173213 kubectlVersion: v1.27.1 diff --git a/acceptance/ci-inputs/kind_acceptance_test_packages.yaml b/acceptance/ci-inputs/kind_acceptance_test_packages.yaml index a4e09abd9c..580b36467c 100644 --- a/acceptance/ci-inputs/kind_acceptance_test_packages.yaml +++ b/acceptance/ci-inputs/kind_acceptance_test_packages.yaml @@ -6,7 +6,7 @@ - {runner: 1, test-packages: "peering"} - {runner: 2, test-packages: "sameness"} - {runner: 3, test-packages: "connect snapshot-agent wan-federation"} -- {runner: 4, test-packages: "cli vault metrics server"} +- {runner: 4, test-packages: "cli vault metrics"} - {runner: 5, test-packages: "api-gateway ingress-gateway sync example consul-dns"} - {runner: 6, test-packages: "config-entries terminating-gateway basic"} -- {runner: 7, test-packages: "mesh_v2 tenancy_v2"} +- {runner: 7, test-packages: "mesh_v2"} diff --git a/acceptance/framework/cli/cli.go b/acceptance/framework/cli/cli.go index f9384cd8d5..11a158269f 100644 --- a/acceptance/framework/cli/cli.go +++ b/acceptance/framework/cli/cli.go @@ -7,10 +7,10 @@ import ( "fmt" "os/exec" "strings" + "testing" "github.com/gruntwork-io/terratest/modules/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/logger" - "github.com/hashicorp/consul/sdk/testutil" ) const ( @@ -28,7 +28,7 @@ func NewCLI() (*CLI, error) { } // Run runs the CLI with the given args. -func (c *CLI) Run(t testutil.TestingTB, options *k8s.KubectlOptions, args ...string) ([]byte, error) { +func (c *CLI) Run(t *testing.T, options *k8s.KubectlOptions, args ...string) ([]byte, error) { if !c.initialized { return nil, fmt.Errorf("CLI must be initialized before calling Run, use `cli.NewCLI()` to initialize.") } diff --git a/acceptance/framework/config/config.go b/acceptance/framework/config/config.go index 4f9a8648c2..49a24a6d10 100644 --- a/acceptance/framework/config/config.go +++ b/acceptance/framework/config/config.go @@ -245,12 +245,6 @@ func (c *TestConfig) SkipWhenOpenshiftAndCNI(t *testing.T) { } } -func (c *TestConfig) SkipWhenCNI(t *testing.T) { - if c.EnableCNI { - t.Skip("skipping because -enable-cni is set and doesn't apply to this accepatance test") - } -} - // setIfNotEmpty sets key to val in map m if value is not empty. func setIfNotEmpty(m map[string]string, key, val string) { if val != "" { diff --git a/acceptance/framework/connhelper/connect_helper.go b/acceptance/framework/connhelper/connect_helper.go index 2746b43348..3f978e1d30 100644 --- a/acceptance/framework/connhelper/connect_helper.go +++ b/acceptance/framework/connhelper/connect_helper.go @@ -171,7 +171,7 @@ func (c *ConnectHelper) DeployClientAndServer(t *testing.T) { &retry.Timer{Timeout: retryTimeout, Wait: 100 * time.Millisecond}, t, func(r *retry.R) { for _, labelSelector := range []string{"app=static-server", "app=static-client"} { - podList, err := c.Ctx.KubernetesClient(r).CoreV1(). + podList, err := c.Ctx.KubernetesClient(t).CoreV1(). Pods(opts.Namespace). List(context.Background(), metav1.ListOptions{ LabelSelector: labelSelector, @@ -294,7 +294,7 @@ func (c *ConnectHelper) SetupAppNamespace(t *testing.T) { } // CreateResolverRedirect creates a resolver that redirects to a static-server, a corresponding k8s service, -// and intentions. This helper is primarily used to ensure that the virtual-ips are persisted to consul properly. +// and intentions. This helper is primarly used to ensure that the virtual-ips are persisted to consul properly. func (c *ConnectHelper) CreateResolverRedirect(t *testing.T) { logger.Log(t, "creating resolver redirect") opts := c.KubectlOptsForApp(t) diff --git a/acceptance/framework/consul/cli_cluster.go b/acceptance/framework/consul/cli_cluster.go index f960a4a612..a45bcc665c 100644 --- a/acceptance/framework/consul/cli_cluster.go +++ b/acceptance/framework/consul/cli_cluster.go @@ -264,7 +264,10 @@ func (c *CLICluster) SetupConsulClient(t *testing.T, secure bool, release ...str // Retry creating the port forward since it can fail occasionally. retry.RunWith(&retry.Counter{Wait: 3 * time.Second, Count: 60}, t, func(r *retry.R) { - require.NoError(r, tunnel.ForwardPortE(r)) + // NOTE: It's okay to pass in `t` to ForwardPortE despite being in a retry + // because we're using ForwardPortE (not ForwardPort) so the `t` won't + // get used to fail the test, just for logging. + require.NoError(r, tunnel.ForwardPortE(t)) }) t.Cleanup(func() { diff --git a/acceptance/framework/consul/helm_cluster.go b/acceptance/framework/consul/helm_cluster.go index 638e0e7c51..22a9fc3ceb 100644 --- a/acceptance/framework/consul/helm_cluster.go +++ b/acceptance/framework/consul/helm_cluster.go @@ -12,9 +12,16 @@ import ( "github.com/gruntwork-io/terratest/modules/helm" terratestLogger "github.com/gruntwork-io/terratest/modules/logger" + "github.com/hashicorp/consul-k8s/acceptance/framework/config" + "github.com/hashicorp/consul-k8s/acceptance/framework/environment" + "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" + "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" + "github.com/hashicorp/consul-k8s/acceptance/framework/logger" + "github.com/hashicorp/consul-k8s/acceptance/framework/portforward" + "github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/stretchr/testify/require" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" corev1 "k8s.io/api/core/v1" policyv1beta "k8s.io/api/policy/v1beta1" rbacv1 "k8s.io/api/rbac/v1" @@ -25,17 +32,6 @@ import ( "k8s.io/client-go/kubernetes" "sigs.k8s.io/controller-runtime/pkg/client" gwv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - - "github.com/hashicorp/consul-k8s/acceptance/framework/config" - "github.com/hashicorp/consul-k8s/acceptance/framework/environment" - "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" - "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" - "github.com/hashicorp/consul-k8s/acceptance/framework/logger" - "github.com/hashicorp/consul-k8s/acceptance/framework/portforward" - "github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1" - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil/retry" ) // HelmCluster implements Cluster and uses Helm @@ -154,12 +150,7 @@ func (h *HelmCluster) Create(t *testing.T) { if h.ChartPath != "" { chartName = h.ChartPath } - - // Retry the install in case previous tests have not finished cleaning up. - retry.RunWith(&retry.Counter{Wait: 2 * time.Second, Count: 30}, t, func(r *retry.R) { - err := helm.InstallE(r, h.helmOptions, chartName, h.releaseName) - require.NoError(r, err) - }) + helm.Install(t, h.helmOptions, chartName, h.releaseName) k8s.WaitForAllPodsToBeReady(t, h.kubernetesClient, h.helmOptions.KubectlOptions.Namespace, fmt.Sprintf("release=%s", h.releaseName)) } @@ -209,7 +200,7 @@ func (h *HelmCluster) Destroy(t *testing.T) { } retry.RunWith(&retry.Counter{Wait: 2 * time.Second, Count: 30}, t, func(r *retry.R) { - err := helm.DeleteE(r, h.helmOptions, h.releaseName, false) + err := helm.DeleteE(t, h.helmOptions, h.releaseName, false) require.NoError(r, err) }) @@ -221,13 +212,13 @@ func (h *HelmCluster) Destroy(t *testing.T) { // graceful termination takes a long time and since this is an uninstall // we don't care that they're stopped gracefully. pods, err := h.kubernetesClient.CoreV1().Pods(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) - require.NoError(r, err) + require.NoError(t, err) for _, pod := range pods.Items { if strings.Contains(pod.Name, h.releaseName) { var gracePeriod int64 = 0 err := h.kubernetesClient.CoreV1().Pods(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), pod.Name, metav1.DeleteOptions{GracePeriodSeconds: &gracePeriod}) if !errors.IsNotFound(err) { - require.NoError(r, err) + require.NoError(t, err) } } } @@ -294,64 +285,64 @@ func (h *HelmCluster) Destroy(t *testing.T) { // Delete PVCs. err = h.kubernetesClient.CoreV1().PersistentVolumeClaims(h.helmOptions.KubectlOptions.Namespace).DeleteCollection(context.Background(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) - require.NoError(r, err) + require.NoError(t, err) // Delete any serviceaccounts that have h.releaseName in their name. sas, err := h.kubernetesClient.CoreV1().ServiceAccounts(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) - require.NoError(r, err) + require.NoError(t, err) for _, sa := range sas.Items { if strings.Contains(sa.Name, h.releaseName) { err := h.kubernetesClient.CoreV1().ServiceAccounts(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), sa.Name, metav1.DeleteOptions{}) if !errors.IsNotFound(err) { - require.NoError(r, err) + require.NoError(t, err) } } } // Delete any roles that have h.releaseName in their name. roles, err := h.kubernetesClient.RbacV1().Roles(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) - require.NoError(r, err) + require.NoError(t, err) for _, role := range roles.Items { if strings.Contains(role.Name, h.releaseName) { err := h.kubernetesClient.RbacV1().Roles(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), role.Name, metav1.DeleteOptions{}) if !errors.IsNotFound(err) { - require.NoError(r, err) + require.NoError(t, err) } } } // Delete any rolebindings that have h.releaseName in their name. roleBindings, err := h.kubernetesClient.RbacV1().RoleBindings(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) - require.NoError(r, err) + require.NoError(t, err) for _, roleBinding := range roleBindings.Items { if strings.Contains(roleBinding.Name, h.releaseName) { err := h.kubernetesClient.RbacV1().RoleBindings(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), roleBinding.Name, metav1.DeleteOptions{}) if !errors.IsNotFound(err) { - require.NoError(r, err) + require.NoError(t, err) } } } // Delete any secrets that have h.releaseName in their name. secrets, err := h.kubernetesClient.CoreV1().Secrets(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{}) - require.NoError(r, err) + require.NoError(t, err) for _, secret := range secrets.Items { if strings.Contains(secret.Name, h.releaseName) { err := h.kubernetesClient.CoreV1().Secrets(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), secret.Name, metav1.DeleteOptions{}) if !errors.IsNotFound(err) { - require.NoError(r, err) + require.NoError(t, err) } } } // Delete any jobs that have h.releaseName in their name. jobs, err := h.kubernetesClient.BatchV1().Jobs(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) - require.NoError(r, err) + require.NoError(t, err) for _, job := range jobs.Items { if strings.Contains(job.Name, h.releaseName) { err := h.kubernetesClient.BatchV1().Jobs(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), job.Name, metav1.DeleteOptions{}) if !errors.IsNotFound(err) { - require.NoError(r, err) + require.NoError(t, err) } } } @@ -474,7 +465,6 @@ func (h *HelmCluster) Upgrade(t *testing.T, helmValues map[string]string) { k8s.WaitForAllPodsToBeReady(t, h.kubernetesClient, h.helmOptions.KubectlOptions.Namespace, fmt.Sprintf("release=%s", h.releaseName)) } -// CreatePortForwardTunnel returns the local address:port of a tunnel to the consul server pod in the given release. func (h *HelmCluster) CreatePortForwardTunnel(t *testing.T, remotePort int, release ...string) string { releaseName := h.releaseName if len(release) > 0 { @@ -484,26 +474,6 @@ func (h *HelmCluster) CreatePortForwardTunnel(t *testing.T, remotePort int, rele return portforward.CreateTunnelToResourcePort(t, serverPod, remotePort, h.helmOptions.KubectlOptions, h.logger) } -// ResourceClient returns a resource service grpc client for the given helm release. -func (h *HelmCluster) ResourceClient(t *testing.T, secure bool, release ...string) (client pbresource.ResourceServiceClient) { - if secure { - panic("TODO: add support for secure resource client") - } - releaseName := h.releaseName - if len(release) > 0 { - releaseName = release[0] - } - - // TODO: get grpc port from somewhere - localTunnelAddr := h.CreatePortForwardTunnel(t, 8502, releaseName) - - // Create a grpc connection to the server pod. - grpcConn, err := grpc.Dial(localTunnelAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) - require.NoError(t, err) - resourceClient := pbresource.NewResourceServiceClient(grpcConn) - return resourceClient -} - func (h *HelmCluster) SetupConsulClient(t *testing.T, secure bool, release ...string) (client *api.Client, configAddress string) { t.Helper() diff --git a/acceptance/framework/consul/helm_cluster_test.go b/acceptance/framework/consul/helm_cluster_test.go index 3544718c9e..011ca23e0f 100644 --- a/acceptance/framework/consul/helm_cluster_test.go +++ b/acceptance/framework/consul/helm_cluster_test.go @@ -9,7 +9,6 @@ import ( "github.com/gruntwork-io/terratest/modules/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/config" "github.com/hashicorp/consul-k8s/acceptance/framework/environment" - "github.com/hashicorp/consul/sdk/testutil" "github.com/stretchr/testify/require" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/fake" @@ -79,16 +78,16 @@ func (c *ctx) Name() string { return "" } -func (c *ctx) KubectlOptions(_ testutil.TestingTB) *k8s.KubectlOptions { +func (c *ctx) KubectlOptions(_ *testing.T) *k8s.KubectlOptions { return &k8s.KubectlOptions{} } func (c *ctx) KubectlOptionsForNamespace(ns string) *k8s.KubectlOptions { return &k8s.KubectlOptions{} } -func (c *ctx) KubernetesClient(_ testutil.TestingTB) kubernetes.Interface { +func (c *ctx) KubernetesClient(_ *testing.T) kubernetes.Interface { return fake.NewSimpleClientset() } -func (c *ctx) ControllerRuntimeClient(_ testutil.TestingTB) client.Client { +func (c *ctx) ControllerRuntimeClient(_ *testing.T) client.Client { return runtimefake.NewClientBuilder().Build() } diff --git a/acceptance/framework/environment/environment.go b/acceptance/framework/environment/environment.go index 9ceecf3e96..7014a3c05f 100644 --- a/acceptance/framework/environment/environment.go +++ b/acceptance/framework/environment/environment.go @@ -5,10 +5,11 @@ package environment import ( "fmt" + "testing" + "github.com/gruntwork-io/terratest/modules/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/config" "github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1" - "github.com/hashicorp/consul/sdk/testutil" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -26,17 +27,18 @@ const ( // TestEnvironment represents the infrastructure environment of the test, // such as the kubernetes cluster(s) the test is running against. type TestEnvironment interface { - DefaultContext(t testutil.TestingTB) TestContext - Context(t testutil.TestingTB, index int) TestContext + DefaultContext(t *testing.T) TestContext + Context(t *testing.T, index int) TestContext } // TestContext represents a specific context a test needs, // for example, information about a specific Kubernetes cluster. type TestContext interface { - KubectlOptions(t testutil.TestingTB) *k8s.KubectlOptions + KubectlOptions(t *testing.T) *k8s.KubectlOptions + // TODO: I don't love this. KubectlOptionsForNamespace(ns string) *k8s.KubectlOptions - KubernetesClient(t testutil.TestingTB) kubernetes.Interface - ControllerRuntimeClient(t testutil.TestingTB) client.Client + KubernetesClient(t *testing.T) kubernetes.Interface + ControllerRuntimeClient(t *testing.T) client.Client } type KubernetesEnvironment struct { @@ -64,13 +66,13 @@ func NewKubernetesEnvironmentFromConfig(config *config.TestConfig) *KubernetesEn return kenv } -func (k *KubernetesEnvironment) Context(t testutil.TestingTB, index int) TestContext { +func (k *KubernetesEnvironment) Context(t *testing.T, index int) TestContext { lenContexts := len(k.contexts) require.Greater(t, lenContexts, index, fmt.Sprintf("context list does not contain an index %d, length is %d", index, lenContexts)) return k.contexts[index] } -func (k *KubernetesEnvironment) DefaultContext(t testutil.TestingTB) TestContext { +func (k *KubernetesEnvironment) DefaultContext(t *testing.T) TestContext { lenContexts := len(k.contexts) require.Greater(t, lenContexts, DefaultContextIndex, fmt.Sprintf("context list does not contain an index %d, length is %d", DefaultContextIndex, lenContexts)) return k.contexts[DefaultContextIndex] @@ -90,7 +92,9 @@ type kubernetesContext struct { // KubernetesContextFromOptions returns the Kubernetes context from options. // If context is explicitly set in options, it returns that context. // Otherwise, it returns the current context. -func KubernetesContextFromOptions(t testutil.TestingTB, options *k8s.KubectlOptions) string { +func KubernetesContextFromOptions(t *testing.T, options *k8s.KubectlOptions) string { + t.Helper() + // First, check if context set in options and return that if options.ContextName != "" { return options.ContextName @@ -106,7 +110,7 @@ func KubernetesContextFromOptions(t testutil.TestingTB, options *k8s.KubectlOpti return rawConfig.CurrentContext } -func (k kubernetesContext) KubectlOptions(t testutil.TestingTB) *k8s.KubectlOptions { +func (k kubernetesContext) KubectlOptions(t *testing.T) *k8s.KubectlOptions { if k.options != nil { return k.options } @@ -145,7 +149,7 @@ func (k kubernetesContext) KubectlOptionsForNamespace(ns string) *k8s.KubectlOpt } // KubernetesClientFromOptions takes KubectlOptions and returns Kubernetes API client. -func KubernetesClientFromOptions(t testutil.TestingTB, options *k8s.KubectlOptions) kubernetes.Interface { +func KubernetesClientFromOptions(t *testing.T, options *k8s.KubectlOptions) kubernetes.Interface { configPath, err := options.GetConfigPath(t) require.NoError(t, err) @@ -158,7 +162,7 @@ func KubernetesClientFromOptions(t testutil.TestingTB, options *k8s.KubectlOptio return client } -func (k kubernetesContext) KubernetesClient(t testutil.TestingTB) kubernetes.Interface { +func (k kubernetesContext) KubernetesClient(t *testing.T) kubernetes.Interface { if k.client != nil { return k.client } @@ -168,7 +172,7 @@ func (k kubernetesContext) KubernetesClient(t testutil.TestingTB) kubernetes.Int return k.client } -func (k kubernetesContext) ControllerRuntimeClient(t testutil.TestingTB) client.Client { +func (k kubernetesContext) ControllerRuntimeClient(t *testing.T) client.Client { if k.runtimeClient != nil { return k.runtimeClient } diff --git a/acceptance/framework/helpers/helpers.go b/acceptance/framework/helpers/helpers.go index 2ef01df26a..6d2641ecd3 100644 --- a/acceptance/framework/helpers/helpers.go +++ b/acceptance/framework/helpers/helpers.go @@ -18,7 +18,6 @@ import ( "github.com/gruntwork-io/terratest/modules/random" "github.com/hashicorp/consul-k8s/acceptance/framework/logger" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -44,7 +43,7 @@ func CheckForPriorInstallations(t *testing.T, client kubernetes.Interface, optio // NOTE: It's okay to pass in `t` to RunHelmCommandAndGetOutputE despite being in a retry // because we're using RunHelmCommandAndGetOutputE (not RunHelmCommandAndGetOutput) so the `t` won't // get used to fail the test, just for logging. - helmListOutput, err = helm.RunHelmCommandAndGetOutputE(r, options, "list", "--output", "json") + helmListOutput, err = helm.RunHelmCommandAndGetOutputE(t, options, "list", "--output", "json") require.NoError(r, err) }) @@ -85,9 +84,10 @@ func SetupInterruptHandler(cleanup func()) { }() } -// Cleanup will both register a cleanup function with t and SetupInterruptHandler to make sure resources -// get cleaned up if an interrupt signal is caught. -func Cleanup(t testutil.TestingTB, noCleanupOnFailure bool, noCleanup bool, cleanup func()) { +// Cleanup will both register a cleanup function with t +// and SetupInterruptHandler to make sure resources get cleaned up +// if an interrupt signal is caught. +func Cleanup(t *testing.T, noCleanupOnFailure bool, noCleanup bool, cleanup func()) { t.Helper() // Always clean up when an interrupt signal is caught. diff --git a/acceptance/framework/k8s/deploy.go b/acceptance/framework/k8s/deploy.go index a877dff54e..e60f4c4730 100644 --- a/acceptance/framework/k8s/deploy.go +++ b/acceptance/framework/k8s/deploy.go @@ -135,7 +135,7 @@ func CheckStaticServerConnectionMultipleFailureMessages(t *testing.T, options *k args = append(args, curlArgs...) retry.RunWith(retrier, t, func(r *retry.R) { - output, err := RunKubectlAndGetOutputE(r, options, args...) + output, err := RunKubectlAndGetOutputE(t, options, args...) if expectSuccess { require.NoError(r, err) require.Contains(r, output, expectedOutput) diff --git a/acceptance/framework/k8s/helpers.go b/acceptance/framework/k8s/helpers.go index ca1cba9d84..a6b4d1ca7c 100644 --- a/acceptance/framework/k8s/helpers.go +++ b/acceptance/framework/k8s/helpers.go @@ -35,18 +35,18 @@ func KubernetesAPIServerHostFromOptions(t *testing.T, options *terratestk8s.Kube } // WaitForAllPodsToBeReady waits until all pods with the provided podLabelSelector -// are in the ready status. It checks every 2 second for 20 minutes. +// are in the ready status. It checks every second for 11 minutes. // If there is at least one container in a pod that isn't ready after that, // it fails the test. func WaitForAllPodsToBeReady(t *testing.T, client kubernetes.Interface, namespace, podLabelSelector string) { t.Helper() + logger.Logf(t, "Waiting for pods with label %q to be ready.", podLabelSelector) + // Wait up to 20m. // On Azure, volume provisioning can sometimes take close to 5 min, // so we need to give a bit more time for pods to become healthy. - counter := &retry.Counter{Count: 10 * 60, Wait: 2 * time.Second} - logger.Logf(t, "Waiting %s for pods with label %q to be ready.", time.Duration(counter.Count*int(counter.Wait)), podLabelSelector) - + counter := &retry.Counter{Count: 20 * 60, Wait: 2 * time.Second} retry.RunWith(counter, t, func(r *retry.R) { pods, err := client.CoreV1().Pods(namespace).List(context.Background(), metav1.ListOptions{LabelSelector: podLabelSelector}) require.NoError(r, err) @@ -114,8 +114,8 @@ func ServiceHost(t *testing.T, cfg *config.TestConfig, ctx environment.TestConte // It can take some time for the load balancers to be ready and have an IP/Hostname. // Wait for 5 minutes before failing. retry.RunWith(&retry.Counter{Wait: 2 * time.Second, Count: 600}, t, func(r *retry.R) { - svc, err := ctx.KubernetesClient(r).CoreV1().Services(ctx.KubectlOptions(r).Namespace).Get(context.Background(), serviceName, metav1.GetOptions{}) - require.NoError(r, err) + svc, err := ctx.KubernetesClient(t).CoreV1().Services(ctx.KubectlOptions(t).Namespace).Get(context.Background(), serviceName, metav1.GetOptions{}) + require.NoError(t, err) require.NotEmpty(r, svc.Status.LoadBalancer.Ingress) // On AWS, load balancers have a hostname for ingress, while on Azure and GCP // load balancers have IPs. @@ -135,7 +135,7 @@ func CopySecret(t *testing.T, sourceContext, destContext environment.TestContext var secret *corev1.Secret var err error retry.Run(t, func(r *retry.R) { - secret, err = sourceContext.KubernetesClient(r).CoreV1().Secrets(sourceContext.KubectlOptions(r).Namespace).Get(context.Background(), secretName, metav1.GetOptions{}) + secret, err = sourceContext.KubernetesClient(t).CoreV1().Secrets(sourceContext.KubectlOptions(t).Namespace).Get(context.Background(), secretName, metav1.GetOptions{}) secret.ResourceVersion = "" require.NoError(r, err) }) diff --git a/acceptance/framework/k8s/kubectl.go b/acceptance/framework/k8s/kubectl.go index e02db4c474..2e37b9bd0a 100644 --- a/acceptance/framework/k8s/kubectl.go +++ b/acceptance/framework/k8s/kubectl.go @@ -13,7 +13,6 @@ import ( terratestLogger "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/shell" "github.com/hashicorp/consul-k8s/acceptance/framework/logger" - "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/stretchr/testify/require" ) @@ -35,14 +34,14 @@ var kubeAPIConnectErrs = []string{ // RunKubectlAndGetOutputE runs an arbitrary kubectl command provided via args // and returns its output and error. -func RunKubectlAndGetOutputE(t testutil.TestingTB, options *k8s.KubectlOptions, args ...string) (string, error) { +func RunKubectlAndGetOutputE(t *testing.T, options *k8s.KubectlOptions, args ...string) (string, error) { return RunKubectlAndGetOutputWithLoggerE(t, options, terratestLogger.New(logger.TestLogger{}), args...) } // RunKubectlAndGetOutputWithLoggerE is the same as RunKubectlAndGetOutputE but // it also allows you to provide a custom logger. This is useful if the command output // contains sensitive information, for example, when you can pass logger.Discard. -func RunKubectlAndGetOutputWithLoggerE(t testutil.TestingTB, options *k8s.KubectlOptions, logger *terratestLogger.Logger, args ...string) (string, error) { +func RunKubectlAndGetOutputWithLoggerE(t *testing.T, options *k8s.KubectlOptions, logger *terratestLogger.Logger, args ...string) (string, error) { var cmdArgs []string if options.ContextName != "" { cmdArgs = append(cmdArgs, "--context", options.ContextName) @@ -68,7 +67,7 @@ func RunKubectlAndGetOutputWithLoggerE(t testutil.TestingTB, options *k8s.Kubect var output string var err error retry.RunWith(counter, t, func(r *retry.R) { - output, err = shell.RunCommandAndGetOutputE(r, command) + output, err = shell.RunCommandAndGetOutputE(t, command) if err != nil { // Want to retry on errors connecting to actual Kube API because // these are intermittent. diff --git a/acceptance/framework/logger/logger.go b/acceptance/framework/logger/logger.go index 34bc0e8a6c..26777c4e22 100644 --- a/acceptance/framework/logger/logger.go +++ b/acceptance/framework/logger/logger.go @@ -5,19 +5,20 @@ package logger import ( "fmt" - "github.com/hashicorp/consul/sdk/testutil" + "testing" "time" - terratesting "github.com/gruntwork-io/terratest/modules/testing" + terratestTesting "github.com/gruntwork-io/terratest/modules/testing" ) -// TestLogger implements Terratest's TestLogger interface so that we can pass it to Terratest objects to have consistent -// logging across all tests. +// TestLogger implements terratest's TestLogger interface +// so that we can pass it to terratest objects to have consistent logging +// across all tests. type TestLogger struct{} // Logf takes a format string and args and calls Logf function. -func (tl TestLogger) Logf(t terratesting.TestingT, format string, args ...any) { - tt, ok := t.(testutil.TestingTB) +func (tl TestLogger) Logf(t terratestTesting.TestingT, format string, args ...interface{}) { + tt, ok := t.(*testing.T) if !ok { t.Error("failed to cast") } @@ -26,18 +27,20 @@ func (tl TestLogger) Logf(t terratesting.TestingT, format string, args ...any) { Logf(tt, format, args...) } -// Logf takes a format string and args and logs formatted string with a timestamp. -func Logf(t testutil.TestingTB, format string, args ...any) { +// Logf takes a format string and args and logs +// formatted string with a timestamp. +func Logf(t *testing.T, format string, args ...interface{}) { t.Helper() log := fmt.Sprintf(format, args...) Log(t, log) } -// Log calls t.Log or r.Log, adding an RFC3339 timestamp to the beginning of the log line. -func Log(t testutil.TestingTB, args ...any) { +// Log calls t.Log, adding an RFC3339 timestamp to the beginning of the log line. +func Log(t *testing.T, args ...interface{}) { t.Helper() - allArgs := []any{time.Now().Format(time.RFC3339)} + + allArgs := []interface{}{time.Now().Format(time.RFC3339)} allArgs = append(allArgs, args...) t.Log(allArgs...) } diff --git a/acceptance/framework/portforward/port_forward.go b/acceptance/framework/portforward/port_forward.go index ac9795c98c..3242541cc5 100644 --- a/acceptance/framework/portforward/port_forward.go +++ b/acceptance/framework/portforward/port_forward.go @@ -16,7 +16,6 @@ import ( "github.com/stretchr/testify/require" ) -// CreateTunnelToResourcePort returns a local address:port that is tunneled to the given resource's port. func CreateTunnelToResourcePort(t *testing.T, resourceName string, remotePort int, options *terratestk8s.KubectlOptions, logger terratestLogger.TestLogger) string { localPort := terratestk8s.GetAvailablePort(t) tunnel := terratestk8s.NewTunnelWithLogger( @@ -32,7 +31,7 @@ func CreateTunnelToResourcePort(t *testing.T, resourceName string, remotePort in // NOTE: It's okay to pass in `t` to ForwardPortE despite being in a retry // because we're using ForwardPortE (not ForwardPort) so the `t` won't // get used to fail the test, just for logging. - require.NoError(r, tunnel.ForwardPortE(r)) + require.NoError(r, tunnel.ForwardPortE(t)) }) doneChan := make(chan bool) diff --git a/acceptance/framework/resource/helpers.go b/acceptance/framework/resource/helpers.go deleted file mode 100644 index 4e94f73faf..0000000000 --- a/acceptance/framework/resource/helpers.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package resource - -import ( - "context" - "time" - - "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" - - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" -) - -// ResourceTester is a helper for making assertions about resources. -type ResourceTester struct { - // resourceClient is the client to use for resource operations. - resourceClient pbresource.ResourceServiceClient - // timeout is the total time across which to apply retries. - timeout time.Duration - // wait is the wait time between retries. - wait time.Duration - // token is the token to use for requests when ACLs are enabled. - token string -} - -func NewResourceTester(resourceClient pbresource.ResourceServiceClient) *ResourceTester { - return &ResourceTester{ - resourceClient: resourceClient, - timeout: 7 * time.Second, - wait: 25 * time.Millisecond, - } -} - -func (rt *ResourceTester) retry(t testutil.TestingTB, fn func(r *retry.R)) { - t.Helper() - retryer := &retry.Timer{Timeout: rt.timeout, Wait: rt.wait} - retry.RunWith(retryer, t, fn) -} - -func (rt *ResourceTester) Context(t testutil.TestingTB) context.Context { - ctx := testutil.TestContext(t) - - if rt.token != "" { - md := metadata.New(map[string]string{ - "x-consul-token": rt.token, - }) - ctx = metadata.NewOutgoingContext(ctx, md) - } - - return ctx -} - -func (rt *ResourceTester) RequireResourceExists(t testutil.TestingTB, id *pbresource.ID) *pbresource.Resource { - t.Helper() - - rsp, err := rt.resourceClient.Read(rt.Context(t), &pbresource.ReadRequest{Id: id}) - require.NoError(t, err, "error reading %s with type %v", id.Name, id.Type) - require.NotNil(t, rsp) - return rsp.Resource -} - -func (rt *ResourceTester) RequireResourceNotFound(t testutil.TestingTB, id *pbresource.ID) { - t.Helper() - - rsp, err := rt.resourceClient.Read(rt.Context(t), &pbresource.ReadRequest{Id: id}) - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - require.Nil(t, rsp) -} - -func (rt *ResourceTester) WaitForResourceExists(t testutil.TestingTB, id *pbresource.ID) *pbresource.Resource { - t.Helper() - - var res *pbresource.Resource - rt.retry(t, func(r *retry.R) { - res = rt.RequireResourceExists(r, id) - }) - - return res -} - -func (rt *ResourceTester) WaitForResourceNotFound(t testutil.TestingTB, id *pbresource.ID) { - t.Helper() - - rt.retry(t, func(r *retry.R) { - rt.RequireResourceNotFound(r, id) - }) -} diff --git a/acceptance/framework/vault/vault_cluster.go b/acceptance/framework/vault/vault_cluster.go index b43957c924..8b82e41841 100644 --- a/acceptance/framework/vault/vault_cluster.go +++ b/acceptance/framework/vault/vault_cluster.go @@ -21,7 +21,6 @@ import ( "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/logger" "github.com/hashicorp/consul-k8s/control-plane/helper/cert" - "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" vapi "github.com/hashicorp/vault/api" "github.com/stretchr/testify/require" @@ -125,7 +124,7 @@ func NewVaultCluster(t *testing.T, ctx environment.TestContext, cfg *config.Test func (v *VaultCluster) VaultClient(*testing.T) *vapi.Client { return v.vaultClient } // SetupVaultClient sets up and returns a Vault Client. -func (v *VaultCluster) SetupVaultClient(t testutil.TestingTB) *vapi.Client { +func (v *VaultCluster) SetupVaultClient(t *testing.T) *vapi.Client { t.Helper() if v.vaultClient != nil { @@ -145,8 +144,12 @@ func (v *VaultCluster) SetupVaultClient(t testutil.TestingTB) *vapi.Client { remotePort, v.logger) + // Retry creating the port forward since it can fail occasionally. retry.RunWith(&retry.Counter{Wait: 5 * time.Second, Count: 60}, t, func(r *retry.R) { - require.NoError(r, tunnel.ForwardPortE(r)) + // NOTE: It's okay to pass in `t` to ForwardPortE despite being in a retry + // because we're using ForwardPortE (not ForwardPort) so the `t` won't + // get used to fail the test, just for logging. + require.NoError(r, tunnel.ForwardPortE(t)) }) t.Cleanup(func() { @@ -198,7 +201,7 @@ func (v *VaultCluster) bootstrap(t *testing.T, vaultNamespace string) { }, Type: corev1.SecretTypeServiceAccountToken, }, metav1.CreateOptions{}) - require.NoError(r, err) + require.NoError(t, err) } }) v.ConfigureAuthMethod(t, v.vaultClient, "kubernetes", "https://kubernetes.default.svc", vaultServerServiceAccountName, namespace) @@ -419,7 +422,7 @@ func (v *VaultCluster) initAndUnseal(t *testing.T) { require.Equal(r, corev1.PodRunning, serverPod.Status.Phase) // Set up the client so that we can make API calls to initialize and unseal. - v.vaultClient = v.SetupVaultClient(r) + v.vaultClient = v.SetupVaultClient(t) // Initialize Vault with 1 secret share. We don't need to // more key shares for this test installation. diff --git a/acceptance/go.mod b/acceptance/go.mod index 404d520293..8605284b2d 100644 --- a/acceptance/go.mod +++ b/acceptance/go.mod @@ -2,18 +2,12 @@ module github.com/hashicorp/consul-k8s/acceptance go 1.20 -replace github.com/hashicorp/consul/sdk => github.com/hashicorp/consul/sdk v0.4.1-0.20231213150639-123bc95e1a3f - -replace github.com/hashicorp/consul/proto-public => github.com/hashicorp/consul/proto-public v0.1.2-0.20240129174413-a2d50af1bdfb - require ( github.com/google/uuid v1.3.0 github.com/gruntwork-io/terratest v0.31.2 - github.com/hashicorp/consul-k8s/control-plane v0.0.0-20240201210635-25708a18e4aa - github.com/hashicorp/consul/api v1.10.1-0.20240122152324-758ddf84e9c9 - github.com/hashicorp/consul/proto-public v0.5.1 - github.com/hashicorp/consul/sdk v0.15.0 - github.com/hashicorp/go-multierror v1.1.1 + github.com/hashicorp/consul-k8s/control-plane v0.0.0-20230609143603-198c4433d892 + github.com/hashicorp/consul/api v1.10.1-0.20230906155245-56917eb4c968 + github.com/hashicorp/consul/sdk v0.14.1 github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.6.0 github.com/hashicorp/hcp-sdk-go v0.50.0 @@ -21,13 +15,12 @@ require ( github.com/hashicorp/vault/api v1.8.3 github.com/stretchr/testify v1.8.4 go.opentelemetry.io/proto/otlp v1.0.0 - google.golang.org/grpc v1.58.3 google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v2 v2.4.0 - k8s.io/api v0.26.12 - k8s.io/apimachinery v0.26.12 - k8s.io/client-go v0.26.12 - k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 + k8s.io/api v0.26.10 + k8s.io/apimachinery v0.26.10 + k8s.io/client-go v0.26.10 + k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 sigs.k8s.io/controller-runtime v0.14.7 sigs.k8s.io/gateway-api v0.7.1 ) @@ -40,7 +33,6 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect github.com/cenkalti/backoff/v3 v3.0.0 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect @@ -48,7 +40,7 @@ require ( github.com/emicklei/go-restful/v3 v3.10.1 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/fatih/color v1.15.0 // indirect + github.com/fatih/color v1.14.1 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-logr/logr v1.2.4 // indirect @@ -78,6 +70,7 @@ require ( github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-plugin v1.4.5 // indirect github.com/hashicorp/go-retryablehttp v0.6.6 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect @@ -95,7 +88,7 @@ require ( github.com/json-iterator/go v1.1.12 // 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/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 @@ -132,8 +125,8 @@ require ( go.opentelemetry.io/otel/trace v1.19.0 // indirect go.uber.org/atomic v1.9.0 // indirect golang.org/x/crypto v0.18.0 // indirect - golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect - golang.org/x/mod v0.12.0 // indirect + golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 // indirect + golang.org/x/mod v0.11.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.10.0 // indirect golang.org/x/sync v0.6.0 // indirect @@ -141,11 +134,12 @@ require ( golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect + golang.org/x/tools v0.10.0 // indirect gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect + google.golang.org/grpc v1.58.3 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/acceptance/go.sum b/acceptance/go.sum index b94ee60157..0108191ee9 100644 --- a/acceptance/go.sum +++ b/acceptance/go.sum @@ -109,8 +109,6 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8 github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= 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/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -186,8 +184,8 @@ github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2Vvl 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.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +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/frankban/quicktest v1.13.0 h1:yNZif1OkDfNoDfb9zZa9aXIpejNR4F23Wely0c+Qdqk= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -395,15 +393,12 @@ github.com/gruntwork-io/gruntwork-cli v0.7.0 h1:YgSAmfCj9c61H+zuvHwKfYUwlMhu5arn github.com/gruntwork-io/gruntwork-cli v0.7.0/go.mod h1:jp6Z7NcLF2avpY8v71fBx6hds9eOFPELSuD/VPv7w00= github.com/gruntwork-io/terratest v0.31.2 h1:xvYHA80MUq5kx670dM18HInewOrrQrAN+XbVVtytUHg= github.com/gruntwork-io/terratest v0.31.2/go.mod h1:EEgJie28gX/4AD71IFqgMj6e99KP5mi81hEtzmDjxTo= -github.com/hashicorp/consul-k8s/control-plane v0.0.0-20240201210635-25708a18e4aa h1:T9u/mKHEqqQvv8jJ3+S4cLj9sn7KDMSW+n4Uc8YlVos= -github.com/hashicorp/consul-k8s/control-plane v0.0.0-20240201210635-25708a18e4aa/go.mod h1:Yj8VIjM3SElLcOVTkjy/A0igua8XBuhteYuQ1O84FDY= -github.com/hashicorp/consul-server-connection-manager v0.1.6 h1:ktj8Fi+dRXn9hhM+FXsfEJayhzzgTqfH08Ne5M6Fmug= -github.com/hashicorp/consul/api v1.10.1-0.20240122152324-758ddf84e9c9 h1:qaS6rE768dt5hGPl2y4DIABXF4eA23BNSmWFpEr3kWQ= -github.com/hashicorp/consul/api v1.10.1-0.20240122152324-758ddf84e9c9/go.mod h1:gInwZGrnWlE1Vvq6rSD5pUf6qwNa69NTLLknbdwQRUk= -github.com/hashicorp/consul/proto-public v0.1.2-0.20240129174413-a2d50af1bdfb h1:4LCdNw3DTe5WRe3fJvY+hkRLNtRlunl/9PJuOlQmPa8= -github.com/hashicorp/consul/proto-public v0.1.2-0.20240129174413-a2d50af1bdfb/go.mod h1:ar/M/Gv31GeE7DxektZgAydwsCiOf6sBeJFcjQVTlVs= -github.com/hashicorp/consul/sdk v0.4.1-0.20231213150639-123bc95e1a3f h1:GKsa7bfoL7xgvCkzYJMF9eYYNfLWQyk8QuRZZl4nMTo= -github.com/hashicorp/consul/sdk v0.4.1-0.20231213150639-123bc95e1a3f/go.mod h1:r/OmRRPbHOe0yxNahLw7G9x5WG17E1BIECMtCjcPSNo= +github.com/hashicorp/consul-k8s/control-plane v0.0.0-20230609143603-198c4433d892 h1:4iI0ztWbVPTSDax+m1/XDs4jIRorxY4kSMyuM0fX+Dc= +github.com/hashicorp/consul-k8s/control-plane v0.0.0-20230609143603-198c4433d892/go.mod h1:iZ8BJGSnY52wnxJTo2VIfGX63CPjqiNzbuqdOtJCKnI= +github.com/hashicorp/consul/api v1.10.1-0.20230906155245-56917eb4c968 h1:lQ7QmlL0N4/ftLBex8n73Raji29o7EVssqCoeeczKac= +github.com/hashicorp/consul/api v1.10.1-0.20230906155245-56917eb4c968/go.mod h1:NZJGRFYruc/80wYowkPFCp1LbGmJC9L8izrwfyVx/Wg= +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= @@ -425,7 +420,6 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh 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-netaddrs v0.1.0 h1:TnlYvODD4C/wO+j7cX1z69kV5gOzI87u3OcUinANaW8= 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-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= @@ -549,8 +543,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA 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/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= @@ -820,8 +814,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= +golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 h1:5llv2sWeaMSnA3w2kS57ouQQ4pudlXrR0dCgw51QK9o= +golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= 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= @@ -844,8 +838,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/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/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20170114055629-f2499483f923/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= @@ -990,7 +984,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc 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.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1075,8 +1068,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.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.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= -golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= +golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= golang.org/x/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= @@ -1222,18 +1215,18 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= -k8s.io/api v0.26.12 h1:jJm3s5ot05SUN3tPGg3b+XWuBE7rO/X0+dnVMhxyd5o= -k8s.io/api v0.26.12/go.mod h1:N+HUXukmtXNOKDngxXrEPbZWggWx01tH/N0nG4nV0oo= +k8s.io/api v0.26.10 h1:skTnrDR0r8dg4MMLf6YZIzugxNM0BjFsWKPkNc5kOvk= +k8s.io/api v0.26.10/go.mod h1:ou/H3yviqrHtP/DSPVTfsc7qNfmU06OhajytJfYXkXw= k8s.io/apiextensions-apiserver v0.26.10 h1:wAriTUc6l7gUqJKOxhmXnYo/VNJzk4oh4QLCUR4Uq+k= k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= -k8s.io/apimachinery v0.26.12 h1:y+OgufxqLIZtyXIydRhjLBGzrYLF+qwiDdCFXYOjeN4= -k8s.io/apimachinery v0.26.12/go.mod h1:2/HZp0l6coXtS26du1Bk36fCuAEr/lVs9Q9NbpBtd1Y= +k8s.io/apimachinery v0.26.10 h1:aE+J2KIbjctFqPp3Y0q4Wh2PD+l1p2g3Zp4UYjSvtGU= +k8s.io/apimachinery v0.26.10/go.mod h1:iT1ZP4JBP34wwM+ZQ8ByPEQ81u043iqAcsJYftX9amM= k8s.io/apiserver v0.17.0/go.mod h1:ABM+9x/prjINN6iiffRVNCBR2Wk7uY4z+EtEGZD48cg= k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k= k8s.io/client-go v0.19.3/go.mod h1:+eEMktZM+MG0KO+PTkci8xnbCZHvj9TqR6Q1XDUIJOM= -k8s.io/client-go v0.26.12 h1:kPpTpIeFNqwo4UyvoqzNp3DNK2mbGcdGv23eS1U8VMo= -k8s.io/client-go v0.26.12/go.mod h1:V7thEnIFroyNZOU30dKLiiVeqQmJz45shJG1mu7nONQ= +k8s.io/client-go v0.26.10 h1:4mDzl+1IrfRxh4Ro0s65JRGJp14w77gSMUTjACYWVRo= +k8s.io/client-go v0.26.10/go.mod h1:sh74ig838gCckU4ElYclWb24lTesPdEDPnlyg5vcbkA= k8s.io/cloud-provider v0.17.0/go.mod h1:Ze4c3w2C0bRsjkBUoHpFi+qWe3ob1wI2/7cUn+YQIDE= k8s.io/code-generator v0.0.0-20191121015212-c4c8f8345c7e/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc= @@ -1256,8 +1249,8 @@ k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3 k8s.io/legacy-cloud-providers v0.17.0/go.mod h1:DdzaepJ3RtRy+e5YhNtrCYwlgyK87j/5+Yfp0L9Syp8= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= -k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +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= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= diff --git a/acceptance/tests/api-gateway/api_gateway_kitchen_sink_test.go b/acceptance/tests/api-gateway/api_gateway_kitchen_sink_test.go deleted file mode 100644 index d701220a8c..0000000000 --- a/acceptance/tests/api-gateway/api_gateway_kitchen_sink_test.go +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package apigateway - -import ( - "context" - "encoding/base64" - "fmt" - "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" - "testing" - "time" - - "github.com/hashicorp/consul-k8s/acceptance/framework/consul" - "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" - "github.com/hashicorp/consul-k8s/acceptance/framework/logger" - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil/retry" - "github.com/stretchr/testify/require" - "k8s.io/apimachinery/pkg/types" - gwv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" -) - -// Enabled everything possible, see if anything breaks. -func TestAPIGateway_KitchenSink(t *testing.T) { - ctx := suite.Environment().DefaultContext(t) - cfg := suite.Config() - - runWithEnterpriseOnlyFeatures := cfg.EnableEnterprise - - serverHelmValues := map[string]string{ - "global.acls.manageSystemACLs": "true", - "global.tls.enabled": "true", - - // Don't install injector, controller and cni on this cluster so that it's not installed twice. - "connectInject.enabled": "false", - "connectInject.cni.enabled": "false", - } - serverReleaseName := helpers.RandomName() - consulServerCluster := consul.NewHelmCluster(t, serverHelmValues, ctx, cfg, serverReleaseName) - consulServerCluster.Create(t) - - helmValues := map[string]string{ - "server.enabled": "false", - "connectInject.consulNamespaces.mirroringK8S": "true", - "global.acls.manageSystemACLs": "true", - "global.tls.enabled": "true", - "global.logLevel": "trace", - "externalServers.enabled": "true", - "externalServers.hosts[0]": fmt.Sprintf("%s-consul-server", serverReleaseName), - "externalServers.httpsPort": "8501", - "global.tls.caCert.secretName": fmt.Sprintf("%s-consul-ca-cert", serverReleaseName), - "global.tls.caCert.secretKey": "tls.crt", - "global.acls.bootstrapToken.secretName": fmt.Sprintf("%s-consul-bootstrap-acl-token", serverReleaseName), - "global.acls.bootstrapToken.secretKey": "token", - } - - releaseName := helpers.RandomName() - consulCluster := consul.NewHelmCluster(t, helmValues, ctx, cfg, releaseName) - consulCluster.SkipCheckForPreviousInstallations = true - - consulCluster.Create(t) - - // Override the default proxy config settings for this test - consulClient, _ := consulCluster.SetupConsulClient(t, true, serverReleaseName) - logger.Log(t, "have consul client") - _, _, err := consulClient.ConfigEntries().Set(&api.ProxyConfigEntry{ - Kind: api.ProxyDefaults, - Name: api.ProxyConfigGlobal, - Config: map[string]interface{}{ - "protocol": "http", - }, - }, nil) - require.NoError(t, err) - logger.Log(t, "set consul config entry") - - logger.Log(t, "creating other namespace") - out, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "create", "namespace", "other") - require.NoError(t, err, out) - helpers.Cleanup(t, cfg.NoCleanupOnFailure, cfg.NoCleanup, func() { - // Ignore errors here because if the test ran as expected - // the custom resources will have been deleted. - k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "delete", "namespace", "other") - }) - - k8sClient := ctx.ControllerRuntimeClient(t) - - logger.Log(t, "creating api-gateway resources") - fixturePath := "../fixtures/cases/api-gateways/kitchen-sink" - if runWithEnterpriseOnlyFeatures { - fixturePath += "-ent" - } - out, err = k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "apply", "-k", fixturePath) - require.NoError(t, err, out) - helpers.Cleanup(t, cfg.NoCleanupOnFailure, cfg.NoCleanup, func() { - // Ignore errors here because if the test ran as expected - // the custom resources will have been deleted. - k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "delete", "-k", fixturePath) - }) - - // Create certificate secret, we do this separately since - // applying the secret will make an invalid certificate that breaks other tests - logger.Log(t, "creating certificate secret") - out, err = k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "apply", "-f", "../fixtures/bases/api-gateway/certificate.yaml") - require.NoError(t, err, out) - helpers.Cleanup(t, cfg.NoCleanupOnFailure, cfg.NoCleanup, func() { - // Ignore errors here because if the test ran as expected - // the custom resources will have been deleted. - k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "delete", "-f", "../fixtures/bases/api-gateway/certificate.yaml") - }) - - // patch certificate with data - logger.Log(t, "patching certificate secret with generated data") - certificate := generateCertificate(t, nil, "gateway.test.local") - k8s.RunKubectl(t, ctx.KubectlOptions(t), "patch", "secret", "certificate", "-p", fmt.Sprintf(`{"data":{"tls.crt":"%s","tls.key":"%s"}}`, base64.StdEncoding.EncodeToString(certificate.CertPEM), base64.StdEncoding.EncodeToString(certificate.PrivateKeyPEM)), "--type=merge") - - // Create static server and static client - logger.Log(t, "creating static-client pod") - k8s.DeployKustomize(t, ctx.KubectlOptions(t), cfg.NoCleanupOnFailure, cfg.NoCleanup, cfg.DebugDirectory, "../fixtures/bases/static-client") - k8s.RunKubectl(t, ctx.KubectlOptions(t), "wait", "--for=condition=available", "--timeout=5m", fmt.Sprintf("deploy/%s", "static-server")) - - // On startup, the controller can take upwards of 1m to perform - // leader election so we may need to wait a long time for - // the reconcile loop to run (hence the 2m timeout here). - var ( - gatewayAddress string - httpRoute gwv1beta1.HTTPRoute - ) - - counter := &retry.Counter{Count: 60, Wait: 2 * time.Second} - retry.RunWith(counter, t, func(r *retry.R) { - var gateway gwv1beta1.Gateway - err = k8sClient.Get(context.Background(), types.NamespacedName{Name: "gateway", Namespace: "default"}, &gateway) - require.NoError(r, err) - - //CHECK TO MAKE SURE EVERYTHING WAS SET UP CORECTLY BEFORE RUNNING TESTS - require.Len(r, gateway.Finalizers, 1) - require.EqualValues(r, gatewayFinalizer, gateway.Finalizers[0]) - - // check our statuses - checkStatusCondition(r, gateway.Status.Conditions, trueCondition("Accepted", "Accepted")) - checkStatusCondition(r, gateway.Status.Conditions, trueCondition("ConsulAccepted", "Accepted")) - require.Len(r, gateway.Status.Listeners, 2) - - require.EqualValues(r, int32(1), gateway.Status.Listeners[0].AttachedRoutes) - checkStatusCondition(r, gateway.Status.Listeners[0].Conditions, trueCondition("Accepted", "Accepted")) - checkStatusCondition(r, gateway.Status.Listeners[0].Conditions, falseCondition("Conflicted", "NoConflicts")) - checkStatusCondition(r, gateway.Status.Listeners[0].Conditions, trueCondition("ResolvedRefs", "ResolvedRefs")) - - // check that we have an address to use - require.Len(r, gateway.Status.Addresses, 2) - // now we know we have an address, set it so we can use it - gatewayAddress = gateway.Status.Addresses[0].Value - - // http route checks - err = k8sClient.Get(context.Background(), types.NamespacedName{Name: "http-route", Namespace: "default"}, &httpRoute) - require.NoError(r, err) - - // check our finalizers - require.Len(r, httpRoute.Finalizers, 1) - require.EqualValues(r, gatewayFinalizer, httpRoute.Finalizers[0]) - - // check parent status - require.Len(r, httpRoute.Status.Parents, 1) - require.EqualValues(r, gatewayClassControllerName, httpRoute.Status.Parents[0].ControllerName) - require.EqualValues(r, "gateway", httpRoute.Status.Parents[0].ParentRef.Name) - checkStatusCondition(r, httpRoute.Status.Parents[0].Conditions, trueCondition("Accepted", "Accepted")) - checkStatusCondition(r, httpRoute.Status.Parents[0].Conditions, trueCondition("ResolvedRefs", "ResolvedRefs")) - checkStatusCondition(r, httpRoute.Status.Parents[0].Conditions, trueCondition("ConsulAccepted", "Accepted")) - - }) - - // GENERAL Asserts- test that assets were created as expected - entry, _, err := consulClient.ConfigEntries().Get(api.APIGateway, "gateway", nil) - require.NoError(t, err) - gateway := entry.(*api.APIGatewayConfigEntry) - - entry, _, err = consulClient.ConfigEntries().Get(api.HTTPRoute, "http-route", nil) - require.NoError(t, err) - consulHTTPRoute := entry.(*api.HTTPRouteConfigEntry) - - // now check the gateway status conditions - checkConsulStatusCondition(t, gateway.Status.Conditions, trueConsulCondition("Accepted", "Accepted")) - - // and the route status conditions - checkConsulStatusCondition(t, consulHTTPRoute.Status.Conditions, trueConsulCondition("Bound", "Bound")) - - // finally we check that we can actually route to the service(s) via the gateway - k8sOptions := ctx.KubectlOptions(t) - targetHTTPAddress := fmt.Sprintf("http://%s/v1", gatewayAddress) - - // Now we create the allow intention. - _, _, err = consulClient.ConfigEntries().Set(&api.ServiceIntentionsConfigEntry{ - Kind: api.ServiceIntentions, - Name: "static-server", - Sources: []*api.SourceIntention{ - { - Name: "gateway", - Action: api.IntentionActionAllow, - }, - }, - }, nil) - require.NoError(t, err) - - _, _, err = consulClient.ConfigEntries().Set(&api.ServiceIntentionsConfigEntry{ - Kind: api.ServiceIntentions, - Name: "static-server-protected", - Sources: []*api.SourceIntention{ - { - Name: "gateway", - Action: api.IntentionActionAllow, - }, - }, - }, nil) - require.NoError(t, err) - - //asserts only valid when running with enterprise - if runWithEnterpriseOnlyFeatures { - //JWT Related Asserts - // should fail because we're missing JWT - logger.Log(t, "trying calls to api gateway /admin should fail without JWT token") - k8s.CheckStaticServerHTTPConnectionFailing(t, k8sOptions, StaticClientName, targetHTTPAddress) - - // will succeed because we use the token with the correct role and the correct issuer - logger.Log(t, "trying calls to api gateway /admin should succeed with JWT token with correct role") - k8s.CheckStaticServerConnectionSuccessful(t, k8sOptions, StaticClientName, "-H", fmt.Sprintf("Authorization: Bearer %s", doctorToken), targetHTTPAddress) - } else { - // Test that we can make a call to the api gateway - logger.Log(t, "trying calls to api gateway http") - k8s.CheckStaticServerConnectionSuccessful(t, k8sOptions, StaticClientName, targetHTTPAddress) - } -} diff --git a/acceptance/tests/api-gateway_v2/api_gateway_v2_test.go b/acceptance/tests/api-gateway_v2/api_gateway_v2_test.go deleted file mode 100644 index 1e01584e32..0000000000 --- a/acceptance/tests/api-gateway_v2/api_gateway_v2_test.go +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package apigatewayv2 - -import ( - "context" - "encoding/base64" - "fmt" - "strconv" - "testing" - "time" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil/retry" - - "github.com/hashicorp/consul-k8s/acceptance/framework/consul" - "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" - "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" - "github.com/hashicorp/consul-k8s/acceptance/framework/logger" - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - - "github.com/stretchr/testify/require" - "k8s.io/apimachinery/pkg/types" -) - -// Test that api gateway basic functionality works in a default installation and a secure installation for V2. -func TestAPIGateway_V2_Basic(t *testing.T) { - - cases := []struct { - secure bool - }{ - { - secure: false, - }, - { - secure: true, - }, - } - for _, c := range cases { - name := fmt.Sprintf("secure: %t", c.secure) - t.Run(name, func(t *testing.T) { - ctx := suite.Environment().DefaultContext(t) - cfg := suite.Config() - helmValues := map[string]string{ - "connectInject.enabled": "true", - "global.acls.manageSystemACLs": strconv.FormatBool(c.secure), - "global.tls.enabled": strconv.FormatBool(c.secure), - "global.logLevel": "trace", - "global.experiments[0]": "resource-apis", - } - - releaseName := helpers.RandomName() - consulCluster := consul.NewHelmCluster(t, helmValues, ctx, cfg, releaseName) - - consulCluster.Create(t) - - // Override the default proxy config settings for this test - consulClient, _ := consulCluster.SetupConsulClient(t, c.secure) - _, _, err := consulClient.ConfigEntries().Set(&api.ProxyConfigEntry{ - Kind: api.ProxyDefaults, - Name: api.ProxyConfigGlobal, - Config: map[string]interface{}{ - "protocol": "http", - }, - }, nil) - require.NoError(t, err) - - logger.Log(t, "creating api-gateway resources") - out, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "apply", "-k", "../fixtures/bases/api-gateway-v2") - require.NoError(t, err, out) - helpers.Cleanup(t, cfg.NoCleanupOnFailure, cfg.NoCleanup, func() { - // Ignore errors here because if the test ran as expected - // the custom resources will have been deleted. - k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "delete", "-k", "../fixtures/bases/api-gateway-v2") - }) - - // Create certificate secret, we do this separately since - // applying the secret will make an invalid certificate that breaks other tests - logger.Log(t, "creating certificate secret") - out, err = k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "apply", "-f", "../fixtures/bases/api-gateway-v2/certificate.yaml") - require.NoError(t, err, out) - helpers.Cleanup(t, cfg.NoCleanupOnFailure, cfg.NoCleanup, func() { - // Ignore errors here because if the test ran as expected - // the custom resources will have been deleted. - k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "delete", "-f", "../fixtures/bases/api-gateway-v2/certificate.yaml") - }) - - // patch certificate with data - logger.Log(t, "patching certificate secret with generated data") - certificate := generateCertificate(t, nil, "gateway.test.local") - k8s.RunKubectl(t, ctx.KubectlOptions(t), "patch", "secret", "certificate", "-p", fmt.Sprintf(`{"data":{"tls.crt":"%s","tls.key":"%s"}}`, base64.StdEncoding.EncodeToString(certificate.CertPEM), base64.StdEncoding.EncodeToString(certificate.PrivateKeyPEM)), "--type=merge") - - // We use the static-client pod so that we can make calls to the api gateway - // via kubectl exec without needing a route into the cluster from the test machine. - logger.Log(t, "creating static-client pod") - k8s.DeployKustomize(t, ctx.KubectlOptions(t), cfg.NoCleanupOnFailure, cfg.NoCleanup, cfg.DebugDirectory, "../fixtures/bases/static-client") - - logger.Log(t, "creating target tcp server") - k8s.DeployKustomize(t, ctx.KubectlOptions(t), cfg.NoCleanupOnFailure, cfg.NoCleanup, cfg.DebugDirectory, "../fixtures/bases/static-server-tcp") - - logger.Log(t, "creating tcp-route") - k8s.RunKubectl(t, ctx.KubectlOptions(t), "apply", "-f", "../fixtures/cases/api-gateways-v2/tcproute/route.yaml") - helpers.Cleanup(t, cfg.NoCleanupOnFailure, cfg.NoCleanup, func() { - // Ignore errors here because if the test ran as expected - // the custom resources will have been deleted. - k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "delete", "-f", "../fixtures/cases/api-gateways-v2/tcproute/route.yaml") - }) - - // Grab a kubernetes client so that we can verify binding - // behavior prior to issuing requests through the gateway. - k8sClient := ctx.ControllerRuntimeClient(t) - - // On startup, the controller can take upwards of 1m to perform - // leader election so we may need to wait a long time for - // the reconcile loop to run (hence the timeout here). - var gatewayAddress string - counter := &retry.Counter{Count: 120, Wait: 2 * time.Second} - retry.RunWith(counter, t, func(r *retry.R) { - var gateway meshv2beta1.APIGateway - err := k8sClient.Get(context.Background(), types.NamespacedName{Name: "gateway", Namespace: "default"}, &gateway) - require.NoError(r, err) - - // check our finalizers - require.Len(r, gateway.Finalizers, 1) - require.EqualValues(r, gatewayFinalizer, gateway.Finalizers()[0]) - - // check our statuses - checkV2StatusCondition(r, gateway.APIGatewayStatus.Conditions, trueV2Condition("Accepted", "Accepted")) - checkV2StatusCondition(r, gateway.APIGatewayStatus.Conditions, trueV2Condition("ConsulAccepted", "Accepted")) - require.Len(r, gateway.APIGatewayStatus.Listeners, 3) - - require.EqualValues(r, 1, gateway.APIGatewayStatus.Listeners[0].AttachedRoutes) - checkV2StatusCondition(r, gateway.APIGatewayStatus.Listeners[0].Conditions, trueV2Condition("Accepted", "Accepted")) - checkV2StatusCondition(r, gateway.APIGatewayStatus.Listeners[0].Conditions, falseV2Condition("Conflicted", "NoConflicts")) - checkV2StatusCondition(r, gateway.APIGatewayStatus.Listeners[0].Conditions, trueV2Condition("ResolvedRefs", "ResolvedRefs")) - require.EqualValues(r, 1, gateway.APIGatewayStatus.Listeners[1].AttachedRoutes) - checkV2StatusCondition(r, gateway.APIGatewayStatus.Listeners[1].Conditions, trueV2Condition("Accepted", "Accepted")) - checkV2StatusCondition(r, gateway.APIGatewayStatus.Listeners[1].Conditions, falseV2Condition("Conflicted", "NoConflicts")) - checkV2StatusCondition(r, gateway.APIGatewayStatus.Listeners[1].Conditions, trueV2Condition("ResolvedRefs", "ResolvedRefs")) - require.EqualValues(r, 1, gateway.APIGatewayStatus.Listeners[2].AttachedRoutes) - checkV2StatusCondition(r, gateway.APIGatewayStatus.Listeners[2].Conditions, trueV2Condition("Accepted", "Accepted")) - checkV2StatusCondition(r, gateway.APIGatewayStatus.Listeners[2].Conditions, falseV2Condition("Conflicted", "NoConflicts")) - checkV2StatusCondition(r, gateway.APIGatewayStatus.Listeners[2].Conditions, trueV2Condition("ResolvedRefs", "ResolvedRefs")) - - // check that we have an address to use - require.Len(r, gateway.APIGatewayStatus.Addresses, 1) - // now we know we have an address, set it so we can use it - gatewayAddress = gateway.APIGatewayStatus.Addresses[0].Value - }) - - // now that we've satisfied those assertions, we know reconciliation is done - // so we can run assertions on the routes and the other objects - - // gateway class checks - var gatewayClass meshv2beta1.GatewayClass - err = k8sClient.Get(context.Background(), types.NamespacedName{Name: "gateway-class"}, &gatewayClass) - require.NoError(t, err) - - // check our finalizers - require.Len(t, gatewayClass.Finalizers, 1) - require.EqualValues(t, gatewayClassFinalizer, gatewayClass.Finalizers()[0]) - - // tcp route checks - var tcpRoute meshv2beta1.TCPRoute - err = k8sClient.Get(context.Background(), types.NamespacedName{Name: "tcp-route", Namespace: "default"}, &tcpRoute) - require.NoError(t, err) - - // check our finalizers - require.Len(t, tcpRoute.Finalizers, 1) - require.EqualValues(t, gatewayFinalizer, tcpRoute.Finalizers()[0]) - - // TODO check values actually created in the resource API - - // finally we check that we can actually route to the service via the gateway - k8sOptions := ctx.KubectlOptions(t) - targetTCPAddress := fmt.Sprintf("http://%s:81", gatewayAddress) - - // Test that we can make a call to the api gateway - // via the static-client pod. It should route to the static-server pod. - logger.Log(t, "trying calls to api gateway tcp") - k8s.CheckStaticServerConnectionSuccessful(t, k8sOptions, StaticClientName, targetTCPAddress) - - }) - } -} diff --git a/acceptance/tests/api-gateway_v2/helpers.go b/acceptance/tests/api-gateway_v2/helpers.go deleted file mode 100644 index 124fa20450..0000000000 --- a/acceptance/tests/api-gateway_v2/helpers.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package apigatewayv2 - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - corev1 "k8s.io/api/core/v1" - "math/big" - "testing" - "time" - - "github.com/stretchr/testify/require" -) - -const ( - StaticClientName = "static-client" - gatewayClassControllerName = "mesh.consul.hashicorp.com/gateway-controller" - //TODO these values will likely need to be update to their V2 values for the test to pass. - gatewayClassFinalizer = "gateway-exists-finalizer.consul.hashicorp.com" - gatewayFinalizer = "gateway-finalizer.consul.hashicorp.com" -) - -type certificateInfo struct { - Cert *x509.Certificate - PrivateKey *rsa.PrivateKey - CertPEM []byte - PrivateKeyPEM []byte -} - -func checkV2StatusCondition(t require.TestingT, conditions []meshv2beta1.Condition, toCheck meshv2beta1.Condition) { - for _, c := range conditions { - if c.Type == toCheck.Type { - require.EqualValues(t, toCheck.Reason, c.Reason) - require.EqualValues(t, toCheck.Status, c.Status) - return - } - } - - t.Errorf("expected condition not found: %s", toCheck.Type) -} - -func trueV2Condition(conditionType, reason string) meshv2beta1.Condition { - return meshv2beta1.Condition{ - Type: meshv2beta1.ConditionType(conditionType), - Reason: reason, - Status: corev1.ConditionTrue, - } -} - -func falseV2Condition(conditionType, reason string) meshv2beta1.Condition { - return meshv2beta1.Condition{ - Type: meshv2beta1.ConditionType(conditionType), - Reason: reason, - Status: corev1.ConditionFalse, - } -} - -func generateCertificate(t *testing.T, ca *certificateInfo, commonName string) *certificateInfo { - t.Helper() - - bits := 2048 - privateKey, err := rsa.GenerateKey(rand.Reader, bits) - require.NoError(t, err) - - usage := x509.KeyUsageDigitalSignature - if ca == nil { - usage = x509.KeyUsageCertSign - } - - expiration := time.Now().AddDate(10, 0, 0) - cert := &x509.Certificate{ - SerialNumber: big.NewInt(1), - Subject: pkix.Name{ - Organization: []string{"Testing, INC."}, - Country: []string{"US"}, - Province: []string{""}, - Locality: []string{"San Francisco"}, - StreetAddress: []string{"Fake Street"}, - PostalCode: []string{"11111"}, - CommonName: commonName, - }, - IsCA: ca == nil, - NotBefore: time.Now().Add(-10 * time.Minute), - NotAfter: expiration, - SubjectKeyId: []byte{1, 2, 3, 4, 6}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, - KeyUsage: usage, - BasicConstraintsValid: true, - } - caCert := cert - if ca != nil { - caCert = ca.Cert - } - caPrivateKey := privateKey - if ca != nil { - caPrivateKey = ca.PrivateKey - } - data, err := x509.CreateCertificate(rand.Reader, cert, caCert, &privateKey.PublicKey, caPrivateKey) - require.NoError(t, err) - - certBytes := pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE", - Bytes: data, - }) - - privateKeyBytes := pem.EncodeToMemory(&pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(privateKey), - }) - - return &certificateInfo{ - Cert: cert, - CertPEM: certBytes, - PrivateKey: privateKey, - PrivateKeyPEM: privateKeyBytes, - } -} diff --git a/acceptance/tests/api-gateway_v2/main_test.go b/acceptance/tests/api-gateway_v2/main_test.go deleted file mode 100644 index 47f4c3b3cf..0000000000 --- a/acceptance/tests/api-gateway_v2/main_test.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package apigatewayv2 - -import ( - "fmt" - "os" - "testing" - - testsuite "github.com/hashicorp/consul-k8s/acceptance/framework/suite" -) - -var suite testsuite.Suite - -func TestMain(m *testing.M) { - runTests := os.Getenv("TEST_APIGW_V2") - if runTests != "TRUE" { - fmt.Println("skipping") - os.Exit(0) - } - suite = testsuite.NewSuite(m) - os.Exit(suite.Run()) -} diff --git a/acceptance/tests/cli/cli_install_test.go b/acceptance/tests/cli/cli_install_test.go index cfee1560ae..c8b66ff451 100644 --- a/acceptance/tests/cli/cli_install_test.go +++ b/acceptance/tests/cli/cli_install_test.go @@ -70,11 +70,11 @@ func TestInstall(t *testing.T) { retrier := &retry.Timer{Timeout: 160 * time.Second, Wait: 2 * time.Second} retry.RunWith(retrier, t, func(r *retry.R) { for podName := range list { - out, err := cli.Run(r, ctx.KubectlOptions(r), "proxy", "read", podName) + out, err := cli.Run(t, ctx.KubectlOptions(t), "proxy", "read", podName) require.NoError(r, err) output := string(out) - r.Log(output) + logger.Log(t, output) // Both proxies must see their own local agent and app as clusters. require.Regexp(r, "consul-dataplane.*STATIC", output) diff --git a/acceptance/tests/cloud/observability_test.go b/acceptance/tests/cloud/observability_test.go index af553b3ecb..63e2d15bd2 100644 --- a/acceptance/tests/cloud/observability_test.go +++ b/acceptance/tests/cloud/observability_test.go @@ -222,11 +222,7 @@ func TestObservabilityCloud(t *testing.T) { // Validate that the consul-telemetry-collector service was deployed to the expected namespace. consulClient, _ := consulCluster.SetupConsulClient(t, c.secure) - q := &api.QueryOptions{} - if cfg.EnableEnterprise { - q.Namespace = ns - } - instances, _, err := consulClient.Catalog().Service("consul-telemetry-collector", "", q) + instances, _, err := consulClient.Catalog().Service("consul-telemetry-collector", "", &api.QueryOptions{Namespace: ns}) require.NoError(t, err) require.Len(t, instances, 1) require.Equal(t, "passing", instances[0].Checks.AggregatedStatus()) diff --git a/acceptance/tests/config-entries/config_entries_namespaces_test.go b/acceptance/tests/config-entries/config_entries_namespaces_test.go index aa74bdc2b5..a013c99e09 100644 --- a/acceptance/tests/config-entries/config_entries_namespaces_test.go +++ b/acceptance/tests/config-entries/config_entries_namespaces_test.go @@ -128,7 +128,7 @@ func TestControllerNamespaces(t *testing.T) { // Retry the kubectl apply because we've seen sporadic // "connection refused" errors where the mutating webhook // endpoint fails initially. - out, err := k8s.RunKubectlAndGetOutputE(r, ctx.KubectlOptions(r), "apply", "-n", KubeNS, "-k", "../fixtures/cases/crds-ent") + out, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "apply", "-n", KubeNS, "-k", "../fixtures/cases/crds-ent") require.NoError(r, err, out) // NOTE: No need to clean up because the namespace will be deleted. }) diff --git a/acceptance/tests/config-entries/config_entries_test.go b/acceptance/tests/config-entries/config_entries_test.go index 9f2595ed4f..81b0a75ff4 100644 --- a/acceptance/tests/config-entries/config_entries_test.go +++ b/acceptance/tests/config-entries/config_entries_test.go @@ -85,13 +85,13 @@ func TestController(t *testing.T) { // Retry the kubectl apply because we've seen sporadic // "connection refused" errors where the mutating webhook // endpoint fails initially. - out, err := k8s.RunKubectlAndGetOutputE(r, ctx.KubectlOptions(r), "apply", "-k", "../fixtures/bases/crds-oss") + out, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "apply", "-k", "../fixtures/bases/crds-oss") require.NoError(r, err, out) - }) - helpers.Cleanup(t, cfg.NoCleanupOnFailure, cfg.NoCleanup, func() { - // Ignore errors here because if the test ran as expected - // the custom resources will have been deleted. - k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "delete", "-k", "../fixtures/bases/crds-oss") + helpers.Cleanup(t, cfg.NoCleanupOnFailure, cfg.NoCleanup, func() { + // Ignore errors here because if the test ran as expected + // the custom resources will have been deleted. + k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "delete", "-k", "../fixtures/bases/crds-oss") + }) }) // On startup, the controller can take upwards of 1m to perform diff --git a/acceptance/tests/connect/connect_proxy_lifecycle_test.go b/acceptance/tests/connect/connect_proxy_lifecycle_test.go index 7a4b3b383f..53c48281fd 100644 --- a/acceptance/tests/connect/connect_proxy_lifecycle_test.go +++ b/acceptance/tests/connect/connect_proxy_lifecycle_test.go @@ -111,7 +111,7 @@ func TestConnectInject_ProxyLifecycleShutdown(t *testing.T) { "static-server", "static-server-sidecar-proxy", } { - logger.Logf(r, "checking for %s service in Consul catalog", name) + logger.Logf(t, "checking for %s service in Consul catalog", name) instances, _, err := connHelper.ConsulClient.Catalog().Service(name, "", nil) r.Check(err) @@ -158,7 +158,7 @@ func TestConnectInject_ProxyLifecycleShutdown(t *testing.T) { // Ensure outbound requests are still successful during grace // period. retry.RunWith(&retry.Timer{Timeout: time.Duration(gracePeriodSeconds) * time.Second, Wait: 2 * time.Second}, t, func(r *retry.R) { - output, err := k8s.RunKubectlAndGetOutputE(r, ctx.KubectlOptions(r), args...) + output, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), args...) require.NoError(r, err) require.Condition(r, func() bool { exists := false @@ -175,7 +175,7 @@ func TestConnectInject_ProxyLifecycleShutdown(t *testing.T) { } else { // Ensure outbound requests fail because proxy has terminated retry.RunWith(&retry.Timer{Timeout: time.Duration(terminationGracePeriod) * time.Second, Wait: 2 * time.Second}, t, func(r *retry.R) { - output, err := k8s.RunKubectlAndGetOutputE(r, ctx.KubectlOptions(r), args...) + output, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), args...) require.Error(r, err) require.Condition(r, func() bool { exists := false @@ -193,7 +193,7 @@ func TestConnectInject_ProxyLifecycleShutdown(t *testing.T) { "static-client", "static-client-sidecar-proxy", } { - logger.Logf(r, "checking for %s service in Consul catalog", name) + logger.Logf(t, "checking for %s service in Consul catalog", name) instances, _, err := connHelper.ConsulClient.Catalog().Service(name, "", nil) r.Check(err) @@ -212,6 +212,7 @@ func TestConnectInject_ProxyLifecycleShutdownJob(t *testing.T) { cfg := suite.Config() if cfg.EnableTransparentProxy { + // TODO t-eckert: Come back and review this with wise counsel. t.Skip("Skipping test because transparent proxy is enabled") } @@ -248,7 +249,7 @@ func TestConnectInject_ProxyLifecycleShutdownJob(t *testing.T) { "static-server", "static-server-sidecar-proxy", } { - logger.Logf(r, "checking for %s service in Consul catalog", name) + logger.Logf(t, "checking for %s service in Consul catalog", name) instances, _, err := connHelper.ConsulClient.Catalog().Service(name, "", nil) r.Check(err) @@ -269,7 +270,7 @@ func TestConnectInject_ProxyLifecycleShutdownJob(t *testing.T) { "job-client", "job-client-sidecar-proxy", } { - logger.Logf(r, "checking for %s service in Consul catalog", name) + logger.Logf(t, "checking for %s service in Consul catalog", name) instances, _, err := connHelper.ConsulClient.Catalog().Service(name, "", nil) r.Check(err) @@ -311,7 +312,7 @@ func TestConnectInject_ProxyLifecycleShutdownJob(t *testing.T) { if gracePeriod > 0 { logger.Log(t, "Checking if connection successful within grace period...") retry.RunWith(&retry.Timer{Timeout: time.Duration(gracePeriod) * time.Second, Wait: 2 * time.Second}, t, func(r *retry.R) { - output, err := k8s.RunKubectlAndGetOutputE(r, ctx.KubectlOptions(r), args...) + output, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), args...) require.NoError(r, err) require.True(r, !strings.Contains(output, "curl: (7) Failed to connect")) }) @@ -322,15 +323,15 @@ func TestConnectInject_ProxyLifecycleShutdownJob(t *testing.T) { // Test that requests fail once grace period has ended, or there was no grace period set. logger.Log(t, "Checking that requests fail now that proxy is killed...") retry.RunWith(&retry.Timer{Timeout: 2 * time.Minute, Wait: 2 * time.Second}, t, func(r *retry.R) { - output, err := k8s.RunKubectlAndGetOutputE(r, ctx.KubectlOptions(r), args...) + output, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), args...) require.Error(r, err) require.True(r, strings.Contains(output, "curl: (7) Failed to connect")) }) // Wait for the job to complete. retry.RunWith(&retry.Timer{Timeout: 4 * time.Minute, Wait: 30 * time.Second}, t, func(r *retry.R) { - logger.Log(r, "Checking if job completed...") - jobs, err := ctx.KubernetesClient(r).BatchV1().Jobs(ns).List( + logger.Log(t, "Checking if job completed...") + jobs, err := ctx.KubernetesClient(t).BatchV1().Jobs(ns).List( context.Background(), metav1.ListOptions{ LabelSelector: "app=job-client", @@ -362,7 +363,7 @@ func TestConnectInject_ProxyLifecycleShutdownJob(t *testing.T) { "job-client", "job-client-sidecar-proxy", } { - logger.Logf(r, "checking for %s service in Consul catalog", name) + logger.Logf(t, "checking for %s service in Consul catalog", name) instances, _, err := connHelper.ConsulClient.Catalog().Service(name, "", nil) r.Check(err) diff --git a/acceptance/tests/connect/local_rate_limit_test.go b/acceptance/tests/connect/local_rate_limit_test.go index eb96be4332..cd0b095c07 100644 --- a/acceptance/tests/connect/local_rate_limit_test.go +++ b/acceptance/tests/connect/local_rate_limit_test.go @@ -104,12 +104,12 @@ func assertRateLimits(t *testing.T, opts *assertRateLimitOptions, addr string) { // Make up to the allowed numbers of calls in a second t0 := time.Now() - output, err := k8s.RunKubectlAndGetOutputE(r, opts.k8sOpts, append(args, repeatAddr)...) + output, err := k8s.RunKubectlAndGetOutputE(t, opts.k8sOpts, append(args, repeatAddr)...) require.NoError(r, err) require.Contains(r, output, opts.successOutput) // Exceed the configured rate limit. - output, err = k8s.RunKubectlAndGetOutputE(r, opts.k8sOpts, append(args, addr)...) + output, err = k8s.RunKubectlAndGetOutputE(t, opts.k8sOpts, append(args, addr)...) require.True(r, time.Since(t0) < time.Second, "failed to make all requests within one second window") if opts.enforced { require.Error(r, err) diff --git a/acceptance/tests/consul-dns/consul_dns_test.go b/acceptance/tests/consul-dns/consul_dns_test.go index f67ac96bd3..84741175af 100644 --- a/acceptance/tests/consul-dns/consul_dns_test.go +++ b/acceptance/tests/consul-dns/consul_dns_test.go @@ -74,7 +74,7 @@ func TestConsulDNS(t *testing.T) { }) retry.Run(t, func(r *retry.R) { - logs, err := k8s.RunKubectlAndGetOutputE(r, ctx.KubectlOptions(r), dnsTestPodArgs...) + logs, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), dnsTestPodArgs...) require.NoError(r, err) // When the `dig` request is successful, a section of it's response looks like the following: diff --git a/acceptance/tests/example/main_test.go b/acceptance/tests/example/main_test.go index e35893a1d3..f92fff8a59 100644 --- a/acceptance/tests/example/main_test.go +++ b/acceptance/tests/example/main_test.go @@ -2,7 +2,6 @@ // SPDX-License-Identifier: MPL-2.0 // Rename package to your test package. -// NOTE: Remember to add your test package to acceptance/ci-inputs so it gets run in CI. package example import ( diff --git a/acceptance/tests/fixtures/bases/api-gateway-v2/apigateway.yaml b/acceptance/tests/fixtures/bases/api-gateway-v2/apigateway.yaml deleted file mode 100644 index c4fa0d6364..0000000000 --- a/acceptance/tests/fixtures/bases/api-gateway-v2/apigateway.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: mesh.consul.hashicorp.com/v2beta1 -kind: APIGateway -metadata: - name: gateway -spec: - gatewayClassName: gateway-class - listeners: - - protocol: TCP - port: 81 - name: tcp - allowedRoutes: - namespaces: - from: "All" diff --git a/acceptance/tests/fixtures/bases/api-gateway-v2/certificate.yaml b/acceptance/tests/fixtures/bases/api-gateway-v2/certificate.yaml deleted file mode 100644 index d35dc559e2..0000000000 --- a/acceptance/tests/fixtures/bases/api-gateway-v2/certificate.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: v1 -kind: Secret -metadata: - name: certificate -type: kubernetes.io/tls -data: - tls.crt: "" - tls.key: "" \ No newline at end of file diff --git a/acceptance/tests/fixtures/bases/api-gateway-v2/gatewayclass.yaml b/acceptance/tests/fixtures/bases/api-gateway-v2/gatewayclass.yaml deleted file mode 100644 index 583ffc210a..0000000000 --- a/acceptance/tests/fixtures/bases/api-gateway-v2/gatewayclass.yaml +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: mesh.consul.hashicorp.com/v2beta1 -kind: GatewayClass -metadata: - name: gateway-class -spec: - controllerName: "consul.hashicorp.com/gateway-controller" - parametersRef: - group: consul.hashicorp.com - kind: GatewayClassConfig - name: gateway-class-config diff --git a/acceptance/tests/fixtures/bases/api-gateway-v2/gatewayclassconfig.yaml b/acceptance/tests/fixtures/bases/api-gateway-v2/gatewayclassconfig.yaml deleted file mode 100644 index 049cdd708f..0000000000 --- a/acceptance/tests/fixtures/bases/api-gateway-v2/gatewayclassconfig.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: mesh.consul.hashicorp.com/v2beta1 -kind: GatewayClassConfig -metadata: - name: gateway-class-config \ No newline at end of file diff --git a/acceptance/tests/fixtures/bases/api-gateway-v2/kustomization.yaml b/acceptance/tests/fixtures/bases/api-gateway-v2/kustomization.yaml deleted file mode 100644 index 871949a1ab..0000000000 --- a/acceptance/tests/fixtures/bases/api-gateway-v2/kustomization.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -resources: - - gatewayclassconfig.yaml - - gatewayclass.yaml - - apigateway.yaml - - tcproute.yaml \ No newline at end of file diff --git a/acceptance/tests/fixtures/bases/api-gateway-v2/tcproute.yaml b/acceptance/tests/fixtures/bases/api-gateway-v2/tcproute.yaml deleted file mode 100644 index c06b0e4ee0..0000000000 --- a/acceptance/tests/fixtures/bases/api-gateway-v2/tcproute.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: mesh.consul.hashicorp.com/v2beta1 -kind: TCPRoute -metadata: - name: tcp-route -spec: - parentRefs: - - name: gateway \ No newline at end of file diff --git a/acceptance/tests/fixtures/bases/cloud/hcp-mock/deployment.yaml b/acceptance/tests/fixtures/bases/cloud/hcp-mock/deployment.yaml index 78547d5118..7278557cdb 100644 --- a/acceptance/tests/fixtures/bases/cloud/hcp-mock/deployment.yaml +++ b/acceptance/tests/fixtures/bases/cloud/hcp-mock/deployment.yaml @@ -19,7 +19,7 @@ spec: containers: - name: fake-server # TODO: move this to a hashicorp mirror - image: docker.io/achooo/fakeserver:latest + image: docker.io/chaapppie/fakeserver:latest ports: - containerPort: 443 name: https diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/api-gateway.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/api-gateway.yaml deleted file mode 100644 index 3b59ada305..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/api-gateway.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: gateway.networking.k8s.io/v1beta1 -kind: Gateway -metadata: - name: gateway -spec: - gatewayClassName: gateway-class - listeners: - - protocol: HTTP - port: 80 - name: http - allowedRoutes: - namespaces: - from: "All" - - protocol: HTTPS - port: 443 - name: https - tls: - certificateRefs: - - name: "certificate" - allowedRoutes: - namespaces: - from: "All" diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/external-ref.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/external-ref.yaml deleted file mode 100644 index 57e6dfee7c..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/external-ref.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: consul.hashicorp.com/v1alpha1 -kind: RouteAuthFilter -metadata: - name: route-jwt-auth-filter - namespace: default -spec: - jwt: - providers: - - name: "local" - verifyClaims: - - path: - - role - value: doctor diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/filters.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/filters.yaml deleted file mode 100644 index 966eab85a6..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/filters.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: consul.hashicorp.com/v1alpha1 -kind: RouteRetryFilter -metadata: - name: retrytrafficfilter -spec: - numRetries: 1 - retryOnConnectFailure: false - retryOn: - - reset - - unavailable - retryOnStatusCodes: - - 500 - - 502 - ---- -apiVersion: consul.hashicorp.com/v1alpha1 -kind: RouteTimeoutFilter -metadata: - name: timeouttrafficfilter -spec: - requestTimeout: "1s" - idleTimeout: "1s" \ No newline at end of file diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/gateway-policy.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/gateway-policy.yaml deleted file mode 100644 index 5552d7e085..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/gateway-policy.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: consul.hashicorp.com/v1alpha1 -kind: GatewayPolicy -metadata: - name: my-policy -spec: - targetRef: - name: gateway - sectionName: http-auth - group: gateway.networking.k8s.io/v1beta1 - kind: Gateway - override: - jwt: - providers: - - name: "local" - default: - jwt: - providers: - - name: "local" - verifyClaims: - - path: - - role - value: pet diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/gatewayclassconfig.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/gatewayclassconfig.yaml deleted file mode 100644 index 42c9bee986..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/gatewayclassconfig.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: consul.hashicorp.com/v1alpha1 -kind: GatewayClassConfig -metadata: - name: gateway-class-config -spec: - deployment: - defaultInstances: 2 - maxInstances: 3 - minInstances: 1 \ No newline at end of file diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/httproute.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/httproute.yaml deleted file mode 100644 index 760791cf51..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/httproute.yaml +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: gateway.networking.k8s.io/v1beta1 -kind: HTTPRoute -metadata: - name: http-route -spec: - parentRefs: - - name: gateway - sectionName: http - rules: - - matches: - - path: - type: PathPrefix - value: "/v1" - backendRefs: - - name: static-server - port: 8080 - filters: - - type: ExtensionRef - extensionRef: - group: consul.hashicorp.com - kind: RouteAuthFilter - name: route-jwt-auth-filter - - type: ExtensionRef - extensionRef: - group: consul.hashicorp.com - kind: RouteRetryFilter - name: retrytrafficfilter - - type: ExtensionRef - extensionRef: - group: consul.hashicorp.com - kind: RouteTimeoutFilter - name: timeouttrafficfilter - - type: RequestHeaderModifier - requestHeaderModifier: - add: - - name: my-header - value: foo - - type: URLRewrite - urlRewrite: - path: - type: "ReplacePrefixMatch" - replacePrefixMatch: "/v1/test" \ No newline at end of file diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/jwt-provider.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/jwt-provider.yaml deleted file mode 100644 index 1e5cbf35d6..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/jwt-provider.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: consul.hashicorp.com/v1alpha1 -kind: JWTProvider -metadata: - name: local -spec: - issuer: local - jsonWebKeySet: - local: - jwks: "ewogICAgImtleXMiOiBbCiAgICAgICAgewogICAgICAgICAgICAicCI6ICI5TTlWSVhJR0hpR3FlTnhseEJ2V0xFV09oUFh3dXhXZUpod01uM3dGdG9STEtfZmF6VWxjWEc1cUViLTdpMXo3VmlPUWVZRnh6WUZYTS1pbVU3OVFRa1dTVUVSazR2dHZuc2R5UnpUSnVPc3A0ZUhuWFVMSHJPOU51NkJ5bC1VeVprMzFvSnFGeGllM0pHQXlRLUM2OVF2NVFkVjFZV0hfVDkyTzk4d1hYZGMiLAogICAgICAgICAgICAia3R5IjogIlJTQSIsCiAgICAgICAgICAgICJxIjogInFIVnZBb3h0ckgxUTVza25veXNMMkhvbC1ubnU3ZlM3Mjg4clRGdE9jeG9Jb29nWXBKVTljemxwcjctSlo2bjc0TUViVHBBMHRkSUR5TEtQQ0xIN3JKTFRrZzBDZVZNQWpmY01zdkRUcWdFOHNBWE42bzd2ZjYya2hwcExYOHVCU3JxSHkyV1JhZXJsbDROU09hcmRGSkQ2MWhHSVF2cEpXRk4xazFTV3pWcyIsCiAgICAgICAgICAgICJkIjogIlp3elJsVklRZkg5ekZ6d1hOZ2hEMHhkZVctalBCbmRkWnJNZ0wwQ2JjeXZZYlg2X1c0ajlhM1dmYWpobmI2bTFILW9CWjRMczVmNXNRVTB2ZFJ2ZG1laFItUG43aWNRcUdURFNKUTYtdWVtNm15UVRWaEo2UmZiM0lINVJ2VDJTOXUzcVFDZWFadWN3aXFoZ1RCbFhnOWFfV0pwVHJYNFhPQ3JCR1ZsTng3Z2JETVJOamNEN0FnRkZ3S2p2TEZVdDRLTkZmdEJqaFF0TDFLQ2VwblNmamtvRm1RUTVlX3RSS2ozX2U1V3pNSkJkekpQejNkR2YxZEk3OF9wYmJFbmFMcWhqNWg0WUx2UU5JUUhVcURYSGx4ZDc1Qlh3aFJReE1nUDRfd1EwTFk2cVRKNGFDa2Q0RDJBTUtqMzJqeVFiVTRKTE9jQjFNMnZBRWFyc2NTU3l0USIsCiAgICAgICAgICAgICJlIjogIkFRQUIiLAogICAgICAgICAgICAidXNlIjogInNpZyIsCiAgICAgICAgICAgICJraWQiOiAiQy1FMW5DandnQkMtUHVHTTJPNDY3RlJEaEt4OEFrVmN0SVNBYm8zcmlldyIsCiAgICAgICAgICAgICJxaSI6ICJ0N2VOQjhQV21xVHdKREZLQlZKZExrZnJJT2drMFJ4MnREODBGNHB5cjhmNzRuNGlVWXFmWG1haVZtbGx2c2FlT3JlNHlIczQ4UE45NVZsZlVvS3Z6ZEJFaDNZTDFINGZTOGlYYXNzNGJiVnVuWHR4U0hMZFFPYUNZYUplSmhBbGMyUWQ4elR0NFFQWk9yRWVWLVJTYU0tN095ekkwUWtSSF9tcmk1YmRrOXMiLAogICAgICAgICAgICAiZHAiOiAiYnBLckQtVXhrRENDal81MFZLU0NFeE1Ec1Zob2VBZm1tNjMxb1o5aDhUTkZ4TUU1YVptbUJ2VzBJUG9wMm1PUF9qTW9FVWxfUG1RYUlBOEgtVEdqTFp2QTMxSlZBeFN3TU5aQzdwaVFPRjYzVnhneTZUTzlmb1hENVdndC1oLUNxU1N6T2V3eFdmUWNTMmpMcTA3NUFxOTYwTnA2SHhjbE8weUdRN1JDSlpjIiwKICAgICAgICAgICAgImFsZyI6ICJQUzI1NiIsCiAgICAgICAgICAgICJkcSI6ICJpdVZveGwwckFKSEM1c2JzbTZpZWQ3c2ZIVXIwS2Rja0hiVFBLb0lPU1BFcU5YaXBlT3BrWkdEdU55NWlDTXNyRnNHaDFrRW9kTkhZdE40ay1USm5KSDliV296SGdXbGloNnN2R1V0Zi1raFMxWC16ckxaMTJudzlyNDRBbjllWG54bjFaVXMxZm5OakltM3dtZ083algyTWxIeVlNVUZVd0RMd09xNEFPUWsiLAogICAgICAgICAgICAibiI6ICJvUmhjeUREdmp3NFZ4SHRRNTZhRDlNSmRTaWhWSk1nTHd1b2FCQVhhc0RjVDNEWVZjcENlVGxDMVBPdzdPNW1Ec2ZSWVFtcGpoendyRDVZWU8yeDE4REl4czdyNTNJdFMxRy1ybnQxQ1diVE9fUzFJT01DR2xxYzh5VWJnLUhSUkRETXQyb2V3TjJoRGtxYlBKVFJNbXpjRkpNMHRpTm1RZVVMcWViZEVYaWVUblJMT1BkMWg2ZmJycVNLS01mSXlIbGZ1WXFQc1VWSEdkMVBESGljZ3NMazFtZDhtYTNIS1hWM0hJdzZrdUV6R0hQb1gxNHo4YWF6RFFZWndUR3ZxVGlPLUdRUlVDZUJueVo4bVhyWnRmSjNqVk83UUhXcEx3MlM1VDVwVTRwcE0xQXppWTFxUDVfY3ZpOTNZT2Zrb09PalRTX3V3RENZWGFxWjB5bTJHYlEiCiAgICAgICAgfQogICAgXQp9Cg==" diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/jwt-route-filter.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/jwt-route-filter.yaml deleted file mode 100644 index 9ea3ee2acd..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/jwt-route-filter.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: consul.hashicorp.com/v1alpha1 -kind: RouteAuthFilter -metadata: - name: route-jwt-auth-filter -spec: - jwt: - providers: - - name: "local" - verifyClaims: - - path: - - role - value: doctor diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/kustomization.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/kustomization.yaml deleted file mode 100644 index 194fc16b6c..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink-ent/kustomization.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: -- ../../../bases/api-gateway -- ../../static-server-inject -- filters.yaml -- jwt-provider.yaml -- jwt-route-filter.yaml -- gateway-policy.yaml - - -patches: -- path: gatewayclassconfig.yaml -- path: httproute.yaml -- path: api-gateway.yaml diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/api-gateway.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/api-gateway.yaml deleted file mode 100644 index 3b59ada305..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/api-gateway.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: gateway.networking.k8s.io/v1beta1 -kind: Gateway -metadata: - name: gateway -spec: - gatewayClassName: gateway-class - listeners: - - protocol: HTTP - port: 80 - name: http - allowedRoutes: - namespaces: - from: "All" - - protocol: HTTPS - port: 443 - name: https - tls: - certificateRefs: - - name: "certificate" - allowedRoutes: - namespaces: - from: "All" diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/external-ref.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/external-ref.yaml deleted file mode 100644 index 57e6dfee7c..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/external-ref.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: consul.hashicorp.com/v1alpha1 -kind: RouteAuthFilter -metadata: - name: route-jwt-auth-filter - namespace: default -spec: - jwt: - providers: - - name: "local" - verifyClaims: - - path: - - role - value: doctor diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/filters.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/filters.yaml deleted file mode 100644 index 966eab85a6..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/filters.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: consul.hashicorp.com/v1alpha1 -kind: RouteRetryFilter -metadata: - name: retrytrafficfilter -spec: - numRetries: 1 - retryOnConnectFailure: false - retryOn: - - reset - - unavailable - retryOnStatusCodes: - - 500 - - 502 - ---- -apiVersion: consul.hashicorp.com/v1alpha1 -kind: RouteTimeoutFilter -metadata: - name: timeouttrafficfilter -spec: - requestTimeout: "1s" - idleTimeout: "1s" \ No newline at end of file diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/gateway-policy.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/gateway-policy.yaml deleted file mode 100644 index 5552d7e085..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/gateway-policy.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: consul.hashicorp.com/v1alpha1 -kind: GatewayPolicy -metadata: - name: my-policy -spec: - targetRef: - name: gateway - sectionName: http-auth - group: gateway.networking.k8s.io/v1beta1 - kind: Gateway - override: - jwt: - providers: - - name: "local" - default: - jwt: - providers: - - name: "local" - verifyClaims: - - path: - - role - value: pet diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/gatewayclassconfig.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/gatewayclassconfig.yaml deleted file mode 100644 index 42c9bee986..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/gatewayclassconfig.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: consul.hashicorp.com/v1alpha1 -kind: GatewayClassConfig -metadata: - name: gateway-class-config -spec: - deployment: - defaultInstances: 2 - maxInstances: 3 - minInstances: 1 \ No newline at end of file diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/httproute.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/httproute.yaml deleted file mode 100644 index 519b790a4d..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/httproute.yaml +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: gateway.networking.k8s.io/v1beta1 -kind: HTTPRoute -metadata: - name: http-route -spec: - parentRefs: - - name: gateway - sectionName: http - rules: - - matches: - - path: - type: PathPrefix - value: "/v1" - backendRefs: - - name: static-server - port: 8080 - filters: - - type: ExtensionRef - extensionRef: - group: consul.hashicorp.com - kind: RouteRetryFilter - name: retrytrafficfilter - - type: ExtensionRef - extensionRef: - group: consul.hashicorp.com - kind: RouteTimeoutFilter - name: timeouttrafficfilter - - type: RequestHeaderModifier - requestHeaderModifier: - add: - - name: my-header - value: foo - - type: URLRewrite - urlRewrite: - path: - type: "ReplacePrefixMatch" - replacePrefixMatch: "/v1/test" \ No newline at end of file diff --git a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/kustomization.yaml b/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/kustomization.yaml deleted file mode 100644 index 55a32c7260..0000000000 --- a/acceptance/tests/fixtures/cases/api-gateways/kitchen-sink/kustomization.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: -- ../../../bases/api-gateway -- ../../static-server-inject -- filters.yaml - - -patches: -- path: gatewayclassconfig.yaml -- path: httproute.yaml -- path: api-gateway.yaml diff --git a/acceptance/tests/mesh_v2/mesh_inject_test.go b/acceptance/tests/mesh_v2/mesh_inject_test.go index e44a2296af..d54229d84b 100644 --- a/acceptance/tests/mesh_v2/mesh_inject_test.go +++ b/acceptance/tests/mesh_v2/mesh_inject_test.go @@ -37,6 +37,7 @@ func TestMeshInject_MultiportService(t *testing.T) { helmValues := map[string]string{ "global.experiments[0]": "resource-apis", + "global.image": "ndhanushkodi/consul-dev:expose2", // The UI is not supported for v2 in 1.17, so for now it must be disabled. "ui.enabled": "false", "connectInject.enabled": "true", diff --git a/acceptance/tests/metrics/metrics_test.go b/acceptance/tests/metrics/metrics_test.go index ec2c4c48dc..ca80d38b75 100644 --- a/acceptance/tests/metrics/metrics_test.go +++ b/acceptance/tests/metrics/metrics_test.go @@ -133,7 +133,7 @@ func TestAppMetrics(t *testing.T) { // Retry because sometimes the merged metrics server takes a couple hundred milliseconds // to start. retry.RunWith(&retry.Counter{Count: 20, Wait: 2 * time.Second}, t, func(r *retry.R) { - metricsOutput, err := k8s.RunKubectlAndGetOutputE(r, ctx.KubectlOptions(r), "exec", "deploy/"+StaticClientName, "-c", "static-client", "--", "curl", "--silent", "--show-error", fmt.Sprintf("http://%s:20200/metrics", podIP)) + metricsOutput, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "exec", "deploy/"+StaticClientName, "-c", "static-client", "--", "curl", "--silent", "--show-error", fmt.Sprintf("http://%s:20200/metrics", podIP)) require.NoError(r, err) // This assertion represents the metrics from the envoy sidecar. require.Contains(r, metricsOutput, `envoy_cluster_assignment_stale{local_cluster="server",consul_source_service="server"`) diff --git a/acceptance/tests/partitions/main_test.go b/acceptance/tests/partitions/main_test.go index 8c4bd7e2a5..89833ec2cc 100644 --- a/acceptance/tests/partitions/main_test.go +++ b/acceptance/tests/partitions/main_test.go @@ -21,7 +21,7 @@ func TestMain(m *testing.M) { os.Exit(suite.Run()) } else { fmt.Println(fmt.Sprintf("Skipping partitions tests because either -enable-multi-cluster is "+ - "not set or the number of clusters, %d, did not match the expected count of %d", len(suite.Config().KubeEnvs), expectedNumberOfClusters)) + "not set or the number of clusters did not match the expected count of %d", expectedNumberOfClusters)) os.Exit(0) } } diff --git a/acceptance/tests/peering/peering_connect_namespaces_test.go b/acceptance/tests/peering/peering_connect_namespaces_test.go index 473e4976be..0fee651f2a 100644 --- a/acceptance/tests/peering/peering_connect_namespaces_test.go +++ b/acceptance/tests/peering/peering_connect_namespaces_test.go @@ -220,7 +220,7 @@ func TestPeering_ConnectNamespaces(t *testing.T) { // Ensure the secret is created. retry.RunWith(timer, t, func(r *retry.R) { - acceptorSecretName, err := k8s.RunKubectlAndGetOutputE(r, staticClientPeerClusterContext.KubectlOptions(r), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.name}") + acceptorSecretName, err := k8s.RunKubectlAndGetOutputE(t, staticClientPeerClusterContext.KubectlOptions(t), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.name}") require.NoError(r, err) require.NotEmpty(r, acceptorSecretName) }) diff --git a/acceptance/tests/peering/peering_connect_test.go b/acceptance/tests/peering/peering_connect_test.go index 6bab0aa909..71233331a2 100644 --- a/acceptance/tests/peering/peering_connect_test.go +++ b/acceptance/tests/peering/peering_connect_test.go @@ -187,7 +187,7 @@ func TestPeering_Connect(t *testing.T) { // Ensure the secret is created. retry.RunWith(timer, t, func(r *retry.R) { - acceptorSecretName, err := k8s.RunKubectlAndGetOutputE(r, staticClientPeerClusterContext.KubectlOptions(r), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.name}") + acceptorSecretName, err := k8s.RunKubectlAndGetOutputE(t, staticClientPeerClusterContext.KubectlOptions(t), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.name}") require.NoError(r, err) require.NotEmpty(r, acceptorSecretName) }) diff --git a/acceptance/tests/peering/peering_gateway_test.go b/acceptance/tests/peering/peering_gateway_test.go index 421db98c71..b22904357f 100644 --- a/acceptance/tests/peering/peering_gateway_test.go +++ b/acceptance/tests/peering/peering_gateway_test.go @@ -167,7 +167,7 @@ func TestPeering_Gateway(t *testing.T) { // Ensure the secret is created. retry.RunWith(timer, t, func(r *retry.R) { - acceptorSecretName, err := k8s.RunKubectlAndGetOutputE(r, staticClientPeerClusterContext.KubectlOptions(r), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.name}") + acceptorSecretName, err := k8s.RunKubectlAndGetOutputE(t, staticClientPeerClusterContext.KubectlOptions(t), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.name}") require.NoError(r, err) require.NotEmpty(r, acceptorSecretName) }) diff --git a/acceptance/tests/sameness/sameness_test.go b/acceptance/tests/sameness/sameness_test.go index e00502463e..3580ead6e6 100644 --- a/acceptance/tests/sameness/sameness_test.go +++ b/acceptance/tests/sameness/sameness_test.go @@ -20,7 +20,6 @@ import ( "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/logger" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -646,7 +645,7 @@ func (c *cluster) serviceTargetCheck(t *testing.T, expectedName string, curlAddr retry.RunWith(timer, t, func(r *retry.R) { // Use -s/--silent and -S/--show-error flags w/ curl to reduce noise during retries. // This silences extra output like the request progress bar, but preserves errors. - resp, err = k8s.RunKubectlAndGetOutputE(r, c.clientOpts, "exec", "-i", + resp, err = k8s.RunKubectlAndGetOutputE(t, c.clientOpts, "exec", "-i", staticClientDeployment, "-c", staticClientName, "--", "curl", "-sS", curlAddress) require.NoError(r, err) assert.Contains(r, resp, expectedName) @@ -672,7 +671,7 @@ func (c *cluster) preparedQueryFailoverCheck(t *testing.T, releaseName string, e // that failover occurred, that is left to client `Execute` dnsPQLookup := []string{fmt.Sprintf("%s.query.consul", *c.pqName)} retry.RunWith(timer, t, func(r *retry.R) { - logs := dnsQuery(r, releaseName, dnsPQLookup, c.primaryCluster, failover) + logs := dnsQuery(t, releaseName, dnsPQLookup, c.primaryCluster, failover) assert.Contains(r, logs, fmt.Sprintf("SERVER: %s", *c.primaryCluster.dnsIP)) assert.Contains(r, logs, "ANSWER SECTION:") assert.Contains(r, logs, *failover.staticServerIP) @@ -686,7 +685,7 @@ func (c *cluster) dnsFailoverCheck(t *testing.T, cfg *config.TestConfig, release retry.RunWith(timer, t, func(r *retry.R) { // Use the primary cluster when performing a DNS lookup, this mostly affects cases // where we are verifying DNS for a partition - logs := dnsQuery(r, releaseName, dnsLookup, c.primaryCluster, failover) + logs := dnsQuery(t, releaseName, dnsLookup, c.primaryCluster, failover) assert.Contains(r, logs, fmt.Sprintf("SERVER: %s", *c.primaryCluster.dnsIP)) assert.Contains(r, logs, "ANSWER SECTION:") @@ -697,7 +696,7 @@ func (c *cluster) dnsFailoverCheck(t *testing.T, cfg *config.TestConfig, release // the context can be used to determine that failover occured to the expected kubernetes cluster // hosting Consul assert.Contains(r, logs, "ADDITIONAL SECTION:") - expectedName := failover.context.KubectlOptions(r).ContextName + expectedName := failover.context.KubectlOptions(t).ContextName if cfg.UseKind { expectedName = strings.Replace(expectedName, "kind-", "", -1) } @@ -712,7 +711,7 @@ func (c *cluster) getPeeringAcceptorSecret(t *testing.T, cfg *config.TestConfig, timer := &retry.Timer{Timeout: retryTimeout, Wait: 1 * time.Second} retry.RunWith(timer, t, func(r *retry.R) { var err error - acceptorSecretName, err = k8s.RunKubectlAndGetOutputE(r, c.context.KubectlOptions(r), "get", "peeringacceptor", acceptorName, "-o", "jsonpath={.status.secret.name}") + acceptorSecretName, err = k8s.RunKubectlAndGetOutputE(t, c.context.KubectlOptions(t), "get", "peeringacceptor", acceptorName, "-o", "jsonpath={.status.secret.name}") require.NoError(r, err) require.NotEmpty(r, acceptorSecretName) }) @@ -830,17 +829,16 @@ func setK8sNodeLocality(t *testing.T, context environment.TestContext, c *cluste } // dnsQuery performs a dns query with the provided query string. -func dnsQuery(t testutil.TestingTB, releaseName string, dnsQuery []string, dnsServer, failover *cluster) string { +func dnsQuery(t *testing.T, releaseName string, dnsQuery []string, dnsServer, failover *cluster) string { timer := &retry.Timer{Timeout: retryTimeout, Wait: 1 * time.Second} var logs string - retry.RunWith(timer, t, func(r *retry.R) { args := []string{"exec", "-i", staticClientDeployment, "-c", staticClientName, "--", "dig", fmt.Sprintf("@%s-consul-dns.default", releaseName)} args = append(args, dnsQuery...) var err error - logs, err = k8s.RunKubectlAndGetOutputE(r, dnsServer.clientOpts, args...) + logs, err = k8s.RunKubectlAndGetOutputE(t, dnsServer.clientOpts, args...) require.NoError(r, err) }) logger.Logf(t, "%s: %s", failover.name, logs) diff --git a/acceptance/tests/server/main_test.go b/acceptance/tests/server/main_test.go deleted file mode 100644 index 497df9dca2..0000000000 --- a/acceptance/tests/server/main_test.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package server - -import ( - "os" - "testing" - - testsuite "github.com/hashicorp/consul-k8s/acceptance/framework/suite" -) - -var suite testsuite.Suite - -func TestMain(m *testing.M) { - suite = testsuite.NewSuite(m) - os.Exit(suite.Run()) -} diff --git a/acceptance/tests/server/server_test.go b/acceptance/tests/server/server_test.go deleted file mode 100644 index 5511671935..0000000000 --- a/acceptance/tests/server/server_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package server - -import ( - "encoding/json" - "fmt" - "testing" - "time" - - "github.com/hashicorp/consul-k8s/acceptance/framework/consul" - "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" - "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" - "github.com/hashicorp/consul-k8s/acceptance/framework/logger" - "github.com/hashicorp/go-multierror" - "github.com/stretchr/testify/require" -) - -// Test that when servers are restarted, they don't lose leadership. -func TestServerRestart(t *testing.T) { - cfg := suite.Config() - if cfg.EnableCNI || cfg.EnableTransparentProxy { - t.Skipf("skipping because -enable-cni or -enable-transparent-proxy is set and server restart " + - "is already tested without those settings and those settings don't affect this test") - } - - ctx := suite.Environment().DefaultContext(t) - replicas := 3 - releaseName := helpers.RandomName() - helmValues := map[string]string{ - "global.enabled": "false", - "connectInject.enabled": "false", - "server.enabled": "true", - "server.replicas": fmt.Sprintf("%d", replicas), - "server.affinity": "null", // Allow >1 pods per node so we can test in minikube with one node. - } - consulCluster := consul.NewHelmCluster(t, helmValues, suite.Environment().DefaultContext(t), suite.Config(), releaseName) - consulCluster.Create(t) - - // Start a separate goroutine to check if at any point more than one server is without - // a leader. We expect the server that is restarting to be without a leader because it hasn't - // yet joined the cluster but the other servers should have a leader. - expReadyPods := replicas - 1 - var unmarshallErrs error - timesWithoutLeader := 0 - done := make(chan bool) - defer close(done) - go func() { - for { - select { - case <-done: - return - default: - out, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "get", fmt.Sprintf("statefulset/%s-consul-server", releaseName), - "-o", "jsonpath={.status}") - if err != nil { - // Not failing the test on this error to reduce flakiness. - logger.Logf(t, "kubectl err: %s: %s", err, out) - break - } - type statefulsetOut struct { - ReadyReplicas *int `json:"readyReplicas,omitempty"` - } - var jsonOut statefulsetOut - if err = json.Unmarshal([]byte(out), &jsonOut); err != nil { - unmarshallErrs = multierror.Append(err) - } else if jsonOut.ReadyReplicas == nil || *jsonOut.ReadyReplicas < expReadyPods { - // note: for some k8s api reason when readyReplicas is 0 it's not included in the json output so - // that's why we're checking if it's nil. - timesWithoutLeader++ - } - time.Sleep(1 * time.Second) - } - } - }() - - // Restart servers - out, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "rollout", "restart", fmt.Sprintf("statefulset/%s-consul-server", releaseName)) - require.NoError(t, err, out) - - // Wait for restart to finish. - start := time.Now() - out, err = k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "rollout", "status", "--timeout", "5m", "--watch", fmt.Sprintf("statefulset/%s-consul-server", releaseName)) - require.NoError(t, err, out, "rollout status command errored, this likely means the rollout didn't complete in time") - - // Check results - require.NoError(t, unmarshallErrs, "there were some json unmarshall errors, this is likely a bug") - logger.Logf(t, "restart took %s, there were %d instances where more than one server had no leader", time.Since(start), timesWithoutLeader) - require.Equal(t, 0, timesWithoutLeader, "there were %d instances where more than one server had no leader", timesWithoutLeader) -} diff --git a/acceptance/tests/snapshot-agent/snapshot_agent_k8s_secret_test.go b/acceptance/tests/snapshot-agent/snapshot_agent_k8s_secret_test.go index e5f1e785af..b5613fe76d 100644 --- a/acceptance/tests/snapshot-agent/snapshot_agent_k8s_secret_test.go +++ b/acceptance/tests/snapshot-agent/snapshot_agent_k8s_secret_test.go @@ -91,9 +91,9 @@ func TestSnapshotAgent_K8sSecret(t *testing.T) { retry.RunWith(timer, t, func(r *retry.R) { // Loop through snapshot agents. Only one will be the leader and have the snapshot files. pod := podList.Items[0] - snapshotFileListOutput, err := k8s.RunKubectlAndGetOutputWithLoggerE(r, kubectlOptions, terratestLogger.Discard, "exec", pod.Name, "-c", "consul-snapshot-agent", "--", "ls", "/tmp") + snapshotFileListOutput, err := k8s.RunKubectlAndGetOutputWithLoggerE(t, kubectlOptions, terratestLogger.Discard, "exec", pod.Name, "-c", "consul-snapshot-agent", "--", "ls", "/tmp") require.NoError(r, err) - logger.Logf(r, "Snapshot: \n%s", snapshotFileListOutput) + logger.Logf(t, "Snapshot: \n%s", snapshotFileListOutput) require.Contains(r, snapshotFileListOutput, ".snap", "Agent pod does not contain snapshot files") }) }) diff --git a/acceptance/tests/snapshot-agent/snapshot_agent_vault_test.go b/acceptance/tests/snapshot-agent/snapshot_agent_vault_test.go index 3c4354547c..10cceb5952 100644 --- a/acceptance/tests/snapshot-agent/snapshot_agent_vault_test.go +++ b/acceptance/tests/snapshot-agent/snapshot_agent_vault_test.go @@ -213,9 +213,9 @@ func TestSnapshotAgent_Vault(t *testing.T) { retry.RunWith(timer, t, func(r *retry.R) { // Loop through snapshot agents. Only one will be the leader and have the snapshot files. pod := podList.Items[0] - snapshotFileListOutput, err := k8s.RunKubectlAndGetOutputWithLoggerE(r, kubectlOptions, terratestLogger.Discard, "exec", pod.Name, "-c", "consul-snapshot-agent", "--", "ls", "/tmp") + snapshotFileListOutput, err := k8s.RunKubectlAndGetOutputWithLoggerE(t, kubectlOptions, terratestLogger.Discard, "exec", pod.Name, "-c", "consul-snapshot-agent", "--", "ls", "/tmp") require.NoError(r, err) - logger.Logf(r, "Snapshot: \n%s", snapshotFileListOutput) + logger.Logf(t, "Snapshot: \n%s", snapshotFileListOutput) require.Contains(r, snapshotFileListOutput, ".snap", "Agent pod does not contain snapshot files") }) } diff --git a/acceptance/tests/sync/sync_catalog_test.go b/acceptance/tests/sync/sync_catalog_test.go index 4bd5f91039..dc30570422 100644 --- a/acceptance/tests/sync/sync_catalog_test.go +++ b/acceptance/tests/sync/sync_catalog_test.go @@ -118,12 +118,12 @@ func TestSyncCatalogWithIngress(t *testing.T) { // Retry the kubectl apply because we've seen sporadic // "connection refused" errors where the mutating webhook // endpoint fails initially. - out, err := k8s.RunKubectlAndGetOutputE(r, ctx.KubectlOptions(r), "apply", "-k", "../fixtures/bases/ingress") + out, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "apply", "-k", "../fixtures/bases/ingress") require.NoError(r, err, out) - helpers.Cleanup(r, cfg.NoCleanupOnFailure, cfg.NoCleanup, func() { + helpers.Cleanup(t, cfg.NoCleanupOnFailure, cfg.NoCleanup, func() { // Ignore errors here because if the test ran as expected // the custom resources will have been deleted. - k8s.RunKubectlAndGetOutputE(r, ctx.KubectlOptions(r), "delete", "-k", "../fixtures/bases/ingress") + k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "delete", "-k", "../fixtures/bases/ingress") }) }) diff --git a/acceptance/tests/tenancy_v2/main_test.go b/acceptance/tests/tenancy_v2/main_test.go deleted file mode 100644 index 1766d95319..0000000000 --- a/acceptance/tests/tenancy_v2/main_test.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package tenancy_v2 - -import ( - "fmt" - "os" - "testing" - - testsuite "github.com/hashicorp/consul-k8s/acceptance/framework/suite" -) - -var suite testsuite.Suite - -func TestMain(m *testing.M) { - suite = testsuite.NewSuite(m) - - expectedNumberOfClusters := 1 - if suite.Config().IsExpectedClusterCount(expectedNumberOfClusters) { - os.Exit(suite.Run()) - } else { - fmt.Printf( - "Skipping tenancy_v2 tests because the number of clusters, %d, did not match the expected count of %d\n", - len(suite.Config().KubeEnvs), - expectedNumberOfClusters, - ) - os.Exit(0) - } -} diff --git a/acceptance/tests/tenancy_v2/namespace_test.go b/acceptance/tests/tenancy_v2/namespace_test.go deleted file mode 100644 index cb19565472..0000000000 --- a/acceptance/tests/tenancy_v2/namespace_test.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package tenancy_v2 - -import ( - "testing" - - "github.com/hashicorp/consul-k8s/acceptance/framework/consul" - "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" - "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" - "github.com/hashicorp/consul-k8s/acceptance/framework/logger" - "github.com/hashicorp/consul-k8s/acceptance/framework/resource" - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" -) - -// TestTenancy_Namespace_Mirrored tests consul namespaces are created/deleted -// to mirror k8s namespaces in the default partition. -func TestTenancy_Namespace_Mirrored(t *testing.T) { - cfg := suite.Config() - cfg.SkipWhenCNI(t) - ctx := suite.Environment().DefaultContext(t) - - serverHelmValues := map[string]string{ - "server.enabled": "true", - "global.experiments[0]": "resource-apis", - "global.experiments[1]": "v2tenancy", - // The UI is not supported for v2 in 1.17, so for now it must be disabled. - "ui.enabled": "false", - } - - serverReleaseName := helpers.RandomName() - serverCluster := consul.NewHelmCluster(t, serverHelmValues, ctx, cfg, serverReleaseName) - serverCluster.Create(t) - - logger.Log(t, "creating namespace ns1 in k8s") - k8s.RunKubectl(t, ctx.KubectlOptions(t), "create", "namespace", "ns1") - - logger.Log(t, "waiting for namespace ns1 to be created in consul") - serverResourceClient := serverCluster.ResourceClient(t, false) - rtest := resource.NewResourceTester(serverResourceClient) - rtest.WaitForResourceExists(t, &pbresource.ID{ - Name: "ns1", - Type: pbtenancy.NamespaceType, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - }, - }) - - logger.Log(t, "deleting namespace ns1 in k8s") - k8s.RunKubectl(t, ctx.KubectlOptions(t), "delete", "namespace", "ns1") - - logger.Log(t, "waiting for namespace ns1 to be deleted in consul") - rtest.WaitForResourceNotFound(t, &pbresource.ID{ - Name: "ns1", - Type: pbtenancy.NamespaceType, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - }, - }) -} diff --git a/acceptance/tests/tenancy_v2/partition_test.go b/acceptance/tests/tenancy_v2/partition_test.go deleted file mode 100644 index 8ad031c8fe..0000000000 --- a/acceptance/tests/tenancy_v2/partition_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package tenancy_v2 - -import ( - "context" - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul-k8s/acceptance/framework/consul" - "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" -) - -// TestTenancy_Partition_Created tests that V2 partitions are created when requested -// by a consul client external to the consul server cluster's k8s cluster. -// -// It sets up an external Consul server in the same cluster but a different Helm installation -// and then treats this server as external. -func TestTenancy_Partition_Created(t *testing.T) { - // Given a single k8s kind cluster - // Where helm "server" release hosts a consul server cluster (server.enabled=true) - // And helm "client" release hosts a consul client cluster (server.enabled=false) - // And both releases have experiments "resource-apis" and "v2tenancy enabled" - // And helm "client" release is configured to point to the helm "server" release as an external server (externalServer.enabled=true) - // And helm "client" release has admin partitions enabled with name "ap1" (global.adminPartitions.name=ap1) - // And helm "server" release is open for business - // When helm "client" release is installed - // Then partition "ap1" is created by the partition-init job in the helm "client" release - - // We're skipping ACLs for now because they're not supported in v2. - cfg := suite.Config() - // Requires connnectInject.enabled which we disable below. - cfg.SkipWhenCNI(t) - ctx := suite.Environment().DefaultContext(t) - - serverHelmValues := map[string]string{ - "server.enabled": "true", - "global.experiments[0]": "resource-apis", - "global.experiments[1]": "v2tenancy", - "global.adminPartitions.enabled": "false", - "global.enableConsulNamespaces": "true", - - // Don't install injector, controller and cni on this k8s cluster so that it's not installed twice. - "connectInject.enabled": "false", - - // The UI is not supported for v2 in 1.17, so for now it must be disabled. - "ui.enabled": "false", - } - - serverReleaseName := helpers.RandomName() - serverCluster := consul.NewHelmCluster(t, serverHelmValues, ctx, cfg, serverReleaseName) - serverCluster.Create(t) - - clientHelmValues := map[string]string{ - "server.enabled": "false", - "global.experiments[0]": "resource-apis", - "global.experiments[1]": "v2tenancy", - "global.adminPartitions.enabled": "true", - "global.adminPartitions.name": "ap1", - "global.enableConsulNamespaces": "true", - "externalServers.enabled": "true", - "externalServers.hosts[0]": fmt.Sprintf("%s-consul-server", serverReleaseName), - - // This needs to be set to true otherwise the pods never materialize - "connectInject.enabled": "true", - - // The UI is not supported for v2 in 1.17, so for now it must be disabled. - "ui.enabled": "false", - } - - clientReleaseName := helpers.RandomName() - clientCluster := consul.NewHelmCluster(t, clientHelmValues, ctx, cfg, clientReleaseName) - clientCluster.SkipCheckForPreviousInstallations = true - - clientCluster.Create(t) - - // verify partition ap1 created by partition init job - serverResourceClient := serverCluster.ResourceClient(t, false) - _, err := serverResourceClient.Read(context.Background(), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Name: "ap1", - Type: pbtenancy.PartitionType, - }, - }) - require.NoError(t, err, "expected partition ap1 to be created by partition init job") -} diff --git a/acceptance/tests/vault/vault_wan_fed_test.go b/acceptance/tests/vault/vault_wan_fed_test.go index e8ae7ba70b..fa63c4d5fb 100644 --- a/acceptance/tests/vault/vault_wan_fed_test.go +++ b/acceptance/tests/vault/vault_wan_fed_test.go @@ -329,8 +329,8 @@ func TestVault_WANFederationViaGateways(t *testing.T) { } srvCAAuthRoleConfigSecondary.ConfigureK8SAuthRole(t, vaultClient) - // Move Vault CA secret from primary to secondary so that we can mount it to pods in the - // secondary cluster. + // // Move Vault CA secret from primary to secondary so that we can mount it to pods in the + // // secondary cluster. vaultCASecretName := vault.CASecretName(vaultReleaseName) logger.Logf(t, "retrieving Vault CA secret %s from the primary cluster and applying to the secondary", vaultCASecretName) vaultCASecret, err := primaryCtx.KubernetesClient(t).CoreV1().Secrets(ns).Get(context.Background(), vaultCASecretName, metav1.GetOptions{}) diff --git a/acceptance/tests/wan-federation/wan_federation_test.go b/acceptance/tests/wan-federation/wan_federation_test.go index 62567ea561..9ca520ab06 100644 --- a/acceptance/tests/wan-federation/wan_federation_test.go +++ b/acceptance/tests/wan-federation/wan_federation_test.go @@ -426,7 +426,7 @@ func serviceFailoverCheck(t *testing.T, options *terratestK8s.KubectlOptions, po // Retry until we get the response we expect, sometimes you get back the previous server until things stabalize logger.Log(t, "Initial failover check") retry.RunWith(timer, t, func(r *retry.R) { - resp, err = k8s.RunKubectlAndGetOutputE(r, options, "exec", "-i", + resp, err = k8s.RunKubectlAndGetOutputE(t, options, "exec", "-i", staticClientDeployment, "-c", connhelper.StaticClientName, "--", "curl", fmt.Sprintf("localhost:%s", port)) assert.NoError(r, err) assert.Contains(r, resp, expectedName) @@ -438,7 +438,7 @@ func serviceFailoverCheck(t *testing.T, options *terratestK8s.KubectlOptions, po time.Sleep(500 * time.Millisecond) resp = "" retry.RunWith(timer, t, func(r *retry.R) { - resp, err = k8s.RunKubectlAndGetOutputE(r, options, "exec", "-i", + resp, err = k8s.RunKubectlAndGetOutputE(t, options, "exec", "-i", staticClientDeployment, "-c", connhelper.StaticClientName, "--", "curl", fmt.Sprintf("localhost:%s", port)) assert.NoError(r, err) }) diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index d74a42ba95..b6248a139c 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -3,8 +3,8 @@ apiVersion: v2 name: consul -version: 1.5.0-dev -appVersion: 1.19-dev +version: 1.3.4-dev +appVersion: 1.17-dev kubeVersion: ">=1.22.0-0" description: Official HashiCorp Consul Chart home: https://www.consul.io @@ -16,11 +16,11 @@ annotations: artifacthub.io/prerelease: true artifacthub.io/images: | - name: consul - image: docker.mirror.hashicorp.services/hashicorppreview/consul:1.19-dev + image: docker.mirror.hashicorp.services/hashicorppreview/consul:1.17-dev - name: consul-k8s-control-plane - image: docker.mirror.hashicorp.services/hashicorppreview/consul-k8s-control-plane:1.5-dev + image: docker.mirror.hashicorp.services/hashicorppreview/consul-k8s-control-plane:1.3.4-dev - name: consul-dataplane - image: docker.mirror.hashicorp.services/hashicorppreview/consul-dataplane:1.5-dev + image: docker.mirror.hashicorp.services/hashicorppreview/consul-dataplane:1.3-dev - name: envoy image: envoyproxy/envoy:v1.25.11 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/README.md b/charts/consul/README.md index a0a9929ed4..e7d7fd9285 100644 --- a/charts/consul/README.md +++ b/charts/consul/README.md @@ -42,7 +42,7 @@ by contacting us at [security@hashicorp.com](mailto:security@hashicorp.com). The following pre-requisites must be met before installing Consul on Kubernetes. - * **Kubernetes 1.26.x - 1.29.x** - This represents the earliest versions of Kubernetes tested. + * **Kubernetes 1.23.x - 1.26.x** - This represents the earliest versions of Kubernetes tested. It is possible that this chart works with earlier versions, but it is untested. * Helm install diff --git a/charts/consul/templates/_helpers.tpl b/charts/consul/templates/_helpers.tpl index ca87485a78..bb2da193fc 100644 --- a/charts/consul/templates/_helpers.tpl +++ b/charts/consul/templates/_helpers.tpl @@ -189,27 +189,24 @@ Expand the name of the chart. {{- end -}} {{/* -Calculate max number of server pods that are allowed to be voluntarily disrupted. -When there's 1 server, this is set to 0 because this pod should not be disrupted. This is an edge -case and I'm not sure it makes a difference when there's only one server but that's what the previous config was and -I don't want to change it for this edge case. -Otherwise we've changed this to always be 1 as part of the move to set leave_on_terminate -to true. With leave_on_terminate set to true, whenever a server pod is stopped, the number of peers in raft -is reduced. If the number of servers is odd and the count is reduced by 1, the quorum size doesn't change, -but if it's reduced by more than 1, the quorum size can change so that's why this is now always hardcoded to 1. +Compute the maximum number of unavailable replicas for the PodDisruptionBudget. +This defaults to (n/2)-1 where n is the number of members of the server cluster. +Special case of replica equaling 3 and allowing a minor disruption of 1 otherwise +use the integer value +Add a special case for replicas=1, where it should default to 0 as well. */}} -{{- define "consul.server.pdb.maxUnavailable" -}} +{{- define "consul.pdb.maxUnavailable" -}} {{- if eq (int .Values.server.replicas) 1 -}} {{ 0 }} {{- else if .Values.server.disruptionBudget.maxUnavailable -}} {{ .Values.server.disruptionBudget.maxUnavailable -}} {{- else -}} -{{ 1 }} +{{- if eq (int .Values.server.replicas) 3 -}} +{{- 1 -}} +{{- else -}} +{{- sub (div (int .Values.server.replicas) 2) 1 -}} {{- end -}} {{- end -}} - -{{- define "consul.server.autopilotMinQuorum" -}} -{{- add (div (int .Values.server.replicas) 2) 1 -}} {{- end -}} {{- define "consul.pdb.connectInject.maxUnavailable" -}} @@ -451,10 +448,10 @@ Usage: {{ template "consul.validateTelemetryCollectorCloud" . }} */}} {{- define "consul.validateTelemetryCollectorCloud" -}} {{- if (and .Values.telemetryCollector.cloud.clientId.secretName (and (not .Values.global.cloud.clientSecret.secretName) (not .Values.telemetryCollector.cloud.clientSecret.secretName))) }} -{{fail "When telemetryCollector.cloud.clientId.secretName is set, telemetryCollector.cloud.clientSecret.secretName must also be set." }} +{{fail "When telemetryCollector.cloud.clientId.secretName is set, telemetryCollector.cloud.clientSecret.secretName must also be set."}} {{- end }} {{- if (and .Values.telemetryCollector.cloud.clientSecret.secretName (and (not .Values.global.cloud.clientId.secretName) (not .Values.telemetryCollector.cloud.clientId.secretName))) }} -{{fail "When telemetryCollector.cloud.clientSecret.secretName is set, telemetryCollector.cloud.clientId.secretName must also be set." }} +{{fail "When telemetryCollector.cloud.clientSecret.secretName is set, telemetryCollector.cloud.clientId.secretName must also be set."}} {{- end }} {{- end }} @@ -514,8 +511,8 @@ Usage: {{ template "consul.validateResourceAPIs" . }} {{- if (and (mustHas "resource-apis" .Values.global.experiments) .Values.global.peering.enabled ) }} {{fail "When the value global.experiments.resourceAPIs is set, global.peering.enabled is currently unsupported."}} {{- end }} -{{- if (and (mustHas "resource-apis" .Values.global.experiments) (not (mustHas "v2tenancy" .Values.global.experiments)) .Values.global.adminPartitions.enabled ) }} -{{fail "When the value global.experiments.resourceAPIs is set, global.experiments.v2tenancy must also be set to support global.adminPartitions.enabled."}} +{{- if (and (mustHas "resource-apis" .Values.global.experiments) .Values.global.adminPartitions.enabled ) }} +{{fail "When the value global.experiments.resourceAPIs is set, global.adminPartitions.enabled is currently unsupported."}} {{- end }} {{- if (and (mustHas "resource-apis" .Values.global.experiments) .Values.global.federation.enabled ) }} {{fail "When the value global.experiments.resourceAPIs is set, global.federation.enabled is currently unsupported."}} @@ -532,6 +529,9 @@ Usage: {{ template "consul.validateResourceAPIs" . }} {{- if (and (mustHas "resource-apis" .Values.global.experiments) .Values.syncCatalog.enabled ) }} {{fail "When the value global.experiments.resourceAPIs is set, syncCatalog.enabled is currently unsupported."}} {{- end }} +{{- if (and (mustHas "resource-apis" .Values.global.experiments) .Values.meshGateway.enabled ) }} +{{fail "When the value global.experiments.resourceAPIs is set, meshGateway.enabled is currently unsupported."}} +{{- end }} {{- if (and (mustHas "resource-apis" .Values.global.experiments) .Values.ingressGateways.enabled ) }} {{fail "When the value global.experiments.resourceAPIs is set, ingressGateways.enabled is currently unsupported."}} {{- end }} diff --git a/charts/consul/templates/connect-inject-clusterrole.yaml b/charts/consul/templates/connect-inject-clusterrole.yaml index be816ff391..2506637949 100644 --- a/charts/consul/templates/connect-inject-clusterrole.yaml +++ b/charts/consul/templates/connect-inject-clusterrole.yaml @@ -96,13 +96,8 @@ rules: - apiGroups: - mesh.consul.hashicorp.com resources: - - gatewayclassconfigs - - gatewayclasses - - meshconfigurations - grpcroutes - httproutes - - meshgateways - - apigateways - tcproutes - proxyconfigurations verbs: @@ -116,43 +111,14 @@ rules: - apiGroups: - mesh.consul.hashicorp.com resources: - - gatewayclassconfigs/status - - gatewayclasses/status - - meshconfigurations/status - grpcroutes/status - httproutes/status - - meshgateways/status - - apigateways/status - tcproutes/status - proxyconfigurations/status verbs: - get - patch - update -- apiGroups: - - multicluster.consul.hashicorp.com - resources: - - exportedservices - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - multicluster.consul.hashicorp.com - resources: - - exportedservices/status - verbs: - - create - - delete - - get - - list - - patch - - update - - watch {{- end }} - apiGroups: [ "" ] resources: [ "secrets", "serviceaccounts", "endpoints", "services", "namespaces", "nodes" ] diff --git a/charts/consul/templates/connect-inject-deployment.yaml b/charts/consul/templates/connect-inject-deployment.yaml index 1565e92811..13c69e83a2 100644 --- a/charts/consul/templates/connect-inject-deployment.yaml +++ b/charts/consul/templates/connect-inject-deployment.yaml @@ -157,9 +157,6 @@ spec: {{- if (mustHas "resource-apis" .Values.global.experiments) }} -enable-resource-apis=true \ {{- end }} - {{- if (mustHas "v2tenancy" .Values.global.experiments) }} - -enable-v2tenancy=true \ - {{- end }} {{- range $k, $v := .Values.connectInject.consulNode.meta }} -node-meta={{ $k }}={{ $v }} \ {{- end }} diff --git a/charts/consul/templates/crd-apigateways.yaml b/charts/consul/templates/crd-apigateways.yaml deleted file mode 100644 index a01d40c027..0000000000 --- a/charts/consul/templates/crd-apigateways.yaml +++ /dev/null @@ -1,302 +0,0 @@ -{{- if .Values.connectInject.enabled }} -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - app: {{ template "consul.name" . }} - chart: {{ template "consul.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - component: crd - name: apigateways.mesh.consul.hashicorp.com -spec: - group: mesh.consul.hashicorp.com - names: - kind: APIGateway - listKind: APIGatewayList - plural: apigateways - singular: apigateway - scope: Cluster - versions: - - additionalPrinterColumns: - - description: The sync status of the resource with Consul - jsonPath: .status.conditions[?(@.type=="Synced")].status - name: Synced - type: string - - description: The last successful synced time of the resource with Consul - jsonPath: .status.lastSyncedTime - name: Last Synced - type: date - - description: The age of the resource - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2beta1 - schema: - openAPIV3Schema: - description: APIGateway is the Schema for the API Gateway - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - gatewayClassName: - description: GatewayClassName is the name of the GatewayClass used - by the APIGateway - type: string - listeners: - items: - properties: - hostname: - description: Hostname is the host name that a listener should - be bound to, if unspecified, the listener accepts requests - for all hostnames. - type: string - name: - description: Name is the name of the listener in a given gateway. - This must be unique within a gateway. - type: string - port: - format: int32 - maximum: 65535 - minimum: 0 - type: integer - protocol: - description: Protocol is the protocol that a listener should - use, it must either be "http" or "tcp" - type: string - tls: - description: TLS is the TLS settings for the listener. - properties: - certificates: - description: Certificates is a set of references to certificates - that a gateway listener uses for TLS termination. - items: - description: Reference identifies which resource a condition - relates to, when it is not the core resource itself. - properties: - name: - description: Name is the user-given name of the resource - (e.g. the "billing" service). - type: string - section: - description: Section identifies which part of the - resource the condition relates to. - type: string - tenancy: - description: Tenancy identifies the tenancy units - (i.e. partition, namespace) in which the resource - resides. - properties: - namespace: - description: "Namespace further isolates resources - within a partition. https://developer.hashicorp.com/consul/docs/enterprise/namespaces - \n When using the List and WatchList endpoints, - provide the wildcard value \"*\" to list resources - across all namespaces." - type: string - partition: - description: "Partition is the topmost administrative - boundary within a cluster. https://developer.hashicorp.com/consul/docs/enterprise/admin-partitions - \n When using the List and WatchList endpoints, - provide the wildcard value \"*\" to list resources - across all partitions." - type: string - type: object - type: - description: Type identifies the resource's type. - properties: - group: - description: Group describes the area of functionality - to which this resource type relates (e.g. "catalog", - "authorization"). - type: string - groupVersion: - description: GroupVersion is incremented when - sweeping or backward-incompatible changes are - made to the group's resource types. - type: string - kind: - description: Kind identifies the specific resource - type within the group. - type: string - type: object - type: object - type: array - tlsParameters: - description: TLSParameters contains optional configuration - for running TLS termination. - properties: - cipherSuites: - items: - enum: - - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256 - - TLS_CIPHER_SUITE_AES256_SHA - - TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305 - - TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256 - - TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305 - - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA - - TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA - - TLS_CIPHER_SUITE_AES128_GCM_SHA256 - - TLS_CIPHER_SUITE_AES128_SHA - - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384 - - TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384 - - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA - - TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA - - TLS_CIPHER_SUITE_AES256_GCM_SHA384 - format: int32 - type: string - type: array - maxVersion: - enum: - - TLS_VERSION_AUTO - - TLS_VERSION_1_0 - - TLS_VERSION_1_1 - - TLS_VERSION_1_2 - - TLS_VERSION_1_3 - - TLS_VERSION_INVALID - - TLS_VERSION_UNSPECIFIED - format: int32 - type: string - minVersion: - enum: - - TLS_VERSION_AUTO - - TLS_VERSION_1_0 - - TLS_VERSION_1_1 - - TLS_VERSION_1_2 - - TLS_VERSION_1_3 - - TLS_VERSION_INVALID - - TLS_VERSION_UNSPECIFIED - format: int32 - type: string - type: object - type: object - type: object - minItems: 1 - type: array - type: object - status: - properties: - addresses: - items: - properties: - type: - default: IPAddress - type: string - value: - type: string - required: - - type - - value - type: object - type: array - listeners: - items: - properties: - attachedRoutes: - format: int32 - type: integer - name: - type: string - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. - items: - description: 'Conditions define a readiness condition - for a Consul resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' - properties: - lastTransitionTime: - description: LastTransitionTime is the last time the - condition transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details - about the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, - False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource - successfully synced with Consul. - format: date-time - type: string - type: object - required: - - attachedRoutes - - name - type: object - type: array - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. - items: - description: 'Conditions define a readiness condition for a - Consul resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' - properties: - lastTransitionTime: - description: LastTransitionTime is the last time the condition - transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details - about the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, - Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource successfully - synced with Consul. - format: date-time - type: string - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} -{{- end }} diff --git a/charts/consul/templates/crd-exportedservices-v1.yaml b/charts/consul/templates/crd-exportedservices-v1.yaml deleted file mode 100644 index 081a2b0cf0..0000000000 --- a/charts/consul/templates/crd-exportedservices-v1.yaml +++ /dev/null @@ -1,139 +0,0 @@ -{{- if .Values.connectInject.enabled }} -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - app: {{ template "consul.name" . }} - chart: {{ template "consul.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - component: crd - name: exportedservices.consul.hashicorp.com -spec: - group: consul.hashicorp.com - names: - kind: ExportedServices - listKind: ExportedServicesList - plural: exportedservices - shortNames: - - exported-services - singular: exportedservices - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: The sync status of the resource with Consul - jsonPath: .status.conditions[?(@.type=="Synced")].status - name: Synced - type: string - - description: The last successful synced time of the resource with Consul - jsonPath: .status.lastSyncedTime - name: Last Synced - type: date - - description: The age of the resource - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: ExportedServices is the Schema for the exportedservices API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: ExportedServicesSpec defines the desired state of ExportedServices. - properties: - services: - description: Services is a list of services to be exported and the - list of partitions to expose them to. - items: - description: ExportedService manages the exporting of a service - in the local partition to other partitions. - properties: - consumers: - description: Consumers is a list of downstream consumers of - the service to be exported. - items: - description: ServiceConsumer represents a downstream consumer - of the service to be exported. - properties: - partition: - description: Partition is the admin partition to export - the service to. - type: string - peer: - description: Peer is the name of the peer to export the - service to. - type: string - samenessGroup: - description: SamenessGroup is the name of the sameness - group to export the service to. - type: string - type: object - type: array - name: - description: Name is the name of the service to be exported. - type: string - namespace: - description: Namespace is the namespace to export the service - from. - type: string - type: object - type: array - type: object - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. - items: - description: 'Conditions define a readiness condition for a Consul - resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' - properties: - lastTransitionTime: - description: LastTransitionTime is the last time the condition - transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource successfully - synced with Consul. - format: date-time - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -{{- end }} diff --git a/charts/consul/templates/crd-exportedservices.yaml b/charts/consul/templates/crd-exportedservices.yaml index 6613e3da7e..081a2b0cf0 100644 --- a/charts/consul/templates/crd-exportedservices.yaml +++ b/charts/consul/templates/crd-exportedservices.yaml @@ -10,13 +10,15 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: crd - name: exportedservices.multicluster.consul.hashicorp.com + name: exportedservices.consul.hashicorp.com spec: - group: multicluster.consul.hashicorp.com + group: consul.hashicorp.com names: kind: ExportedServices listKind: ExportedServicesList plural: exportedservices + shortNames: + - exported-services singular: exportedservices scope: Namespaced versions: @@ -33,10 +35,10 @@ spec: jsonPath: .metadata.creationTimestamp name: Age type: date - name: v2 + name: v1alpha1 schema: openAPIV3Schema: - description: ExportedServices is the Schema for the Exported Services API + description: ExportedServices is the Schema for the exportedservices API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -51,15 +53,44 @@ spec: metadata: type: object spec: + description: ExportedServicesSpec defines the desired state of ExportedServices. properties: - consumers: - items: - type: object - x-kubernetes-preserve-unknown-fields: true - type: array services: + description: Services is a list of services to be exported and the + list of partitions to expose them to. items: - type: string + description: ExportedService manages the exporting of a service + in the local partition to other partitions. + properties: + consumers: + description: Consumers is a list of downstream consumers of + the service to be exported. + items: + description: ServiceConsumer represents a downstream consumer + of the service to be exported. + properties: + partition: + description: Partition is the admin partition to export + the service to. + type: string + peer: + description: Peer is the name of the peer to export the + service to. + type: string + samenessGroup: + description: SamenessGroup is the name of the sameness + group to export the service to. + type: string + type: object + type: array + name: + description: Name is the name of the service to be exported. + type: string + namespace: + description: Namespace is the namespace to export the service + from. + type: string + type: object type: array type: object status: diff --git a/charts/consul/templates/crd-gatewayclassconfigs-v1.yaml b/charts/consul/templates/crd-gatewayclassconfigs-v1.yaml deleted file mode 100644 index 130db72a22..0000000000 --- a/charts/consul/templates/crd-gatewayclassconfigs-v1.yaml +++ /dev/null @@ -1,201 +0,0 @@ -{{- if .Values.connectInject.enabled }} -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - app: {{ template "consul.name" . }} - chart: {{ template "consul.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - component: crd - name: gatewayclassconfigs.consul.hashicorp.com -spec: - group: consul.hashicorp.com - names: - kind: GatewayClassConfig - listKind: GatewayClassConfigList - plural: gatewayclassconfigs - singular: gatewayclassconfig - scope: Cluster - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: GatewayClassConfig defines the values that may be set on a GatewayClass - for Consul API Gateway. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of GatewayClassConfig. - properties: - copyAnnotations: - description: Annotation Information to copy to services or deployments - properties: - service: - description: List of annotations to copy to the gateway service. - items: - type: string - type: array - type: object - deployment: - description: Deployment defines the deployment configuration for the - gateway. - properties: - defaultInstances: - default: 1 - description: Number of gateway instances that should be deployed - by default - format: int32 - maximum: 8 - minimum: 1 - type: integer - maxInstances: - default: 8 - description: Max allowed number of gateway instances - format: int32 - maximum: 8 - minimum: 1 - type: integer - minInstances: - default: 1 - description: Minimum allowed number of gateway instances - format: int32 - maximum: 8 - minimum: 1 - type: integer - resources: - description: Resources defines the resource requirements for the - gateway. - properties: - claims: - description: "Claims lists the names of resources, defined - in spec.resourceClaims, that are used by this container. - \n This is an alpha field and requires enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. It can only be - set for containers." - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one entry in - pod.spec.resourceClaims of the Pod where this field - is used. It makes that resource available inside a - container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute - resources required. If Requests is omitted for a container, - it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' - type: object - type: object - type: object - mapPrivilegedContainerPorts: - description: The value to add to privileged ports ( ports < 1024) - for gateway containers - format: int32 - type: integer - nodeSelector: - additionalProperties: - type: string - description: 'NodeSelector is a selector which must be true for the - pod to fit on a node. Selector which must match a node''s labels - for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' - type: object - openshiftSCCName: - description: The name of the OpenShift SecurityContextConstraints - resource for this gateway class to use. - type: string - podSecurityPolicy: - description: The name of an existing Kubernetes PodSecurityPolicy - to bind to the managed ServiceAccount if ACLs are managed. - type: string - serviceType: - description: Service Type string describes ingress methods for a service - enum: - - ClusterIP - - NodePort - - LoadBalancer - type: string - tolerations: - description: 'Tolerations allow the scheduler to schedule nodes with - matching taints. More Info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' - items: - description: The pod this Toleration is attached to tolerates any - taint that matches the triple using the matching - operator . - properties: - effect: - description: Effect indicates the taint effect to match. Empty - means match all taint effects. When specified, allowed values - are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies - to. Empty means match all taint keys. If the key is empty, - operator must be Exists; this combination means to match all - values and all keys. - type: string - operator: - description: Operator represents a key's relationship to the - value. Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod - can tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: TolerationSeconds represents the period of time - the toleration (which must be of effect NoExecute, otherwise - this field is ignored) tolerates the taint. By default, it - is not set, which means tolerate the taint forever (do not - evict). Zero and negative values will be treated as 0 (evict - immediately) by the system. - format: int64 - type: integer - value: - description: Value is the taint value the toleration matches - to. If the operator is Exists, the value should be empty, - otherwise just a regular string. - type: string - type: object - type: array - type: object - type: object - served: true - storage: true -{{- end }} diff --git a/charts/consul/templates/crd-gatewayclassconfigs.yaml b/charts/consul/templates/crd-gatewayclassconfigs.yaml index 93effd843b..130db72a22 100644 --- a/charts/consul/templates/crd-gatewayclassconfigs.yaml +++ b/charts/consul/templates/crd-gatewayclassconfigs.yaml @@ -10,9 +10,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: crd - name: gatewayclassconfigs.mesh.consul.hashicorp.com + name: gatewayclassconfigs.consul.hashicorp.com spec: - group: mesh.consul.hashicorp.com + group: consul.hashicorp.com names: kind: GatewayClassConfig listKind: GatewayClassConfigList @@ -20,15 +20,11 @@ spec: singular: gatewayclassconfig scope: Cluster versions: - - additionalPrinterColumns: - - description: The age of the resource - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2beta1 + - name: v1alpha1 schema: openAPIV3Schema: - description: GatewayClassConfig is the Schema for the Mesh Gateway API + description: GatewayClassConfig defines the values that may be set on a GatewayClass + for Consul API Gateway. properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -43,1784 +39,163 @@ spec: metadata: type: object spec: - description: GatewayClassConfigSpec specifies the desired state of the - GatewayClassConfig CRD. + description: Spec defines the desired state of GatewayClassConfig. properties: - annotations: - description: Annotations are applied to the created resource + copyAnnotations: + description: Annotation Information to copy to services or deployments properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key included - here will override those in Set if specified on the Gateway. + service: + description: List of annotations to copy to the gateway service. items: type: string type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included here - will be overridden if present in InheritFromGateway and set - on the Gateway. - type: object type: object deployment: - description: Deployment contains config specific to the Deployment - created from this GatewayClass + description: Deployment defines the deployment configuration for the + gateway. properties: - affinity: - description: Affinity specifies the affinity to use on the created - Deployment. - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for - the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods - to nodes that satisfy the affinity expressions specified - by this field, but it may choose a node that violates - one or more of the expressions. The node that is most - preferred is the one with the greatest sum of weights, - i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node matches the corresponding matchExpressions; - the node(s) with the highest sum are the most preferred. - items: - description: An empty preferred scheduling term matches - all objects with implicit weight 0 (i.e. it's a no-op). - A null preferred scheduling term matches no objects - (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated with - the corresponding weight. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching the - corresponding nodeSelectorTerm, in the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by - this field are not met at scheduling time, the pod will - not be scheduled onto the node. If the affinity requirements - specified by this field cease to be met at some point - during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from - its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. - The terms are ORed. - items: - description: A null or empty node selector term - matches no objects. The requirements of them are - ANDed. The TopologySelectorTerm type implements - a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - x-kubernetes-map-type: atomic - type: array - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules (e.g. - co-locate this pod in the same node, zone, etc. as some - other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods - to nodes that satisfy the affinity expressions specified - by this field, but it may choose a node that violates - one or more of the expressions. The node that is most - preferred is the one with the greatest sum of weights, - i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node has pods which matches the corresponding - podAffinityTerm; the node(s) with the highest sum are - the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: A label query over the set of namespaces - that the term applies to. The term is applied - to the union of the namespaces selected by - this field and the ones listed in the namespaces - field. null selector and null or empty namespaces - list means "this pod's namespace". An empty - selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list - of namespace names that the term applies to. - The term is applied to the union of the namespaces - listed in this field and the ones selected - by namespaceSelector. null or empty namespaces - list and null namespaceSelector means "this - pod's namespace". - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the - pods matching the labelSelector in the specified - namespaces, where co-located is defined as - running on a node whose value of the label - with key topologyKey matches that of any node - on which any of the selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: weight associated with matching the - corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by - this field are not met at scheduling time, the pod will - not be scheduled onto the node. If the affinity requirements - specified by this field cease to be met at some point - during pod execution (e.g. due to a pod label update), - the system may or may not try to eventually evict the - pod from its node. When there are multiple elements, - the lists of nodes corresponding to each podAffinityTerm - are intersected, i.e. all terms must be satisfied. - items: - description: Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) - that this pod should be co-located (affinity) or not - co-located (anti-affinity) with, where co-located - is defined as running on a node whose value of the - label with key matches that of any node - on which a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: A label query over the set of namespaces - that the term applies to. The term is applied - to the union of the namespaces selected by this - field and the ones listed in the namespaces field. - null selector and null or empty namespaces list - means "this pod's namespace". An empty selector - ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list - of namespace names that the term applies to. The - term is applied to the union of the namespaces - listed in this field and the ones selected by - namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey - matches that of any node on which any of the selected - pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules - (e.g. avoid putting this pod in the same node, zone, etc. - as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods - to nodes that satisfy the anti-affinity expressions - specified by this field, but it may choose a node that - violates one or more of the expressions. The node that - is most preferred is the one with the greatest sum of - weights, i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - anti-affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node has pods which matches the corresponding - podAffinityTerm; the node(s) with the highest sum are - the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: A label query over the set of namespaces - that the term applies to. The term is applied - to the union of the namespaces selected by - this field and the ones listed in the namespaces - field. null selector and null or empty namespaces - list means "this pod's namespace". An empty - selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list - of namespace names that the term applies to. - The term is applied to the union of the namespaces - listed in this field and the ones selected - by namespaceSelector. null or empty namespaces - list and null namespaceSelector means "this - pod's namespace". - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the - pods matching the labelSelector in the specified - namespaces, where co-located is defined as - running on a node whose value of the label - with key topologyKey matches that of any node - on which any of the selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: weight associated with matching the - corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified - by this field are not met at scheduling time, the pod - will not be scheduled onto the node. If the anti-affinity - requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod - label update), the system may or may not try to eventually - evict the pod from its node. When there are multiple - elements, the lists of nodes corresponding to each podAffinityTerm - are intersected, i.e. all terms must be satisfied. - items: - description: Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) - that this pod should be co-located (affinity) or not - co-located (anti-affinity) with, where co-located - is defined as running on a node whose value of the - label with key matches that of any node - on which a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: A label query over the set of namespaces - that the term applies to. The term is applied - to the union of the namespaces selected by this - field and the ones listed in the namespaces field. - null selector and null or empty namespaces list - means "this pod's namespace". An empty selector - ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list - of namespace names that the term applies to. The - term is applied to the union of the namespaces - listed in this field and the ones selected by - namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey - matches that of any node on which any of the selected - pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - annotations: - description: Annotations are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - container: - description: Container contains config specific to the created - Deployment's container. - properties: - consul: - description: Consul specifies configuration for the consul-dataplane - container - properties: - logging: - description: Logging specifies the logging configuration - for Consul Dataplane - properties: - level: - description: Level sets the logging level for Consul - Dataplane (debug, info, etc.) - type: string - type: object - type: object - hostPort: - description: HostPort specifies a port to be exposed to the - external host network - format: int32 - type: integer - portModifier: - description: PortModifier specifies the value to be added - to every port value for listeners on this gateway. This - is generally used to avoid binding to privileged ports in - the container. - format: int32 - type: integer - resources: - description: Resources specifies the resource requirements - for the created Deployment's container - properties: - claims: - description: "Claims lists the names of resources, defined - in spec.resourceClaims, that are used by this container. - \n This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. \n This field - is immutable. It can only be set for containers." - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one entry - in pod.spec.resourceClaims of the Pod where this - field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of - compute resources required. If Requests is omitted for - a container, it defaults to Limits if that is explicitly - specified, otherwise to an implementation-defined value. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' - type: object - type: object - type: object - dnsPolicy: - description: DNSPolicy specifies the dns policy to use. These - are set on a per pod basis. - enum: - - Default - - ClusterFirst - - ClusterFirstWithHostNet - - None - type: string - hostNetwork: - description: HostNetwork specifies whether the gateway pods should - run on the host network. - type: boolean - initContainer: - description: InitContainer contains config specific to the created - Deployment's init container. - properties: - consul: - description: Consul specifies configuration for the consul-k8s-control-plane - init container - properties: - logging: - description: Logging specifies the logging configuration - for Consul Dataplane - properties: - level: - description: Level sets the logging level for Consul - Dataplane (debug, info, etc.) - type: string - type: object - type: object - resources: - description: Resources specifies the resource requirements - for the created Deployment's init container - properties: - claims: - description: "Claims lists the names of resources, defined - in spec.resourceClaims, that are used by this container. - \n This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. \n This field - is immutable. It can only be set for containers." - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one entry - in pod.spec.resourceClaims of the Pod where this - field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of - compute resources required. If Requests is omitted for - a container, it defaults to Limits if that is explicitly - specified, otherwise to an implementation-defined value. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' - type: object - type: object - type: object - labels: - description: Labels are applied to the created resource + defaultInstances: + default: 1 + description: Number of gateway instances that should be deployed + by default + format: int32 + maximum: 8 + minimum: 1 + type: integer + maxInstances: + default: 8 + description: Max allowed number of gateway instances + format: int32 + maximum: 8 + minimum: 1 + type: integer + minInstances: + default: 1 + description: Minimum allowed number of gateway instances + format: int32 + maximum: 8 + minimum: 1 + type: integer + resources: + description: Resources defines the resource requirements for the + gateway. properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - nodeSelector: - additionalProperties: - type: string - description: 'NodeSelector is a feature that constrains the scheduling - of a pod to nodes that match specified labels. By defining NodeSelector - in a pod''s configuration, you can ensure that the pod is only - scheduled to nodes with the corresponding labels, providing - a way to influence the placement of workloads based on node - attributes. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' - type: object - priorityClassName: - description: PriorityClassName specifies the priority class name - to use on the created Deployment. - type: string - replicas: - description: Replicas specifies the configuration to control the - number of replicas for the created Deployment. - properties: - default: - description: Default is the number of replicas assigned to - the Deployment when created - format: int32 - type: integer - max: - description: Max is the maximum number of replicas allowed - for a gateway with this class. If the replica count exceeds - this value due to manual or automated scaling, the replica - count will be restored to this value. - format: int32 - type: integer - min: - description: Min is the minimum number of replicas allowed - for a gateway with this class. If the replica count drops - below this value due to manual or automated scaling, the - replica count will be restored to this value. - format: int32 - type: integer - type: object - securityContext: - description: SecurityContext specifies the security context for - the created Deployment's Pod. - properties: - fsGroup: - description: "A special supplemental group that applies to - all containers in a pod. Some volume types allow the Kubelet - to change the ownership of that volume to be owned by the - pod: \n 1. The owning GID will be the FSGroup 2. The setgid - bit is set (new files created in the volume will be owned - by FSGroup) 3. The permission bits are OR'd with rw-rw---- - \n If unset, the Kubelet will not modify the ownership and - permissions of any volume. Note that this field cannot be - set when spec.os.name is windows." - format: int64 - type: integer - fsGroupChangePolicy: - description: 'fsGroupChangePolicy defines behavior of changing - ownership and permission of the volume before being exposed - inside Pod. This field will only apply to volume types which - support fsGroup based ownership(and permissions). It will - have no effect on ephemeral volume types such as: secret, - configmaps and emptydir. Valid values are "OnRootMismatch" - and "Always". If not specified, "Always" is used. Note that - this field cannot be set when spec.os.name is windows.' - type: string - runAsGroup: - description: The GID to run the entrypoint of the container - process. Uses runtime default if unset. May also be set - in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. Note that this field - cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root - user. If true, the Kubelet will validate the image at runtime - to ensure that it does not run as UID 0 (root) and fail - to start the container if it does. If unset or false, no - such validation will be performed. May also be set in SecurityContext. If - set in both SecurityContext and PodSecurityContext, the - value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: The UID to run the entrypoint of the container - process. Defaults to user specified in image metadata if - unspecified. May also be set in SecurityContext. If set - in both SecurityContext and PodSecurityContext, the value - specified in SecurityContext takes precedence for that container. - Note that this field cannot be set when spec.os.name is - windows. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random - SELinux context for each container. May also be set in - SecurityContext. If set in both SecurityContext and PodSecurityContext, - the value specified in SecurityContext takes precedence - for that container. Note that this field cannot be set when - spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies - to the container. - type: string - role: - description: Role is a SELinux role label that applies - to the container. - type: string - type: - description: Type is a SELinux type label that applies - to the container. - type: string - user: - description: User is a SELinux user label that applies - to the container. - type: string - type: object - seccompProfile: - description: The seccomp options to use by the containers - in this pod. Note that this field cannot be set when spec.os.name - is windows. - properties: - localhostProfile: - description: localhostProfile indicates a profile defined - in a file on the node should be used. The profile must - be preconfigured on the node to work. Must be a descending - path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". - type: string - type: - description: "type indicates which kind of seccomp profile - will be applied. Valid options are: \n Localhost - a - profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile - should be used. Unconfined - no profile should be applied." - type: string - required: - - type - type: object - supplementalGroups: - description: A list of groups applied to the first process - run in each container, in addition to the container's primary - GID, the fsGroup (if specified), and group memberships defined - in the container image for the uid of the container process. - If unspecified, no additional groups are added to any container. - Note that group memberships defined in the container image - for the uid of the container process are still effective, - even if they are not included in this list. Note that this - field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - sysctls: - description: Sysctls hold a list of namespaced sysctls used - for the pod. Pods with unsupported sysctls (by the container - runtime) might fail to launch. Note that this field cannot - be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to be set + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: - description: Name of a property to set - type: string - value: - description: Value of a property to set + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. type: string required: - name - - value type: object type: array - windowsOptions: - description: The Windows specific settings applied to all - containers. If unspecified, the options within a container's - SecurityContext will be used. If set in both SecurityContext - and PodSecurityContext, the value specified in SecurityContext - takes precedence. Note that this field cannot be set when - spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: GMSACredentialSpec is where the GMSA admission - webhook (https://github.com/kubernetes-sigs/windows-gmsa) - inlines the contents of the GMSA credential spec named - by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the - GMSA credential spec to use. - type: string - hostProcess: - description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components that - enable the WindowsHostProcessContainers feature flag. - Setting this field without the feature flag will result - in errors when validating the Pod. All of a Pod's containers - must have the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: The UserName in Windows to run the entrypoint - of the container process. Defaults to the user specified - in image metadata if unspecified. May also be set in - PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext - takes precedence. - type: string - type: object - type: object - tolerations: - description: Tolerations specifies the tolerations to use on the - created Deployment. - items: - description: The pod this Toleration is attached to tolerates - any taint that matches the triple using - the matching operator . - properties: - effect: - description: Effect indicates the taint effect to match. - Empty means match all taint effects. When specified, allowed - values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies - to. Empty means match all taint keys. If the key is empty, - operator must be Exists; this combination means to match - all values and all keys. - type: string - operator: - description: Operator represents a key's relationship to - the value. Valid operators are Exists and Equal. Defaults - to Equal. Exists is equivalent to wildcard for value, - so that a pod can tolerate all taints of a particular - category. - type: string - tolerationSeconds: - description: TolerationSeconds represents the period of - time the toleration (which must be of effect NoExecute, - otherwise this field is ignored) tolerates the taint. - By default, it is not set, which means tolerate the taint - forever (do not evict). Zero and negative values will - be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: Value is the taint value the toleration matches - to. If the operator is Exists, the value should be empty, - otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: - description: 'TopologySpreadConstraints is a feature that controls - how pods are spead across your topology. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/' - items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. - properties: - labelSelector: - description: LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine - the number of pods in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. - If the operator is In or NotIn, the values array - must be non-empty. If the operator is Exists - or DoesNotExist, the values array must be empty. - This array is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} pairs. - A single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field - is "key", the operator is "In", and the values array - contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to - select the pods over which spreading will be calculated. - The keys are used to lookup values from the incoming pod - labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading - will be calculated for the incoming pod. Keys that don't - exist in the incoming pod labels will be ignored. A null - or empty list means only match against labelSelector. - items: - type: string - type: array - x-kubernetes-list-type: atomic - maxSkew: - description: 'MaxSkew describes the degree to which pods - may be unevenly distributed. When `whenUnsatisfiable=DoNotSchedule`, - it is the maximum permitted difference between the number - of matching pods in the target topology and the global - minimum. The global minimum is the minimum number of matching - pods in an eligible domain or zero if the number of eligible - domains is less than MinDomains. For example, in a 3-zone - cluster, MaxSkew is set to 1, and pods with the same labelSelector - spread as 2/2/1: In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to - zone3 to become 2/2/2; scheduling it onto zone1(zone2) - would make the ActualSkew(3-1) on zone1(zone2) violate - MaxSkew(1). - if MaxSkew is 2, incoming pod can be scheduled - onto any zone. When `whenUnsatisfiable=ScheduleAnyway`, - it is used to give higher precedence to topologies that - satisfy it. It''s a required field. Default value is 1 - and 0 is not allowed.' - format: int32 - type: integer - minDomains: - description: "MinDomains indicates a minimum number of eligible - domains. When the number of eligible domains with matching - topology keys is less than minDomains, Pod Topology Spread - treats \"global minimum\" as 0, and then the calculation - of Skew is performed. And when the number of eligible - domains with matching topology keys equals or greater - than minDomains, this value has no effect on scheduling. - As a result, when the number of eligible domains is less - than minDomains, scheduler won't schedule more than maxSkew - Pods to those domains. If value is nil, the constraint - behaves as if MinDomains is equal to 1. Valid values are - integers greater than 0. When value is not nil, WhenUnsatisfiable - must be DoNotSchedule. \n For example, in a 3-zone cluster, - MaxSkew is set to 2, MinDomains is set to 5 and pods with - the same labelSelector spread as 2/2/2: | zone1 | zone2 - | zone3 | | P P | P P | P P | The number of domains - is less than 5(MinDomains), so \"global minimum\" is treated - as 0. In this situation, new pod with the same labelSelector - cannot be scheduled, because computed skew will be 3(3 - - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. \n This is a beta field and requires - the MinDomainsInPodTopologySpread feature gate to be enabled - (enabled by default)." - format: int32 - type: integer - nodeAffinityPolicy: - description: "NodeAffinityPolicy indicates how we will treat - Pod's nodeAffinity/nodeSelector when calculating pod topology - spread skew. Options are: - Honor: only nodes matching - nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes - are included in the calculations. \n If this value is - nil, the behavior is equivalent to the Honor policy. This - is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread - feature flag." - type: string - nodeTaintsPolicy: - description: "NodeTaintsPolicy indicates how we will treat - node taints when calculating pod topology spread skew. - Options are: - Honor: nodes without taints, along with - tainted nodes for which the incoming pod has a toleration, - are included. - Ignore: node taints are ignored. All nodes - are included. \n If this value is nil, the behavior is - equivalent to the Ignore policy. This is a beta-level - feature default enabled by the NodeInclusionPolicyInPodTopologySpread - feature flag." - type: string - topologyKey: - description: TopologyKey is the key of node labels. Nodes - that have a label with this key and identical values are - considered to be in the same topology. We consider each - as a "bucket", and try to put balanced number - of pods into each bucket. We define a domain as a particular - instance of a topology. Also, we define an eligible domain - as a domain whose nodes meet the requirements of nodeAffinityPolicy - and nodeTaintsPolicy. e.g. If TopologyKey is "kubernetes.io/hostname", - each Node is a domain of that topology. And, if TopologyKey - is "topology.kubernetes.io/zone", each zone is a domain - of that topology. It's a required field. - type: string - whenUnsatisfiable: - description: 'WhenUnsatisfiable indicates how to deal with - a pod if it doesn''t satisfy the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule - it. - ScheduleAnyway tells the scheduler to schedule the - pod in any location, but giving higher precedence to topologies - that would help reduce the skew. A constraint is considered - "Unsatisfiable" for an incoming pod if and only if every - possible node assignment for that pod would violate "MaxSkew" - on some topology. For example, in a 3-zone cluster, MaxSkew - is set to 1, and pods with the same labelSelector spread - as 3/1/1: | zone1 | zone2 | zone3 | | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming - pod can only be scheduled to zone2(zone3) to become 3/2/1(3/1/2) - as ActualSkew(2-1) on zone2(zone3) satisfies MaxSkew(1). - In other words, the cluster can still be imbalanced, but - scheduler won''t make it *more* imbalanced. It''s a required - field.' - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - type: object - labels: - description: Labels are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key included - here will override those in Set if specified on the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included here - will be overridden if present in InheritFromGateway and set - on the Gateway. - type: object - type: object - role: - description: Role contains config specific to the Role created from - this GatewayClass - properties: - annotations: - description: Annotations are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - labels: - description: Labels are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - type: object - roleBinding: - description: RoleBinding contains config specific to the RoleBinding - created from this GatewayClass - properties: - annotations: - description: Annotations are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - labels: - description: Labels are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - type: object - service: - description: Service contains config specific to the Service created - from this GatewayClass - properties: - annotations: - description: Annotations are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - labels: - description: Labels are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object - type: - description: Type specifies the type of Service to use (LoadBalancer, - ClusterIP, etc.) - enum: - - ClusterIP - - NodePort - - LoadBalancer - type: string type: object - serviceAccount: - description: ServiceAccount contains config specific to the corev1.ServiceAccount - created from this GatewayClass - properties: - annotations: - description: Annotations are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - labels: - description: Labels are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object + mapPrivilegedContainerPorts: + description: The value to add to privileged ports ( ports < 1024) + for gateway containers + format: int32 + type: integer + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true for the + pod to fit on a node. Selector which must match a node''s labels + for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' type: object - type: object - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. + openshiftSCCName: + description: The name of the OpenShift SecurityContextConstraints + resource for this gateway class to use. + type: string + podSecurityPolicy: + description: The name of an existing Kubernetes PodSecurityPolicy + to bind to the managed ServiceAccount if ACLs are managed. + type: string + serviceType: + description: Service Type string describes ingress methods for a service + enum: + - ClusterIP + - NodePort + - LoadBalancer + type: string + tolerations: + description: 'Tolerations allow the scheduler to schedule nodes with + matching taints. More Info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' items: - description: 'Conditions define a readiness condition for a Consul - resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . properties: - lastTransitionTime: - description: LastTransitionTime is the last time the condition - transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. type: string - reason: - description: The reason for the condition's last transition. + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. type: string - status: - description: Status of the condition, one of True, False, Unknown. + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. type: string - type: - description: Type of condition. + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. type: string - required: - - status - - type type: object type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource successfully - synced with Consul. - format: date-time - type: string type: object type: object served: true storage: true - subresources: - status: {} {{- end }} diff --git a/charts/consul/templates/crd-gatewayclasses-external.yaml b/charts/consul/templates/crd-gatewayclasses-external.yaml index 93435b7fce..391637b5f7 100644 --- a/charts/consul/templates/crd-gatewayclasses-external.yaml +++ b/charts/consul/templates/crd-gatewayclasses-external.yaml @@ -1,18 +1,21 @@ {{- if and .Values.connectInject.enabled .Values.connectInject.apiGateway.manageExternalCRDs }} +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/1538 - gateway.networking.k8s.io/bundle-version: v0.6.2 - gateway.networking.k8s.io/channel: experimental - creationTimestamp: null labels: app: {{ template "consul.name" . }} chart: {{ template "consul.chart" . }} heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: crd + gateway.networking.k8s.io/bundle-version: v0.6.2 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null name: gatewayclasses.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/charts/consul/templates/crd-gatewayclasses.yaml b/charts/consul/templates/crd-gatewayclasses.yaml deleted file mode 100644 index 70763f9104..0000000000 --- a/charts/consul/templates/crd-gatewayclasses.yaml +++ /dev/null @@ -1,122 +0,0 @@ -{{- if .Values.connectInject.enabled }} -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - app: {{ template "consul.name" . }} - chart: {{ template "consul.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - component: crd - name: gatewayclasses.mesh.consul.hashicorp.com -spec: - group: mesh.consul.hashicorp.com - names: - kind: GatewayClass - listKind: GatewayClassList - plural: gatewayclasses - singular: gatewayclass - scope: Cluster - versions: - - additionalPrinterColumns: - - description: The age of the resource - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2beta1 - schema: - openAPIV3Schema: - description: GatewayClass is the Schema for the Gateway Class API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - controllerName: - description: ControllerName is the name of the Kubernetes controller - that manages Gateways of this class - type: string - description: - description: Description of GatewayClass - type: string - parametersRef: - description: ParametersRef refers to a resource responsible for configuring - the behavior of the GatewayClass. - properties: - group: - description: The Kubernetes Group that the referred object belongs - to - type: string - kind: - description: The Kubernetes Kind that the referred object is - type: string - name: - description: The Name of the referred object - type: string - namespace: - description: The kubernetes namespace that the referred object - is in - type: string - required: - - name - type: object - required: - - controllerName - - parametersRef - type: object - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. - items: - description: 'Conditions define a readiness condition for a Consul - resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' - properties: - lastTransitionTime: - description: LastTransitionTime is the last time the condition - transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource successfully - synced with Consul. - format: date-time - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -{{- end }} diff --git a/charts/consul/templates/crd-gateways-external.yaml b/charts/consul/templates/crd-gateways-external.yaml index 41df34942a..ab56d4f5fb 100644 --- a/charts/consul/templates/crd-gateways-external.yaml +++ b/charts/consul/templates/crd-gateways-external.yaml @@ -1,18 +1,21 @@ {{- if and .Values.connectInject.enabled .Values.connectInject.apiGateway.manageExternalCRDs }} +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/1538 - gateway.networking.k8s.io/bundle-version: v0.6.2 - gateway.networking.k8s.io/channel: experimental - creationTimestamp: null labels: app: {{ template "consul.name" . }} chart: {{ template "consul.chart" . }} heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: crd + gateway.networking.k8s.io/bundle-version: v0.6.2 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null name: gateways.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/charts/consul/templates/crd-grpcroutes-external.yaml b/charts/consul/templates/crd-grpcroutes-external.yaml index 739ed2c659..3e4aa75853 100644 --- a/charts/consul/templates/crd-grpcroutes-external.yaml +++ b/charts/consul/templates/crd-grpcroutes-external.yaml @@ -1,18 +1,21 @@ {{- if and .Values.connectInject.enabled .Values.connectInject.apiGateway.manageExternalCRDs }} +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/1538 - gateway.networking.k8s.io/bundle-version: v0.6.2 - gateway.networking.k8s.io/channel: experimental - creationTimestamp: null labels: app: {{ template "consul.name" . }} chart: {{ template "consul.chart" . }} heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: crd + gateway.networking.k8s.io/bundle-version: v0.6.2 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null name: grpcroutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/charts/consul/templates/crd-grpcroutes.yaml b/charts/consul/templates/crd-grpcroutes.yaml index 8766c8edbe..31812fff35 100644 --- a/charts/consul/templates/crd-grpcroutes.yaml +++ b/charts/consul/templates/crd-grpcroutes.yaml @@ -72,10 +72,9 @@ spec: description: 'NOTE: roughly equivalent to structs.ResourceReference' properties: port: - description: "For east/west this is the name of the Consul Service + description: For east/west this is the name of the Consul Service port to direct traffic to or empty to imply all. For north/south - this is TBD. \n For more details on potential values of this - field, see documentation for Service.ServicePort." + this is TBD. type: string ref: description: For east/west configuration, this should point @@ -107,6 +106,13 @@ spec: the wildcard value \"*\" to list resources across all partitions." type: string + peerName: + description: "PeerName identifies which peer the resource + is imported from. https://developer.hashicorp.com/consul/docs/connect/cluster-peering + \n When using the List and WatchList endpoints, provide + the wildcard value \"*\" to list resources across + all peers." + type: string type: object type: description: Type identifies the resource's type. @@ -160,9 +166,7 @@ spec: description: "For east/west this is the name of the Consul Service port to direct traffic to or empty to imply using the same value as the parent ref. - For north/south this is TBD. \n For more details - on potential values of this field, see documentation - for Service.ServicePort." + \n For north/south this is TBD." type: string ref: description: For east/west configuration, this should @@ -195,6 +199,13 @@ spec: provide the wildcard value \"*\" to list resources across all partitions." type: string + peerName: + description: "PeerName identifies which peer + the resource is imported from. https://developer.hashicorp.com/consul/docs/connect/cluster-peering + \n When using the List and WatchList endpoints, + provide the wildcard value \"*\" to list + resources across all peers." + type: string type: object type: description: Type identifies the resource's type. diff --git a/charts/consul/templates/crd-httproutes-external.yaml b/charts/consul/templates/crd-httproutes-external.yaml index bba3672d16..c89591376a 100644 --- a/charts/consul/templates/crd-httproutes-external.yaml +++ b/charts/consul/templates/crd-httproutes-external.yaml @@ -1,18 +1,21 @@ {{- if and .Values.connectInject.enabled .Values.connectInject.apiGateway.manageExternalCRDs }} +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/1538 - gateway.networking.k8s.io/bundle-version: v0.6.2 - gateway.networking.k8s.io/channel: experimental - creationTimestamp: null labels: app: {{ template "consul.name" . }} chart: {{ template "consul.chart" . }} heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: crd + gateway.networking.k8s.io/bundle-version: v0.6.2 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null name: httproutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/charts/consul/templates/crd-httproutes.yaml b/charts/consul/templates/crd-httproutes.yaml index c829bf1fc3..3da6e1e637 100644 --- a/charts/consul/templates/crd-httproutes.yaml +++ b/charts/consul/templates/crd-httproutes.yaml @@ -72,10 +72,9 @@ spec: description: 'NOTE: roughly equivalent to structs.ResourceReference' properties: port: - description: "For east/west this is the name of the Consul Service + description: For east/west this is the name of the Consul Service port to direct traffic to or empty to imply all. For north/south - this is TBD. \n For more details on potential values of this - field, see documentation for Service.ServicePort." + this is TBD. type: string ref: description: For east/west configuration, this should point @@ -107,6 +106,13 @@ spec: the wildcard value \"*\" to list resources across all partitions." type: string + peerName: + description: "PeerName identifies which peer the resource + is imported from. https://developer.hashicorp.com/consul/docs/connect/cluster-peering + \n When using the List and WatchList endpoints, provide + the wildcard value \"*\" to list resources across + all peers." + type: string type: object type: description: Type identifies the resource's type. @@ -163,9 +169,7 @@ spec: description: "For east/west this is the name of the Consul Service port to direct traffic to or empty to imply using the same value as the parent ref. - For north/south this is TBD. \n For more details - on potential values of this field, see documentation - for Service.ServicePort." + \n For north/south this is TBD." type: string ref: description: For east/west configuration, this should @@ -198,6 +202,13 @@ spec: provide the wildcard value \"*\" to list resources across all partitions." type: string + peerName: + description: "PeerName identifies which peer + the resource is imported from. https://developer.hashicorp.com/consul/docs/connect/cluster-peering + \n When using the List and WatchList endpoints, + provide the wildcard value \"*\" to list + resources across all peers." + type: string type: object type: description: Type identifies the resource's type. diff --git a/charts/consul/templates/crd-meshconfigurations.yaml b/charts/consul/templates/crd-meshconfigurations.yaml deleted file mode 100644 index 21114d723f..0000000000 --- a/charts/consul/templates/crd-meshconfigurations.yaml +++ /dev/null @@ -1,100 +0,0 @@ -{{- if .Values.connectInject.enabled }} -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - app: {{ template "consul.name" . }} - chart: {{ template "consul.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - component: crd - name: meshconfigurations.mesh.consul.hashicorp.com -spec: - group: mesh.consul.hashicorp.com - names: - kind: MeshConfiguration - listKind: MeshConfigurationList - plural: meshconfigurations - singular: meshconfiguration - scope: Cluster - versions: - - additionalPrinterColumns: - - description: The sync status of the resource with Consul - jsonPath: .status.conditions[?(@.type=="Synced")].status - name: Synced - type: string - - description: The last successful synced time of the resource with Consul - jsonPath: .status.lastSyncedTime - name: Last Synced - type: date - - description: The age of the resource - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2beta1 - schema: - openAPIV3Schema: - description: MeshConfiguration is the Schema for the Mesh Configuration - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: MeshConfiguration is responsible for configuring the default - behavior of Mesh Gateways. This is a Resource type. - type: object - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. - items: - description: 'Conditions define a readiness condition for a Consul - resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' - properties: - lastTransitionTime: - description: LastTransitionTime is the last time the condition - transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource successfully - synced with Consul. - format: date-time - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -{{- end }} diff --git a/charts/consul/templates/crd-meshgateways.yaml b/charts/consul/templates/crd-meshgateways.yaml deleted file mode 100644 index 6202add695..0000000000 --- a/charts/consul/templates/crd-meshgateways.yaml +++ /dev/null @@ -1,134 +0,0 @@ -{{- if .Values.connectInject.enabled }} -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - app: {{ template "consul.name" . }} - chart: {{ template "consul.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - component: crd - name: meshgateways.mesh.consul.hashicorp.com -spec: - group: mesh.consul.hashicorp.com - names: - kind: MeshGateway - listKind: MeshGatewayList - plural: meshgateways - singular: meshgateway - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: The sync status of the resource with Consul - jsonPath: .status.conditions[?(@.type=="Synced")].status - name: Synced - type: string - - description: The last successful synced time of the resource with Consul - jsonPath: .status.lastSyncedTime - name: Last Synced - type: date - - description: The age of the resource - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2beta1 - schema: - openAPIV3Schema: - description: MeshGateway is the Schema for the Mesh Gateway API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - gatewayClassName: - description: GatewayClassName is the name of the GatewayClass used - by the MeshGateway - type: string - listeners: - items: - properties: - name: - type: string - port: - format: int32 - maximum: 65535 - minimum: 0 - type: integer - protocol: - enum: - - TCP - type: string - type: object - minItems: 1 - type: array - workloads: - description: Selection of workloads to be configured as mesh gateways - properties: - filter: - type: string - names: - items: - type: string - type: array - prefixes: - items: - type: string - type: array - type: object - type: object - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. - items: - description: 'Conditions define a readiness condition for a Consul - resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' - properties: - lastTransitionTime: - description: LastTransitionTime is the last time the condition - transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource successfully - synced with Consul. - format: date-time - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -{{- end }} diff --git a/charts/consul/templates/crd-proxyconfigurations.yaml b/charts/consul/templates/crd-proxyconfigurations.yaml index 3d19d5ea4f..9a33bd2bab 100644 --- a/charts/consul/templates/crd-proxyconfigurations.yaml +++ b/charts/consul/templates/crd-proxyconfigurations.yaml @@ -127,6 +127,24 @@ spec: format: int32 type: string type: object + envoyExtensions: + items: + description: EnvoyExtension has configuration for an extension + that patches Envoy resources. + properties: + arguments: + type: object + x-kubernetes-preserve-unknown-fields: true + consulVersion: + type: string + envoyVersion: + type: string + name: + type: string + required: + type: boolean + type: object + type: array exposeConfig: properties: exposePaths: @@ -160,7 +178,7 @@ spec: format: int32 type: string maxInboundConnections: - format: int32 + format: int64 type: integer type: object listenerTracingJson: diff --git a/charts/consul/templates/crd-referencegrants-external.yaml b/charts/consul/templates/crd-referencegrants-external.yaml index db9cf12027..6ae177d987 100644 --- a/charts/consul/templates/crd-referencegrants-external.yaml +++ b/charts/consul/templates/crd-referencegrants-external.yaml @@ -1,18 +1,21 @@ {{- if and .Values.connectInject.enabled .Values.connectInject.apiGateway.manageExternalCRDs }} +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/1538 - gateway.networking.k8s.io/bundle-version: v0.6.2 - gateway.networking.k8s.io/channel: experimental - creationTimestamp: null labels: app: {{ template "consul.name" . }} chart: {{ template "consul.chart" . }} heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: crd + gateway.networking.k8s.io/bundle-version: v0.6.2 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null name: referencegrants.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/charts/consul/templates/crd-routetimeoutfilters.yaml b/charts/consul/templates/crd-routetimeoutfilters.yaml index 07ebfe9386..95ab50320d 100644 --- a/charts/consul/templates/crd-routetimeoutfilters.yaml +++ b/charts/consul/templates/crd-routetimeoutfilters.yaml @@ -55,10 +55,8 @@ spec: description: RouteTimeoutFilterSpec defines the desired state of RouteTimeoutFilter. properties: idleTimeout: - format: duration type: string requestTimeout: - format: duration type: string type: object status: diff --git a/charts/consul/templates/crd-servicerouters.yaml b/charts/consul/templates/crd-servicerouters.yaml index c7924081fd..dca5aa7fc3 100644 --- a/charts/consul/templates/crd-servicerouters.yaml +++ b/charts/consul/templates/crd-servicerouters.yaml @@ -149,9 +149,9 @@ spec: type: object type: object retryOn: - description: 'RetryOn is a flat list of conditions for Consul + description: RetryOn is a flat list of conditions for Consul to retry requests based on the response from an upstream - service. Refer to the valid conditions here: https://developer.hashicorp.com/consul/docs/connect/config-entries/service-router#routes-destination-retryon' + service. items: type: string type: array diff --git a/charts/consul/templates/crd-tcproutes-external.yaml b/charts/consul/templates/crd-tcproutes-external.yaml index b5bc7be13c..91989135e2 100644 --- a/charts/consul/templates/crd-tcproutes-external.yaml +++ b/charts/consul/templates/crd-tcproutes-external.yaml @@ -1,18 +1,21 @@ {{- if and .Values.connectInject.enabled .Values.connectInject.apiGateway.manageExternalCRDs }} +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/1538 - gateway.networking.k8s.io/bundle-version: v0.6.2 - gateway.networking.k8s.io/channel: experimental - creationTimestamp: null labels: app: {{ template "consul.name" . }} chart: {{ template "consul.chart" . }} heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: crd + gateway.networking.k8s.io/bundle-version: v0.6.2 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null name: tcproutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/charts/consul/templates/crd-tcproutes.yaml b/charts/consul/templates/crd-tcproutes.yaml index c0e87a9c3c..ae9d2cd080 100644 --- a/charts/consul/templates/crd-tcproutes.yaml +++ b/charts/consul/templates/crd-tcproutes.yaml @@ -66,10 +66,9 @@ spec: description: 'NOTE: roughly equivalent to structs.ResourceReference' properties: port: - description: "For east/west this is the name of the Consul Service + description: For east/west this is the name of the Consul Service port to direct traffic to or empty to imply all. For north/south - this is TBD. \n For more details on potential values of this - field, see documentation for Service.ServicePort." + this is TBD. type: string ref: description: For east/west configuration, this should point @@ -101,6 +100,13 @@ spec: the wildcard value \"*\" to list resources across all partitions." type: string + peerName: + description: "PeerName identifies which peer the resource + is imported from. https://developer.hashicorp.com/consul/docs/connect/cluster-peering + \n When using the List and WatchList endpoints, provide + the wildcard value \"*\" to list resources across + all peers." + type: string type: object type: description: Type identifies the resource's type. @@ -145,9 +151,7 @@ spec: description: "For east/west this is the name of the Consul Service port to direct traffic to or empty to imply using the same value as the parent ref. - For north/south this is TBD. \n For more details - on potential values of this field, see documentation - for Service.ServicePort." + \n For north/south this is TBD." type: string ref: description: For east/west configuration, this should @@ -180,6 +184,13 @@ spec: provide the wildcard value \"*\" to list resources across all partitions." type: string + peerName: + description: "PeerName identifies which peer + the resource is imported from. https://developer.hashicorp.com/consul/docs/connect/cluster-peering + \n When using the List and WatchList endpoints, + provide the wildcard value \"*\" to list + resources across all peers." + type: string type: object type: description: Type identifies the resource's type. diff --git a/charts/consul/templates/crd-tlsroutes-external.yaml b/charts/consul/templates/crd-tlsroutes-external.yaml index 1acd1b973a..dfabd80713 100644 --- a/charts/consul/templates/crd-tlsroutes-external.yaml +++ b/charts/consul/templates/crd-tlsroutes-external.yaml @@ -1,18 +1,21 @@ {{- if and .Values.connectInject.enabled .Values.connectInject.apiGateway.manageExternalCRDs }} +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/1538 - gateway.networking.k8s.io/bundle-version: v0.6.2 - gateway.networking.k8s.io/channel: experimental - creationTimestamp: null labels: app: {{ template "consul.name" . }} chart: {{ template "consul.chart" . }} heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: crd + gateway.networking.k8s.io/bundle-version: v0.6.2 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null name: tlsroutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/charts/consul/templates/crd-trafficpermissions.yaml b/charts/consul/templates/crd-trafficpermissions.yaml index 87727f4fbf..27ab6f5e3d 100644 --- a/charts/consul/templates/crd-trafficpermissions.yaml +++ b/charts/consul/templates/crd-trafficpermissions.yaml @@ -101,25 +101,23 @@ spec: when evaluating rules for the incoming connection. items: properties: - headers: - items: - properties: - exact: - type: string - invert: - type: boolean - name: - type: string - prefix: - type: string - present: - type: boolean - regex: - type: string - suffix: - type: string - type: object - type: array + header: + properties: + exact: + type: string + invert: + type: boolean + name: + type: string + prefix: + type: string + present: + type: boolean + regex: + type: string + suffix: + type: string + type: object methods: description: Methods is the list of HTTP methods. items: @@ -140,25 +138,23 @@ spec: type: array type: object type: array - headers: - items: - properties: - exact: - type: string - invert: - type: boolean - name: - type: string - prefix: - type: string - present: - type: boolean - regex: - type: string - suffix: - type: string - type: object - type: array + header: + properties: + exact: + type: string + invert: + type: boolean + name: + type: string + prefix: + type: string + present: + type: boolean + regex: + type: string + suffix: + type: string + type: object methods: description: Methods is the list of HTTP methods. If no methods are specified, this rule will apply to all methods. diff --git a/charts/consul/templates/crd-udproutes-external.yaml b/charts/consul/templates/crd-udproutes-external.yaml index 0661b24c1a..935cce22fa 100644 --- a/charts/consul/templates/crd-udproutes-external.yaml +++ b/charts/consul/templates/crd-udproutes-external.yaml @@ -1,18 +1,21 @@ {{- if and .Values.connectInject.enabled .Values.connectInject.apiGateway.manageExternalCRDs }} +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/1538 - gateway.networking.k8s.io/bundle-version: v0.6.2 - gateway.networking.k8s.io/channel: experimental - creationTimestamp: null labels: app: {{ template "consul.name" . }} chart: {{ template "consul.chart" . }} heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: crd + gateway.networking.k8s.io/bundle-version: v0.6.2 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null name: udproutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/charts/consul/templates/gateway-cleanup-clusterrole.yaml b/charts/consul/templates/gateway-cleanup-clusterrole.yaml index 5518bfc390..c533a882f5 100644 --- a/charts/consul/templates/gateway-cleanup-clusterrole.yaml +++ b/charts/consul/templates/gateway-cleanup-clusterrole.yaml @@ -24,15 +24,6 @@ rules: verbs: - get - delete - - apiGroups: - - mesh.consul.hashicorp.com - resources: - - gatewayclassconfigs - - gatewayclasses - - meshgateways - verbs: - - get - - delete {{- if .Values.global.enablePodSecurityPolicies }} - apiGroups: ["policy"] resources: ["podsecuritypolicies"] diff --git a/charts/consul/templates/gateway-cleanup-job.yaml b/charts/consul/templates/gateway-cleanup-job.yaml index 0d4f84272c..df6c22fd30 100644 --- a/charts/consul/templates/gateway-cleanup-job.yaml +++ b/charts/consul/templates/gateway-cleanup-job.yaml @@ -52,16 +52,8 @@ spec: limits: memory: "50Mi" cpu: "50m" - volumeMounts: - - name: config - mountPath: /consul/config - readOnly: true {{- if .Values.global.acls.tolerations }} tolerations: {{ tpl .Values.global.acls.tolerations . | indent 8 | trim }} {{- end }} - volumes: - - name: config - configMap: - name: {{ template "consul.fullname" . }}-gateway-resources-config {{- end }} diff --git a/charts/consul/templates/gateway-resources-clusterrole.yaml b/charts/consul/templates/gateway-resources-clusterrole.yaml index ad7082f060..c3bdfeb4a3 100644 --- a/charts/consul/templates/gateway-resources-clusterrole.yaml +++ b/charts/consul/templates/gateway-resources-clusterrole.yaml @@ -10,17 +10,8 @@ metadata: release: {{ .Release.Name }} component: gateway-resources rules: - - apiGroups: - - mesh.consul.hashicorp.com - resources: - - meshgateways - verbs: - - get - - update - - create - apiGroups: - consul.hashicorp.com - - mesh.consul.hashicorp.com resources: - gatewayclassconfigs verbs: @@ -29,7 +20,6 @@ rules: - create - apiGroups: - gateway.networking.k8s.io - - mesh.consul.hashicorp.com resources: - gatewayclasses verbs: diff --git a/charts/consul/templates/gateway-resources-configmap.yaml b/charts/consul/templates/gateway-resources-configmap.yaml index d00f9b3e86..591aaa2129 100644 --- a/charts/consul/templates/gateway-resources-configmap.yaml +++ b/charts/consul/templates/gateway-resources-configmap.yaml @@ -1,16 +1,11 @@ {{- if .Values.connectInject.enabled }} - -# Validation -# For meshGateway.wanAddress, static must be set if source is "Static" -{{if (and (eq .Values.meshGateway.wanAddress.source "Static") (eq .Values.meshGateway.wanAddress.static ""))}}{{fail ".meshGateway.wanAddress.static must be set to a value if .meshGateway.wanAddress.source is Static"}}{{ end }} - # Configuration of Gateway Resources Job which creates managed Gateway configuration. apiVersion: v1 kind: ConfigMap metadata: name: {{ template "consul.fullname" . }}-gateway-resources-config namespace: {{ .Release.Namespace }} - labels: + labels: app: {{ template "consul.name" . }} chart: {{ template "consul.chart" . }} heritage: {{ .Release.Service }} @@ -21,175 +16,4 @@ data: resources.json: | {{ toJson .Values.connectInject.apiGateway.managedGatewayClass.resources }} {{- end }} - {{- if and (mustHas "resource-apis" .Values.global.experiments) (or .Values.meshGateway.enabled .Values.connectInject.apiGateway.managedGatewayClass) }} - config.yaml: | - gatewayClassConfigs: - {{- if .Values.meshGateway.enabled }} - - apiVersion: mesh.consul.hashicorp.com/v2beta1 - metadata: - name: consul-mesh-gateway - kind: GatewayClassConfig - spec: - labels: - set: - app: {{ template "consul.name" . }} - chart: {{ template "consul.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - component: mesh-gateway - deployment: - {{- if .Values.meshGateway.priorityClassName }} - priorityClassName: {{ .Values.meshGateway.priorityClassName | quote }} - {{- end }} - {{- if .Values.meshGateway.affinity }} - affinity: {{ toJson (default "{}" .Values.meshGateway.affinity) }} - {{- end }} - {{- if .Values.meshGateway.annotations }} - annotations: - set: {{ toJson .Values.meshGateway.annotations }} - {{- end }} - {{- if .Values.global.extraLabels }} - labels: - set: {{ toJson .Values.global.extraLabels }} - {{- end }} - container: - consul: - logging: - level: {{ default .Values.global.logLevel .Values.meshGateway.logLevel }} - portModifier: {{ sub .Values.meshGateway.containerPort .Values.meshGateway.service.port }} - {{- if .Values.meshGateway.hostPort }} - hostPort: {{ .Values.meshGateway.hostPort }} - {{- end }} - resources: {{ toJson .Values.meshGateway.resources }} - initContainer: - consul: - logging: - level: {{ default .Values.global.logLevel .Values.meshGateway.logLevel }} - resources: {{ toJson .Values.meshGateway.initServiceInitContainer.resources }} - {{- with .Values.meshGateway.nodeSelector }} - nodeSelector: {{ fromYaml . | toJson }} - {{- end }} - {{- with .Values.meshGateway.hostNetwork }} - hostNetwork: {{ . }} - {{- end }} - {{- with .Values.meshGateway.dnsPolicy }} - dnsPolicy: {{ . }} - {{- end }} - {{- with .Values.meshGateway.topologySpreadConstraints }} - topologySpreadConstraints: - {{ fromYamlArray . | toJson }} - {{- end }} - {{- if .Values.meshGateway.affinity }} - affinity: - {{ tpl .Values.meshGateway.affinity . | nindent 16 | trim }} - {{- end }} - replicas: - default: {{ .Values.meshGateway.replicas }} - min: {{ .Values.meshGateway.replicas }} - max: {{ .Values.meshGateway.replicas }} - {{- if .Values.meshGateway.tolerations }} - tolerations: - {{ fromYamlArray .Values.meshGateway.tolerations | toJson }} - {{- end }} - service: - {{- if .Values.meshGateway.service.annotations }} - annotations: - set: {{ toJson .Values.meshGateway.service.annotations }} - {{- end }} - type: {{ .Values.meshGateway.service.type }} - {{- if .Values.meshGateway.serviceAccount.annotations }} - serviceAccount: - annotations: - set: {{ toJson .Values.meshGateway.serviceAccount.annotations }} - {{- end }} - {{- end }} - {{- if .Values.connectInject.apiGateway.managedGatewayClass }} - - apiVersion: mesh.consul.hashicorp.com/v2beta1 - metadata: - name: consul-api-gateway - kind: GatewayClassConfig - spec: - labels: - set: - app: {{ template "consul.name" . }} - chart: {{ template "consul.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - component: api-gateway - {{- if .Values.connectInject.apiGateway.managedGatewayClass.copyAnnotations }} - {{- if .Values.connectInject.apiGateway.managedGatewayClass.copyAnnotations.service }} - annotations: - service: - {{ fromYamlArray .Values.connectInject.apiGateway.managedGatewayClass.copyAnnotations.service.annotations | toYaml }} - {{- end}} - {{- end}} - deployment: - {{- if .Values.connectInject.apiGateway.managedGatewayClass.nodeSelector }} - nodeSelector: - {{ fromYamlArray .Values.connectInject.apiGateway.managedGatewayClass.nodeSelector | toYaml }} - {{- end }} - initContainer: - {{- if .Values.connectInject.apiGateway.managedGatewayClass.mapPrivilegedContainerPorts }} - portModifier: {{ .Values.connectInject.apiGateway.managedGatewayClass.mapPrivilegedContainerPorts }} - {{- end }} - consul: - logging: - level: {{ .Values.global.logLevel }} - container: - {{- if .Values.connectInject.apiGateway.managedGatewayClass.mapPrivilegedContainerPorts }} - portModifier: {{ .Values.connectInject.apiGateway.managedGatewayClass.mapPrivilegedContainerPorts }} - {{- end }} - consul: - logging: - level: {{ .Values.global.logLevel }} - replicas: - default: {{ .Values.connectInject.apiGateway.managedGatewayClass.deployment.defaultInstances }} - min: {{ .Values.connectInject.apiGateway.managedGatewayClass.deployment.minInstances }} - max: {{ .Values.connectInject.apiGateway.managedGatewayClass.deployment.maxInstances }} - {{- if .Values.connectInject.apiGateway.managedGatewayClass.tolerations }} - tolerations: - {{ fromYamlArray .Values.connectInject.apiGateway.managedGatewayClass.tolerations | toYaml }} - {{- end }} - {{- if .Values.connectInject.apiGateway.managedGatewayClass.service }} - service: - annotations: - set: {{ toYaml .Values.connectInject.apiGateway.managedGatewayClass.service.annotations }} - {{- end }} - type: {{ .Values.connectInject.apiGateway.managedGatewayClass.serviceType }} - {{- if .Values.connectInject.apiGateway.managedGatewayClass.serviceAccount }} - serviceAccount: - annotations: - set: {{ toYaml .Values.connectInject.apiGateway.managedGatewayClass.serviceAccount.annotations }} - {{- end }} - {{- end }} - {{- if .Values.meshGateway.enabled }} - meshGateways: - - apiVersion: mesh.consul.hashicorp.com/v2beta1 - kind: MeshGateway - metadata: - name: mesh-gateway - namespace: {{ .Release.Namespace }} - annotations: - "consul.hashicorp.com/gateway-wan-address-source": {{ .Values.meshGateway.wanAddress.source | quote }} - "consul.hashicorp.com/gateway-wan-address-static": {{ .Values.meshGateway.wanAddress.static | quote }} - {{- if eq .Values.meshGateway.wanAddress.source "Service" }} - {{- if eq .Values.meshGateway.service.type "NodePort" }} - "consul.hashicorp.com/gateway-wan-port": {{ .Values.meshGateway.service.nodePort | quote }} - {{- else }} - "consul.hashicorp.com/gateway-wan-port": {{ .Values.meshGateway.service.port | quote }} - {{- end }} - {{- else }} - "consul.hashicorp.com/gateway-wan-port": {{ .Values.meshGateway.wanAddress.port | quote }} - {{- end }} - spec: - gatewayClassName: consul-mesh-gateway - listeners: - - name: "wan" - port: {{ .Values.meshGateway.service.port }} - protocol: "TCP" - workloads: - prefixes: - - "mesh-gateway" - {{- end }} - {{- end }} {{- end }} diff --git a/charts/consul/templates/gateway-resources-job.yaml b/charts/consul/templates/gateway-resources-job.yaml index 5934372ed3..1136d2e0fe 100644 --- a/charts/consul/templates/gateway-resources-job.yaml +++ b/charts/consul/templates/gateway-resources-job.yaml @@ -51,7 +51,7 @@ spec: - -heritage={{ .Release.Service }} - -release-name={{ .Release.Name }} - -component=api-gateway - {{- if .Values.apiGateway.enabled }} # Override values from the old stanza. To be removed after ~1.18 (t-eckert 2023-05-19) NET-6263 + {{- if .Values.apiGateway.enabled }} # Overide values from the old stanza. To be removed in 1.17 (t-eckert 2023-05-19) {{- if .Values.apiGateway.managedGatewayClass.deployment }} {{- if .Values.apiGateway.managedGatewayClass.deployment.defaultInstances }} - -deployment-default-instances={{ .Values.apiGateway.managedGatewayClass.deployment.defaultInstances }} diff --git a/charts/consul/templates/mesh-gateway-clusterrole.yaml b/charts/consul/templates/mesh-gateway-clusterrole.yaml index 3053105105..b951418b26 100644 --- a/charts/consul/templates/mesh-gateway-clusterrole.yaml +++ b/charts/consul/templates/mesh-gateway-clusterrole.yaml @@ -1,5 +1,4 @@ {{- if .Values.meshGateway.enabled }} -{{- if not (mustHas "resource-apis" .Values.global.experiments) }} apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: @@ -33,4 +32,3 @@ rules: rules: [] {{- end }} {{- end }} -{{- end }} diff --git a/charts/consul/templates/mesh-gateway-clusterrolebinding.yaml b/charts/consul/templates/mesh-gateway-clusterrolebinding.yaml index 2fb80fc04c..f8150ebb53 100644 --- a/charts/consul/templates/mesh-gateway-clusterrolebinding.yaml +++ b/charts/consul/templates/mesh-gateway-clusterrolebinding.yaml @@ -1,5 +1,4 @@ {{- if .Values.meshGateway.enabled }} -{{- if not (mustHas "resource-apis" .Values.global.experiments) }} apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: @@ -19,4 +18,3 @@ subjects: name: {{ template "consul.fullname" . }}-mesh-gateway namespace: {{ .Release.Namespace }} {{- end }} -{{- end }} diff --git a/charts/consul/templates/mesh-gateway-deployment.yaml b/charts/consul/templates/mesh-gateway-deployment.yaml index efcc1f910b..a22bdc0879 100644 --- a/charts/consul/templates/mesh-gateway-deployment.yaml +++ b/charts/consul/templates/mesh-gateway-deployment.yaml @@ -1,5 +1,4 @@ {{- if .Values.meshGateway.enabled }} -{{- if not (mustHas "resource-apis" .Values.global.experiments) }} {{- if not .Values.connectInject.enabled }}{{ fail "connectInject.enabled must be true" }}{{ end -}} {{- if and .Values.global.acls.manageSystemACLs (ne .Values.meshGateway.consulServiceName "") (ne .Values.meshGateway.consulServiceName "mesh-gateway") }}{{ fail "if global.acls.manageSystemACLs is true, meshGateway.consulServiceName cannot be set" }}{{ end -}} {{- if .Values.meshGateway.globalMode }}{{ fail "meshGateway.globalMode is no longer supported; instead, you must migrate to CRDs (see www.consul.io/docs/k8s/crds/upgrade-to-crds)" }}{{ end -}} @@ -318,4 +317,3 @@ spec: {{ tpl .Values.meshGateway.nodeSelector . | indent 8 | trim }} {{- end }} {{- end }} -{{- end }} diff --git a/charts/consul/templates/mesh-gateway-podsecuritypolicy.yaml b/charts/consul/templates/mesh-gateway-podsecuritypolicy.yaml index 56e4b7924c..04576fe926 100644 --- a/charts/consul/templates/mesh-gateway-podsecuritypolicy.yaml +++ b/charts/consul/templates/mesh-gateway-podsecuritypolicy.yaml @@ -1,5 +1,4 @@ {{- if and .Values.global.enablePodSecurityPolicies .Values.meshGateway.enabled }} -{{- if not (mustHas "resource-apis" .Values.global.experiments) }} apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: @@ -53,4 +52,3 @@ spec: rule: 'RunAsAny' readOnlyRootFilesystem: false {{- end }} -{{- end }} diff --git a/charts/consul/templates/mesh-gateway-service.yaml b/charts/consul/templates/mesh-gateway-service.yaml index 80f82ac897..5fdceca8df 100644 --- a/charts/consul/templates/mesh-gateway-service.yaml +++ b/charts/consul/templates/mesh-gateway-service.yaml @@ -1,5 +1,4 @@ {{- if and .Values.meshGateway.enabled }} -{{- if not (mustHas "resource-apis" .Values.global.experiments) }} apiVersion: v1 kind: Service metadata: @@ -32,4 +31,3 @@ spec: {{ tpl .Values.meshGateway.service.additionalSpec . | nindent 2 | trim }} {{- end }} {{- end }} -{{- end }} diff --git a/charts/consul/templates/mesh-gateway-serviceaccount.yaml b/charts/consul/templates/mesh-gateway-serviceaccount.yaml index b1a0661eaa..8c2da5ae06 100644 --- a/charts/consul/templates/mesh-gateway-serviceaccount.yaml +++ b/charts/consul/templates/mesh-gateway-serviceaccount.yaml @@ -1,5 +1,4 @@ {{- if .Values.meshGateway.enabled }} -{{- if not (mustHas "resource-apis" .Values.global.experiments) }} apiVersion: v1 kind: ServiceAccount metadata: @@ -22,4 +21,3 @@ imagePullSecrets: {{- end }} {{- end }} {{- end }} -{{- end }} diff --git a/charts/consul/templates/partition-init-job.yaml b/charts/consul/templates/partition-init-job.yaml index 21ad2930b8..bb4e7b3706 100644 --- a/charts/consul/templates/partition-init-job.yaml +++ b/charts/consul/templates/partition-init-job.yaml @@ -118,9 +118,6 @@ spec: {{- if .Values.global.cloud.enabled }} -tls-server-name=server.{{ .Values.global.datacenter}}.{{ .Values.global.domain}} \ {{- end }} - {{- if and (mustHas "resource-apis" .Values.global.experiments) (mustHas "v2tenancy" .Values.global.experiments) }} - -enable-v2tenancy=true - {{- end }} resources: requests: memory: "50Mi" diff --git a/charts/consul/templates/server-config-configmap.yaml b/charts/consul/templates/server-config-configmap.yaml index 8c74364a29..423eeac60a 100644 --- a/charts/consul/templates/server-config-configmap.yaml +++ b/charts/consul/templates/server-config-configmap.yaml @@ -57,12 +57,7 @@ data: "enabled": true }, {{- end }} - "server": true, - "leave_on_terminate": true, - "autopilot": { - "min_quorum": {{ template "consul.server.autopilotMinQuorum" . }}, - "disable_upgrade_migration": true - } + "server": true } {{- $vaultConnectCAEnabled := and .Values.global.secretsBackend.vault.connectCA.address .Values.global.secretsBackend.vault.connectCA.rootPKIPath .Values.global.secretsBackend.vault.connectCA.intermediatePKIPath -}} {{- if and .Values.global.secretsBackend.vault.enabled $vaultConnectCAEnabled }} diff --git a/charts/consul/templates/server-disruptionbudget.yaml b/charts/consul/templates/server-disruptionbudget.yaml index 56805edc2a..edf9c1c57f 100644 --- a/charts/consul/templates/server-disruptionbudget.yaml +++ b/charts/consul/templates/server-disruptionbudget.yaml @@ -17,7 +17,7 @@ metadata: release: {{ .Release.Name }} component: server spec: - maxUnavailable: {{ template "consul.server.pdb.maxUnavailable" . }} + maxUnavailable: {{ template "consul.pdb.maxUnavailable" . }} selector: matchLabels: app: {{ template "consul.name" . }} diff --git a/charts/consul/templates/server-statefulset.yaml b/charts/consul/templates/server-statefulset.yaml index 6dcd2e320a..e744f2fe80 100644 --- a/charts/consul/templates/server-statefulset.yaml +++ b/charts/consul/templates/server-statefulset.yaml @@ -506,17 +506,8 @@ spec: {{- if and .Values.global.cloud.enabled .Values.global.cloud.resourceId.secretName }} -hcl="cloud { resource_id = \"${HCP_RESOURCE_ID}\" }" {{- end }} - - {{- if .Values.global.experiments }} - {{- $commaSeparatedValues := "" }} - {{- range $index, $value := .Values.global.experiments }} - {{- if ne $index 0 }} - {{- $commaSeparatedValues = printf "%s,\\\"%s\\\"" $commaSeparatedValues $value }} - {{- else }} - {{- $commaSeparatedValues = printf "\\\"%s\\\"" $value }} - {{- end }} - {{- end }} - -hcl="experiments=[{{ $commaSeparatedValues }}]" + {{- if (mustHas "resource-apis" .Values.global.experiments) }} + -hcl="experiments=[\"resource-apis\"]" {{- end }} volumeMounts: - name: data-{{ .Release.Namespace | trunc 58 | trimSuffix "-" }} diff --git a/charts/consul/test/unit/connect-inject-clusterrole.bats b/charts/consul/test/unit/connect-inject-clusterrole.bats index cfe64337d9..d02b9eacde 100644 --- a/charts/consul/test/unit/connect-inject-clusterrole.bats +++ b/charts/consul/test/unit/connect-inject-clusterrole.bats @@ -241,28 +241,3 @@ load _helpers yq '.rules[13].resourceNames | index("fakescc")' | tee /dev/stderr) [ "${object}" == 0 ] } - -#-------------------------------------------------------------------- -# resource-apis - -@test "connectInject/ClusterRole: adds permission to mesh.consul.hashicorp.com with resource-apis in global.experiments" { - cd `chart_dir` - local object=$(helm template \ - -s templates/connect-inject-clusterrole.yaml \ - --set 'ui.enabled=false' \ - --set 'global.experiments={resource-apis}' \ - . | tee /dev/stderr | - yq '.rules[4].apiGroups | index("mesh.consul.hashicorp.com")' | tee /dev/stderr) - [ "${object}" == 0 ] -} - -@test "connectInject/ClusterRole: adds permission to multicluster.consul.hashicorp.com with resource-apis in global.experiments" { - cd `chart_dir` - local object=$(helm template \ - -s templates/connect-inject-clusterrole.yaml \ - --set 'ui.enabled=false' \ - --set 'global.experiments={resource-apis}' \ - . | tee /dev/stderr | - yq '.rules[6].apiGroups | index("multicluster.consul.hashicorp.com")' | tee /dev/stderr) - [ "${object}" == 0 ] -} \ No newline at end of file diff --git a/charts/consul/test/unit/connect-inject-deployment.bats b/charts/consul/test/unit/connect-inject-deployment.bats index 1e6397e39c..67be4474ea 100755 --- a/charts/consul/test/unit/connect-inject-deployment.bats +++ b/charts/consul/test/unit/connect-inject-deployment.bats @@ -2710,32 +2710,4 @@ reservedNameTest() { yq '.spec.template.spec.containers[0].command | any(contains("-enable-resource-apis=true"))' | tee /dev/stderr) [ "${actual}" = "true" ] -} - -#-------------------------------------------------------------------- -# v2tenancy - -@test "connectInject/Deployment: v2tenancy is not set by default" { - cd `chart_dir` - local actual=$(helm template \ - -s templates/connect-inject-deployment.yaml \ - --set 'connectInject.enabled=true' \ - . | tee /dev/stderr | - yq '.spec.template.spec.containers[0].command | any(contains("-enable-v2tenancy=true"))' | tee /dev/stderr) - - [ "${actual}" = "false" ] -} - -@test "connectInject/Deployment: -enable-v2tenancy=true is set when global.experiments contains [\"resource-apis\", \"v2tenancy\"]" { - cd `chart_dir` - local actual=$(helm template \ - -s templates/connect-inject-deployment.yaml \ - --set 'connectInject.enabled=true' \ - --set 'global.experiments[0]=resource-apis' \ - --set 'global.experiments[1]=v2tenancy' \ - --set 'ui.enabled=false' \ - . | tee /dev/stderr | - yq '.spec.template.spec.containers[0].command | any(contains("-enable-v2tenancy=true"))' | tee /dev/stderr) - - [ "${actual}" = "true" ] -} +} \ No newline at end of file diff --git a/charts/consul/test/unit/gateway-resources-configmap.bats b/charts/consul/test/unit/gateway-resources-configmap.bats index ea3decc5c7..80225eeefb 100644 --- a/charts/consul/test/unit/gateway-resources-configmap.bats +++ b/charts/consul/test/unit/gateway-resources-configmap.bats @@ -2,20 +2,18 @@ load _helpers -target=templates/gateway-resources-configmap.yaml - @test "gateway-resources/ConfigMap: disabled with connectInject.enabled=false" { cd `chart_dir` assert_empty helm template \ - -s $target \ + -s templates/gateway-resources-configmap.yaml \ --set 'connectInject.enabled=false' \ - . + . } @test "gateway-resources/ConfigMap: enabled with connectInject.enabled=true" { cd `chart_dir` local actual=$(helm template \ - -s $target \ + -s templates/gateway-resources-configmap.yaml \ --set 'connectInject.enabled=true' \ . | tee /dev/stderr | yq 'length > 0' | tee /dev/stderr) @@ -25,7 +23,7 @@ target=templates/gateway-resources-configmap.yaml @test "gateway-resources/ConfigMap: contains resources configuration as JSON" { cd `chart_dir` local resources=$(helm template \ - -s $target \ + -s templates/gateway-resources-configmap.yaml \ --set 'connectInject.enabled=true' \ --set 'connectInject.apiGateway.managedGatewayClass.resources.requests.memory=200Mi' \ --set 'connectInject.apiGateway.managedGatewayClass.resources.requests.cpu=200m' \ @@ -46,432 +44,3 @@ target=templates/gateway-resources-configmap.yaml local actual=$(echo $resources | jq -r '.limits.cpu') [ $actual = '220m' ] } - -@test "gateway-resources/ConfigMap: does not contain config.yaml resources without .global.experiments equal to resource-apis" { - cd `chart_dir` - local resources=$(helm template \ - -s $target \ - --set 'connectInject.enabled=true' \ - --set 'ui.enabled=false' \ - . | tee /dev/stderr | - yq '.data["config.yaml"]' | tee /dev/stderr) - [ $resources = null ] - -} - -@test "gateway-resources/ConfigMap: contains config.yaml resources with .global.experiments equal to resource-apis" { - cd `chart_dir` - local resources=$(helm template \ - -s $target \ - --set 'connectInject.enabled=true' \ - --set 'meshGateway.enabled=true' \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - . | tee /dev/stderr | - yq '.data["config.yaml"]' | tee /dev/stderr) - - [ "$resources" != null ] -} - -#-------------------------------------------------------------------- -# Mesh Gateway logLevel configuration - -@test "gateway-resources/ConfigMap: Mesh Gateway logLevel default configuration" { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'meshGateway.enabled=true' \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.container.consul.logging.level') - [ "${actual}" = 'info' ] - - local actual=$(echo "$config" | yq -r '.initContainer.consul.logging.level') - [ "${actual}" = 'info' ] -} - - -#-------------------------------------------------------------------- -# API Gateway logLevel configuration - -@test "gateway-resources/ConfigMap: API Gateway logLevel default configuration" { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'meshGateway.enabled=false' \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.container.consul.logging.level') - [ "${actual}" = 'info' ] - - local actual=$(echo "$config" | yq -r '.initContainer.consul.logging.level') - [ "${actual}" = 'info' ] -} - - - -@test "gateway-resources/ConfigMap: Mesh Gateway logLevel custom global configuration" { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'meshGateway.enabled=true' \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'global.logLevel=debug' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.container.consul.logging.level') - [ "${actual}" = 'debug' ] - - local actual=$(echo "$config" | yq -r '.initContainer.consul.logging.level') - [ "${actual}" = 'debug' ] -} - -@test "gateway-resources/ConfigMap: Mesh Gateway logLevel custom meshGateway configuration" { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'meshGateway.enabled=true' \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'meshGateway.logLevel=debug' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.container.consul.logging.level') - [ "${actual}" = 'debug' ] - - local actual=$(echo "$config" | yq -r '.initContainer.consul.logging.level') - [ "${actual}" = 'debug' ] -} - -@test "gateway-resources/ConfigMap: Mesh Gateway logLevel custom meshGateway configuration overrides global configuration" { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'meshGateway.enabled=true' \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'global.logLevel=error' \ - --set 'meshGateway.logLevel=debug' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.container.consul.logging.level') - [ "${actual}" = 'debug' ] - - local actual=$(echo "$config" | yq -r '.initContainer.consul.logging.level') - [ "${actual}" = 'debug' ] -} - -#-------------------------------------------------------------------- -# Mesh Gateway Extra Labels configuration - -@test "gateway-resources/ConfigMap: Mesh Gateway gets Extra Labels when set" { - cd `chart_dir` - local actual=$(helm template \ - -s $target \ - --set 'connectInject.enabled=true' \ - --set 'meshGateway.enabled=true' \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'global.extraLabels.foo'='bar' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment.labels.set.foo' | tee /dev/stderr - ) - [ "$actual" = 'bar' ] -} - -#-------------------------------------------------------------------- -# Mesh Gateway annotations configuration - -@test "gateway-resources/ConfigMap: Mesh Gateway gets annotations when set" { - cd `chart_dir` - local actual=$(helm template \ - -s $target \ - --set 'connectInject.enabled=true' \ - --set 'meshGateway.enabled=true' \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'meshGateway.annotations.foo'='bar' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment.annotations.set.foo' | tee /dev/stderr - ) - [ "$actual" = 'bar' ] -} - -#-------------------------------------------------------------------- -# Mesh Gateway WAN Address configuration - -@test "gateway-resources/ConfigMap: Mesh Gateway WAN Address default annotations" { - cd `chart_dir` - local annotations=$(helm template \ - -s $target \ - --set 'connectInject.enabled=true' \ - --set 'meshGateway.enabled=true' \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.meshGateways[0].metadata.annotations' | tee /dev/stderr) - - local actual=$(echo "$annotations" | yq -r '.["consul.hashicorp.com/gateway-wan-address-source"]') - [ "${actual}" = 'Service' ] - - local actual=$(echo "$annotations" | yq -r '.["consul.hashicorp.com/gateway-wan-port"]') - [ "${actual}" = '443' ] - - local actual=$(echo "$annotations" | yq -r '.["consul.hashicorp.com/gateway-wan-address-static"]') - [ "${actual}" = '' ] -} - - -@test "gateway-resources/ConfigMap: Mesh Gateway WAN Address NodePort annotations" { - cd `chart_dir` - local annotations=$(helm template \ - -s $target \ - --set 'connectInject.enabled=true' \ - --set 'meshGateway.enabled=true' \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'meshGateway.wanAddress.source=Service' \ - --set 'meshGateway.service.type=NodePort' \ - --set 'meshGateway.service.nodePort=30000' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.meshGateways[0].metadata.annotations' | tee /dev/stderr) - - local actual=$(echo "$annotations" | yq -r '.["consul.hashicorp.com/gateway-wan-address-source"]') - [ "${actual}" = 'Service' ] - - local actual=$(echo "$annotations" | yq -r '.["consul.hashicorp.com/gateway-wan-port"]') - [ "${actual}" = '30000' ] - - local actual=$(echo "$annotations" | yq -r '.["consul.hashicorp.com/gateway-wan-address-static"]') - [ "${actual}" = '' ] -} - -@test "gateway-resources/ConfigMap: Mesh Gateway WAN Address static configuration" { - cd `chart_dir` - local annotations=$(helm template \ - -s $target \ - --set 'connectInject.enabled=true' \ - --set 'meshGateway.enabled=true' \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'meshGateway.wanAddress.source=Static' \ - --set 'meshGateway.wanAddress.static=127.0.0.1' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.meshGateways[0].metadata.annotations' | tee /dev/stderr) - - local actual=$(echo "$annotations" | yq -r '.["consul.hashicorp.com/gateway-wan-address-source"]') - [ "${actual}" = 'Static' ] - - local actual=$(echo "$annotations" | yq -r '.["consul.hashicorp.com/gateway-wan-port"]') - [ "${actual}" = '443' ] - - local actual=$(echo "$annotations" | yq -r '.["consul.hashicorp.com/gateway-wan-address-static"]') - [ "${actual}" = '127.0.0.1' ] -} - -#-------------------------------------------------------------------- -# API Gateway Tests mapPrivilageContainerPorts - -@test "gateway-resources/ConfigMap: API Gateway mapPrivilageContainerPorts empty by default { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'global.logLevel=error' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.container.portModifier') - - [ "${actual}" = 'null' ] - - local actual=$(echo "$config" | yq -r '.initContainer.portModifier') - - [ "${actual}" = 'null' ] -} - - -@test "gateway-resources/ConfigMap: API Gateway mapPrivilageContainerPorts overrides default { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'global.logLevel=error' \ - --set 'connectInject.apiGateway.managedGatewayClass.mapPrivilegedContainerPorts=80' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.container.portModifier') - - [ "${actual}" = '80' ] - - local actual=$(echo "$config" | yq -r '.initContainer.portModifier') - - [ "${actual}" = '80' ] -} - -#-------------------------------------------------------------------- -# API Gateway Tests deployment replicas - -@test "gateway-resources/ConfigMap: API Gateway deploymentConfig overrides default { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'global.logLevel=error' \ - --set 'connectInject.apiGateway.managedGatewayClass.deployment.defaultInstances=2' \ - --set 'connectInject.apiGateway.managedGatewayClass.deployment.maxInstances=3' \ - --set 'connectInject.apiGateway.managedGatewayClass.deployment.minInstances=1' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.replicas.default') - [ "${actual}" = '2' ] - - local actual=$(echo "$config" | yq -r '.replicas.min') - [ "${actual}" = '1' ] - - local actual=$(echo "$config" | yq -r '.replicas.max') - [ "${actual}" = '3' ] -} - -@test "gateway-resources/ConfigMap: API Gateway deploymentConfig default { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'global.logLevel=error' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.replicas.default') - [ "${actual}" = '1' ] - - local actual=$(echo "$config" | yq -r '.replicas.min') - [ "${actual}" = '1' ] - - local actual=$(echo "$config" | yq -r '.replicas.max') - [ "${actual}" = '1' ] -} - -#-------------------------------------------------------------------- -# API Gateway Tests nodeSelector - -@test "gateway-resources/ConfigMap: API Gateway nodeSelector overrides default { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'global.logLevel=error' \ - --set 'connectInject.apiGateway.managedGatewayClass.nodeSelector=- key: value' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.nodeSelector[0].key') - echo ${actual} - - [ "${actual}" = 'value' ] -} - -@test "gateway-resources/ConfigMap: API Gateway nodeSelector default { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'global.logLevel=error' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.nodeSelector') - [ "${actual}" = 'null' ] -} - -#-------------------------------------------------------------------- -# API Gateway Tests tolerations - -@test "gateway-resources/ConfigMap: API Gateway tolerations overrides default { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'global.logLevel=error' \ - --set 'connectInject.apiGateway.managedGatewayClass.tolerations=- key: value' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.tolerations[0].key') - echo "${actual}" - - [ "${actual}" = 'value' ] -} - - - -@test "gateway-resources/ConfigMap: API Gateway tolerations default { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'global.logLevel=error' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.deployment' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.tolerations') - [ "${actual}" = 'null' ] -} - - -#-------------------------------------------------------------------- -# API Gateway Tests copyAnnotations - -@test "gateway-resources/ConfigMap: API Gateway copyAnnotations overrides default { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'global.logLevel=error' \ - --set 'connectInject.apiGateway.managedGatewayClass.copyAnnotations.service.annotations=- annotation.name' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.annotations' | tee /dev/stderr) - - local actual=$(echo "$config" | yq -r '.service[0]') - echo "${actual}" - [ "${actual}" = 'annotation.name' ] -} - -@test "gateway-resources/ConfigMap: API Gateway copyAnnotations default { - cd `chart_dir` - local config=$(helm template \ - -s $target \ - --set 'global.experiments[0]=resource-apis' \ - --set 'ui.enabled=false' \ - --set 'global.logLevel=error' \ - . | tee /dev/stderr | - yq -r '.data["config.yaml"]' | yq -r '.gatewayClassConfigs[0].spec.annotations' | tee /dev/stderr) - - local actual=$(echo "$config" | jq -r '.service') - [ "${actual}" = 'null' ] -} - - -#-------------------------------------------------------------------- -# TODO openShiftSSCName \ No newline at end of file diff --git a/charts/consul/test/unit/helpers.bats b/charts/consul/test/unit/helpers.bats index 20772788f8..f8523a7220 100644 --- a/charts/consul/test/unit/helpers.bats +++ b/charts/consul/test/unit/helpers.bats @@ -348,7 +348,7 @@ load _helpers [[ "$output" =~ "When the value global.experiments.resourceAPIs is set, global.peering.enabled is currently unsupported." ]] } -@test "connectInject/Deployment: fails if resource-apis is set, v2tenancy is unset, and admin partitions are enabled" { +@test "connectInject/Deployment: fails if resource-apis is set and admin partitions are enabled" { cd `chart_dir` run helm template \ -s templates/tests/test-runner.yaml \ @@ -359,7 +359,7 @@ load _helpers --set 'global.adminPartitions.enabled=true' \ . [ "$status" -eq 1 ] - [[ "$output" =~ "When the value global.experiments.resourceAPIs is set, global.experiments.v2tenancy must also be set to support global.adminPartitions.enabled." ]] + [[ "$output" =~ "When the value global.experiments.resourceAPIs is set, global.adminPartitions.enabled is currently unsupported." ]] } @test "connectInject/Deployment: fails if resource-apis is set and federation is enabled" { @@ -431,6 +431,18 @@ load _helpers [[ "$output" =~ "When the value global.experiments.resourceAPIs is set, syncCatalog.enabled is currently unsupported." ]] } +@test "connectInject/Deployment: fails if resource-apis is set and meshGateway is enabled" { + cd `chart_dir` + run helm template \ + -s templates/tests/test-runner.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.experiments[0]=resource-apis' \ + --set 'ui.enabled=false' \ + --set 'meshGateway.enabled=true' . + [ "$status" -eq 1 ] + [[ "$output" =~ "When the value global.experiments.resourceAPIs is set, meshGateway.enabled is currently unsupported." ]] +} + @test "connectInject/Deployment: fails if resource-apis is set and ingressGateways is enabled" { cd `chart_dir` run helm template \ diff --git a/charts/consul/test/unit/partition-init-job.bats b/charts/consul/test/unit/partition-init-job.bats index 745e23adfe..131d13f8a1 100644 --- a/charts/consul/test/unit/partition-init-job.bats +++ b/charts/consul/test/unit/partition-init-job.bats @@ -58,7 +58,9 @@ load _helpers cd `chart_dir` assert_empty helm template \ -s templates/partition-init-job.yaml \ - --set 'global.adminPartitions.enabled=false' \ + --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ + --set 'server.enabled=true' \ . } @@ -109,27 +111,6 @@ load _helpers [ "${actual}" = "5s" ] } -#-------------------------------------------------------------------- -# v2tenancy experiment - -@test "partitionInit/Job: -enable-v2tenancy=true is set when global.experiments contains [\"resource-apis\", \"v2tenancy\"]" { - cd `chart_dir` - local actual=$(helm template \ - -s templates/partition-init-job.yaml \ - --set 'global.adminPartitions.enabled=true' \ - --set 'global.enableConsulNamespaces=true' \ - --set 'server.enabled=false' \ - --set 'global.adminPartitions.name=bar' \ - --set 'externalServers.enabled=true' \ - --set 'externalServers.hosts[0]=foo' \ - --set 'global.experiments[0]=resource-apis' \ - --set 'global.experiments[1]=v2tenancy' \ - --set 'ui.enabled=false' \ - . | tee /dev/stderr | - yq '.spec.template.spec.containers[0].command | any(contains("-enable-v2tenancy=true"))' | tee /dev/stderr) - [ "${actual}" = "true" ] -} - #-------------------------------------------------------------------- # global.tls.enabled diff --git a/charts/consul/test/unit/server-config-configmap.bats b/charts/consul/test/unit/server-config-configmap.bats index 45b8f09518..9f3185626e 100755 --- a/charts/consul/test/unit/server-config-configmap.bats +++ b/charts/consul/test/unit/server-config-configmap.bats @@ -1521,62 +1521,4 @@ load _helpers yq -r '.data["telemetry-config.json"]' | jq -r .telemetry.enable_host_metrics | tee /dev/stderr) [ "${actual}" = "true" ] -} - -#-------------------------------------------------------------------- -# server.autopilot.min_quorum - -@test "server/ConfigMap: autopilot.min_quorum=1 when replicas=1" { - cd `chart_dir` - local actual=$(helm template \ - -s templates/server-config-configmap.yaml \ - --set 'server.replicas=1' \ - . | tee /dev/stderr | - yq -r '.data["server.json"]' | jq -r .autopilot.min_quorum | tee /dev/stderr) - - [ "${actual}" = "1" ] -} - -@test "server/ConfigMap: autopilot.min_quorum=2 when replicas=2" { - cd `chart_dir` - local actual=$(helm template \ - -s templates/server-config-configmap.yaml \ - --set 'server.replicas=2' \ - . | tee /dev/stderr | - yq -r '.data["server.json"]' | jq -r .autopilot.min_quorum | tee /dev/stderr) - - [ "${actual}" = "2" ] -} - -@test "server/ConfigMap: autopilot.min_quorum=2 when replicas=3" { - cd `chart_dir` - local actual=$(helm template \ - -s templates/server-config-configmap.yaml \ - --set 'server.replicas=3' \ - . | tee /dev/stderr | - yq -r '.data["server.json"]' | jq -r .autopilot.min_quorum | tee /dev/stderr) - - [ "${actual}" = "2" ] -} - -@test "server/ConfigMap: autopilot.min_quorum=3 when replicas=4" { - cd `chart_dir` - local actual=$(helm template \ - -s templates/server-config-configmap.yaml \ - --set 'server.replicas=4' \ - . | tee /dev/stderr | - yq -r '.data["server.json"]' | jq -r .autopilot.min_quorum | tee /dev/stderr) - - [ "${actual}" = "3" ] -} - -@test "server/ConfigMap: autopilot.min_quorum=3 when replicas=5" { - cd `chart_dir` - local actual=$(helm template \ - -s templates/server-config-configmap.yaml \ - --set 'server.replicas=5' \ - . | tee /dev/stderr | - yq -r '.data["server.json"]' | jq -r .autopilot.min_quorum | tee /dev/stderr) - - [ "${actual}" = "3" ] -} +} \ No newline at end of file diff --git a/charts/consul/test/unit/server-disruptionbudget.bats b/charts/consul/test/unit/server-disruptionbudget.bats index 5d30d8b628..eb076ac775 100755 --- a/charts/consul/test/unit/server-disruptionbudget.bats +++ b/charts/consul/test/unit/server-disruptionbudget.bats @@ -59,16 +59,6 @@ load _helpers [ "${actual}" = "0" ] } -@test "server/DisruptionBudget: correct maxUnavailable with replicas=2" { - cd `chart_dir` - local actual=$(helm template \ - -s templates/server-disruptionbudget.yaml \ - --set 'server.replicas=2' \ - . | tee /dev/stderr | - yq '.spec.maxUnavailable' | tee /dev/stderr) - [ "${actual}" = "1" ] -} - @test "server/DisruptionBudget: correct maxUnavailable with replicas=3" { cd `chart_dir` local actual=$(helm template \ @@ -107,7 +97,7 @@ load _helpers --set 'server.replicas=6' \ . | tee /dev/stderr | yq '.spec.maxUnavailable' | tee /dev/stderr) - [ "${actual}" = "1" ] + [ "${actual}" = "2" ] } @test "server/DisruptionBudget: correct maxUnavailable with replicas=7" { @@ -117,7 +107,7 @@ load _helpers --set 'server.replicas=7' \ . | tee /dev/stderr | yq '.spec.maxUnavailable' | tee /dev/stderr) - [ "${actual}" = "1" ] + [ "${actual}" = "2" ] } @test "server/DisruptionBudget: correct maxUnavailable with replicas=8" { @@ -127,21 +117,9 @@ load _helpers --set 'server.replicas=8' \ . | tee /dev/stderr | yq '.spec.maxUnavailable' | tee /dev/stderr) - [ "${actual}" = "1" ] -} - -@test "server/DisruptionBudget: correct maxUnavailable when set with value" { - cd `chart_dir` - local actual=$(helm template \ - -s templates/server-disruptionbudget.yaml \ - --set 'server.replicas=5' \ - --set 'server.disruptionBudget.maxUnavailable=5' \ - . | tee /dev/stderr | - yq '.spec.maxUnavailable' | tee /dev/stderr) - [ "${actual}" = "5" ] + [ "${actual}" = "3" ] } - #-------------------------------------------------------------------- # apiVersion diff --git a/charts/consul/test/unit/server-statefulset.bats b/charts/consul/test/unit/server-statefulset.bats index 8fceb5c474..d2b1e2ba86 100755 --- a/charts/consul/test/unit/server-statefulset.bats +++ b/charts/consul/test/unit/server-statefulset.bats @@ -1079,7 +1079,7 @@ load _helpers -s templates/server-statefulset.yaml \ . | tee /dev/stderr | yq -r '.spec.template.metadata.annotations."consul.hashicorp.com/config-checksum"' | tee /dev/stderr) - [ "${actual}" = a4771bea366d4a6ee9037572665dc4040519dc22e9b0ff3463a263aab13675b8 ] + [ "${actual}" = 0fb82d8e2e58b3e11c8803a5e6a6575b735b011b373304a724317c299d95cdbb ] } @test "server/StatefulSet: adds config-checksum annotation when extraConfig is provided" { @@ -1089,7 +1089,7 @@ load _helpers --set 'server.extraConfig="{\"hello\": \"world\"}"' \ . | tee /dev/stderr | yq -r '.spec.template.metadata.annotations."consul.hashicorp.com/config-checksum"' | tee /dev/stderr) - [ "${actual}" = c6b872933263bf5fe847d61e638035637d2db89edf31ad25d0aaeaa5261649c9 ] + [ "${actual}" = a05ee305cfb15c76587e815d08472098c790ccce6322ab79f1d9702020be5a5e ] } @test "server/StatefulSet: adds config-checksum annotation when config is updated" { @@ -1099,7 +1099,7 @@ load _helpers --set 'global.acls.manageSystemACLs=true' \ . | tee /dev/stderr | yq -r '.spec.template.metadata.annotations."consul.hashicorp.com/config-checksum"' | tee /dev/stderr) - [ "${actual}" = 576044232d6181bca69628af87c12f15311ebd3f0ab700e112b3e1dea9225125 ] + [ "${actual}" = 13e6436e0a8e2ee57e35abc358c068eb575737e706dd9e4b3231dff69228d89d ] } #-------------------------------------------------------------------- diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index b547377747..f0f56092e4 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -66,7 +66,7 @@ global: # image: "hashicorp/consul-enterprise:1.10.0-ent" # ``` # @default: hashicorp/consul: - image: docker.mirror.hashicorp.services/hashicorppreview/consul:1.19-dev + image: docker.mirror.hashicorp.services/hashicorppreview/consul:1.17-dev # Array of objects containing image pull secret names that will be applied to each service account. # This can be used to reference image pull secrets if using a custom consul or consul-k8s-control-plane Docker image. @@ -86,7 +86,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: docker.mirror.hashicorp.services/hashicorppreview/consul-k8s-control-plane:1.5-dev + imageK8S: docker.mirror.hashicorp.services/hashicorppreview/consul-k8s-control-plane:1.3.4-dev # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running @@ -791,7 +791,7 @@ global: # The name (and tag) of the consul-dataplane Docker image used for the # connect-injected sidecar proxies and mesh, terminating, and ingress gateways. # @default: hashicorp/consul-dataplane: - imageConsulDataplane: docker.mirror.hashicorp.services/hashicorppreview/consul-dataplane:1.5-dev + imageConsulDataplane: docker.mirror.hashicorp.services/hashicorppreview/consul-dataplane:1.3-dev # Configuration for running this Helm chart on the Red Hat OpenShift platform. # This Helm chart currently supports OpenShift v4.x+. @@ -911,14 +911,6 @@ global: # upgrade could risk breaking your Consul cluster. # If this flag is set, Consul components will use the # V2 resources APIs for all operations. - # * `v2tenancy`: - # _**Danger**_! This feature is under active development. It is not - # recommended for production use. Setting this flag during an - # upgrade could risk breaking your Consul cluster. - # If this flag is set, Consul V2 resources (catalog, mesh, auth, etc) - # will use V2 implementations for tenancy (partitions and namesapces) - # instead of bridging to the existing V1 implementations. The - # `resource-apis` feature flag must also be set. # # Example: # @@ -1163,14 +1155,8 @@ server: # the server cluster is enabled. To disable, set to `false`. enabled: true - # The maximum number of unavailable pods. In most cases you should not change this as it is automatically set to - # the correct number when left as null. This setting has been kept to not break backwards compatibility. - # - # By default, this is set to 1 internally in the chart. When server pods are stopped gracefully, they leave the Raft - # consensus pool. When running an odd number of servers, one server leaving the pool does not change the quorum - # size, and so fault tolerance is not affected. However, if more than one server were to leave the pool, the quorum - # size would change. That's why this is set to 1 internally and should not be changed in most cases. - # + # The maximum number of unavailable pods. By default, this will be + # automatically computed based on the `server.replicas` value to be `(n/2)-1`. # If you need to set this to `0`, you will need to add a # --set 'server.disruptionBudget.maxUnavailable=0'` flag to the helm chart installation # command because of a limitation in the Helm templating language. @@ -2942,7 +2928,7 @@ meshGateway: # are routable from other datacenters. # # - `Static` - Use the address hardcoded in `meshGateway.wanAddress.static`. - source: Service + source: "Service" # Port that gets registered for WAN traffic. # If source is set to "Service" then this setting will have no effect. diff --git a/cli/cmd/proxy/list/command.go b/cli/cmd/proxy/list/command.go index 0204832c44..e0211ebe37 100644 --- a/cli/cmd/proxy/list/command.go +++ b/cli/cmd/proxy/list/command.go @@ -335,5 +335,4 @@ func (c *ListCommand) output(pods []v1.Pod) { } else { c.UI.Table(tbl) } - } diff --git a/cli/go.mod b/cli/go.mod index f54431034b..e2fba6d8a7 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -19,11 +19,11 @@ require ( github.com/stretchr/testify v1.8.4 golang.org/x/text v0.14.0 helm.sh/helm/v3 v3.11.3 - k8s.io/api v0.26.12 + k8s.io/api v0.26.10 k8s.io/apiextensions-apiserver v0.26.10 - k8s.io/apimachinery v0.26.12 + k8s.io/apimachinery v0.26.10 k8s.io/cli-runtime v0.26.10 - k8s.io/client-go v0.26.12 + k8s.io/client-go v0.26.10 k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 sigs.k8s.io/yaml v1.3.0 ) diff --git a/cli/go.sum b/cli/go.sum index bceafc1d72..21f9e84fcf 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -1286,18 +1286,18 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh 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.12 h1:jJm3s5ot05SUN3tPGg3b+XWuBE7rO/X0+dnVMhxyd5o= -k8s.io/api v0.26.12/go.mod h1:N+HUXukmtXNOKDngxXrEPbZWggWx01tH/N0nG4nV0oo= +k8s.io/api v0.26.10 h1:skTnrDR0r8dg4MMLf6YZIzugxNM0BjFsWKPkNc5kOvk= +k8s.io/api v0.26.10/go.mod h1:ou/H3yviqrHtP/DSPVTfsc7qNfmU06OhajytJfYXkXw= k8s.io/apiextensions-apiserver v0.26.10 h1:wAriTUc6l7gUqJKOxhmXnYo/VNJzk4oh4QLCUR4Uq+k= k8s.io/apiextensions-apiserver v0.26.10/go.mod h1:N2qhlxkhJLSoC4f0M1/1lNG627b45SYqnOPEVFoQXw4= -k8s.io/apimachinery v0.26.12 h1:y+OgufxqLIZtyXIydRhjLBGzrYLF+qwiDdCFXYOjeN4= -k8s.io/apimachinery v0.26.12/go.mod h1:2/HZp0l6coXtS26du1Bk36fCuAEr/lVs9Q9NbpBtd1Y= +k8s.io/apimachinery v0.26.10 h1:aE+J2KIbjctFqPp3Y0q4Wh2PD+l1p2g3Zp4UYjSvtGU= +k8s.io/apimachinery v0.26.10/go.mod h1:iT1ZP4JBP34wwM+ZQ8ByPEQ81u043iqAcsJYftX9amM= k8s.io/apiserver v0.26.10 h1:gradpIHygzZN87yK+o6V3gpbCSF78HZ0hejLZQQwdDs= k8s.io/apiserver v0.26.10/go.mod h1:TGrQKQWUfQcotK3P4TtoVZxXOWklFF36QZlA5wufLs4= k8s.io/cli-runtime v0.26.10 h1:a5t8ejLCCjWBEny70uMDyPfOyOJH1qAxrrEo2a9fopU= k8s.io/cli-runtime v0.26.10/go.mod h1:i1UCYrl+n32ej4N2n2eacOMv4T94vRL0/ooOLopN23Q= -k8s.io/client-go v0.26.12 h1:kPpTpIeFNqwo4UyvoqzNp3DNK2mbGcdGv23eS1U8VMo= -k8s.io/client-go v0.26.12/go.mod h1:V7thEnIFroyNZOU30dKLiiVeqQmJz45shJG1mu7nONQ= +k8s.io/client-go v0.26.10 h1:4mDzl+1IrfRxh4Ro0s65JRGJp14w77gSMUTjACYWVRo= +k8s.io/client-go v0.26.10/go.mod h1:sh74ig838gCckU4ElYclWb24lTesPdEDPnlyg5vcbkA= k8s.io/component-base v0.26.10 h1:vl3Gfe5aC09mNxfnQtTng7u3rnBVrShOK3MAkqEleb0= k8s.io/component-base v0.26.10/go.mod h1:/IDdENUHG5uGxqcofZajovYXE9KSPzJ4yQbkYQt7oN0= k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= diff --git a/cli/version/version.go b/cli/version/version.go index f68d1632a6..feb168fbe4 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -17,7 +17,7 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "1.5.0" + Version = "1.3.4" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release diff --git a/control-plane/Dockerfile.dev b/control-plane/Dockerfile.dev deleted file mode 100644 index 5da7e2a236..0000000000 --- a/control-plane/Dockerfile.dev +++ /dev/null @@ -1,11 +0,0 @@ -# DANGER: this dockerfile is experimental and could be modified/removed at any time. -# A simple image for testing changes to consul-k8s -# -# Meant to be used with the following make target -# DEV_IMAGE= make control-plane-dev-skaffold - -FROM hashicorp/consul-k8s-control-plane as cache -ARG TARGETARCH - -COPY pkg/bin/linux_${TARGETARCH}/consul-k8s-control-plane /bin -COPY cni/pkg/bin/linux_${TARGETARCH}/consul-cni /bin diff --git a/control-plane/api-gateway/cache/consul.go b/control-plane/api-gateway/cache/consul.go index f2d6ec9bf9..0858e8959c 100644 --- a/control-plane/api-gateway/cache/consul.go +++ b/control-plane/api-gateway/cache/consul.go @@ -29,7 +29,6 @@ func init() { type templateArgs struct { EnableNamespaces bool - APIGatewayName string } var ( @@ -42,10 +41,7 @@ mesh = "read" node_prefix "" { policy = "read" } - service_prefix "" { - policy = "read" - } - service "{{.APIGatewayName}}" { + service_prefix "" { policy = "write" } {{- if .EnableNamespaces }} @@ -338,8 +334,8 @@ func (c *Cache) Write(ctx context.Context, entry api.ConfigEntry) error { return nil } -func (c *Cache) ensurePolicy(client *api.Client, gatewayName string) (string, error) { - policy := c.gatewayPolicy(gatewayName) +func (c *Cache) ensurePolicy(client *api.Client) (string, error) { + policy := c.gatewayPolicy() created, _, err := client.ACL().PolicyCreate(&policy, &api.WriteOptions{}) @@ -356,13 +352,13 @@ func (c *Cache) ensurePolicy(client *api.Client, gatewayName string) (string, er return created.ID, nil } -func (c *Cache) ensureRole(client *api.Client, gatewayName string) (string, error) { - policyID, err := c.ensurePolicy(client, gatewayName) +func (c *Cache) ensureRole(client *api.Client) (string, error) { + policyID, err := c.ensurePolicy(client) if err != nil { return "", err } - aclRoleName := fmt.Sprint("managed-gateway-acl-role-", gatewayName) + aclRoleName := "managed-gateway-acl-role" aclRole, _, err := client.ACL().RoleReadByName(aclRoleName, &api.QueryOptions{}) if err != nil { @@ -382,11 +378,10 @@ func (c *Cache) ensureRole(client *api.Client, gatewayName string) (string, erro return aclRoleName, err } -func (c *Cache) gatewayPolicy(gatewayName string) api.ACLPolicy { +func (c *Cache) gatewayPolicy() api.ACLPolicy { var data bytes.Buffer if err := gatewayTpl.Execute(&data, templateArgs{ EnableNamespaces: c.namespacesEnabled, - APIGatewayName: gatewayName, }); err != nil { // just panic if we can't compile the simple template // as it means something else is going severly wrong. @@ -394,7 +389,7 @@ func (c *Cache) gatewayPolicy(gatewayName string) api.ACLPolicy { } return api.ACLPolicy{ - Name: fmt.Sprint("api-gateway-policy-for-", gatewayName), + Name: "api-gateway-token-policy", Description: "API Gateway token Policy", Rules: data.String(), } @@ -462,7 +457,7 @@ func (c *Cache) EnsureRoleBinding(authMethod, service, namespace string) error { return err } - role, err := c.ensureRole(client, service) + role, err := c.ensureRole(client) if err != nil { return ignoreACLsDisabled(err) } diff --git a/control-plane/api-gateway/gatekeeper/init.go b/control-plane/api-gateway/gatekeeper/init.go index 1cd616bfc9..1d57123fed 100644 --- a/control-plane/api-gateway/gatekeeper/init.go +++ b/control-plane/api-gateway/gatekeeper/init.go @@ -14,7 +14,6 @@ import ( "k8s.io/utils/pointer" "github.com/hashicorp/consul-k8s/control-plane/api-gateway/common" - "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" "github.com/hashicorp/consul-k8s/control-plane/namespaces" ) @@ -121,15 +120,15 @@ func initContainer(config common.HelmConfig, name, namespace string) (corev1.Con if config.TLSEnabled { container.Env = append(container.Env, corev1.EnvVar{ - Name: constants.UseTLSEnvVar, + Name: "CONSUL_USE_TLS", Value: "true", }, corev1.EnvVar{ - Name: constants.CACertPEMEnvVar, + Name: "CONSUL_CACERT_PEM", Value: config.ConsulCACert, }, corev1.EnvVar{ - Name: constants.TLSServerNameEnvVar, + Name: "CONSUL_TLS_SERVER_NAME", Value: config.ConsulTLSServerName, }) } diff --git a/control-plane/api/auth/v2beta1/traffic_permissions_types.go b/control-plane/api/auth/v2beta1/traffic_permissions_types.go index f237fd3e12..e3a0d32f1a 100644 --- a/control-plane/api/auth/v2beta1/traffic_permissions_types.go +++ b/control-plane/api/auth/v2beta1/traffic_permissions_types.go @@ -19,6 +19,7 @@ import ( "github.com/hashicorp/consul-k8s/control-plane/api/common" inject "github.com/hashicorp/consul-k8s/control-plane/connect-inject/common" + "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" ) const ( @@ -61,6 +62,10 @@ func (in *TrafficPermissions) ResourceID(namespace, partition string) *pbresourc Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, } } diff --git a/control-plane/api/auth/v2beta1/traffic_permissions_types_test.go b/control-plane/api/auth/v2beta1/traffic_permissions_types_test.go index 85bedb6c40..79b5e71b85 100644 --- a/control-plane/api/auth/v2beta1/traffic_permissions_types_test.go +++ b/control-plane/api/auth/v2beta1/traffic_permissions_types_test.go @@ -186,16 +186,14 @@ func TestTrafficPermissions_MatchesConsul(t *testing.T) { PathExact: "/hello", PathPrefix: "/world", PathRegex: "/.*/foo", - Headers: []*pbauth.DestinationRuleHeader{ - { - Name: "x-consul-test", - Present: true, - Exact: "true", - Prefix: "prefix", - Suffix: "suffix", - Regex: "reg.*ex", - Invert: true, - }, + Header: &pbauth.DestinationRuleHeader{ + Name: "x-consul-test", + Present: true, + Exact: "true", + Prefix: "prefix", + Suffix: "suffix", + Regex: "reg.*ex", + Invert: true, }, Methods: []string{"GET", "POST"}, Exclude: []*pbauth.ExcludePermissionRule{ @@ -203,16 +201,14 @@ func TestTrafficPermissions_MatchesConsul(t *testing.T) { PathExact: "/hello", PathPrefix: "/world", PathRegex: "/.*/foo", - Headers: []*pbauth.DestinationRuleHeader{ - { - Name: "x-consul-not-test", - Present: true, - Exact: "false", - Prefix: "~prefix", - Suffix: "~suffix", - Regex: "~reg.*ex", - Invert: true, - }, + Header: &pbauth.DestinationRuleHeader{ + Name: "x-consul-not-test", + Present: true, + Exact: "false", + Prefix: "~prefix", + Suffix: "~suffix", + Regex: "~reg.*ex", + Invert: true, }, Methods: []string{"DELETE"}, PortNames: []string{"log"}, @@ -261,16 +257,14 @@ func TestTrafficPermissions_MatchesConsul(t *testing.T) { PathExact: "/hello", PathPrefix: "/world", PathRegex: "/.*/foo", - Headers: []*pbauth.DestinationRuleHeader{ - { - Name: "x-consul-test", - Present: true, - Exact: "true", - Prefix: "prefix", - Suffix: "suffix", - Regex: "reg.*ex", - Invert: true, - }, + Header: &pbauth.DestinationRuleHeader{ + Name: "x-consul-test", + Present: true, + Exact: "true", + Prefix: "prefix", + Suffix: "suffix", + Regex: "reg.*ex", + Invert: true, }, Methods: []string{"GET", "POST"}, Exclude: []*pbauth.ExcludePermissionRule{ @@ -278,16 +272,14 @@ func TestTrafficPermissions_MatchesConsul(t *testing.T) { PathExact: "/hello", PathPrefix: "/world", PathRegex: "/.*/foo", - Headers: []*pbauth.DestinationRuleHeader{ - { - Name: "x-consul-not-test", - Present: true, - Exact: "false", - Prefix: "~prefix", - Suffix: "~suffix", - Regex: "~reg.*ex", - Invert: true, - }, + Header: &pbauth.DestinationRuleHeader{ + Name: "x-consul-not-test", + Present: true, + Exact: "false", + Prefix: "~prefix", + Suffix: "~suffix", + Regex: "~reg.*ex", + Invert: true, }, Methods: []string{"DELETE"}, PortNames: []string{"log"}, @@ -317,6 +309,10 @@ func TestTrafficPermissions_MatchesConsul(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.DefaultConsulNS, Namespace: constants.DefaultConsulPartition, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, }, Data: inject.ToProtoAny(&pbmesh.ProxyConfiguration{}), @@ -395,7 +391,7 @@ func TestTrafficPermissions_Resource(t *testing.T) { PathExact: "/hello", PathPrefix: "/world", PathRegex: "/.*/foo", - Headers: []*pbauth.DestinationRuleHeader{{ + Header: &pbauth.DestinationRuleHeader{ Name: "x-consul-test", Present: true, Exact: "true", @@ -403,14 +399,14 @@ func TestTrafficPermissions_Resource(t *testing.T) { Suffix: "suffix", Regex: "reg.*ex", Invert: true, - }}, + }, Methods: []string{"GET", "POST"}, Exclude: []*pbauth.ExcludePermissionRule{ { PathExact: "/hello", PathPrefix: "/world", PathRegex: "/.*/foo", - Headers: []*pbauth.DestinationRuleHeader{{ + Header: &pbauth.DestinationRuleHeader{ Name: "x-consul-not-test", Present: true, Exact: "false", @@ -418,7 +414,7 @@ func TestTrafficPermissions_Resource(t *testing.T) { Suffix: "~suffix", Regex: "~reg.*ex", Invert: true, - }}, + }, Methods: []string{"DELETE"}, PortNames: []string{"log"}, }, @@ -466,7 +462,7 @@ func TestTrafficPermissions_Resource(t *testing.T) { PathExact: "/hello", PathPrefix: "/world", PathRegex: "/.*/foo", - Headers: []*pbauth.DestinationRuleHeader{{ + Header: &pbauth.DestinationRuleHeader{ Name: "x-consul-test", Present: true, Exact: "true", @@ -474,14 +470,14 @@ func TestTrafficPermissions_Resource(t *testing.T) { Suffix: "suffix", Regex: "reg.*ex", Invert: true, - }}, + }, Methods: []string{"GET", "POST"}, Exclude: []*pbauth.ExcludePermissionRule{ { PathExact: "/hello", PathPrefix: "/world", PathRegex: "/.*/foo", - Headers: []*pbauth.DestinationRuleHeader{{ + Header: &pbauth.DestinationRuleHeader{ Name: "x-consul-not-test", Present: true, Exact: "false", @@ -489,7 +485,7 @@ func TestTrafficPermissions_Resource(t *testing.T) { Suffix: "~suffix", Regex: "~reg.*ex", Invert: true, - }}, + }, Methods: []string{"DELETE"}, PortNames: []string{"log"}, }, @@ -646,31 +642,27 @@ func TestTrafficPermissions_Validate(t *testing.T) { DestinationRules: []*pbauth.DestinationRule{ { PathExact: "/hello", - Headers: []*pbauth.DestinationRuleHeader{ - { - Name: "x-consul-test", - Present: true, - Exact: "true", - Prefix: "prefix", - Suffix: "suffix", - Regex: "reg.*ex", - Invert: true, - }, + Header: &pbauth.DestinationRuleHeader{ + Name: "x-consul-test", + Present: true, + Exact: "true", + Prefix: "prefix", + Suffix: "suffix", + Regex: "reg.*ex", + Invert: true, }, Methods: []string{"GET", "POST"}, Exclude: []*pbauth.ExcludePermissionRule{ { PathPrefix: "/world", - Headers: []*pbauth.DestinationRuleHeader{ - { - Name: "x-consul-not-test", - Present: true, - Exact: "false", - Prefix: "~prefix", - Suffix: "~suffix", - Regex: "~reg.*ex", - Invert: true, - }, + Header: &pbauth.DestinationRuleHeader{ + Name: "x-consul-not-test", + Present: true, + Exact: "false", + Prefix: "~prefix", + Suffix: "~suffix", + Regex: "~reg.*ex", + Invert: true, }, Methods: []string{"DELETE"}, PortNames: []string{"log"}, @@ -945,9 +937,9 @@ func TestTrafficPermissions_Validate(t *testing.T) { }, }, expectedErrMsgs: []string{ - `spec.permissions[0].destinationRules[0]: Invalid value: authv2beta1.DestinationRule{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(nil)}, sizeCache:0, unknownFields:[]uint8(nil), PathExact:"/hello", PathPrefix:"foobar", PathRegex:"", Methods:[]string(nil), Headers:[]*authv2beta1.DestinationRuleHeader(nil), PortNames:[]string(nil), Exclude:[]*authv2beta1.ExcludePermissionRule(nil)}: prefix values, regex values, and explicit names must not combined`, - `spec.permissions[0].destinationRules[1]: Invalid value: authv2beta1.DestinationRule{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(nil)}, sizeCache:0, unknownFields:[]uint8(nil), PathExact:"/hello", PathPrefix:"", PathRegex:"path-regex", Methods:[]string(nil), Headers:[]*authv2beta1.DestinationRuleHeader(nil), PortNames:[]string(nil), Exclude:[]*authv2beta1.ExcludePermissionRule(nil)}: prefix values, regex values, and explicit names must not combined`, - `spec.permissions[0].destinationRules[2]: Invalid value: authv2beta1.DestinationRule{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(nil)}, sizeCache:0, unknownFields:[]uint8(nil), PathExact:"", PathPrefix:"foobar", PathRegex:"path-regex", Methods:[]string(nil), Headers:[]*authv2beta1.DestinationRuleHeader(nil), PortNames:[]string(nil), Exclude:[]*authv2beta1.ExcludePermissionRule(nil)}: prefix values, regex values, and explicit names must not combined`, + `spec.permissions[0].destinationRules[0]: Invalid value: authv2beta1.DestinationRule{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(nil)}, sizeCache:0, unknownFields:[]uint8(nil), PathExact:"/hello", PathPrefix:"foobar", PathRegex:"", Methods:[]string(nil), Header:(*authv2beta1.DestinationRuleHeader)(nil), PortNames:[]string(nil), Exclude:[]*authv2beta1.ExcludePermissionRule(nil)}: prefix values, regex values, and explicit names must not combined`, + `spec.permissions[0].destinationRules[1]: Invalid value: authv2beta1.DestinationRule{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(nil)}, sizeCache:0, unknownFields:[]uint8(nil), PathExact:"/hello", PathPrefix:"", PathRegex:"path-regex", Methods:[]string(nil), Header:(*authv2beta1.DestinationRuleHeader)(nil), PortNames:[]string(nil), Exclude:[]*authv2beta1.ExcludePermissionRule(nil)}: prefix values, regex values, and explicit names must not combined`, + `spec.permissions[0].destinationRules[2]: Invalid value: authv2beta1.DestinationRule{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(nil)}, sizeCache:0, unknownFields:[]uint8(nil), PathExact:"", PathPrefix:"foobar", PathRegex:"path-regex", Methods:[]string(nil), Header:(*authv2beta1.DestinationRuleHeader)(nil), PortNames:[]string(nil), Exclude:[]*authv2beta1.ExcludePermissionRule(nil)}: prefix values, regex values, and explicit names must not combined`, }, }, { @@ -987,9 +979,9 @@ func TestTrafficPermissions_Validate(t *testing.T) { }, }, expectedErrMsgs: []string{ - `spec.permissions[0].destinationRules[0].exclude[0]: Invalid value: authv2beta1.ExcludePermissionRule{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(nil)}, sizeCache:0, unknownFields:[]uint8(nil), PathExact:"/hello", PathPrefix:"foobar", PathRegex:"", Methods:[]string(nil), Headers:[]*authv2beta1.DestinationRuleHeader(nil), PortNames:[]string(nil)}: prefix values, regex values, and explicit names must not combined`, - `spec.permissions[0].destinationRules[0].exclude[1]: Invalid value: authv2beta1.ExcludePermissionRule{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(nil)}, sizeCache:0, unknownFields:[]uint8(nil), PathExact:"/hello", PathPrefix:"", PathRegex:"path-regex", Methods:[]string(nil), Headers:[]*authv2beta1.DestinationRuleHeader(nil), PortNames:[]string(nil)}: prefix values, regex values, and explicit names must not combined`, - `spec.permissions[0].destinationRules[0].exclude[2]: Invalid value: authv2beta1.ExcludePermissionRule{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(nil)}, sizeCache:0, unknownFields:[]uint8(nil), PathExact:"", PathPrefix:"foobar", PathRegex:"path-regex", Methods:[]string(nil), Headers:[]*authv2beta1.DestinationRuleHeader(nil), PortNames:[]string(nil)}: prefix values, regex values, and explicit names must not combined`, + `spec.permissions[0].destinationRules[0].exclude[0]: Invalid value: authv2beta1.ExcludePermissionRule{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(nil)}, sizeCache:0, unknownFields:[]uint8(nil), PathExact:"/hello", PathPrefix:"foobar", PathRegex:"", Methods:[]string(nil), Header:(*authv2beta1.DestinationRuleHeader)(nil), PortNames:[]string(nil)}: prefix values, regex values, and explicit names must not combined`, + `spec.permissions[0].destinationRules[0].exclude[1]: Invalid value: authv2beta1.ExcludePermissionRule{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(nil)}, sizeCache:0, unknownFields:[]uint8(nil), PathExact:"/hello", PathPrefix:"", PathRegex:"path-regex", Methods:[]string(nil), Header:(*authv2beta1.DestinationRuleHeader)(nil), PortNames:[]string(nil)}: prefix values, regex values, and explicit names must not combined`, + `spec.permissions[0].destinationRules[0].exclude[2]: Invalid value: authv2beta1.ExcludePermissionRule{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(nil)}, sizeCache:0, unknownFields:[]uint8(nil), PathExact:"", PathPrefix:"foobar", PathRegex:"path-regex", Methods:[]string(nil), Header:(*authv2beta1.DestinationRuleHeader)(nil), PortNames:[]string(nil)}: prefix values, regex values, and explicit names must not combined`, }, }, } @@ -1017,6 +1009,10 @@ func constructTrafficPermissionResource(tp *pbauth.TrafficPermissions, name, nam Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, Uid: "ABCD", // We add this to show it does not factor into the comparison } diff --git a/control-plane/api/auth/v2beta1/trafficpermissions_webhook.go b/control-plane/api/auth/v2beta1/trafficpermissions_webhook.go index 277fa885ef..c7d8d0189d 100644 --- a/control-plane/api/auth/v2beta1/trafficpermissions_webhook.go +++ b/control-plane/api/auth/v2beta1/trafficpermissions_webhook.go @@ -27,7 +27,7 @@ type TrafficPermissionsWebhook struct { client.Client } -var _ common.ConsulResourceLister = &TrafficPermissionsWebhook{} +var _ common.MeshConfigLister = &TrafficPermissionsWebhook{} // NOTE: The path value in the below line is the path to the webhook. // If it is updated, run code-gen, update subcommand/inject-connect/command.go @@ -44,17 +44,17 @@ func (v *TrafficPermissionsWebhook) Handle(ctx context.Context, req admission.Re return admission.Errored(http.StatusBadRequest, err) } - return common.ValidateConsulResource(ctx, req, v.Logger, v, &resource, v.ConsulTenancyConfig) + return common.ValidateMeshConfig(ctx, req, v.Logger, v, &resource, v.ConsulTenancyConfig) } -func (v *TrafficPermissionsWebhook) List(ctx context.Context) ([]common.ConsulResource, error) { +func (v *TrafficPermissionsWebhook) List(ctx context.Context) ([]common.MeshConfig, error) { var resourceList TrafficPermissionsList if err := v.Client.List(ctx, &resourceList); err != nil { return nil, err } - var entries []common.ConsulResource + var entries []common.MeshConfig for _, item := range resourceList.Items { - entries = append(entries, common.ConsulResource(item)) + entries = append(entries, common.MeshConfig(item)) } return entries, nil } diff --git a/control-plane/api/common/common.go b/control-plane/api/common/common.go index 730fd622ac..2cf32fdc0b 100644 --- a/control-plane/api/common/common.go +++ b/control-plane/api/common/common.go @@ -4,15 +4,9 @@ // Package common holds code that isn't tied to a particular CRD version or type. package common -import ( - "time" - - mapset "github.com/deckarep/golang-set" -) +import mapset "github.com/deckarep/golang-set" const ( - // NOTE: these are only used in consul types, they do not map to k8s kinds. - // V1 config entries. ServiceDefaults string = "servicedefaults" ProxyDefaults string = "proxydefaults" @@ -29,17 +23,12 @@ const ( RouteAuthFilter string = "routeauthfilter" GatewayPolicy string = "gatewaypolicy" - // V2 resources. + // V2 config entries. TrafficPermissions string = "trafficpermissions" GRPCRoute string = "grpcroute" HTTPRoute string = "httproute" TCPRoute string = "tcproute" ProxyConfiguration string = "proxyconfiguration" - MeshGateway string = "meshgateway" - APIGateway string = "apigateway" - GatewayClass string = "gatewayclass" - GatewayClassConfig string = "gatewayclassconfig" - MeshConfiguration string = "meshconfiguration" Global string = "global" Mesh string = "mesh" @@ -87,11 +76,3 @@ type K8sNamespaceConfig struct { // Endpoints in the DenyK8sNamespacesSet are ignored. DenyK8sNamespacesSet mapset.Set } - -// ConsulConfig manages config to tell a pod where consul is located. -type ConsulConfig struct { - Address string - GRPCPort int - HTTPPort int - APITimeout time.Duration -} diff --git a/control-plane/api/common/consul_resource.go b/control-plane/api/common/meshconfig.go similarity index 98% rename from control-plane/api/common/consul_resource.go rename to control-plane/api/common/meshconfig.go index b957d0fb79..139818d307 100644 --- a/control-plane/api/common/consul_resource.go +++ b/control-plane/api/common/meshconfig.go @@ -11,7 +11,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" ) -type ConsulResource interface { +type MeshConfig interface { ResourceID(namespace, partition string) *pbresource.ID Resource(namespace, partition string) *pbresource.Resource diff --git a/control-plane/api/common/consul_resource_webhook.go b/control-plane/api/common/meshconfig_webhook.go similarity index 62% rename from control-plane/api/common/consul_resource_webhook.go rename to control-plane/api/common/meshconfig_webhook.go index afda672873..004b47a589 100644 --- a/control-plane/api/common/consul_resource_webhook.go +++ b/control-plane/api/common/meshconfig_webhook.go @@ -15,26 +15,26 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) -// ConsulResourceLister is implemented by CRD-specific webhooks. -type ConsulResourceLister interface { +// MeshConfigLister is implemented by CRD-specific webhooks. +type MeshConfigLister interface { // List returns all resources of this type across all namespaces in a // Kubernetes cluster. - List(ctx context.Context) ([]ConsulResource, error) + List(ctx context.Context) ([]MeshConfig, error) } -// ValidateConsulResource validates a Consul Resource. It is a generic method that +// ValidateMeshConfig validates a MeshConfig. It is a generic method that // can be used by all CRD-specific validators. // Callers should pass themselves as validator and kind should be the custom // resource name, e.g. "TrafficPermissions". -func ValidateConsulResource( +func ValidateMeshConfig( ctx context.Context, req admission.Request, logger logr.Logger, - resourceLister ConsulResourceLister, - resource ConsulResource, + meshConfigLister MeshConfigLister, + meshConfig MeshConfig, tenancy ConsulTenancyConfig) admission.Response { - defaultingPatches, err := ConsulResourceDefaultingPatches(resource, tenancy) + defaultingPatches, err := MeshConfigDefaultingPatches(meshConfig, tenancy) if err != nil { return admission.Errored(http.StatusInternalServerError, err) } @@ -45,36 +45,36 @@ func ValidateConsulResource( // are running Consul enterprise with namespace mirroring. singleConsulDestNS := !(tenancy.EnableConsulNamespaces && tenancy.EnableNSMirroring) if req.Operation == admissionv1.Create && singleConsulDestNS { - logger.Info("validate create", "name", resource.KubernetesName()) + logger.Info("validate create", "name", meshConfig.KubernetesName()) - list, err := resourceLister.List(ctx) + list, err := meshConfigLister.List(ctx) if err != nil { return admission.Errored(http.StatusInternalServerError, err) } for _, item := range list { - if item.KubernetesName() == resource.KubernetesName() { + if item.KubernetesName() == meshConfig.KubernetesName() { return admission.Errored(http.StatusBadRequest, fmt.Errorf("%s resource with name %q is already defined – all %s resources must have unique names across namespaces", - resource.KubeKind(), - resource.KubernetesName(), - resource.KubeKind())) + meshConfig.KubeKind(), + meshConfig.KubernetesName(), + meshConfig.KubeKind())) } } } - if err := resource.Validate(tenancy); err != nil { + if err := meshConfig.Validate(tenancy); err != nil { return admission.Errored(http.StatusBadRequest, err) } - return admission.Patched(fmt.Sprintf("valid %s request", resource.KubeKind()), defaultingPatches...) + return admission.Patched(fmt.Sprintf("valid %s request", meshConfig.KubeKind()), defaultingPatches...) } -// ConsulResourceDefaultingPatches returns the patches needed to set fields to their defaults. -func ConsulResourceDefaultingPatches(resource ConsulResource, tenancy ConsulTenancyConfig) ([]jsonpatch.Operation, error) { - beforeDefaulting, err := json.Marshal(resource) +// MeshConfigDefaultingPatches returns the patches needed to set fields to their defaults. +func MeshConfigDefaultingPatches(meshConfig MeshConfig, tenancy ConsulTenancyConfig) ([]jsonpatch.Operation, error) { + beforeDefaulting, err := json.Marshal(meshConfig) if err != nil { return nil, fmt.Errorf("marshalling input: %s", err) } - resource.DefaultNamespaceFields(tenancy) - afterDefaulting, err := json.Marshal(resource) + meshConfig.DefaultNamespaceFields(tenancy) + afterDefaulting, err := json.Marshal(meshConfig) if err != nil { return nil, fmt.Errorf("marshalling after defaulting: %s", err) } diff --git a/control-plane/api/common/consul_resource_webhook_test.go b/control-plane/api/common/meshconfig_webhook_test.go similarity index 50% rename from control-plane/api/common/consul_resource_webhook_test.go rename to control-plane/api/common/meshconfig_webhook_test.go index 63bbf9a6e0..1da2c143dd 100644 --- a/control-plane/api/common/consul_resource_webhook_test.go +++ b/control-plane/api/common/meshconfig_webhook_test.go @@ -22,12 +22,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) -func TestValidateConsulResource(t *testing.T) { +func TestValidateMeshConfig(t *testing.T) { otherNS := "other" cases := map[string]struct { - existingResources []ConsulResource - newResource ConsulResource + existingResources []MeshConfig + newResource MeshConfig enableNamespaces bool nsMirroring bool consulDestinationNS string @@ -37,7 +37,7 @@ func TestValidateConsulResource(t *testing.T) { }{ "no duplicates, valid": { existingResources: nil, - newResource: &mockConsulResource{ + newResource: &mockMeshConfig{ MockName: "foo", MockNamespace: otherNS, Valid: true, @@ -46,7 +46,7 @@ func TestValidateConsulResource(t *testing.T) { }, "no duplicates, invalid": { existingResources: nil, - newResource: &mockConsulResource{ + newResource: &mockMeshConfig{ MockName: "foo", MockNamespace: otherNS, Valid: false, @@ -55,11 +55,11 @@ func TestValidateConsulResource(t *testing.T) { expErrMessage: "invalid", }, "duplicate name": { - existingResources: []ConsulResource{&mockConsulResource{ + existingResources: []MeshConfig{&mockMeshConfig{ MockName: "foo", MockNamespace: "default", }}, - newResource: &mockConsulResource{ + newResource: &mockMeshConfig{ MockName: "foo", MockNamespace: otherNS, Valid: true, @@ -68,11 +68,11 @@ func TestValidateConsulResource(t *testing.T) { expErrMessage: "mockkind resource with name \"foo\" is already defined – all mockkind resources must have unique names across namespaces", }, "duplicate name, namespaces enabled": { - existingResources: []ConsulResource{&mockConsulResource{ + existingResources: []MeshConfig{&mockMeshConfig{ MockName: "foo", MockNamespace: "default", }}, - newResource: &mockConsulResource{ + newResource: &mockMeshConfig{ MockName: "foo", MockNamespace: otherNS, Valid: true, @@ -82,11 +82,11 @@ func TestValidateConsulResource(t *testing.T) { expErrMessage: "mockkind resource with name \"foo\" is already defined – all mockkind resources must have unique names across namespaces", }, "duplicate name, namespaces enabled, mirroring enabled": { - existingResources: []ConsulResource{&mockConsulResource{ + existingResources: []MeshConfig{&mockMeshConfig{ MockName: "foo", MockNamespace: "default", }}, - newResource: &mockConsulResource{ + newResource: &mockMeshConfig{ MockName: "foo", MockNamespace: otherNS, Valid: true, @@ -102,10 +102,10 @@ func TestValidateConsulResource(t *testing.T) { marshalledRequestObject, err := json.Marshal(c.newResource) require.NoError(t, err) - lister := &mockConsulResourceLister{ + lister := &mockMeshConfigLister{ Resources: c.existingResources, } - response := ValidateConsulResource(ctx, admission.Request{ + response := ValidateMeshConfig(ctx, admission.Request{ AdmissionRequest: admissionv1.AdmissionRequest{ Name: c.newResource.KubernetesName(), Namespace: otherNS, @@ -132,14 +132,14 @@ func TestValidateConsulResource(t *testing.T) { } } -func TestConsulResourceDefaultingPatches(t *testing.T) { - meshConfig := &mockConsulResource{ +func TestMeshConfigDefaultingPatches(t *testing.T) { + meshConfig := &mockMeshConfig{ MockName: "test", Valid: true, } // This test validates that DefaultingPatches invokes DefaultNamespaceFields on the Config Entry. - patches, err := ConsulResourceDefaultingPatches(meshConfig, ConsulTenancyConfig{}) + patches, err := MeshConfigDefaultingPatches(meshConfig, ConsulTenancyConfig{}) require.NoError(t, err) require.Equal(t, []jsonpatch.Operation{ @@ -151,183 +151,183 @@ func TestConsulResourceDefaultingPatches(t *testing.T) { }, patches) } -type mockConsulResourceLister struct { - Resources []ConsulResource +type mockMeshConfigLister struct { + Resources []MeshConfig } -var _ ConsulResourceLister = &mockConsulResourceLister{} +var _ MeshConfigLister = &mockMeshConfigLister{} -func (in *mockConsulResourceLister) List(_ context.Context) ([]ConsulResource, error) { +func (in *mockMeshConfigLister) List(_ context.Context) ([]MeshConfig, error) { return in.Resources, nil } -type mockConsulResource struct { +type mockMeshConfig struct { MockName string MockNamespace string Valid bool } -var _ ConsulResource = &mockConsulResource{} +var _ MeshConfig = &mockMeshConfig{} -func (in *mockConsulResource) ResourceID(_, _ string) *pbresource.ID { +func (in *mockMeshConfig) ResourceID(_, _ string) *pbresource.ID { return nil } -func (in *mockConsulResource) Resource(_, _ string) *pbresource.Resource { +func (in *mockMeshConfig) Resource(_, _ string) *pbresource.Resource { return nil } -func (in *mockConsulResource) GetNamespace() string { +func (in *mockMeshConfig) GetNamespace() string { return in.MockNamespace } -func (in *mockConsulResource) SetNamespace(namespace string) { +func (in *mockMeshConfig) SetNamespace(namespace string) { in.MockNamespace = namespace } -func (in *mockConsulResource) GetName() string { +func (in *mockMeshConfig) GetName() string { return in.MockName } -func (in *mockConsulResource) SetName(name string) { +func (in *mockMeshConfig) SetName(name string) { in.MockName = name } -func (in *mockConsulResource) GetGenerateName() string { +func (in *mockMeshConfig) GetGenerateName() string { return "" } -func (in *mockConsulResource) SetGenerateName(_ string) {} +func (in *mockMeshConfig) SetGenerateName(_ string) {} -func (in *mockConsulResource) GetUID() types.UID { +func (in *mockMeshConfig) GetUID() types.UID { return "" } -func (in *mockConsulResource) SetUID(_ types.UID) {} +func (in *mockMeshConfig) SetUID(_ types.UID) {} -func (in *mockConsulResource) GetResourceVersion() string { +func (in *mockMeshConfig) GetResourceVersion() string { return "" } -func (in *mockConsulResource) SetResourceVersion(_ string) {} +func (in *mockMeshConfig) SetResourceVersion(_ string) {} -func (in *mockConsulResource) GetGeneration() int64 { +func (in *mockMeshConfig) GetGeneration() int64 { return 0 } -func (in *mockConsulResource) SetGeneration(_ int64) {} +func (in *mockMeshConfig) SetGeneration(_ int64) {} -func (in *mockConsulResource) GetSelfLink() string { +func (in *mockMeshConfig) GetSelfLink() string { return "" } -func (in *mockConsulResource) SetSelfLink(_ string) {} +func (in *mockMeshConfig) SetSelfLink(_ string) {} -func (in *mockConsulResource) GetCreationTimestamp() metav1.Time { +func (in *mockMeshConfig) GetCreationTimestamp() metav1.Time { return metav1.Time{} } -func (in *mockConsulResource) SetCreationTimestamp(_ metav1.Time) {} +func (in *mockMeshConfig) SetCreationTimestamp(_ metav1.Time) {} -func (in *mockConsulResource) GetDeletionTimestamp() *metav1.Time { +func (in *mockMeshConfig) GetDeletionTimestamp() *metav1.Time { return nil } -func (in *mockConsulResource) SetDeletionTimestamp(_ *metav1.Time) {} +func (in *mockMeshConfig) SetDeletionTimestamp(_ *metav1.Time) {} -func (in *mockConsulResource) GetDeletionGracePeriodSeconds() *int64 { +func (in *mockMeshConfig) GetDeletionGracePeriodSeconds() *int64 { return nil } -func (in *mockConsulResource) SetDeletionGracePeriodSeconds(_ *int64) {} +func (in *mockMeshConfig) SetDeletionGracePeriodSeconds(_ *int64) {} -func (in *mockConsulResource) GetLabels() map[string]string { +func (in *mockMeshConfig) GetLabels() map[string]string { return nil } -func (in *mockConsulResource) SetLabels(_ map[string]string) {} +func (in *mockMeshConfig) SetLabels(_ map[string]string) {} -func (in *mockConsulResource) GetAnnotations() map[string]string { +func (in *mockMeshConfig) GetAnnotations() map[string]string { return nil } -func (in *mockConsulResource) SetAnnotations(_ map[string]string) {} +func (in *mockMeshConfig) SetAnnotations(_ map[string]string) {} -func (in *mockConsulResource) GetFinalizers() []string { +func (in *mockMeshConfig) GetFinalizers() []string { return nil } -func (in *mockConsulResource) SetFinalizers(_ []string) {} +func (in *mockMeshConfig) SetFinalizers(_ []string) {} -func (in *mockConsulResource) GetOwnerReferences() []metav1.OwnerReference { +func (in *mockMeshConfig) GetOwnerReferences() []metav1.OwnerReference { return nil } -func (in *mockConsulResource) SetOwnerReferences(_ []metav1.OwnerReference) {} +func (in *mockMeshConfig) SetOwnerReferences(_ []metav1.OwnerReference) {} -func (in *mockConsulResource) GetClusterName() string { +func (in *mockMeshConfig) GetClusterName() string { return "" } -func (in *mockConsulResource) SetClusterName(_ string) {} +func (in *mockMeshConfig) SetClusterName(_ string) {} -func (in *mockConsulResource) GetManagedFields() []metav1.ManagedFieldsEntry { +func (in *mockMeshConfig) GetManagedFields() []metav1.ManagedFieldsEntry { return nil } -func (in *mockConsulResource) SetManagedFields(_ []metav1.ManagedFieldsEntry) {} +func (in *mockMeshConfig) SetManagedFields(_ []metav1.ManagedFieldsEntry) {} -func (in *mockConsulResource) KubernetesName() string { +func (in *mockMeshConfig) KubernetesName() string { return in.MockName } -func (in *mockConsulResource) GetObjectMeta() metav1.ObjectMeta { +func (in *mockMeshConfig) GetObjectMeta() metav1.ObjectMeta { return metav1.ObjectMeta{} } -func (in *mockConsulResource) GetObjectKind() schema.ObjectKind { +func (in *mockMeshConfig) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind } -func (in *mockConsulResource) DeepCopyObject() runtime.Object { +func (in *mockMeshConfig) DeepCopyObject() runtime.Object { return in } -func (in *mockConsulResource) AddFinalizer(_ string) {} +func (in *mockMeshConfig) AddFinalizer(_ string) {} -func (in *mockConsulResource) RemoveFinalizer(_ string) {} +func (in *mockMeshConfig) RemoveFinalizer(_ string) {} -func (in *mockConsulResource) Finalizers() []string { +func (in *mockMeshConfig) Finalizers() []string { return nil } -func (in *mockConsulResource) KubeKind() string { +func (in *mockMeshConfig) KubeKind() string { return "mockkind" } -func (in *mockConsulResource) SetSyncedCondition(_ corev1.ConditionStatus, _ string, _ string) {} +func (in *mockMeshConfig) SetSyncedCondition(_ corev1.ConditionStatus, _ string, _ string) {} -func (in *mockConsulResource) SetLastSyncedTime(_ *metav1.Time) {} +func (in *mockMeshConfig) SetLastSyncedTime(_ *metav1.Time) {} -func (in *mockConsulResource) SyncedCondition() (status corev1.ConditionStatus, reason string, message string) { +func (in *mockMeshConfig) SyncedCondition() (status corev1.ConditionStatus, reason string, message string) { return corev1.ConditionTrue, "", "" } -func (in *mockConsulResource) SyncedConditionStatus() corev1.ConditionStatus { +func (in *mockMeshConfig) SyncedConditionStatus() corev1.ConditionStatus { return corev1.ConditionTrue } -func (in *mockConsulResource) Validate(_ ConsulTenancyConfig) error { +func (in *mockMeshConfig) Validate(_ ConsulTenancyConfig) error { if !in.Valid { return errors.New("invalid") } return nil } -func (in *mockConsulResource) DefaultNamespaceFields(_ ConsulTenancyConfig) { +func (in *mockMeshConfig) DefaultNamespaceFields(_ ConsulTenancyConfig) { in.MockNamespace = "bar" } -func (in *mockConsulResource) MatchesConsul(_ *pbresource.Resource, _, _ string) bool { +func (in *mockMeshConfig) MatchesConsul(_ *pbresource.Resource, _, _ string) bool { return false } diff --git a/control-plane/api/mesh/v2beta1/api_gateway_types.go b/control-plane/api/mesh/v2beta1/api_gateway_types.go deleted file mode 100644 index 18bd4ad5b1..0000000000 --- a/control-plane/api/mesh/v2beta1/api_gateway_types.go +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 -package v2beta1 - -import ( - "fmt" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "google.golang.org/protobuf/testing/protocmp" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/intstr" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - "github.com/hashicorp/consul-k8s/control-plane/api/common" - inject "github.com/hashicorp/consul-k8s/control-plane/connect-inject/common" -) - -const ( - apiGatewayKubeKind = "gateway" -) - -func init() { - MeshSchemeBuilder.Register(&APIGateway{}, &APIGatewayList{}) -} - -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status - -// APIGateway is the Schema for the API Gateway -// +kubebuilder:printcolumn:name="Synced",type="string",JSONPath=".status.conditions[?(@.type==\"Synced\")].status",description="The sync status of the resource with Consul" -// +kubebuilder:printcolumn:name="Last Synced",type="date",JSONPath=".status.lastSyncedTime",description="The last successful synced time of the resource with Consul" -// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the resource" -// +kubebuilder:resource:scope=Cluster -type APIGateway struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec pbmesh.APIGateway `json:"spec,omitempty"` - APIGatewayStatus `json:"status,omitempty"` -} - -type APIGatewayStatus struct { - Status `json:"status,omitempty"` - Addresses []GatewayAddress `json:"addresses,omitempty"` - Listeners []ListenerStatus `json:"listeners,omitempty"` -} - -type ListenerStatus struct { - Status `json:"status,omitempty"` - Name string `json:"name"` - AttachedRoutes int32 `json:"attachedRoutes"` -} - -type GatewayAddress struct { - // +kubebuilder:default=IPAddress - Type string `json:"type"` - Value string `json:"value"` -} - -// +kubebuilder:object:root=true - -// APIGatewayList contains a list of APIGateway. -type APIGatewayList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []*APIGateway `json:"items"` -} - -func (in *APIGatewayList) ReconcileRequests() []reconcile.Request { - requests := make([]reconcile.Request, 0, len(in.Items)) - - for _, item := range in.Items { - requests = append(requests, reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: item.Name, - Namespace: item.Namespace, - }, - }) - } - return requests -} - -func (in *APIGateway) ResourceID(namespace, partition string) *pbresource.ID { - return &pbresource.ID{ - Name: in.Name, - Type: pbmesh.APIGatewayType, - Tenancy: &pbresource.Tenancy{ - Partition: partition, - Namespace: namespace, - }, - } -} - -func (in *APIGateway) Resource(namespace, partition string) *pbresource.Resource { - return &pbresource.Resource{ - Id: in.ResourceID(namespace, partition), - Data: inject.ToProtoAny(&in.Spec), - Metadata: meshConfigMeta(), - } -} - -func (in *APIGateway) AddFinalizer(f string) { - in.ObjectMeta.Finalizers = append(in.Finalizers(), f) -} - -func (in *APIGateway) RemoveFinalizer(f string) { - var newFinalizers []string - for _, oldF := range in.Finalizers() { - if oldF != f { - newFinalizers = append(newFinalizers, oldF) - } - } - in.ObjectMeta.Finalizers = newFinalizers -} - -func (in *APIGateway) Finalizers() []string { - return in.ObjectMeta.Finalizers -} - -func (in *APIGateway) MatchesConsul(candidate *pbresource.Resource, namespace, partition string) bool { - return cmp.Equal( - in.Resource(namespace, partition), - candidate, - protocmp.IgnoreFields(&pbresource.Resource{}, "status", "generation", "version"), - protocmp.IgnoreFields(&pbresource.ID{}, "uid"), - protocmp.Transform(), - cmpopts.SortSlices(func(a, b any) bool { return fmt.Sprintf("%v", a) < fmt.Sprintf("%v", b) }), - ) -} - -func (in *APIGateway) KubeKind() string { - return apiGatewayKubeKind -} - -func (in *APIGateway) KubernetesName() string { - return in.ObjectMeta.Name -} - -func (in *APIGateway) SetSyncedCondition(status corev1.ConditionStatus, reason, message string) { - in.Status.Conditions = Conditions{ - { - Type: ConditionSynced, - Status: status, - LastTransitionTime: metav1.Now(), - Reason: reason, - Message: message, - }, - } -} - -func (in *APIGateway) SetLastSyncedTime(time *metav1.Time) { - in.Status.LastSyncedTime = time -} - -func (in *APIGateway) SyncedCondition() (status corev1.ConditionStatus, reason, message string) { - cond := in.Status.GetCondition(ConditionSynced) - if cond == nil { - return corev1.ConditionUnknown, "", "" - } - return cond.Status, cond.Reason, cond.Message -} - -func (in *APIGateway) SyncedConditionStatus() corev1.ConditionStatus { - condition := in.Status.GetCondition(ConditionSynced) - if condition == nil { - return corev1.ConditionUnknown - } - return condition.Status -} - -func (in *APIGateway) Validate(tenancy common.ConsulTenancyConfig) error { - return nil -} - -// DefaultNamespaceFields is required as part of the common.MeshConfig interface. -func (in *APIGateway) DefaultNamespaceFields(tenancy common.ConsulTenancyConfig) {} - -// ListenersToServicePorts converts the APIGateway listeners to ServicePorts. -func (in *APIGateway) ListenersToServicePorts(portModifier int32) []corev1.ServicePort { - ports := []corev1.ServicePort{} - - for _, listener := range in.Spec.Listeners { - port := int32(listener.Port) - ports = append(ports, corev1.ServicePort{ - Name: listener.Name, - Port: port, - TargetPort: intstr.IntOrString{ - IntVal: port + portModifier, - }, - Protocol: corev1.Protocol(listener.Protocol), - }) - } - - return ports -} - -func (in *APIGateway) ListenersToContainerPorts(_ int32, _ int32) []corev1.ContainerPort { - // TODO: check if this is actually needed: we don't map any container ports in v1 - return []corev1.ContainerPort{} -} diff --git a/control-plane/api/mesh/v2beta1/gateway_class_config_types.go b/control-plane/api/mesh/v2beta1/gateway_class_config_types.go deleted file mode 100644 index 1678a14b55..0000000000 --- a/control-plane/api/mesh/v2beta1/gateway_class_config_types.go +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package v2beta1 - -import ( - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const KindGatewayClassConfig = "GatewayClassConfig" - -func init() { - MeshSchemeBuilder.Register(&GatewayClassConfig{}, &GatewayClassConfigList{}) -} - -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status - -// GatewayClassConfig is the Schema for the Mesh Gateway API -// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the resource" -// +kubebuilder:resource:scope=Cluster -type GatewayClassConfig struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec GatewayClassConfigSpec `json:"spec,omitempty"` - Status `json:"status,omitempty"` -} - -// +k8s:deepcopy-gen=true - -// GatewayClassConfigSpec specifies the desired state of the GatewayClassConfig CRD. -type GatewayClassConfigSpec struct { - GatewayClassAnnotationsAndLabels `json:",inline"` - - // Deployment contains config specific to the Deployment created from this GatewayClass - Deployment GatewayClassDeploymentConfig `json:"deployment,omitempty"` - // Role contains config specific to the Role created from this GatewayClass - Role GatewayClassRoleConfig `json:"role,omitempty"` - // RoleBinding contains config specific to the RoleBinding created from this GatewayClass - RoleBinding GatewayClassRoleBindingConfig `json:"roleBinding,omitempty"` - // Service contains config specific to the Service created from this GatewayClass - Service GatewayClassServiceConfig `json:"service,omitempty"` - // ServiceAccount contains config specific to the corev1.ServiceAccount created from this GatewayClass - ServiceAccount GatewayClassServiceAccountConfig `json:"serviceAccount,omitempty"` -} - -// GatewayClassDeploymentConfig specifies the desired state of the Deployment created from the GatewayClassConfig. -type GatewayClassDeploymentConfig struct { - GatewayClassAnnotationsAndLabels `json:",inline"` - - // Container contains config specific to the created Deployment's container. - Container *GatewayClassContainerConfig `json:"container,omitempty"` - // InitContainer contains config specific to the created Deployment's init container. - InitContainer *GatewayClassInitContainerConfig `json:"initContainer,omitempty"` - // NodeSelector is a feature that constrains the scheduling of a pod to nodes that - // match specified labels. - // By defining NodeSelector in a pod's configuration, you can ensure that the pod is - // only scheduled to nodes with the corresponding labels, providing a way to - // influence the placement of workloads based on node attributes. - // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - // PriorityClassName specifies the priority class name to use on the created Deployment. - PriorityClassName string `json:"priorityClassName,omitempty"` - // Replicas specifies the configuration to control the number of replicas for the created Deployment. - Replicas *GatewayClassReplicasConfig `json:"replicas,omitempty"` - // SecurityContext specifies the security context for the created Deployment's Pod. - SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` - // Tolerations specifies the tolerations to use on the created Deployment. - Tolerations []corev1.Toleration `json:"tolerations,omitempty"` - // HostNetwork specifies whether the gateway pods should run on the host network. - HostNetwork bool `json:"hostNetwork,omitempty"` - // TopologySpreadConstraints is a feature that controls how pods are spead across your topology. - // More info: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ - TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"` - // DNSPolicy specifies the dns policy to use. These are set on a per pod basis. - // +kubebuilder:validation:Enum=Default;ClusterFirst;ClusterFirstWithHostNet;None - DNSPolicy corev1.DNSPolicy `json:"dnsPolicy,omitempty"` - // Affinity specifies the affinity to use on the created Deployment. - Affinity *corev1.Affinity `json:"affinity,omitempty"` -} - -type GatewayClassReplicasConfig struct { - // Default is the number of replicas assigned to the Deployment when created - Default *int32 `json:"default,omitempty"` - // Min is the minimum number of replicas allowed for a gateway with this class. - // If the replica count drops below this value due to manual or automated scaling, - // the replica count will be restored to this value. - Min *int32 `json:"min,omitempty"` - // Max is the maximum number of replicas allowed for a gateway with this class. - // If the replica count exceeds this value due to manual or automated scaling, - // the replica count will be restored to this value. - Max *int32 `json:"max,omitempty"` -} - -type GatewayClassInitContainerConfig struct { - // Consul specifies configuration for the consul-k8s-control-plane init container - Consul GatewayClassConsulConfig `json:"consul,omitempty"` - // Resources specifies the resource requirements for the created Deployment's init container - Resources *corev1.ResourceRequirements `json:"resources,omitempty"` -} - -type GatewayClassContainerConfig struct { - // Consul specifies configuration for the consul-dataplane container - Consul GatewayClassConsulConfig `json:"consul,omitempty"` - // Resources specifies the resource requirements for the created Deployment's container - Resources *corev1.ResourceRequirements `json:"resources,omitempty"` - // PortModifier specifies the value to be added to every port value for listeners on this gateway. - // This is generally used to avoid binding to privileged ports in the container. - PortModifier int32 `json:"portModifier,omitempty"` - // HostPort specifies a port to be exposed to the external host network - HostPort int32 `json:"hostPort,omitempty"` -} - -type GatewayClassRoleConfig struct { - GatewayClassAnnotationsAndLabels `json:",inline"` -} - -type GatewayClassRoleBindingConfig struct { - GatewayClassAnnotationsAndLabels `json:",inline"` -} - -type GatewayClassServiceConfig struct { - GatewayClassAnnotationsAndLabels `json:",inline"` - - // Type specifies the type of Service to use (LoadBalancer, ClusterIP, etc.) - // +kubebuilder:validation:Enum=ClusterIP;NodePort;LoadBalancer - Type *corev1.ServiceType `json:"type,omitempty"` -} - -type GatewayClassServiceAccountConfig struct { - GatewayClassAnnotationsAndLabels `json:",inline"` -} - -type GatewayClassConsulConfig struct { - // Logging specifies the logging configuration for Consul Dataplane - Logging GatewayClassConsulLoggingConfig `json:"logging,omitempty"` -} - -type GatewayClassConsulLoggingConfig struct { - // Level sets the logging level for Consul Dataplane (debug, info, etc.) - Level string `json:"level,omitempty"` -} - -// GatewayClassAnnotationsAndLabels exists to provide a commonly-embedded wrapper -// for Annotations and Labels on a given resource configuration. -type GatewayClassAnnotationsAndLabels struct { - // Annotations are applied to the created resource - Annotations GatewayClassAnnotationsLabelsConfig `json:"annotations,omitempty"` - // Labels are applied to the created resource - Labels GatewayClassAnnotationsLabelsConfig `json:"labels,omitempty"` -} - -type GatewayClassAnnotationsLabelsConfig struct { - // InheritFromGateway lists the names/keys of annotations or labels to copy from the Gateway resource. - // Any name/key included here will override those in Set if specified on the Gateway. - InheritFromGateway []string `json:"inheritFromGateway,omitempty"` - // Set lists the names/keys and values of annotations or labels to set on the resource. - // Any name/key included here will be overridden if present in InheritFromGateway and set on the Gateway. - Set map[string]string `json:"set,omitempty"` -} - -// +kubebuilder:object:root=true - -// GatewayClassConfigList contains a list of GatewayClassConfig. -type GatewayClassConfigList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []*GatewayClassConfig `json:"items"` -} diff --git a/control-plane/api/mesh/v2beta1/gateway_class_types.go b/control-plane/api/mesh/v2beta1/gateway_class_types.go deleted file mode 100644 index 4e82e0a6b1..0000000000 --- a/control-plane/api/mesh/v2beta1/gateway_class_types.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 -package v2beta1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const KindGatewayClass = "GatewayClass" - -func init() { - MeshSchemeBuilder.Register(&GatewayClass{}, &GatewayClassList{}) -} - -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status - -// GatewayClass is the Schema for the Gateway Class API -// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the resource" -// +kubebuilder:resource:scope=Cluster -type GatewayClass struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec GatewayClassSpec `json:"spec,omitempty"` - Status `json:"status,omitempty"` -} - -// +kubebuilder:object:root=true - -// GatewayClassList contains a list of GatewayClass. -type GatewayClassList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []*GatewayClass `json:"items"` -} - -type GatewayClassSpec struct { - // ControllerName is the name of the Kubernetes controller - // that manages Gateways of this class - ControllerName string `json:"controllerName"` - - // ParametersRef refers to a resource responsible for configuring - // the behavior of the GatewayClass. - ParametersRef *ParametersReference `json:"parametersRef"` - - // Description of GatewayClass - Description string `json:"description,omitempty"` -} - -type ParametersReference struct { - // The Kubernetes Group that the referred object belongs to - Group string `json:"group,omitempty"` - - // The Kubernetes Kind that the referred object is - Kind string `json:"kind,omitempty"` - - // The Name of the referred object - Name string `json:"name"` - - // The kubernetes namespace that the referred object is in - Namespace *string `json:"namespace,omitempty"` -} diff --git a/control-plane/api/mesh/v2beta1/grpc_route_types.go b/control-plane/api/mesh/v2beta1/grpc_route_types.go index 16c6725cf9..44a8949e1d 100644 --- a/control-plane/api/mesh/v2beta1/grpc_route_types.go +++ b/control-plane/api/mesh/v2beta1/grpc_route_types.go @@ -1,5 +1,5 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 +// // Copyright (c) HashiCorp, Inc. +// // SPDX-License-Identifier: MPL-2.0 package v2beta1 import ( @@ -18,6 +18,7 @@ import ( "github.com/hashicorp/consul-k8s/control-plane/api/common" inject "github.com/hashicorp/consul-k8s/control-plane/connect-inject/common" + "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" ) const ( @@ -60,6 +61,10 @@ func (in *GRPCRoute) ResourceID(namespace, partition string) *pbresource.ID { Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, } } diff --git a/control-plane/api/mesh/v2beta1/grpc_route_types_test.go b/control-plane/api/mesh/v2beta1/grpc_route_types_test.go index c5ae7864de..69695284d0 100644 --- a/control-plane/api/mesh/v2beta1/grpc_route_types_test.go +++ b/control-plane/api/mesh/v2beta1/grpc_route_types_test.go @@ -277,6 +277,10 @@ func TestGRPCRoute_MatchesConsul(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.DefaultConsulNS, Namespace: constants.DefaultConsulPartition, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, }, Data: inject.ToProtoAny(&pbmesh.ProxyConfiguration{}), @@ -1170,6 +1174,10 @@ func constructGRPCRouteResource(tp *pbmesh.GRPCRoute, name, namespace, partition Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, Uid: "ABCD", // We add this to show it does not factor into the comparison } diff --git a/control-plane/api/mesh/v2beta1/grpc_route_webhook.go b/control-plane/api/mesh/v2beta1/grpc_route_webhook.go index b73388b4cf..15b4cbfc46 100644 --- a/control-plane/api/mesh/v2beta1/grpc_route_webhook.go +++ b/control-plane/api/mesh/v2beta1/grpc_route_webhook.go @@ -27,7 +27,7 @@ type GRPCRouteWebhook struct { client.Client } -var _ common.ConsulResourceLister = &GRPCRouteWebhook{} +var _ common.MeshConfigLister = &GRPCRouteWebhook{} // NOTE: The path value in the below line is the path to the webhook. // If it is updated, run code-gen, update subcommand/inject-connect/command.go @@ -44,17 +44,17 @@ func (v *GRPCRouteWebhook) Handle(ctx context.Context, req admission.Request) ad return admission.Errored(http.StatusBadRequest, err) } - return common.ValidateConsulResource(ctx, req, v.Logger, v, &resource, v.ConsulTenancyConfig) + return common.ValidateMeshConfig(ctx, req, v.Logger, v, &resource, v.ConsulTenancyConfig) } -func (v *GRPCRouteWebhook) List(ctx context.Context) ([]common.ConsulResource, error) { +func (v *GRPCRouteWebhook) List(ctx context.Context) ([]common.MeshConfig, error) { var resourceList GRPCRouteList if err := v.Client.List(ctx, &resourceList); err != nil { return nil, err } - var entries []common.ConsulResource + var entries []common.MeshConfig for _, item := range resourceList.Items { - entries = append(entries, common.ConsulResource(item)) + entries = append(entries, common.MeshConfig(item)) } return entries, nil } diff --git a/control-plane/api/mesh/v2beta1/http_route_types.go b/control-plane/api/mesh/v2beta1/http_route_types.go index dd8e0848f4..7ea1b97936 100644 --- a/control-plane/api/mesh/v2beta1/http_route_types.go +++ b/control-plane/api/mesh/v2beta1/http_route_types.go @@ -1,5 +1,5 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 +// // Copyright (c) HashiCorp, Inc. +// // SPDX-License-Identifier: MPL-2.0 package v2beta1 import ( @@ -20,6 +20,7 @@ import ( "github.com/hashicorp/consul-k8s/control-plane/api/common" inject "github.com/hashicorp/consul-k8s/control-plane/connect-inject/common" + "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" ) const ( @@ -62,6 +63,10 @@ func (in *HTTPRoute) ResourceID(namespace, partition string) *pbresource.ID { Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, } } diff --git a/control-plane/api/mesh/v2beta1/http_route_types_test.go b/control-plane/api/mesh/v2beta1/http_route_types_test.go index 7c9996f185..824d7e35b7 100644 --- a/control-plane/api/mesh/v2beta1/http_route_types_test.go +++ b/control-plane/api/mesh/v2beta1/http_route_types_test.go @@ -435,6 +435,10 @@ func TestHTTPRoute_MatchesConsul(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.DefaultConsulNS, Namespace: constants.DefaultConsulPartition, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, }, Data: inject.ToProtoAny(&pbmesh.ProxyConfiguration{}), @@ -1307,6 +1311,10 @@ func constructHTTPRouteResource(tp *pbmesh.HTTPRoute, name, namespace, partition Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, Uid: "ABCD", // We add this to show it does not factor into the comparison } diff --git a/control-plane/api/mesh/v2beta1/http_route_webhook.go b/control-plane/api/mesh/v2beta1/http_route_webhook.go index 323db0c74a..e16db17458 100644 --- a/control-plane/api/mesh/v2beta1/http_route_webhook.go +++ b/control-plane/api/mesh/v2beta1/http_route_webhook.go @@ -27,7 +27,7 @@ type HTTPRouteWebhook struct { client.Client } -var _ common.ConsulResourceLister = &HTTPRouteWebhook{} +var _ common.MeshConfigLister = &HTTPRouteWebhook{} // NOTE: The path value in the below line is the path to the webhook. // If it is updated, run code-gen, update subcommand/inject-connect/command.go @@ -44,17 +44,17 @@ func (v *HTTPRouteWebhook) Handle(ctx context.Context, req admission.Request) ad return admission.Errored(http.StatusBadRequest, err) } - return common.ValidateConsulResource(ctx, req, v.Logger, v, &resource, v.ConsulTenancyConfig) + return common.ValidateMeshConfig(ctx, req, v.Logger, v, &resource, v.ConsulTenancyConfig) } -func (v *HTTPRouteWebhook) List(ctx context.Context) ([]common.ConsulResource, error) { +func (v *HTTPRouteWebhook) List(ctx context.Context) ([]common.MeshConfig, error) { var resourceList HTTPRouteList if err := v.Client.List(ctx, &resourceList); err != nil { return nil, err } - var entries []common.ConsulResource + var entries []common.MeshConfig for _, item := range resourceList.Items { - entries = append(entries, common.ConsulResource(item)) + entries = append(entries, common.MeshConfig(item)) } return entries, nil } diff --git a/control-plane/api/mesh/v2beta1/mesh_configuration_types.go b/control-plane/api/mesh/v2beta1/mesh_configuration_types.go deleted file mode 100644 index 32a19ae2e7..0000000000 --- a/control-plane/api/mesh/v2beta1/mesh_configuration_types.go +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 -package v2beta1 - -import ( - "fmt" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/hashicorp/consul-k8s/control-plane/api/common" - inject "github.com/hashicorp/consul-k8s/control-plane/connect-inject/common" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "google.golang.org/protobuf/testing/protocmp" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const ( - meshConfigurationKind = "meshconfiguration" -) - -func init() { - MeshSchemeBuilder.Register(&MeshConfiguration{}, &MeshConfigurationList{}) -} - -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status - -// MeshConfiguration is the Schema for the Mesh Configuration -// +kubebuilder:printcolumn:name="Synced",type="string",JSONPath=".status.conditions[?(@.type==\"Synced\")].status",description="The sync status of the resource with Consul" -// +kubebuilder:printcolumn:name="Last Synced",type="date",JSONPath=".status.lastSyncedTime",description="The last successful synced time of the resource with Consul" -// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the resource" -// +kubebuilder:resource:scope=Cluster -type MeshConfiguration struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec pbmesh.MeshConfiguration `json:"spec,omitempty"` - Status `json:"status,omitempty"` -} - -// +kubebuilder:object:root=true - -// MeshConfigurationList contains a list of MeshConfiguration. -type MeshConfigurationList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []*MeshConfiguration `json:"items"` -} - -func (in *MeshConfiguration) ResourceID(_, partition string) *pbresource.ID { - return &pbresource.ID{ - Name: in.Name, - Type: pbmesh.MeshConfigurationType, - Tenancy: &pbresource.Tenancy{ - // we don't pass a namespace here because MeshConfiguration is partition-scoped - Partition: partition, - }, - } -} - -func (in *MeshConfiguration) Resource(_, partition string) *pbresource.Resource { - return &pbresource.Resource{ - Id: in.ResourceID("", partition), - Data: inject.ToProtoAny(&in.Spec), - Metadata: meshConfigMeta(), - } -} - -func (in *MeshConfiguration) AddFinalizer(f string) { - in.ObjectMeta.Finalizers = append(in.Finalizers(), f) -} - -func (in *MeshConfiguration) RemoveFinalizer(f string) { - var newFinalizers []string - for _, oldF := range in.Finalizers() { - if oldF != f { - newFinalizers = append(newFinalizers, oldF) - } - } - in.ObjectMeta.Finalizers = newFinalizers -} - -func (in *MeshConfiguration) Finalizers() []string { - return in.ObjectMeta.Finalizers -} - -func (in *MeshConfiguration) MatchesConsul(candidate *pbresource.Resource, _, partition string) bool { - return cmp.Equal( - in.Resource("", partition), - candidate, - protocmp.IgnoreFields(&pbresource.Resource{}, "status", "generation", "version"), - protocmp.IgnoreFields(&pbresource.ID{}, "uid"), - protocmp.Transform(), - cmpopts.SortSlices(func(a, b any) bool { return fmt.Sprintf("%v", a) < fmt.Sprintf("%v", b) }), - ) -} - -func (in *MeshConfiguration) KubeKind() string { - return meshConfigurationKind -} - -func (in *MeshConfiguration) KubernetesName() string { - return in.ObjectMeta.Name -} - -func (in *MeshConfiguration) SetSyncedCondition(status corev1.ConditionStatus, reason, message string) { - in.Status.Conditions = Conditions{ - { - Type: ConditionSynced, - Status: status, - LastTransitionTime: metav1.Now(), - Reason: reason, - Message: message, - }, - } -} - -func (in *MeshConfiguration) SetLastSyncedTime(time *metav1.Time) { - in.Status.LastSyncedTime = time -} - -func (in *MeshConfiguration) SyncedCondition() (status corev1.ConditionStatus, reason, message string) { - cond := in.Status.GetCondition(ConditionSynced) - if cond == nil { - return corev1.ConditionUnknown, "", "" - } - return cond.Status, cond.Reason, cond.Message -} - -func (in *MeshConfiguration) SyncedConditionStatus() corev1.ConditionStatus { - condition := in.Status.GetCondition(ConditionSynced) - if condition == nil { - return corev1.ConditionUnknown - } - return condition.Status -} - -func (in *MeshConfiguration) Validate(tenancy common.ConsulTenancyConfig) error { - return nil -} - -// DefaultNamespaceFields is required as part of the common.MeshConfig interface. -func (in *MeshConfiguration) DefaultNamespaceFields(tenancy common.ConsulTenancyConfig) {} diff --git a/control-plane/api/mesh/v2beta1/mesh_gateway_types.go b/control-plane/api/mesh/v2beta1/mesh_gateway_types.go deleted file mode 100644 index 4531a2089e..0000000000 --- a/control-plane/api/mesh/v2beta1/mesh_gateway_types.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 -package v2beta1 - -import ( - "fmt" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "google.golang.org/protobuf/testing/protocmp" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/intstr" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - "github.com/hashicorp/consul-k8s/control-plane/api/common" - inject "github.com/hashicorp/consul-k8s/control-plane/connect-inject/common" -) - -const ( - meshGatewayKubeKind = "meshgateway" -) - -func init() { - MeshSchemeBuilder.Register(&MeshGateway{}, &MeshGatewayList{}) -} - -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status - -// MeshGateway is the Schema for the Mesh Gateway API -// +kubebuilder:printcolumn:name="Synced",type="string",JSONPath=".status.conditions[?(@.type==\"Synced\")].status",description="The sync status of the resource with Consul" -// +kubebuilder:printcolumn:name="Last Synced",type="date",JSONPath=".status.lastSyncedTime",description="The last successful synced time of the resource with Consul" -// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the resource" -// +kubebuilder:resource:scope="Namespaced" -type MeshGateway struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec pbmesh.MeshGateway `json:"spec,omitempty"` - Status `json:"status,omitempty"` -} - -// +kubebuilder:object:root=true - -// MeshGatewayList contains a list of MeshGateway. -type MeshGatewayList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []*MeshGateway `json:"items"` -} - -func (in *MeshGatewayList) ReconcileRequests() []reconcile.Request { - requests := make([]reconcile.Request, 0, len(in.Items)) - - for _, item := range in.Items { - requests = append(requests, reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: item.Name, - Namespace: item.Namespace, - }, - }) - } - return requests -} - -func (in *MeshGateway) ResourceID(_, partition string) *pbresource.ID { - return &pbresource.ID{ - Name: in.Name, - Type: pbmesh.MeshGatewayType, - Tenancy: &pbresource.Tenancy{ - Partition: partition, - Namespace: "", // Namespace is always unset because MeshGateway is partition-scoped - }, - } -} - -func (in *MeshGateway) Resource(namespace, partition string) *pbresource.Resource { - return &pbresource.Resource{ - Id: in.ResourceID(namespace, partition), - Data: inject.ToProtoAny(&in.Spec), - Metadata: meshConfigMeta(), - } -} - -func (in *MeshGateway) AddFinalizer(f string) { - in.ObjectMeta.Finalizers = append(in.Finalizers(), f) -} - -func (in *MeshGateway) RemoveFinalizer(f string) { - var newFinalizers []string - for _, oldF := range in.Finalizers() { - if oldF != f { - newFinalizers = append(newFinalizers, oldF) - } - } - in.ObjectMeta.Finalizers = newFinalizers -} - -func (in *MeshGateway) Finalizers() []string { - return in.ObjectMeta.Finalizers -} - -func (in *MeshGateway) MatchesConsul(candidate *pbresource.Resource, namespace, partition string) bool { - return cmp.Equal( - in.Resource(namespace, partition), - candidate, - protocmp.IgnoreFields(&pbresource.Resource{}, "status", "generation", "version"), - protocmp.IgnoreFields(&pbresource.ID{}, "uid"), - protocmp.Transform(), - cmpopts.SortSlices(func(a, b any) bool { return fmt.Sprintf("%v", a) < fmt.Sprintf("%v", b) }), - ) -} - -func (in *MeshGateway) KubeKind() string { - return meshGatewayKubeKind -} - -func (in *MeshGateway) KubernetesName() string { - return in.ObjectMeta.Name -} - -func (in *MeshGateway) SetSyncedCondition(status corev1.ConditionStatus, reason, message string) { - in.Status.Conditions = Conditions{ - { - Type: ConditionSynced, - Status: status, - LastTransitionTime: metav1.Now(), - Reason: reason, - Message: message, - }, - } -} - -func (in *MeshGateway) SetLastSyncedTime(time *metav1.Time) { - in.Status.LastSyncedTime = time -} - -func (in *MeshGateway) SyncedCondition() (status corev1.ConditionStatus, reason, message string) { - cond := in.Status.GetCondition(ConditionSynced) - if cond == nil { - return corev1.ConditionUnknown, "", "" - } - return cond.Status, cond.Reason, cond.Message -} - -func (in *MeshGateway) SyncedConditionStatus() corev1.ConditionStatus { - condition := in.Status.GetCondition(ConditionSynced) - if condition == nil { - return corev1.ConditionUnknown - } - return condition.Status -} - -func (in *MeshGateway) Validate(tenancy common.ConsulTenancyConfig) error { - // TODO add validation logic that ensures we only ever write this to the default namespace. - return nil -} - -// DefaultNamespaceFields is required as part of the common.MeshConfig interface. -func (in *MeshGateway) DefaultNamespaceFields(tenancy common.ConsulTenancyConfig) {} - -// ListenersToServicePorts converts the MeshGateway listeners to ServicePorts. -func (in *MeshGateway) ListenersToServicePorts(portModifier int32) []corev1.ServicePort { - ports := []corev1.ServicePort{} - - for _, listener := range in.Spec.Listeners { - port := int32(listener.Port) - - ports = append(ports, corev1.ServicePort{ - Name: listener.Name, - Port: port, - TargetPort: intstr.IntOrString{ - IntVal: port + portModifier, - }, - Protocol: corev1.Protocol(listener.Protocol), - }) - } - return ports -} - -func (in *MeshGateway) ListenersToContainerPorts(portModifier int32, hostPort int32) []corev1.ContainerPort { - ports := []corev1.ContainerPort{} - - for _, listener := range in.Spec.Listeners { - port := int32(listener.Port) - - ports = append(ports, corev1.ContainerPort{ - Name: listener.Name, - ContainerPort: port + portModifier, - HostPort: hostPort, - Protocol: corev1.Protocol(listener.Protocol), - }) - } - return ports -} diff --git a/control-plane/api/mesh/v2beta1/proxy_configuration_route_webhook.go b/control-plane/api/mesh/v2beta1/proxy_configuration_route_webhook.go index 8c210703ea..711d8c81bc 100644 --- a/control-plane/api/mesh/v2beta1/proxy_configuration_route_webhook.go +++ b/control-plane/api/mesh/v2beta1/proxy_configuration_route_webhook.go @@ -27,7 +27,7 @@ type ProxyConfigurationWebhook struct { client.Client } -var _ common.ConsulResourceLister = &ProxyConfigurationWebhook{} +var _ common.MeshConfigLister = &ProxyConfigurationWebhook{} // NOTE: The path value in the below line is the path to the webhook. // If it is updated, run code-gen, update subcommand/inject-connect/command.go @@ -44,17 +44,17 @@ func (v *ProxyConfigurationWebhook) Handle(ctx context.Context, req admission.Re return admission.Errored(http.StatusBadRequest, err) } - return common.ValidateConsulResource(ctx, req, v.Logger, v, &resource, v.ConsulTenancyConfig) + return common.ValidateMeshConfig(ctx, req, v.Logger, v, &resource, v.ConsulTenancyConfig) } -func (v *ProxyConfigurationWebhook) List(ctx context.Context) ([]common.ConsulResource, error) { +func (v *ProxyConfigurationWebhook) List(ctx context.Context) ([]common.MeshConfig, error) { var resourceList ProxyConfigurationList if err := v.Client.List(ctx, &resourceList); err != nil { return nil, err } - var entries []common.ConsulResource + var entries []common.MeshConfig for _, item := range resourceList.Items { - entries = append(entries, common.ConsulResource(item)) + entries = append(entries, common.MeshConfig(item)) } return entries, nil } diff --git a/control-plane/api/mesh/v2beta1/proxy_configuration_types.go b/control-plane/api/mesh/v2beta1/proxy_configuration_types.go index cc1b5db9bd..4df6ff95e1 100644 --- a/control-plane/api/mesh/v2beta1/proxy_configuration_types.go +++ b/control-plane/api/mesh/v2beta1/proxy_configuration_types.go @@ -1,5 +1,5 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 +// // Copyright (c) HashiCorp, Inc. +// // SPDX-License-Identifier: MPL-2.0 package v2beta1 import ( @@ -18,6 +18,7 @@ import ( "github.com/hashicorp/consul-k8s/control-plane/api/common" inject "github.com/hashicorp/consul-k8s/control-plane/connect-inject/common" + "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" ) const ( @@ -60,6 +61,10 @@ func (in *ProxyConfiguration) ResourceID(namespace, partition string) *pbresourc Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, } } diff --git a/control-plane/api/mesh/v2beta1/proxy_configuration_types_test.go b/control-plane/api/mesh/v2beta1/proxy_configuration_types_test.go index 55e6ce45a9..67ad339697 100644 --- a/control-plane/api/mesh/v2beta1/proxy_configuration_types_test.go +++ b/control-plane/api/mesh/v2beta1/proxy_configuration_types_test.go @@ -220,6 +220,10 @@ func TestProxyConfiguration_MatchesConsul(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.DefaultConsulNS, Namespace: constants.DefaultConsulPartition, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, }, Data: inject.ToProtoAny(&pbmesh.ProxyConfiguration{}), @@ -520,6 +524,10 @@ func constructProxyConfigurationResource(tp *pbmesh.ProxyConfiguration, name, na Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, Uid: "ABCD", // We add this to show it does not factor into the comparison } diff --git a/control-plane/api/mesh/v2beta1/tcp_route_types.go b/control-plane/api/mesh/v2beta1/tcp_route_types.go index f5fa2888d6..207ef7afb3 100644 --- a/control-plane/api/mesh/v2beta1/tcp_route_types.go +++ b/control-plane/api/mesh/v2beta1/tcp_route_types.go @@ -1,5 +1,5 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 +// // Copyright (c) HashiCorp, Inc. +// // SPDX-License-Identifier: MPL-2.0 package v2beta1 import ( @@ -18,6 +18,7 @@ import ( "github.com/hashicorp/consul-k8s/control-plane/api/common" inject "github.com/hashicorp/consul-k8s/control-plane/connect-inject/common" + "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" ) const ( @@ -60,6 +61,10 @@ func (in *TCPRoute) ResourceID(namespace, partition string) *pbresource.ID { Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, } } diff --git a/control-plane/api/mesh/v2beta1/tcp_route_types_test.go b/control-plane/api/mesh/v2beta1/tcp_route_types_test.go index f03e5232db..9bedc58293 100644 --- a/control-plane/api/mesh/v2beta1/tcp_route_types_test.go +++ b/control-plane/api/mesh/v2beta1/tcp_route_types_test.go @@ -83,6 +83,7 @@ func TestTCPRoute_MatchesConsul(t *testing.T) { Type: pbmesh.ComputedRoutesType, Tenancy: &pbresource.Tenancy{ Namespace: "another-namespace", + PeerName: "another-peer", }, Name: "backend-name", Section: "backend-section", @@ -124,6 +125,7 @@ func TestTCPRoute_MatchesConsul(t *testing.T) { Type: pbmesh.ComputedRoutesType, Tenancy: &pbresource.Tenancy{ Namespace: "another-namespace", + PeerName: "another-peer", }, Name: "backend-name", Section: "backend-section", @@ -155,6 +157,10 @@ func TestTCPRoute_MatchesConsul(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.DefaultConsulNS, Namespace: constants.DefaultConsulPartition, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, }, Data: inject.ToProtoAny(&pbmesh.ProxyConfiguration{}), @@ -225,6 +231,7 @@ func TestTCPRoute_Resource(t *testing.T) { Type: pbmesh.ComputedRoutesType, Tenancy: &pbresource.Tenancy{ Namespace: "another-namespace", + PeerName: "another-peer", }, Name: "backend-name", Section: "backend-section", @@ -266,6 +273,7 @@ func TestTCPRoute_Resource(t *testing.T) { Type: pbmesh.ComputedRoutesType, Tenancy: &pbresource.Tenancy{ Namespace: "another-namespace", + PeerName: "another-peer", }, Name: "backend-name", Section: "backend-section", @@ -418,6 +426,7 @@ func TestTCPRoute_Validate(t *testing.T) { Type: pbmesh.ComputedRoutesType, Tenancy: &pbresource.Tenancy{ Namespace: "another-namespace", + PeerName: "another-peer", }, Name: "backend-name", Section: "backend-section", @@ -541,6 +550,10 @@ func constructTCPRouteResource(tp *pbmesh.TCPRoute, name, namespace, partition s Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, Uid: "ABCD", // We add this to show it does not factor into the comparison } diff --git a/control-plane/api/mesh/v2beta1/tcp_route_webhook.go b/control-plane/api/mesh/v2beta1/tcp_route_webhook.go index 4a7038276e..68e72c6e35 100644 --- a/control-plane/api/mesh/v2beta1/tcp_route_webhook.go +++ b/control-plane/api/mesh/v2beta1/tcp_route_webhook.go @@ -27,7 +27,7 @@ type TCPRouteWebhook struct { client.Client } -var _ common.ConsulResourceLister = &TCPRouteWebhook{} +var _ common.MeshConfigLister = &TCPRouteWebhook{} // NOTE: The path value in the below line is the path to the webhook. // If it is updated, run code-gen, update subcommand/inject-connect/command.go @@ -44,17 +44,17 @@ func (v *TCPRouteWebhook) Handle(ctx context.Context, req admission.Request) adm return admission.Errored(http.StatusBadRequest, err) } - return common.ValidateConsulResource(ctx, req, v.Logger, v, &resource, v.ConsulTenancyConfig) + return common.ValidateMeshConfig(ctx, req, v.Logger, v, &resource, v.ConsulTenancyConfig) } -func (v *TCPRouteWebhook) List(ctx context.Context) ([]common.ConsulResource, error) { +func (v *TCPRouteWebhook) List(ctx context.Context) ([]common.MeshConfig, error) { var resourceList TCPRouteList if err := v.Client.List(ctx, &resourceList); err != nil { return nil, err } - var entries []common.ConsulResource + var entries []common.MeshConfig for _, item := range resourceList.Items { - entries = append(entries, common.ConsulResource(item)) + entries = append(entries, common.MeshConfig(item)) } return entries, nil } diff --git a/control-plane/api/mesh/v2beta1/zz_generated.deepcopy.go b/control-plane/api/mesh/v2beta1/zz_generated.deepcopy.go index d4ca224b61..2d7aadbee7 100644 --- a/control-plane/api/mesh/v2beta1/zz_generated.deepcopy.go +++ b/control-plane/api/mesh/v2beta1/zz_generated.deepcopy.go @@ -6,101 +6,9 @@ package v2beta1 import ( - "k8s.io/api/core/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *APIGateway) DeepCopyInto(out *APIGateway) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.APIGatewayStatus.DeepCopyInto(&out.APIGatewayStatus) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIGateway. -func (in *APIGateway) DeepCopy() *APIGateway { - if in == nil { - return nil - } - out := new(APIGateway) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *APIGateway) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *APIGatewayList) DeepCopyInto(out *APIGatewayList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]*APIGateway, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(APIGateway) - (*in).DeepCopyInto(*out) - } - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIGatewayList. -func (in *APIGatewayList) DeepCopy() *APIGatewayList { - if in == nil { - return nil - } - out := new(APIGatewayList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *APIGatewayList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *APIGatewayStatus) DeepCopyInto(out *APIGatewayStatus) { - *out = *in - in.Status.DeepCopyInto(&out.Status) - if in.Addresses != nil { - in, out := &in.Addresses, &out.Addresses - *out = make([]GatewayAddress, len(*in)) - copy(*out, *in) - } - if in.Listeners != nil { - in, out := &in.Listeners, &out.Listeners - *out = make([]ListenerStatus, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIGatewayStatus. -func (in *APIGatewayStatus) DeepCopy() *APIGatewayStatus { - if in == nil { - return nil - } - out := new(APIGatewayStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Condition) DeepCopyInto(out *Condition) { *out = *in @@ -201,466 +109,6 @@ func (in *GRPCRouteList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayAddress) DeepCopyInto(out *GatewayAddress) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayAddress. -func (in *GatewayAddress) DeepCopy() *GatewayAddress { - if in == nil { - return nil - } - out := new(GatewayAddress) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClass) DeepCopyInto(out *GatewayClass) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClass. -func (in *GatewayClass) DeepCopy() *GatewayClass { - if in == nil { - return nil - } - out := new(GatewayClass) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GatewayClass) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassAnnotationsAndLabels) DeepCopyInto(out *GatewayClassAnnotationsAndLabels) { - *out = *in - in.Annotations.DeepCopyInto(&out.Annotations) - in.Labels.DeepCopyInto(&out.Labels) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassAnnotationsAndLabels. -func (in *GatewayClassAnnotationsAndLabels) DeepCopy() *GatewayClassAnnotationsAndLabels { - if in == nil { - return nil - } - out := new(GatewayClassAnnotationsAndLabels) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassAnnotationsLabelsConfig) DeepCopyInto(out *GatewayClassAnnotationsLabelsConfig) { - *out = *in - if in.InheritFromGateway != nil { - in, out := &in.InheritFromGateway, &out.InheritFromGateway - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Set != nil { - in, out := &in.Set, &out.Set - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassAnnotationsLabelsConfig. -func (in *GatewayClassAnnotationsLabelsConfig) DeepCopy() *GatewayClassAnnotationsLabelsConfig { - if in == nil { - return nil - } - out := new(GatewayClassAnnotationsLabelsConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassConfig) DeepCopyInto(out *GatewayClassConfig) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassConfig. -func (in *GatewayClassConfig) DeepCopy() *GatewayClassConfig { - if in == nil { - return nil - } - out := new(GatewayClassConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GatewayClassConfig) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassConfigList) DeepCopyInto(out *GatewayClassConfigList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]*GatewayClassConfig, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(GatewayClassConfig) - (*in).DeepCopyInto(*out) - } - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassConfigList. -func (in *GatewayClassConfigList) DeepCopy() *GatewayClassConfigList { - if in == nil { - return nil - } - out := new(GatewayClassConfigList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GatewayClassConfigList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassConfigSpec) DeepCopyInto(out *GatewayClassConfigSpec) { - *out = *in - in.GatewayClassAnnotationsAndLabels.DeepCopyInto(&out.GatewayClassAnnotationsAndLabels) - in.Deployment.DeepCopyInto(&out.Deployment) - in.Role.DeepCopyInto(&out.Role) - in.RoleBinding.DeepCopyInto(&out.RoleBinding) - in.Service.DeepCopyInto(&out.Service) - in.ServiceAccount.DeepCopyInto(&out.ServiceAccount) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassConfigSpec. -func (in *GatewayClassConfigSpec) DeepCopy() *GatewayClassConfigSpec { - if in == nil { - return nil - } - out := new(GatewayClassConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassConsulConfig) DeepCopyInto(out *GatewayClassConsulConfig) { - *out = *in - out.Logging = in.Logging -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassConsulConfig. -func (in *GatewayClassConsulConfig) DeepCopy() *GatewayClassConsulConfig { - if in == nil { - return nil - } - out := new(GatewayClassConsulConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassConsulLoggingConfig) DeepCopyInto(out *GatewayClassConsulLoggingConfig) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassConsulLoggingConfig. -func (in *GatewayClassConsulLoggingConfig) DeepCopy() *GatewayClassConsulLoggingConfig { - if in == nil { - return nil - } - out := new(GatewayClassConsulLoggingConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassContainerConfig) DeepCopyInto(out *GatewayClassContainerConfig) { - *out = *in - out.Consul = in.Consul - if in.Resources != nil { - in, out := &in.Resources, &out.Resources - *out = new(v1.ResourceRequirements) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassContainerConfig. -func (in *GatewayClassContainerConfig) DeepCopy() *GatewayClassContainerConfig { - if in == nil { - return nil - } - out := new(GatewayClassContainerConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassDeploymentConfig) DeepCopyInto(out *GatewayClassDeploymentConfig) { - *out = *in - in.GatewayClassAnnotationsAndLabels.DeepCopyInto(&out.GatewayClassAnnotationsAndLabels) - if in.Container != nil { - in, out := &in.Container, &out.Container - *out = new(GatewayClassContainerConfig) - (*in).DeepCopyInto(*out) - } - if in.InitContainer != nil { - in, out := &in.InitContainer, &out.InitContainer - *out = new(GatewayClassInitContainerConfig) - (*in).DeepCopyInto(*out) - } - if in.NodeSelector != nil { - in, out := &in.NodeSelector, &out.NodeSelector - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Replicas != nil { - in, out := &in.Replicas, &out.Replicas - *out = new(GatewayClassReplicasConfig) - (*in).DeepCopyInto(*out) - } - if in.SecurityContext != nil { - in, out := &in.SecurityContext, &out.SecurityContext - *out = new(v1.PodSecurityContext) - (*in).DeepCopyInto(*out) - } - if in.Tolerations != nil { - in, out := &in.Tolerations, &out.Tolerations - *out = make([]v1.Toleration, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.TopologySpreadConstraints != nil { - in, out := &in.TopologySpreadConstraints, &out.TopologySpreadConstraints - *out = make([]v1.TopologySpreadConstraint, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Affinity != nil { - in, out := &in.Affinity, &out.Affinity - *out = new(v1.Affinity) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassDeploymentConfig. -func (in *GatewayClassDeploymentConfig) DeepCopy() *GatewayClassDeploymentConfig { - if in == nil { - return nil - } - out := new(GatewayClassDeploymentConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassInitContainerConfig) DeepCopyInto(out *GatewayClassInitContainerConfig) { - *out = *in - out.Consul = in.Consul - if in.Resources != nil { - in, out := &in.Resources, &out.Resources - *out = new(v1.ResourceRequirements) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassInitContainerConfig. -func (in *GatewayClassInitContainerConfig) DeepCopy() *GatewayClassInitContainerConfig { - if in == nil { - return nil - } - out := new(GatewayClassInitContainerConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassList) DeepCopyInto(out *GatewayClassList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]*GatewayClass, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(GatewayClass) - (*in).DeepCopyInto(*out) - } - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassList. -func (in *GatewayClassList) DeepCopy() *GatewayClassList { - if in == nil { - return nil - } - out := new(GatewayClassList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GatewayClassList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassReplicasConfig) DeepCopyInto(out *GatewayClassReplicasConfig) { - *out = *in - if in.Default != nil { - in, out := &in.Default, &out.Default - *out = new(int32) - **out = **in - } - if in.Min != nil { - in, out := &in.Min, &out.Min - *out = new(int32) - **out = **in - } - if in.Max != nil { - in, out := &in.Max, &out.Max - *out = new(int32) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassReplicasConfig. -func (in *GatewayClassReplicasConfig) DeepCopy() *GatewayClassReplicasConfig { - if in == nil { - return nil - } - out := new(GatewayClassReplicasConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassRoleBindingConfig) DeepCopyInto(out *GatewayClassRoleBindingConfig) { - *out = *in - in.GatewayClassAnnotationsAndLabels.DeepCopyInto(&out.GatewayClassAnnotationsAndLabels) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassRoleBindingConfig. -func (in *GatewayClassRoleBindingConfig) DeepCopy() *GatewayClassRoleBindingConfig { - if in == nil { - return nil - } - out := new(GatewayClassRoleBindingConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassRoleConfig) DeepCopyInto(out *GatewayClassRoleConfig) { - *out = *in - in.GatewayClassAnnotationsAndLabels.DeepCopyInto(&out.GatewayClassAnnotationsAndLabels) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassRoleConfig. -func (in *GatewayClassRoleConfig) DeepCopy() *GatewayClassRoleConfig { - if in == nil { - return nil - } - out := new(GatewayClassRoleConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassServiceAccountConfig) DeepCopyInto(out *GatewayClassServiceAccountConfig) { - *out = *in - in.GatewayClassAnnotationsAndLabels.DeepCopyInto(&out.GatewayClassAnnotationsAndLabels) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassServiceAccountConfig. -func (in *GatewayClassServiceAccountConfig) DeepCopy() *GatewayClassServiceAccountConfig { - if in == nil { - return nil - } - out := new(GatewayClassServiceAccountConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassServiceConfig) DeepCopyInto(out *GatewayClassServiceConfig) { - *out = *in - in.GatewayClassAnnotationsAndLabels.DeepCopyInto(&out.GatewayClassAnnotationsAndLabels) - if in.Type != nil { - in, out := &in.Type, &out.Type - *out = new(v1.ServiceType) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassServiceConfig. -func (in *GatewayClassServiceConfig) DeepCopy() *GatewayClassServiceConfig { - if in == nil { - return nil - } - out := new(GatewayClassServiceConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayClassSpec) DeepCopyInto(out *GatewayClassSpec) { - *out = *in - if in.ParametersRef != nil { - in, out := &in.ParametersRef, &out.ParametersRef - *out = new(ParametersReference) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassSpec. -func (in *GatewayClassSpec) DeepCopy() *GatewayClassSpec { - if in == nil { - return nil - } - out := new(GatewayClassSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { *out = *in @@ -724,168 +172,6 @@ func (in *HTTPRouteList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ListenerStatus) DeepCopyInto(out *ListenerStatus) { - *out = *in - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerStatus. -func (in *ListenerStatus) DeepCopy() *ListenerStatus { - if in == nil { - return nil - } - out := new(ListenerStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MeshConfiguration) DeepCopyInto(out *MeshConfiguration) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshConfiguration. -func (in *MeshConfiguration) DeepCopy() *MeshConfiguration { - if in == nil { - return nil - } - out := new(MeshConfiguration) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *MeshConfiguration) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MeshConfigurationList) DeepCopyInto(out *MeshConfigurationList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]*MeshConfiguration, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(MeshConfiguration) - (*in).DeepCopyInto(*out) - } - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshConfigurationList. -func (in *MeshConfigurationList) DeepCopy() *MeshConfigurationList { - if in == nil { - return nil - } - out := new(MeshConfigurationList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *MeshConfigurationList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MeshGateway) DeepCopyInto(out *MeshGateway) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshGateway. -func (in *MeshGateway) DeepCopy() *MeshGateway { - if in == nil { - return nil - } - out := new(MeshGateway) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *MeshGateway) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MeshGatewayList) DeepCopyInto(out *MeshGatewayList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]*MeshGateway, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(MeshGateway) - (*in).DeepCopyInto(*out) - } - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshGatewayList. -func (in *MeshGatewayList) DeepCopy() *MeshGatewayList { - if in == nil { - return nil - } - out := new(MeshGatewayList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *MeshGatewayList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ParametersReference) DeepCopyInto(out *ParametersReference) { - *out = *in - if in.Namespace != nil { - in, out := &in.Namespace, &out.Namespace - *out = new(string) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParametersReference. -func (in *ParametersReference) DeepCopy() *ParametersReference { - if in == nil { - return nil - } - out := new(ParametersReference) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProxyConfiguration) DeepCopyInto(out *ProxyConfiguration) { *out = *in diff --git a/control-plane/api/multicluster/v2/exported_services_types.go b/control-plane/api/multicluster/v2/exported_services_types.go deleted file mode 100644 index 032e10bd03..0000000000 --- a/control-plane/api/multicluster/v2/exported_services_types.go +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 -package v2 - -import ( - "fmt" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" - "github.com/hashicorp/consul/proto-public/pbresource" - "google.golang.org/protobuf/testing/protocmp" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/hashicorp/consul-k8s/control-plane/api/common" - inject "github.com/hashicorp/consul-k8s/control-plane/connect-inject/common" -) - -const ( - exportedServicesKubeKind = "exportedservices" -) - -func init() { - MultiClusterSchemeBuilder.Register(&ExportedServices{}, &ExportedServicesList{}) -} - -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status - -// ExportedServices is the Schema for the Exported Services API -// +kubebuilder:printcolumn:name="Synced",type="string",JSONPath=".status.conditions[?(@.type==\"Synced\")].status",description="The sync status of the resource with Consul" -// +kubebuilder:printcolumn:name="Last Synced",type="date",JSONPath=".status.lastSyncedTime",description="The last successful synced time of the resource with Consul" -// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the resource" -// +kubebuilder:resource:scope="Namespaced" -type ExportedServices struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec pbmulticluster.ExportedServices `json:"spec,omitempty"` - Status `json:"status,omitempty"` -} - -// +kubebuilder:object:root=true - -// ExportedServicesList contains a list of ExportedServices. -type ExportedServicesList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []*ExportedServices `json:"items"` -} - -func (in *ExportedServices) ResourceID(_, partition string) *pbresource.ID { - return &pbresource.ID{ - Name: in.Name, - Type: pbmulticluster.ExportedServicesType, - Tenancy: &pbresource.Tenancy{ - Partition: partition, - Namespace: "", // Namespace is always unset because ExportedServices is partition-scoped - }, - } -} - -func (in *ExportedServices) Resource(namespace, partition string) *pbresource.Resource { - return &pbresource.Resource{ - Id: in.ResourceID(namespace, partition), - Data: inject.ToProtoAny(&in.Spec), - Metadata: multiClusterConfigMeta(), - } -} - -func (in *ExportedServices) AddFinalizer(f string) { - in.ObjectMeta.Finalizers = append(in.Finalizers(), f) -} - -func (in *ExportedServices) RemoveFinalizer(f string) { - var newFinalizers []string - for _, oldF := range in.Finalizers() { - if oldF != f { - newFinalizers = append(newFinalizers, oldF) - } - } - in.ObjectMeta.Finalizers = newFinalizers -} - -func (in *ExportedServices) Finalizers() []string { - return in.ObjectMeta.Finalizers -} - -func (in *ExportedServices) MatchesConsul(candidate *pbresource.Resource, namespace, partition string) bool { - return cmp.Equal( - in.Resource(namespace, partition), - candidate, - protocmp.IgnoreFields(&pbresource.Resource{}, "status", "generation", "version"), - protocmp.IgnoreFields(&pbresource.ID{}, "uid"), - protocmp.Transform(), - cmpopts.SortSlices(func(a, b any) bool { return fmt.Sprintf("%v", a) < fmt.Sprintf("%v", b) }), - ) -} - -func (in *ExportedServices) KubeKind() string { - return exportedServicesKubeKind -} - -func (in *ExportedServices) KubernetesName() string { - return in.ObjectMeta.Name -} - -func (in *ExportedServices) SetSyncedCondition(status corev1.ConditionStatus, reason, message string) { - in.Status.Conditions = Conditions{ - { - Type: ConditionSynced, - Status: status, - LastTransitionTime: metav1.Now(), - Reason: reason, - Message: message, - }, - } -} - -func (in *ExportedServices) SetLastSyncedTime(time *metav1.Time) { - in.Status.LastSyncedTime = time -} - -func (in *ExportedServices) SyncedCondition() (status corev1.ConditionStatus, reason, message string) { - cond := in.Status.GetCondition(ConditionSynced) - if cond == nil { - return corev1.ConditionUnknown, "", "" - } - return cond.Status, cond.Reason, cond.Message -} - -func (in *ExportedServices) SyncedConditionStatus() corev1.ConditionStatus { - condition := in.Status.GetCondition(ConditionSynced) - if condition == nil { - return corev1.ConditionUnknown - } - return condition.Status -} - -func (in *ExportedServices) Validate(tenancy common.ConsulTenancyConfig) error { - // TODO add validation logic that ensures we only ever write this to the default namespace. - return nil -} - -// DefaultNamespaceFields is required as part of the common.MeshConfig interface. -func (in *ExportedServices) DefaultNamespaceFields(tenancy common.ConsulTenancyConfig) {} diff --git a/control-plane/api/multicluster/v2/multicluster_groupversion_info.go b/control-plane/api/multicluster/v2/multicluster_groupversion_info.go deleted file mode 100644 index 7b8f92f4ac..0000000000 --- a/control-plane/api/multicluster/v2/multicluster_groupversion_info.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Package v2 contains API Schema definitions for the consul.hashicorp.com v2 API group -// +kubebuilder:object:generate=true -// +groupName=multicluster.consul.hashicorp.com -package v2 - -import ( - "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/controller-runtime/pkg/scheme" -) - -var ( - - // MultiClusterGroup is a collection of multi-cluster resources. - MultiClusterGroup = "multicluster.consul.hashicorp.com" - - // MultiClusterGroupVersion is group version used to register these objects. - MultiClusterGroupVersion = schema.GroupVersion{Group: MultiClusterGroup, Version: "v2"} - - // MultiClusterSchemeBuilder is used to add go types to the GroupVersionKind scheme. - MultiClusterSchemeBuilder = &scheme.Builder{GroupVersion: MultiClusterGroupVersion} - - // AddMultiClusterToScheme adds the types in this group-version to the given scheme. - AddMultiClusterToScheme = MultiClusterSchemeBuilder.AddToScheme -) diff --git a/control-plane/api/multicluster/v2/shared_types.go b/control-plane/api/multicluster/v2/shared_types.go deleted file mode 100644 index 04f9fcefa4..0000000000 --- a/control-plane/api/multicluster/v2/shared_types.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package v2 - -import ( - "github.com/hashicorp/consul-k8s/control-plane/api/common" -) - -func multiClusterConfigMeta() map[string]string { - return map[string]string{ - common.SourceKey: common.SourceValue, - } -} diff --git a/control-plane/api/multicluster/v2/status.go b/control-plane/api/multicluster/v2/status.go deleted file mode 100644 index 070c57a7d9..0000000000 --- a/control-plane/api/multicluster/v2/status.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package v2 - -import ( - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// Conditions is the schema for the conditions portion of the payload. -type Conditions []Condition - -// ConditionType is a camel-cased condition type. -type ConditionType string - -const ( - // ConditionSynced specifies that the resource has been synced with Consul. - ConditionSynced ConditionType = "Synced" -) - -// Conditions define a readiness condition for a Consul resource. -// See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties -// +k8s:deepcopy-gen=true -// +k8s:openapi-gen=true -type Condition struct { - // Type of condition. - // +required - Type ConditionType `json:"type" description:"type of status condition"` - - // Status of the condition, one of True, False, Unknown. - // +required - Status corev1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"` - - // LastTransitionTime is the last time the condition transitioned from one status to another. - // +optional - LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty" description:"last time the condition transitioned from one status to another"` - - // The reason for the condition's last transition. - // +optional - Reason string `json:"reason,omitempty" description:"one-word CamelCase reason for the condition's last transition"` - - // A human readable message indicating details about the transition. - // +optional - Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"` -} - -// IsTrue is true if the condition is True. -func (c *Condition) IsTrue() bool { - if c == nil { - return false - } - return c.Status == corev1.ConditionTrue -} - -// IsFalse is true if the condition is False. -func (c *Condition) IsFalse() bool { - if c == nil { - return false - } - return c.Status == corev1.ConditionFalse -} - -// IsUnknown is true if the condition is Unknown. -func (c *Condition) IsUnknown() bool { - if c == nil { - return true - } - return c.Status == corev1.ConditionUnknown -} - -// +k8s:deepcopy-gen=true -// +k8s:openapi-gen=true -type Status struct { - // Conditions indicate the latest available observations of a resource's current state. - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - Conditions Conditions `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` - - // LastSyncedTime is the last time the resource successfully synced with Consul. - // +optional - LastSyncedTime *metav1.Time `json:"lastSyncedTime,omitempty" description:"last time the condition transitioned from one status to another"` -} - -func (s *Status) GetCondition(t ConditionType) *Condition { - for _, cond := range s.Conditions { - if cond.Type == t { - return &cond - } - } - return nil -} diff --git a/control-plane/api/multicluster/v2/zz_generated.deepcopy.go b/control-plane/api/multicluster/v2/zz_generated.deepcopy.go deleted file mode 100644 index c52d2bfe81..0000000000 --- a/control-plane/api/multicluster/v2/zz_generated.deepcopy.go +++ /dev/null @@ -1,136 +0,0 @@ -//go:build !ignore_autogenerated -// +build !ignore_autogenerated - -// Code generated by controller-gen. DO NOT EDIT. - -package v2 - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Condition) DeepCopyInto(out *Condition) { - *out = *in - in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition. -func (in *Condition) DeepCopy() *Condition { - if in == nil { - return nil - } - out := new(Condition) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in Conditions) DeepCopyInto(out *Conditions) { - { - in := &in - *out = make(Conditions, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Conditions. -func (in Conditions) DeepCopy() Conditions { - if in == nil { - return nil - } - out := new(Conditions) - in.DeepCopyInto(out) - return *out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExportedServices) DeepCopyInto(out *ExportedServices) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExportedServices. -func (in *ExportedServices) DeepCopy() *ExportedServices { - if in == nil { - return nil - } - out := new(ExportedServices) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ExportedServices) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExportedServicesList) DeepCopyInto(out *ExportedServicesList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]*ExportedServices, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(ExportedServices) - (*in).DeepCopyInto(*out) - } - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExportedServicesList. -func (in *ExportedServicesList) DeepCopy() *ExportedServicesList { - if in == nil { - return nil - } - out := new(ExportedServicesList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ExportedServicesList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Status) DeepCopyInto(out *Status) { - *out = *in - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make(Conditions, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.LastSyncedTime != nil { - in, out := &in.LastSyncedTime, &out.LastSyncedTime - *out = (*in).DeepCopy() - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. -func (in *Status) DeepCopy() *Status { - if in == nil { - return nil - } - out := new(Status) - in.DeepCopyInto(out) - return out -} diff --git a/control-plane/build-support/functions/10-util.sh b/control-plane/build-support/functions/10-util.sh index dfcf5eb361..9473226b2c 100644 --- a/control-plane/build-support/functions/10-util.sh +++ b/control-plane/build-support/functions/10-util.sh @@ -95,7 +95,7 @@ function have_gpg_key { function parse_version { # Arguments: - # $1 - Path to the top level Consul K8s source + # $1 - Path to the top level Consul source # $2 - boolean value for whether the release version should be parsed from the source # $3 - boolean whether to use GIT_DESCRIBE and GIT_COMMIT environment variables # $4 - boolean whether to omit the version part of the version string. (optional) @@ -190,7 +190,7 @@ function parse_version { function get_version { # Arguments: - # $1 - Path to the top level Consul K8s source + # $1 - Path to the top level Consul source # $2 - Whether the release version should be parsed from source (optional) # $3 - Whether to use GIT_DESCRIBE and GIT_COMMIT environment variables # @@ -344,7 +344,7 @@ function normalize_git_url { function git_remote_url { # Arguments: - # $1 - Path to the top level Consul K8s source + # $1 - Path to the top level Consul source # $2 - Remote name # # Returns: @@ -380,7 +380,7 @@ function git_remote_url { function find_git_remote { # Arguments: - # $1 - Path to the top level Consul K8s source + # $1 - Path to the top level Consul source # # Returns: # 0 - success @@ -482,7 +482,7 @@ function update_git_env { function git_push_ref { # Arguments: - # $1 - Path to the top level Consul K8s source + # $1 - Path to the top level Consul source # $2 - Git ref (optional) # $3 - remote (optional - if not specified we will try to determine it) # @@ -629,8 +629,7 @@ function update_version_helm { full_consul_version="$5-$3" full_consul_dataplane_version="$7-$3" elif test "$3" == "dev"; then - full_version="${2%.*}-$3" - full_version_k8s_for_chart_version="$2-$3" + full_version="$2-$3" # strip off the last minor patch version so that the consul image can be set to something like 1.16-dev. The image # is produced by Consul every night full_consul_version="${5%.*}-$3" @@ -638,7 +637,7 @@ function update_version_helm { fi sed_i ${SED_EXT} -e "s/(imageK8S:.*\/consul-k8s-control-plane:)[^\"]*/imageK8S: $4${full_version}/g" "${vfile}" - sed_i ${SED_EXT} -e "s/(version:[[:space:]]*)[^\"]*/\1${full_version_k8s_for_chart_version}/g" "${cfile}" + sed_i ${SED_EXT} -e "s/(version:[[:space:]]*)[^\"]*/\1${full_version}/g" "${cfile}" sed_i ${SED_EXT} -e "s/(appVersion:[[:space:]]*)[^\"]*/\1${full_consul_version}/g" "${cfile}" sed_i ${SED_EXT} -e "s/(image:.*\/consul-k8s-control-plane:)[^\"]*/image: $4${full_version}/g" "${cfile}" @@ -660,7 +659,7 @@ function update_version_helm { function set_version { # Arguments: - # $1 - Path to top level Consul K8s source + # $1 - Path to top level Consul source # $2 - The version of the release # $3 - The release date # $4 - The pre-release version @@ -710,13 +709,11 @@ function set_version { function set_changelog { # Arguments: - # $1 - Path to top level Consul K8s source + # $1 - Path to top level Consul source # $2 - Version # $3 - Release Date # $4 - The last git release tag # $5 - Pre-release version - # $6 - The version of Consul corresponding to the release (only used for .0) - # $7 - The version of Consul Dataplane corresponding to the release (only used for .0) # # # Returns: @@ -736,13 +733,7 @@ function set_changelog { rel_date="$3" fi local last_release_date_git_tag=$4 - - # Only set prerelease suffix if prerelease version is set - local preReleaseVersion="${5:+-${5}}" - - local version_short="${version%\.*}" - local consul_version_short="${6%\.*}" - local consul_dataplane_version_short="${7%\.*}" + local preReleaseVersion="-$5" if test -z "${version}"; then err "ERROR: Must specify a version to put into the changelog" @@ -754,18 +745,8 @@ function set_changelog { exit 1 fi - if [[ "${version}" =~ \.0$ ]]; then - if [ -z "$version_short" ] || [ -z "$consul_version_short" ] || [ -z "$consul_dataplane_version_short" ]; then - echo "Error: Consul K8s, Consul or Consul Dataplane short version could not be detected." - exit 1 - fi - compatibility_note=" - -> NOTE: Consul K8s ${version_short}.x is compatible with Consul ${consul_version_short}.x and Consul Dataplane ${consul_dataplane_version_short}.x. Refer to our [compatibility matrix](https://developer.hashicorp.com/consul/docs/k8s/compatibility) for more info." - fi - cat <tmp && mv tmp "${curdir}"/CHANGELOG.MD -## ${version}${preReleaseVersion} (${rel_date})${compatibility_note} +## ${version}${preReleaseVersion} (${rel_date}) $(changelog-build -last-release ${CONSUL_K8S_LAST_RELEASE_GIT_TAG} \ -entries-dir .changelog/ \ -changelog-template .changelog/changelog.tmpl \ @@ -777,13 +758,13 @@ EOT function prepare_release { # Arguments: - # $1 - Path to top level Consul K8s source + # $1 - Path to top level Consul source # $2 - The version of the release # $3 - The release date # $4 - The last release git tag for this branch (eg. v1.1.0) - # $5 - The consul version + # $5 - The consul version # $6 - The consul-dataplane version - # $7 - The pre-release version + # $7 - The pre-release version # # # Returns: @@ -800,12 +781,12 @@ function prepare_release { echo "prepare_release: dir:${curDir} consul-k8s:${version} consul:${consulVersion} consul-dataplane:${consulDataplaneVersion} date:"${releaseDate}" git tag:${lastGitTag}" set_version "${curDir}" "${version}" "${releaseDate}" "${prereleaseVersion}" "hashicorp\/consul-k8s-control-plane:" "${consulVersion}" "hashicorp\/consul" "${consulDataplaneVersion}" "hashicorp\/consul-dataplane" - set_changelog "${curDir}" "${version}" "${releaseDate}" "${lastGitTag}" "${prereleaseVersion}" "${consulVersion}" "${consulDataplaneVersion}" + set_changelog "${curDir}" "${version}" "${releaseDate}" "${lastGitTag}" "${prereleaseVersion}" } function prepare_rc_branch { # Arguments: - # $1 - Path to top level Consul K8s source + # $1 - Path to top level Consul source # $2 - The version of the release # $3 - The release date # $4 - The last release git tag for this branch (eg. v1.1.0) @@ -832,7 +813,7 @@ function prepare_rc_branch { function prepare_dev { # Arguments: - # $1 - Path to top level Consul K8s source + # $1 - Path to top level Consul source # $2 - The version of the release # $3 - The release date # $4 - The last release git tag for this branch (eg. v1.1.0) (Unused) @@ -887,7 +868,7 @@ function git_staging_empty { function commit_dev_mode { # Arguments: - # $1 - Path to top level Consul K8s source + # $1 - Path to top level Consul source # # Returns: # 0 - success diff --git a/control-plane/build-support/scripts/consul-enterprise-version.sh b/control-plane/build-support/scripts/consul-enterprise-version.sh index d910f428ab..d0a1a40b53 100755 --- a/control-plane/build-support/scripts/consul-enterprise-version.sh +++ b/control-plane/build-support/scripts/consul-enterprise-version.sh @@ -4,11 +4,11 @@ FILE=$1 VERSION=$(yq .global.image $FILE) -if [[ "${VERSION}" == *"hashicorp/consul:"* ]]; then - # for matching release image repos with a -ent label +if [[ !"${VERSION}" == *"hashicorp/consul:"* ]]; then VERSION=$(echo ${VERSION} | sed "s/consul:/consul-enterprise:/g" | sed "s/$/-ent/g") +elif [[ !"${VERSION}" == *"-rc"* ]]; then + VERSION=$(echo ${VERSION} | sed "s/consul:/consul-enterprise:/g" | sed "s/$/-ent/g") else - # for matching preview image repos VERSION=$(echo ${VERSION} | sed "s/consul:/consul-enterprise:/g") fi diff --git a/control-plane/cni/go.mod b/control-plane/cni/go.mod index cd4d529fb3..fc5d41546e 100644 --- a/control-plane/cni/go.mod +++ b/control-plane/cni/go.mod @@ -3,19 +3,19 @@ module github.com/hashicorp/consul-k8s/control-plane/cni require ( github.com/containernetworking/cni v1.1.2 github.com/containernetworking/plugins v1.2.0 - github.com/hashicorp/consul/sdk v0.15.0 - github.com/hashicorp/go-hclog v1.5.0 + github.com/hashicorp/consul/sdk v0.13.1 + github.com/hashicorp/go-hclog v1.2.2 github.com/stretchr/testify v1.8.4 - k8s.io/api v0.26.12 - k8s.io/apimachinery v0.26.12 - k8s.io/client-go v0.26.12 + k8s.io/api v0.26.10 + k8s.io/apimachinery v0.26.10 + k8s.io/client-go v0.26.10 ) require ( - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.10.1 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/fatih/color v1.14.1 // indirect + github.com/fatih/color v1.13.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.20.0 // indirect @@ -36,7 +36,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/onsi/ginkgo/v2 v2.6.1 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.10.0 // indirect @@ -57,6 +57,6 @@ require ( sigs.k8s.io/yaml v1.3.0 // indirect ) -//replace github.com/hashicorp/consul/sdk => github.com/hashicorp/consul/sdk v0.4.1-0.20221021205723-cc843c4be892 +replace github.com/hashicorp/consul/sdk => github.com/hashicorp/consul/sdk v0.4.1-0.20221021205723-cc843c4be892 go 1.20 diff --git a/control-plane/cni/go.sum b/control-plane/cni/go.sum index 798ec2ab74..824239c7f5 100644 --- a/control-plane/cni/go.sum +++ b/control-plane/cni/go.sum @@ -11,9 +11,8 @@ github.com/containernetworking/plugins v1.2.0 h1:SWgg3dQG1yzUo4d9iD8cwSVh1VqI+bP github.com/containernetworking/plugins v1.2.0/go.mod h1:/VjX4uHecW5vVimFa1wkG4s+r/s9qIfPdqlLF4TW8c4= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/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/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= @@ -21,9 +20,10 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -69,10 +69,13 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ 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/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/hashicorp/consul/sdk v0.15.0 h1:2qK9nDrr4tiJKRoxPGhm6B7xJjLVIQqkjiab2M4aKjU= -github.com/hashicorp/consul/sdk v0.15.0/go.mod h1:r/OmRRPbHOe0yxNahLw7G9x5WG17E1BIECMtCjcPSNo= -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/consul/sdk v0.4.1-0.20221021205723-cc843c4be892 h1:jw0NwPmNPr5CxAU04hACdj61JSaJBKZ0FdBo+kwfNp4= +github.com/hashicorp/consul/sdk v0.4.1-0.20221021205723-cc843c4be892/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.2.2 h1:ihRI7YFwcZdiSD7SIenIhHfQH3OuDvWerAUBZbeQS3M= +github.com/hashicorp/go-hclog v1.2.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= @@ -85,7 +88,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -94,10 +96,14 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 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.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= @@ -110,6 +116,7 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -123,18 +130,19 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +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.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= @@ -176,9 +184,12 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/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-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -190,6 +201,7 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= @@ -245,8 +257,8 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -264,12 +276,12 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.26.12 h1:jJm3s5ot05SUN3tPGg3b+XWuBE7rO/X0+dnVMhxyd5o= -k8s.io/api v0.26.12/go.mod h1:N+HUXukmtXNOKDngxXrEPbZWggWx01tH/N0nG4nV0oo= -k8s.io/apimachinery v0.26.12 h1:y+OgufxqLIZtyXIydRhjLBGzrYLF+qwiDdCFXYOjeN4= -k8s.io/apimachinery v0.26.12/go.mod h1:2/HZp0l6coXtS26du1Bk36fCuAEr/lVs9Q9NbpBtd1Y= -k8s.io/client-go v0.26.12 h1:kPpTpIeFNqwo4UyvoqzNp3DNK2mbGcdGv23eS1U8VMo= -k8s.io/client-go v0.26.12/go.mod h1:V7thEnIFroyNZOU30dKLiiVeqQmJz45shJG1mu7nONQ= +k8s.io/api v0.26.10 h1:skTnrDR0r8dg4MMLf6YZIzugxNM0BjFsWKPkNc5kOvk= +k8s.io/api v0.26.10/go.mod h1:ou/H3yviqrHtP/DSPVTfsc7qNfmU06OhajytJfYXkXw= +k8s.io/apimachinery v0.26.10 h1:aE+J2KIbjctFqPp3Y0q4Wh2PD+l1p2g3Zp4UYjSvtGU= +k8s.io/apimachinery v0.26.10/go.mod h1:iT1ZP4JBP34wwM+ZQ8ByPEQ81u043iqAcsJYftX9amM= +k8s.io/client-go v0.26.10 h1:4mDzl+1IrfRxh4Ro0s65JRGJp14w77gSMUTjACYWVRo= +k8s.io/client-go v0.26.10/go.mod h1:sh74ig838gCckU4ElYclWb24lTesPdEDPnlyg5vcbkA= 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= diff --git a/control-plane/controllers/configentries/configentry_controller.go b/control-plane/config-entries/controllers/configentry_controller.go similarity index 99% rename from control-plane/controllers/configentries/configentry_controller.go rename to control-plane/config-entries/controllers/configentry_controller.go index 9e9459308f..03d30c0aa1 100644 --- a/control-plane/controllers/configentries/configentry_controller.go +++ b/control-plane/config-entries/controllers/configentry_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" @@ -36,8 +36,8 @@ const ( MigrationFailedError = "MigrationFailedError" ) -// Controller is implemented by CRD-specific configentries. It is used by -// ConfigEntryController to abstract CRD-specific configentries. +// Controller is implemented by CRD-specific controllers. It is used by +// ConfigEntryController to abstract CRD-specific controllers. type Controller interface { // AddFinalizersPatch creates a patch with the original finalizers with new ones appended to the end. AddFinalizersPatch(obj client.Object, finalizers ...string) *FinalizerPatch diff --git a/control-plane/controllers/configentries/configentry_controller_ent_test.go b/control-plane/config-entries/controllers/configentry_controller_ent_test.go similarity index 99% rename from control-plane/controllers/configentries/configentry_controller_ent_test.go rename to control-plane/config-entries/controllers/configentry_controller_ent_test.go index b9eabf3a72..a0fb5ce91e 100644 --- a/control-plane/controllers/configentries/configentry_controller_ent_test.go +++ b/control-plane/config-entries/controllers/configentry_controller_ent_test.go @@ -3,7 +3,7 @@ //go:build enterprise -package configentries +package controllers import ( "context" @@ -32,7 +32,7 @@ import ( // NOTE: We're not testing each controller type here because that's mostly done in // the OSS tests and it would result in too many permutations. Instead -// we're only testing with the ServiceDefaults and ProxyDefaults configentries which +// we're only testing with the ServiceDefaults and ProxyDefaults controllers which // will exercise all the namespaces code for config entries that are namespaced and those that // exist in the global namespace. // We also test Enterprise only features like SamenessGroups. diff --git a/control-plane/controllers/configentries/configentry_controller_test.go b/control-plane/config-entries/controllers/configentry_controller_test.go similarity index 99% rename from control-plane/controllers/configentries/configentry_controller_test.go rename to control-plane/config-entries/controllers/configentry_controller_test.go index faa153c323..57e48dd46c 100644 --- a/control-plane/controllers/configentries/configentry_controller_test.go +++ b/control-plane/config-entries/controllers/configentry_controller_test.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/configentries/controlplanerequestlimit_controller.go b/control-plane/config-entries/controllers/controlplanerequestlimit_controller.go similarity index 98% rename from control-plane/controllers/configentries/controlplanerequestlimit_controller.go rename to control-plane/config-entries/controllers/controlplanerequestlimit_controller.go index c636f7fec5..d5a41cf8ec 100644 --- a/control-plane/controllers/configentries/controlplanerequestlimit_controller.go +++ b/control-plane/config-entries/controllers/controlplanerequestlimit_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/configentries/exportedservices_controller.go b/control-plane/config-entries/controllers/exportedservices_controller.go similarity index 98% rename from control-plane/controllers/configentries/exportedservices_controller.go rename to control-plane/config-entries/controllers/exportedservices_controller.go index 474431832a..28d0f9c807 100644 --- a/control-plane/controllers/configentries/exportedservices_controller.go +++ b/control-plane/config-entries/controllers/exportedservices_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/configentries/exportedservices_controller_ent_test.go b/control-plane/config-entries/controllers/exportedservices_controller_ent_test.go similarity index 95% rename from control-plane/controllers/configentries/exportedservices_controller_ent_test.go rename to control-plane/config-entries/controllers/exportedservices_controller_ent_test.go index 61ec75288f..70b774eb53 100644 --- a/control-plane/controllers/configentries/exportedservices_controller_ent_test.go +++ b/control-plane/config-entries/controllers/exportedservices_controller_ent_test.go @@ -3,7 +3,7 @@ //go:build enterprise -package configentries_test +package controllers_test import ( "context" @@ -23,7 +23,7 @@ import ( "github.com/hashicorp/consul-k8s/control-plane/api/common" "github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1" - "github.com/hashicorp/consul-k8s/control-plane/controllers/configentries" + "github.com/hashicorp/consul-k8s/control-plane/config-entries/controllers" "github.com/hashicorp/consul-k8s/control-plane/helper/test" ) @@ -104,11 +104,11 @@ func TestExportedServicesController_createsExportedServices(tt *testing.T) { fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(exportedServices).Build() - controller := &configentries.ExportedServicesController{ + controller := &controllers.ExportedServicesController{ Client: fakeClient, Log: logrtest.NewTestLogger(t), Scheme: s, - ConfigEntryController: &configentries.ConfigEntryController{ + ConfigEntryController: &controllers.ConfigEntryController{ ConsulClientConfig: testClient.Cfg, ConsulServerConnMgr: testClient.Watcher, EnableConsulNamespaces: true, @@ -196,7 +196,7 @@ func TestExportedServicesController_updatesExportedServices(tt *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "default", Namespace: c.SourceKubeNS, - Finalizers: []string{configentries.FinalizerName}, + Finalizers: []string{controllers.FinalizerName}, }, Spec: v1alpha1.ExportedServicesSpec{ Services: []v1alpha1.ExportedService{ @@ -219,11 +219,11 @@ func TestExportedServicesController_updatesExportedServices(tt *testing.T) { consulClient := testClient.APIClient fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(exportedServices).Build() - controller := &configentries.ExportedServicesController{ + controller := &controllers.ExportedServicesController{ Client: fakeClient, Log: logrtest.NewTestLogger(t), Scheme: s, - ConfigEntryController: &configentries.ConfigEntryController{ + ConfigEntryController: &controllers.ConfigEntryController{ ConsulClientConfig: testClient.Cfg, ConsulServerConnMgr: testClient.Watcher, EnableConsulNamespaces: true, @@ -333,7 +333,7 @@ func TestExportedServicesController_deletesExportedServices(tt *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "default", Namespace: c.SourceKubeNS, - Finalizers: []string{configentries.FinalizerName}, + Finalizers: []string{controllers.FinalizerName}, DeletionTimestamp: &metav1.Time{Time: time.Now()}, }, Spec: v1alpha1.ExportedServicesSpec{ @@ -357,11 +357,11 @@ func TestExportedServicesController_deletesExportedServices(tt *testing.T) { fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(exportedServices).Build() - controller := &configentries.ExportedServicesController{ + controller := &controllers.ExportedServicesController{ Client: fakeClient, Log: logrtest.NewTestLogger(t), Scheme: s, - ConfigEntryController: &configentries.ConfigEntryController{ + ConfigEntryController: &controllers.ConfigEntryController{ ConsulClientConfig: testClient.Cfg, ConsulServerConnMgr: testClient.Watcher, EnableConsulNamespaces: true, diff --git a/control-plane/controllers/configentries/finalizer_patch.go b/control-plane/config-entries/controllers/finalizer_patch.go similarity index 95% rename from control-plane/controllers/configentries/finalizer_patch.go rename to control-plane/config-entries/controllers/finalizer_patch.go index a261220c8f..5eec8d5d29 100644 --- a/control-plane/controllers/configentries/finalizer_patch.go +++ b/control-plane/config-entries/controllers/finalizer_patch.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "encoding/json" @@ -25,7 +25,7 @@ type FinalizerPatch struct { // user or another controller process). Before the addition of this finalizer patcher implementation, this race // condition still existed, but applied to the entirety of the CRD because we used to update the entire CRD rather than // just the finalizer, so this reduces the surface area of the race condition. Generally we should not expect users or -// other configentries to be touching the finalizers of consul-k8s managed CRDs. +// other controllers to be touching the finalizers of consul-k8s managed CRDs. func (fp *FinalizerPatch) Type() types.PatchType { return types.MergePatchType } diff --git a/control-plane/controllers/configentries/finalizer_patch_test.go b/control-plane/config-entries/controllers/finalizer_patch_test.go similarity index 99% rename from control-plane/controllers/configentries/finalizer_patch_test.go rename to control-plane/config-entries/controllers/finalizer_patch_test.go index 70dc782d0e..5b9e3350d1 100644 --- a/control-plane/controllers/configentries/finalizer_patch_test.go +++ b/control-plane/config-entries/controllers/finalizer_patch_test.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "testing" diff --git a/control-plane/controllers/configentries/ingressgateway_controller.go b/control-plane/config-entries/controllers/ingressgateway_controller.go similarity index 98% rename from control-plane/controllers/configentries/ingressgateway_controller.go rename to control-plane/config-entries/controllers/ingressgateway_controller.go index d1cced515e..563b9aa606 100644 --- a/control-plane/controllers/configentries/ingressgateway_controller.go +++ b/control-plane/config-entries/controllers/ingressgateway_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/configentries/jwtprovider_controller.go b/control-plane/config-entries/controllers/jwtprovider_controller.go similarity index 98% rename from control-plane/controllers/configentries/jwtprovider_controller.go rename to control-plane/config-entries/controllers/jwtprovider_controller.go index 6e4aa6c6d1..39e76d502c 100644 --- a/control-plane/controllers/configentries/jwtprovider_controller.go +++ b/control-plane/config-entries/controllers/jwtprovider_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/configentries/mesh_controller.go b/control-plane/config-entries/controllers/mesh_controller.go similarity index 98% rename from control-plane/controllers/configentries/mesh_controller.go rename to control-plane/config-entries/controllers/mesh_controller.go index 7593e287ad..7cd6997fc6 100644 --- a/control-plane/controllers/configentries/mesh_controller.go +++ b/control-plane/config-entries/controllers/mesh_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/configentries/proxydefaults_controller.go b/control-plane/config-entries/controllers/proxydefaults_controller.go similarity index 98% rename from control-plane/controllers/configentries/proxydefaults_controller.go rename to control-plane/config-entries/controllers/proxydefaults_controller.go index 0edea71136..c96c5968d3 100644 --- a/control-plane/controllers/configentries/proxydefaults_controller.go +++ b/control-plane/config-entries/controllers/proxydefaults_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/configentries/samenessgroups_controller.go b/control-plane/config-entries/controllers/samenessgroups_controller.go similarity index 98% rename from control-plane/controllers/configentries/samenessgroups_controller.go rename to control-plane/config-entries/controllers/samenessgroups_controller.go index 9a33744d7a..c34b017761 100644 --- a/control-plane/controllers/configentries/samenessgroups_controller.go +++ b/control-plane/config-entries/controllers/samenessgroups_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/configentries/servicedefaults_controller.go b/control-plane/config-entries/controllers/servicedefaults_controller.go similarity index 98% rename from control-plane/controllers/configentries/servicedefaults_controller.go rename to control-plane/config-entries/controllers/servicedefaults_controller.go index 00c5235889..69e001a741 100644 --- a/control-plane/controllers/configentries/servicedefaults_controller.go +++ b/control-plane/config-entries/controllers/servicedefaults_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/configentries/serviceintentions_controller.go b/control-plane/config-entries/controllers/serviceintentions_controller.go similarity index 98% rename from control-plane/controllers/configentries/serviceintentions_controller.go rename to control-plane/config-entries/controllers/serviceintentions_controller.go index 95706fc960..e20cf34317 100644 --- a/control-plane/controllers/configentries/serviceintentions_controller.go +++ b/control-plane/config-entries/controllers/serviceintentions_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/configentries/serviceresolver_controller.go b/control-plane/config-entries/controllers/serviceresolver_controller.go similarity index 98% rename from control-plane/controllers/configentries/serviceresolver_controller.go rename to control-plane/config-entries/controllers/serviceresolver_controller.go index 7e2352a287..5bbc9c9f11 100644 --- a/control-plane/controllers/configentries/serviceresolver_controller.go +++ b/control-plane/config-entries/controllers/serviceresolver_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/configentries/servicerouter_controller.go b/control-plane/config-entries/controllers/servicerouter_controller.go similarity index 98% rename from control-plane/controllers/configentries/servicerouter_controller.go rename to control-plane/config-entries/controllers/servicerouter_controller.go index 7f16addbf2..6ea87b590a 100644 --- a/control-plane/controllers/configentries/servicerouter_controller.go +++ b/control-plane/config-entries/controllers/servicerouter_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/configentries/servicesplitter_controller.go b/control-plane/config-entries/controllers/servicesplitter_controller.go similarity index 98% rename from control-plane/controllers/configentries/servicesplitter_controller.go rename to control-plane/config-entries/controllers/servicesplitter_controller.go index 274020a8d8..07e2603833 100644 --- a/control-plane/controllers/configentries/servicesplitter_controller.go +++ b/control-plane/config-entries/controllers/servicesplitter_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/configentries/terminatinggateway_controller.go b/control-plane/config-entries/controllers/terminatinggateway_controller.go similarity index 98% rename from control-plane/controllers/configentries/terminatinggateway_controller.go rename to control-plane/config-entries/controllers/terminatinggateway_controller.go index f8e4a0bc0b..c68db70538 100644 --- a/control-plane/controllers/configentries/terminatinggateway_controller.go +++ b/control-plane/config-entries/controllers/terminatinggateway_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package configentries +package controllers import ( "context" diff --git a/control-plane/controllers/resources/grpc_route_controller.go b/control-plane/config-entries/controllersv2/grpc_route_controller.go similarity index 84% rename from control-plane/controllers/resources/grpc_route_controller.go rename to control-plane/config-entries/controllersv2/grpc_route_controller.go index fa5401c800..06accae268 100644 --- a/control-plane/controllers/resources/grpc_route_controller.go +++ b/control-plane/config-entries/controllersv2/grpc_route_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package resources +package controllersv2 import ( "context" @@ -18,16 +18,16 @@ import ( // GRPCRouteController reconciles a GRPCRoute object. type GRPCRouteController struct { client.Client - Log logr.Logger - Scheme *runtime.Scheme - Controller *ConsulResourceController + Log logr.Logger + Scheme *runtime.Scheme + MeshConfigController *MeshConfigController } // +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=grpcroute,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=grpcroute/status,verbs=get;update;patch func (r *GRPCRouteController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - return r.Controller.ReconcileResource(ctx, r, req, &meshv2beta1.GRPCRoute{}) + return r.MeshConfigController.ReconcileEntry(ctx, r, req, &meshv2beta1.GRPCRoute{}) } func (r *GRPCRouteController) Logger(name types.NamespacedName) logr.Logger { diff --git a/control-plane/controllers/resources/http_route_controller.go b/control-plane/config-entries/controllersv2/http_route_controller.go similarity index 84% rename from control-plane/controllers/resources/http_route_controller.go rename to control-plane/config-entries/controllersv2/http_route_controller.go index 9275d8f265..545250af74 100644 --- a/control-plane/controllers/resources/http_route_controller.go +++ b/control-plane/config-entries/controllersv2/http_route_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package resources +package controllersv2 import ( "context" @@ -18,16 +18,16 @@ import ( // HTTPRouteController reconciles a HTTPRoute object. type HTTPRouteController struct { client.Client - Log logr.Logger - Scheme *runtime.Scheme - Controller *ConsulResourceController + Log logr.Logger + Scheme *runtime.Scheme + MeshConfigController *MeshConfigController } // +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=httproute,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=httproute/status,verbs=get;update;patch func (r *HTTPRouteController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - return r.Controller.ReconcileResource(ctx, r, req, &meshv2beta1.HTTPRoute{}) + return r.MeshConfigController.ReconcileEntry(ctx, r, req, &meshv2beta1.HTTPRoute{}) } func (r *HTTPRouteController) Logger(name types.NamespacedName) logr.Logger { diff --git a/control-plane/controllers/resources/consul_resource_controller.go b/control-plane/config-entries/controllersv2/meshconfig_controller.go similarity index 71% rename from control-plane/controllers/resources/consul_resource_controller.go rename to control-plane/config-entries/controllersv2/meshconfig_controller.go index 95c5cbcac6..c2b2501ebc 100644 --- a/control-plane/controllers/resources/consul_resource_controller.go +++ b/control-plane/config-entries/controllersv2/meshconfig_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package resources +package controllersv2 import ( "context" @@ -38,14 +38,14 @@ const ( ExternallyManagedConfigError = "ExternallyManagedConfigError" ) -// ResourceController is implemented by resources syncing Consul Resources from their CRD counterparts. -// It is used by ConsulResourceController to abstract CRD-specific Consul Resources. -type ResourceController interface { +// Controller is implemented by CRD-specific config-entries. It is used by +// MeshConfigController to abstract CRD-specific config-entries. +type Controller interface { // Update updates the state of the whole object. Update(context.Context, client.Object, ...client.UpdateOption) error // UpdateStatus updates the state of just the object's status. UpdateStatus(context.Context, client.Object, ...client.SubResourceUpdateOption) error - // Get retrieves an object for the given object key from the Kubernetes Cluster. + // Get retrieves an obj for the given object key from the Kubernetes Cluster. // obj must be a struct pointer so that obj can be updated with the response // returned by the Server. Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error @@ -54,10 +54,10 @@ type ResourceController interface { Logger(types.NamespacedName) logr.Logger } -// ConsulResourceController is a generic controller that is used to reconcile -// all Consul Resource types, e.g. TrafficPermissions, ProxyConfiguration, etc., since +// MeshConfigController is a generic controller that is used to reconcile +// all resource types, e.g. TrafficPermissions, ProxyConfiguration, etc., since // they share the same reconcile behaviour. -type ConsulResourceController struct { +type MeshConfigController struct { // ConsulClientConfig is the config for the Consul API client. ConsulClientConfig *consul.Config @@ -67,15 +67,15 @@ type ConsulResourceController struct { common.ConsulTenancyConfig } -// ReconcileResource reconciles an update to a resource. CRD-specific controller's +// ReconcileEntry reconciles an update to a resource. CRD-specific controller's // call this function because it handles reconciliation of config entries // generically. // CRD-specific controller should pass themselves in as updater since we // need to call back into their own update methods to ensure they update their // internal state. -func (r *ConsulResourceController) ReconcileResource(ctx context.Context, crdCtrl ResourceController, req ctrl.Request, resource common.ConsulResource) (ctrl.Result, error) { +func (r *MeshConfigController) ReconcileEntry(ctx context.Context, crdCtrl Controller, req ctrl.Request, meshConfig common.MeshConfig) (ctrl.Result, error) { logger := crdCtrl.Logger(req.NamespacedName) - err := crdCtrl.Get(ctx, req.NamespacedName, resource) + err := crdCtrl.Get(ctx, req.NamespacedName, meshConfig) if k8serr.IsNotFound(err) { return ctrl.Result{}, client.IgnoreNotFound(err) } else if err != nil { @@ -99,24 +99,24 @@ func (r *ConsulResourceController) ReconcileResource(ctx context.Context, crdCtr ctx = metadata.AppendToOutgoingContext(ctx, "x-consul-token", state.Token) } - if resource.GetDeletionTimestamp().IsZero() { + if meshConfig.GetDeletionTimestamp().IsZero() { // The object is not being deleted, so if it does not have our finalizer, // then let's add the finalizer and update the object. This is equivalent // registering our finalizer. - if !slices.Contains(resource.GetFinalizers(), FinalizerName) { - resource.AddFinalizer(FinalizerName) - if err := r.syncUnknown(ctx, crdCtrl, resource); err != nil { + if !slices.Contains(meshConfig.GetFinalizers(), FinalizerName) { + meshConfig.AddFinalizer(FinalizerName) + if err := r.syncUnknown(ctx, crdCtrl, meshConfig); err != nil { return ctrl.Result{}, err } } } - if !resource.GetDeletionTimestamp().IsZero() { - if slices.Contains(resource.GetFinalizers(), FinalizerName) { + if !meshConfig.GetDeletionTimestamp().IsZero() { + if slices.Contains(meshConfig.GetFinalizers(), FinalizerName) { // The object is being deleted logger.Info("deletion event") // Check to see if consul has config entry with the same name - res, err := resourceClient.Read(ctx, &pbresource.ReadRequest{Id: resource.ResourceID(r.consulNamespace(req.Namespace), r.getConsulPartition())}) + res, err := resourceClient.Read(ctx, &pbresource.ReadRequest{Id: meshConfig.ResourceID(r.consulNamespace(req.Namespace), r.getConsulPartition())}) // Ignore the error where the resource isn't found in Consul. // It is indicative of desired state. @@ -125,21 +125,21 @@ func (r *ConsulResourceController) ReconcileResource(ctx context.Context, crdCtr } // In the case this resource was created outside of consul, skip the deletion process and continue - if !managedByConsulResourceController(res.GetResource()) { - logger.Info("resource in Consul was created outside of Kubernetes - skipping delete from Consul") + if !managedByMeshController(res.GetResource()) { + logger.Info("resource in Consul was created outside of kubernetes - skipping delete from Consul") } - if err == nil && managedByConsulResourceController(res.GetResource()) { - _, err := resourceClient.Delete(ctx, &pbresource.DeleteRequest{Id: resource.ResourceID(r.consulNamespace(req.Namespace), r.getConsulPartition())}) + if err == nil && managedByMeshController(res.GetResource()) { + _, err := resourceClient.Delete(ctx, &pbresource.DeleteRequest{Id: meshConfig.ResourceID(r.consulNamespace(req.Namespace), r.getConsulPartition())}) if err != nil { - return r.syncFailed(ctx, logger, crdCtrl, resource, ConsulAgentError, - fmt.Errorf("deleting resource from Consul: %w", err)) + return r.syncFailed(ctx, logger, crdCtrl, meshConfig, ConsulAgentError, + fmt.Errorf("deleting config entry from consul: %w", err)) } logger.Info("deletion from Consul successful") } // remove our finalizer from the list and update it. - resource.RemoveFinalizer(FinalizerName) - if err := crdCtrl.Update(ctx, resource); err != nil { + meshConfig.RemoveFinalizer(FinalizerName) + if err := crdCtrl.Update(ctx, meshConfig); err != nil { return ctrl.Result{}, err } logger.Info("finalizer removed") @@ -150,7 +150,7 @@ func (r *ConsulResourceController) ReconcileResource(ctx context.Context, crdCtr } // Check to see if consul has config entry with the same name - res, err := resourceClient.Read(ctx, &pbresource.ReadRequest{Id: resource.ResourceID(r.consulNamespace(req.Namespace), r.getConsulPartition())}) + res, err := resourceClient.Read(ctx, &pbresource.ReadRequest{Id: meshConfig.ResourceID(r.consulNamespace(req.Namespace), r.getConsulPartition())}) // In the case the namespace doesn't exist in Consul yet, assume we are racing with the namespace controller // and requeue. @@ -163,42 +163,42 @@ func (r *ConsulResourceController) ReconcileResource(ctx context.Context, crdCtr // If resource with this name does not exist if isNotFoundErr(err) { - logger.Info("resource not found in Consul") + logger.Info("resource not found in consul") // Create the config entry - _, err := resourceClient.Write(ctx, &pbresource.WriteRequest{Resource: resource.Resource(r.consulNamespace(req.Namespace), r.getConsulPartition())}) + _, err := resourceClient.Write(ctx, &pbresource.WriteRequest{Resource: meshConfig.Resource(r.consulNamespace(req.Namespace), r.getConsulPartition())}) if err != nil { - return r.syncFailed(ctx, logger, crdCtrl, resource, ConsulAgentError, - fmt.Errorf("writing resource to Consul: %w", err)) + return r.syncFailed(ctx, logger, crdCtrl, meshConfig, ConsulAgentError, + fmt.Errorf("writing resource to consul: %w", err)) } logger.Info("resource created") - return r.syncSuccessful(ctx, crdCtrl, resource) + return r.syncSuccessful(ctx, crdCtrl, meshConfig) } // If there is an error when trying to get the resource from the api server, // fail the reconcile. if err != nil { - return r.syncFailed(ctx, logger, crdCtrl, resource, ConsulAgentError, err) + return r.syncFailed(ctx, logger, crdCtrl, meshConfig, ConsulAgentError, err) } // TODO: consider the case where we want to migrate a resource existing into Consul to a CRD with an annotation - if !managedByConsulResourceController(res.Resource) { - return r.syncFailed(ctx, logger, crdCtrl, resource, ExternallyManagedConfigError, + if !managedByMeshController(res.Resource) { + return r.syncFailed(ctx, logger, crdCtrl, meshConfig, ExternallyManagedConfigError, fmt.Errorf("resource already exists in Consul")) } - if !resource.MatchesConsul(res.Resource, r.consulNamespace(req.Namespace), r.getConsulPartition()) { + if !meshConfig.MatchesConsul(res.Resource, r.consulNamespace(req.Namespace), r.getConsulPartition()) { logger.Info("resource does not match Consul") - _, err := resourceClient.Write(ctx, &pbresource.WriteRequest{Resource: resource.Resource(r.consulNamespace(req.Namespace), r.getConsulPartition())}) + _, err := resourceClient.Write(ctx, &pbresource.WriteRequest{Resource: meshConfig.Resource(r.consulNamespace(req.Namespace), r.getConsulPartition())}) if err != nil { - return r.syncUnknownWithError(ctx, logger, crdCtrl, resource, ConsulAgentError, + return r.syncUnknownWithError(ctx, logger, crdCtrl, meshConfig, ConsulAgentError, fmt.Errorf("updating resource in Consul: %w", err)) } - logger.Info("resource updated") - return r.syncSuccessful(ctx, crdCtrl, resource) - } else if resource.SyncedConditionStatus() != corev1.ConditionTrue { - return r.syncSuccessful(ctx, crdCtrl, resource) + logger.Info("config entry updated") + return r.syncSuccessful(ctx, crdCtrl, meshConfig) + } else if meshConfig.SyncedConditionStatus() != corev1.ConditionTrue { + return r.syncSuccessful(ctx, crdCtrl, meshConfig) } return ctrl.Result{}, nil @@ -235,7 +235,7 @@ func setupWithManager(mgr ctrl.Manager, resource client.Object, reconciler recon Complete(reconciler) } -func (r *ConsulResourceController) syncFailed(ctx context.Context, logger logr.Logger, updater ResourceController, resource common.ConsulResource, errType string, err error) (ctrl.Result, error) { +func (r *MeshConfigController) syncFailed(ctx context.Context, logger logr.Logger, updater Controller, resource common.MeshConfig, errType string, err error) (ctrl.Result, error) { resource.SetSyncedCondition(corev1.ConditionFalse, errType, err.Error()) if updateErr := updater.UpdateStatus(ctx, resource); updateErr != nil { // Log the original error here because we are returning the updateErr. @@ -246,25 +246,25 @@ func (r *ConsulResourceController) syncFailed(ctx context.Context, logger logr.L return ctrl.Result{}, err } -func (r *ConsulResourceController) syncSuccessful(ctx context.Context, updater ResourceController, resource common.ConsulResource) (ctrl.Result, error) { +func (r *MeshConfigController) syncSuccessful(ctx context.Context, updater Controller, resource common.MeshConfig) (ctrl.Result, error) { resource.SetSyncedCondition(corev1.ConditionTrue, "", "") timeNow := metav1.NewTime(time.Now()) resource.SetLastSyncedTime(&timeNow) return ctrl.Result{}, updater.UpdateStatus(ctx, resource) } -func (r *ConsulResourceController) syncUnknown(ctx context.Context, updater ResourceController, resource common.ConsulResource) error { +func (r *MeshConfigController) syncUnknown(ctx context.Context, updater Controller, resource common.MeshConfig) error { resource.SetSyncedCondition(corev1.ConditionUnknown, "", "") return updater.Update(ctx, resource) } -func (r *ConsulResourceController) syncUnknownWithError(ctx context.Context, +func (r *MeshConfigController) syncUnknownWithError(ctx context.Context, logger logr.Logger, - updater ResourceController, - resource common.ConsulResource, + updater Controller, + resource common.MeshConfig, errType string, - err error, -) (ctrl.Result, error) { + err error) (ctrl.Result, error) { + resource.SetSyncedCondition(corev1.ConditionUnknown, errType, err.Error()) if updateErr := updater.UpdateStatus(ctx, resource); updateErr != nil { // Log the original error here because we are returning the updateErr. @@ -287,7 +287,7 @@ func isNotFoundErr(err error) bool { return codes.NotFound == s.Code() } -func (r *ConsulResourceController) consulNamespace(namespace string) string { +func (r *MeshConfigController) consulNamespace(namespace string) string { ns := namespaces.ConsulNamespace( namespace, r.EnableConsulNamespaces, @@ -303,14 +303,14 @@ func (r *ConsulResourceController) consulNamespace(namespace string) string { return ns } -func (r *ConsulResourceController) getConsulPartition() string { +func (r *MeshConfigController) getConsulPartition() string { if !r.EnableConsulPartitions || r.ConsulPartition == "" { return constants.DefaultConsulPartition } return r.ConsulPartition } -func managedByConsulResourceController(resource *pbresource.Resource) bool { +func managedByMeshController(resource *pbresource.Resource) bool { if resource == nil { return false } diff --git a/control-plane/controllers/resources/consul_resource_controller_test.go b/control-plane/config-entries/controllersv2/meshconfig_controller_test.go similarity index 78% rename from control-plane/controllers/resources/consul_resource_controller_test.go rename to control-plane/config-entries/controllersv2/meshconfig_controller_test.go index cb8c1cf6bd..c7da7b3de3 100644 --- a/control-plane/controllers/resources/consul_resource_controller_test.go +++ b/control-plane/config-entries/controllersv2/meshconfig_controller_test.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package resources +package controllersv2 import ( "context" @@ -11,6 +11,9 @@ import ( "github.com/go-logr/logr" logrtest "github.com/go-logr/logr/testr" "github.com/google/go-cmp/cmp" + pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" @@ -22,10 +25,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul-k8s/control-plane/api/auth/v2beta1" "github.com/hashicorp/consul-k8s/control-plane/api/common" "github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1" @@ -38,20 +37,20 @@ type testReconciler interface { Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) } -// TestConsulResourceController_CreatesConsulResource validated resources are created in Consul from kube objects. -func TestConsulResourceController_CreatesConsulResource(t *testing.T) { +// TestMeshConfigController_createsMeshConfig validated resources are created in Consul from kube objects. +func TestMeshConfigController_createsMeshConfig(t *testing.T) { t.Parallel() cases := []struct { name string - resource common.ConsulResource + meshConfig common.MeshConfig expected *pbauth.TrafficPermissions reconciler func(client.Client, *consul.Config, consul.ServerConnectionManager, logr.Logger) testReconciler unmarshal func(t *testing.T, consul *pbresource.Resource) proto.Message }{ { name: "TrafficPermissions", - resource: &v2beta1.TrafficPermissions{ + meshConfig: &v2beta1.TrafficPermissions{ ObjectMeta: metav1.ObjectMeta{ Name: "my-traffic-permission", Namespace: metav1.NamespaceDefault, @@ -117,7 +116,7 @@ func TestConsulResourceController_CreatesConsulResource(t *testing.T) { return &TrafficPermissionsController{ Client: client, Log: logger, - Controller: &ConsulResourceController{ + MeshConfigController: &MeshConfigController{ ConsulClientConfig: cfg, ConsulServerConnMgr: watcher, }, @@ -138,17 +137,24 @@ func TestConsulResourceController_CreatesConsulResource(t *testing.T) { ctx := context.Background() s := runtime.NewScheme() - s.AddKnownTypes(v2beta1.AuthGroupVersion, c.resource) - fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(c.resource).Build() + s.AddKnownTypes(v2beta1.AuthGroupVersion, c.meshConfig) + fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(c.meshConfig).Build() testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) r := c.reconciler(fakeClient, testClient.Cfg, testClient.Watcher, logrtest.New(t)) namespacedName := types.NamespacedName{ Namespace: metav1.NamespaceDefault, - Name: c.resource.KubernetesName(), + Name: c.meshConfig.KubernetesName(), } resp, err := r.Reconcile(ctx, ctrl.Request{ NamespacedName: namespacedName, @@ -156,11 +162,11 @@ func TestConsulResourceController_CreatesConsulResource(t *testing.T) { require.NoError(t, err) require.False(t, resp.Requeue) - req := &pbresource.ReadRequest{Id: c.resource.ResourceID(constants.DefaultConsulNS, constants.DefaultConsulPartition)} - res, err := testClient.ResourceClient.Read(ctx, req) + req := &pbresource.ReadRequest{Id: c.meshConfig.ResourceID(constants.DefaultConsulNS, constants.DefaultConsulPartition)} + res, err := resourceClient.Read(ctx, req) require.NoError(t, err) require.NotNil(t, res) - require.Equal(t, c.resource.GetName(), res.GetResource().GetId().GetName()) + require.Equal(t, c.meshConfig.GetName(), res.GetResource().GetId().GetName()) actual := c.unmarshal(t, res.GetResource()) opts := append([]cmp.Option{protocmp.IgnoreFields(&pbresource.Resource{}, "status", "generation", "version")}, test.CmpProtoIgnoreOrder()...) @@ -168,30 +174,30 @@ func TestConsulResourceController_CreatesConsulResource(t *testing.T) { require.Equal(t, "", diff, "TrafficPermissions do not match") // Check that the status is "synced". - err = fakeClient.Get(ctx, namespacedName, c.resource) + err = fakeClient.Get(ctx, namespacedName, c.meshConfig) require.NoError(t, err) - require.Equal(t, corev1.ConditionTrue, c.resource.SyncedConditionStatus()) + require.Equal(t, corev1.ConditionTrue, c.meshConfig.SyncedConditionStatus()) // Check that the finalizer is added. - require.Contains(t, c.resource.Finalizers(), FinalizerName) + require.Contains(t, c.meshConfig.Finalizers(), FinalizerName) }) } } -func TestConsulResourceController_UpdatesConsulResource(t *testing.T) { +func TestMeshConfigController_updatesMeshConfig(t *testing.T) { t.Parallel() cases := []struct { name string - resource common.ConsulResource + meshConfig common.MeshConfig expected *pbauth.TrafficPermissions reconciler func(client.Client, *consul.Config, consul.ServerConnectionManager, logr.Logger) testReconciler - updateF func(config common.ConsulResource) + updateF func(config common.MeshConfig) unmarshal func(t *testing.T, consul *pbresource.Resource) proto.Message }{ { name: "TrafficPermissions", - resource: &v2beta1.TrafficPermissions{ + meshConfig: &v2beta1.TrafficPermissions{ ObjectMeta: metav1.ObjectMeta{ Name: "my-traffic-permission", Namespace: metav1.NamespaceDefault, @@ -227,7 +233,7 @@ func TestConsulResourceController_UpdatesConsulResource(t *testing.T) { Destination: &pbauth.Destination{ IdentityName: "destination-identity", }, - Action: pbauth.Action_ACTION_ALLOW, + Action: pbauth.Action_ACTION_DENY, Permissions: []*pbauth.Permission{ { Sources: []*pbauth.Source{ @@ -251,14 +257,15 @@ func TestConsulResourceController_UpdatesConsulResource(t *testing.T) { return &TrafficPermissionsController{ Client: client, Log: logger, - Controller: &ConsulResourceController{ + MeshConfigController: &MeshConfigController{ ConsulClientConfig: cfg, ConsulServerConnMgr: watcher, }, } }, - updateF: func(resource common.ConsulResource) { + updateF: func(resource common.MeshConfig) { trafficPermissions := resource.(*v2beta1.TrafficPermissions) + trafficPermissions.Spec.Action = pbauth.Action_ACTION_DENY trafficPermissions.Spec.Permissions[0].Sources = trafficPermissions.Spec.Permissions[0].Sources[:1] }, unmarshal: func(t *testing.T, resource *pbresource.Resource) proto.Message { @@ -276,19 +283,26 @@ func TestConsulResourceController_UpdatesConsulResource(t *testing.T) { ctx := context.Background() s := runtime.NewScheme() - s.AddKnownTypes(v1alpha1.GroupVersion, c.resource) - fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(c.resource).Build() + s.AddKnownTypes(v1alpha1.GroupVersion, c.meshConfig) + fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(c.meshConfig).Build() testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) - // We haven't run reconcile yet, so we must create the resource + // We haven't run reconcile yet, so we must create the MeshConfig // in Consul ourselves. { - resource := c.resource.Resource(constants.DefaultConsulNS, constants.DefaultConsulPartition) + resource := c.meshConfig.Resource(constants.DefaultConsulNS, constants.DefaultConsulPartition) req := &pbresource.WriteRequest{Resource: resource} - _, err := testClient.ResourceClient.Write(ctx, req) + _, err := resourceClient.Write(ctx, req) require.NoError(t, err) } @@ -296,15 +310,15 @@ func TestConsulResourceController_UpdatesConsulResource(t *testing.T) { { namespacedName := types.NamespacedName{ Namespace: metav1.NamespaceDefault, - Name: c.resource.KubernetesName(), + Name: c.meshConfig.KubernetesName(), } // First get it, so we have the latest revision number. - err := fakeClient.Get(ctx, namespacedName, c.resource) + err := fakeClient.Get(ctx, namespacedName, c.meshConfig) require.NoError(t, err) // Update the entry in Kube and run reconcile. - c.updateF(c.resource) - err = fakeClient.Update(ctx, c.resource) + c.updateF(c.meshConfig) + err = fakeClient.Update(ctx, c.meshConfig) require.NoError(t, err) r := c.reconciler(fakeClient, testClient.Cfg, testClient.Watcher, logrtest.New(t)) resp, err := r.Reconcile(ctx, ctrl.Request{ @@ -314,11 +328,11 @@ func TestConsulResourceController_UpdatesConsulResource(t *testing.T) { require.False(t, resp.Requeue) // Now check that the object in Consul is as expected. - req := &pbresource.ReadRequest{Id: c.resource.ResourceID(constants.DefaultConsulNS, constants.DefaultConsulPartition)} - res, err := testClient.ResourceClient.Read(ctx, req) + req := &pbresource.ReadRequest{Id: c.meshConfig.ResourceID(constants.DefaultConsulNS, constants.DefaultConsulPartition)} + res, err := resourceClient.Read(ctx, req) require.NoError(t, err) require.NotNil(t, res) - require.Equal(t, c.resource.GetName(), res.GetResource().GetId().GetName()) + require.Equal(t, c.meshConfig.GetName(), res.GetResource().GetId().GetName()) actual := c.unmarshal(t, res.GetResource()) opts := append([]cmp.Option{protocmp.IgnoreFields(&pbresource.Resource{}, "status", "generation", "version")}, test.CmpProtoIgnoreOrder()...) @@ -329,17 +343,17 @@ func TestConsulResourceController_UpdatesConsulResource(t *testing.T) { } } -func TestConsulResourceController_DeletesConsulResource(t *testing.T) { +func TestMeshConfigController_deletesMeshConfig(t *testing.T) { t.Parallel() cases := []struct { - name string - resource common.ConsulResource - reconciler func(client.Client, *consul.Config, consul.ServerConnectionManager, logr.Logger) testReconciler + name string + MeshConfigWithDeletion common.MeshConfig + reconciler func(client.Client, *consul.Config, consul.ServerConnectionManager, logr.Logger) testReconciler }{ { name: "TrafficPermissions", - resource: &v2beta1.TrafficPermissions{ + MeshConfigWithDeletion: &v2beta1.TrafficPermissions{ ObjectMeta: metav1.ObjectMeta{ Name: "test-name", Namespace: metav1.NamespaceDefault, @@ -377,7 +391,7 @@ func TestConsulResourceController_DeletesConsulResource(t *testing.T) { return &TrafficPermissionsController{ Client: client, Log: logger, - Controller: &ConsulResourceController{ + MeshConfigController: &MeshConfigController{ ConsulClientConfig: cfg, ConsulServerConnMgr: watcher, }, @@ -391,19 +405,26 @@ func TestConsulResourceController_DeletesConsulResource(t *testing.T) { ctx := context.Background() s := runtime.NewScheme() - s.AddKnownTypes(v2beta1.AuthGroupVersion, c.resource) - fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(c.resource).Build() + s.AddKnownTypes(v2beta1.AuthGroupVersion, c.MeshConfigWithDeletion) + fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(c.MeshConfigWithDeletion).Build() testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) // We haven't run reconcile yet, so we must create the config entry // in Consul ourselves. { - resource := c.resource.Resource(constants.DefaultConsulNS, constants.DefaultConsulPartition) + resource := c.MeshConfigWithDeletion.Resource(constants.DefaultConsulNS, constants.DefaultConsulPartition) req := &pbresource.WriteRequest{Resource: resource} - _, err := testClient.ResourceClient.Write(ctx, req) + _, err := resourceClient.Write(ctx, req) require.NoError(t, err) } @@ -411,7 +432,7 @@ func TestConsulResourceController_DeletesConsulResource(t *testing.T) { { namespacedName := types.NamespacedName{ Namespace: metav1.NamespaceDefault, - Name: c.resource.KubernetesName(), + Name: c.MeshConfigWithDeletion.KubernetesName(), } r := c.reconciler(fakeClient, testClient.Cfg, testClient.Watcher, logrtest.New(t)) resp, err := r.Reconcile(context.Background(), ctrl.Request{ @@ -421,8 +442,8 @@ func TestConsulResourceController_DeletesConsulResource(t *testing.T) { require.False(t, resp.Requeue) // Now check that the object in Consul is as expected. - req := &pbresource.ReadRequest{Id: c.resource.ResourceID(constants.DefaultConsulNS, constants.DefaultConsulPartition)} - _, err = testClient.ResourceClient.Read(ctx, req) + req := &pbresource.ReadRequest{Id: c.MeshConfigWithDeletion.ResourceID(constants.DefaultConsulNS, constants.DefaultConsulPartition)} + _, err = resourceClient.Read(ctx, req) require.Error(t, err) require.True(t, isNotFoundErr(err)) } @@ -430,7 +451,7 @@ func TestConsulResourceController_DeletesConsulResource(t *testing.T) { } } -func TestConsulResourceController_ErrorUpdatesSyncStatus(t *testing.T) { +func TestMeshConfigController_errorUpdatesSyncStatus(t *testing.T) { t.Parallel() ctx := context.Background() @@ -464,19 +485,24 @@ func TestConsulResourceController_ErrorUpdatesSyncStatus(t *testing.T) { c.Experiments = []string{"resource-apis"} }) + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) + // Stop the server before calling reconcile imitating a server that's not running. _ = testClient.TestServer.Stop() reconciler := &TrafficPermissionsController{ Client: fakeClient, Log: logrtest.New(t), - Controller: &ConsulResourceController{ + MeshConfigController: &MeshConfigController{ ConsulClientConfig: testClient.Cfg, ConsulServerConnMgr: testClient.Watcher, }, } - // ReconcileResource should result in an error. + // ReconcileEntry should result in an error. namespacedName := types.NamespacedName{ Namespace: metav1.NamespaceDefault, Name: trafficpermissions.KubernetesName(), @@ -497,9 +523,9 @@ func TestConsulResourceController_ErrorUpdatesSyncStatus(t *testing.T) { require.Contains(t, errMsg, actualErrMsg) } -// TestConsulResourceController_SetsSyncedToTrue tests that if the resource hasn't changed in +// TestMeshConfigController_setsSyncedToTrue tests that if the resource hasn't changed in // Consul but our resource's synced status isn't set to true, then we update its status. -func TestConsulResourceController_SetsSyncedToTrue(t *testing.T) { +func TestMeshConfigController_setsSyncedToTrue(t *testing.T) { t.Parallel() ctx := context.Background() @@ -542,11 +568,18 @@ func TestConsulResourceController_SetsSyncedToTrue(t *testing.T) { testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) reconciler := &TrafficPermissionsController{ Client: fakeClient, Log: logrtest.New(t), - Controller: &ConsulResourceController{ + MeshConfigController: &MeshConfigController{ ConsulClientConfig: testClient.Cfg, ConsulServerConnMgr: testClient.Watcher, }, @@ -557,7 +590,7 @@ func TestConsulResourceController_SetsSyncedToTrue(t *testing.T) { { resource := trafficpermissions.Resource(constants.DefaultConsulNS, constants.DefaultConsulPartition) req := &pbresource.WriteRequest{Resource: resource} - _, err := testClient.ResourceClient.Write(ctx, req) + _, err := resourceClient.Write(ctx, req) require.NoError(t, err) } @@ -577,9 +610,9 @@ func TestConsulResourceController_SetsSyncedToTrue(t *testing.T) { require.Equal(t, corev1.ConditionTrue, trafficpermissions.SyncedConditionStatus()) } -// TestConsulResourceController_DoesNotCreateUnownedResource test that if the resource +// TestMeshConfigController_doesNotCreateUnownedMeshConfig test that if the resource // exists in Consul but is not managed by the controller, creating/updating the resource fails. -func TestConsulResourceController_DoesNotCreateUnownedResource(t *testing.T) { +func TestMeshConfigController_doesNotCreateUnownedMeshConfig(t *testing.T) { t.Parallel() ctx := context.Background() @@ -615,6 +648,13 @@ func TestConsulResourceController_DoesNotCreateUnownedResource(t *testing.T) { testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) unmanagedResource := trafficpermissions.Resource(constants.DefaultConsulNS, constants.DefaultConsulPartition) unmanagedResource.Metadata = make(map[string]string) // Zero out the metadata @@ -623,7 +663,7 @@ func TestConsulResourceController_DoesNotCreateUnownedResource(t *testing.T) { // in Consul ourselves, without the metadata indicating it is owned by the controller. { req := &pbresource.WriteRequest{Resource: unmanagedResource} - _, err := testClient.ResourceClient.Write(ctx, req) + _, err := resourceClient.Write(ctx, req) require.NoError(t, err) } @@ -641,7 +681,7 @@ func TestConsulResourceController_DoesNotCreateUnownedResource(t *testing.T) { reconciler := TrafficPermissionsController{ Client: fakeClient, Log: logrtest.New(t), - Controller: &ConsulResourceController{ + MeshConfigController: &MeshConfigController{ ConsulClientConfig: testClient.Cfg, ConsulServerConnMgr: testClient.Watcher, }, @@ -654,7 +694,7 @@ func TestConsulResourceController_DoesNotCreateUnownedResource(t *testing.T) { // Now check that the object in Consul is as expected. req := &pbresource.ReadRequest{Id: trafficpermissions.ResourceID(constants.DefaultConsulNS, constants.DefaultConsulPartition)} - readResp, err := testClient.ResourceClient.Read(ctx, req) + readResp, err := resourceClient.Read(ctx, req) require.NoError(t, err) require.NotNil(t, readResp.GetResource()) opts := append([]cmp.Option{ @@ -675,10 +715,10 @@ func TestConsulResourceController_DoesNotCreateUnownedResource(t *testing.T) { } -// TestConsulResourceController_doesNotDeleteUnownedConfig tests that if the resource +// TestMeshConfigController_doesNotDeleteUnownedConfig tests that if the resource // exists in Consul but is not managed by the controller, deleting the resource does // not delete the Consul resource. -func TestConsulResourceController_doesNotDeleteUnownedConfig(t *testing.T) { +func TestMeshConfigController_doesNotDeleteUnownedConfig(t *testing.T) { t.Parallel() ctx := context.Background() @@ -716,11 +756,18 @@ func TestConsulResourceController_doesNotDeleteUnownedConfig(t *testing.T) { testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) reconciler := &TrafficPermissionsController{ Client: fakeClient, Log: logrtest.New(t), - Controller: &ConsulResourceController{ + MeshConfigController: &MeshConfigController{ ConsulClientConfig: testClient.Cfg, ConsulServerConnMgr: testClient.Watcher, }, @@ -733,7 +780,7 @@ func TestConsulResourceController_doesNotDeleteUnownedConfig(t *testing.T) { // in Consul ourselves, without the metadata indicating it is owned by the controller. { req := &pbresource.WriteRequest{Resource: unmanagedResource} - _, err := testClient.ResourceClient.Write(ctx, req) + _, err := resourceClient.Write(ctx, req) require.NoError(t, err) } @@ -752,7 +799,7 @@ func TestConsulResourceController_doesNotDeleteUnownedConfig(t *testing.T) { // Now check that the object in Consul is as expected. req := &pbresource.ReadRequest{Id: trafficpermissionsWithDeletion.ResourceID(constants.DefaultConsulNS, constants.DefaultConsulPartition)} - readResp, err := testClient.ResourceClient.Read(ctx, req) + readResp, err := resourceClient.Read(ctx, req) require.NoError(t, err) require.NotNil(t, readResp.GetResource()) opts := append([]cmp.Option{ diff --git a/control-plane/controllers/resources/proxy_configuration_controller.go b/control-plane/config-entries/controllersv2/proxy_configuration_controller.go similarity index 85% rename from control-plane/controllers/resources/proxy_configuration_controller.go rename to control-plane/config-entries/controllersv2/proxy_configuration_controller.go index 7f67afe26a..f45dda1962 100644 --- a/control-plane/controllers/resources/proxy_configuration_controller.go +++ b/control-plane/config-entries/controllersv2/proxy_configuration_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package resources +package controllersv2 import ( "context" @@ -18,16 +18,16 @@ import ( // ProxyConfigurationController reconciles a ProxyConfiguration object. type ProxyConfigurationController struct { client.Client - Log logr.Logger - Scheme *runtime.Scheme - Controller *ConsulResourceController + Log logr.Logger + Scheme *runtime.Scheme + MeshConfigController *MeshConfigController } // +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=proxyconfiguration,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=proxyconfiguration/status,verbs=get;update;patch func (r *ProxyConfigurationController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - return r.Controller.ReconcileResource(ctx, r, req, &meshv2beta1.ProxyConfiguration{}) + return r.MeshConfigController.ReconcileEntry(ctx, r, req, &meshv2beta1.ProxyConfiguration{}) } func (r *ProxyConfigurationController) Logger(name types.NamespacedName) logr.Logger { diff --git a/control-plane/controllers/resources/tcp_route_controller.go b/control-plane/config-entries/controllersv2/tcp_route_controller.go similarity index 84% rename from control-plane/controllers/resources/tcp_route_controller.go rename to control-plane/config-entries/controllersv2/tcp_route_controller.go index dc69f879b2..170dbb9fd4 100644 --- a/control-plane/controllers/resources/tcp_route_controller.go +++ b/control-plane/config-entries/controllersv2/tcp_route_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package resources +package controllersv2 import ( "context" @@ -18,16 +18,16 @@ import ( // TCPRouteController reconciles a TCPRoute object. type TCPRouteController struct { client.Client - Log logr.Logger - Scheme *runtime.Scheme - Controller *ConsulResourceController + Log logr.Logger + Scheme *runtime.Scheme + MeshConfigController *MeshConfigController } // +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=tcproute,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=tcproute/status,verbs=get;update;patch func (r *TCPRouteController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - return r.Controller.ReconcileResource(ctx, r, req, &meshv2beta1.TCPRoute{}) + return r.MeshConfigController.ReconcileEntry(ctx, r, req, &meshv2beta1.TCPRoute{}) } func (r *TCPRouteController) Logger(name types.NamespacedName) logr.Logger { diff --git a/control-plane/controllers/resources/traffic_permissions_controller.go b/control-plane/config-entries/controllersv2/traffic_permissions_controller.go similarity index 84% rename from control-plane/controllers/resources/traffic_permissions_controller.go rename to control-plane/config-entries/controllersv2/traffic_permissions_controller.go index f844473b0c..abcaf98906 100644 --- a/control-plane/controllers/resources/traffic_permissions_controller.go +++ b/control-plane/config-entries/controllersv2/traffic_permissions_controller.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package resources +package controllersv2 import ( "context" @@ -18,16 +18,16 @@ import ( // TrafficPermissionsController reconciles a TrafficPermissions object. type TrafficPermissionsController struct { client.Client - Log logr.Logger - Scheme *runtime.Scheme - Controller *ConsulResourceController + Log logr.Logger + Scheme *runtime.Scheme + MeshConfigController *MeshConfigController } // +kubebuilder:rbac:groups=auth.consul.hashicorp.com,resources=trafficpermissions,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=auth.consul.hashicorp.com,resources=trafficpermissions/status,verbs=get;update;patch func (r *TrafficPermissionsController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - return r.Controller.ReconcileResource(ctx, r, req, &consulv2beta1.TrafficPermissions{}) + return r.MeshConfigController.ReconcileEntry(ctx, r, req, &consulv2beta1.TrafficPermissions{}) } func (r *TrafficPermissionsController) Logger(name types.NamespacedName) logr.Logger { diff --git a/control-plane/config/crd/bases/auth.consul.hashicorp.com_trafficpermissions.yaml b/control-plane/config/crd/bases/auth.consul.hashicorp.com_trafficpermissions.yaml index ca29923851..3a7699dce4 100644 --- a/control-plane/config/crd/bases/auth.consul.hashicorp.com_trafficpermissions.yaml +++ b/control-plane/config/crd/bases/auth.consul.hashicorp.com_trafficpermissions.yaml @@ -97,25 +97,23 @@ spec: when evaluating rules for the incoming connection. items: properties: - headers: - items: - properties: - exact: - type: string - invert: - type: boolean - name: - type: string - prefix: - type: string - present: - type: boolean - regex: - type: string - suffix: - type: string - type: object - type: array + header: + properties: + exact: + type: string + invert: + type: boolean + name: + type: string + prefix: + type: string + present: + type: boolean + regex: + type: string + suffix: + type: string + type: object methods: description: Methods is the list of HTTP methods. items: @@ -136,25 +134,23 @@ spec: type: array type: object type: array - headers: - items: - properties: - exact: - type: string - invert: - type: boolean - name: - type: string - prefix: - type: string - present: - type: boolean - regex: - type: string - suffix: - type: string - type: object - type: array + header: + properties: + exact: + type: string + invert: + type: boolean + name: + type: string + prefix: + type: string + present: + type: boolean + regex: + type: string + suffix: + type: string + type: object methods: description: Methods is the list of HTTP methods. If no methods are specified, this rule will apply to all methods. diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_servicerouters.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_servicerouters.yaml index 41d4bfbd81..4c982dbf8e 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_servicerouters.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_servicerouters.yaml @@ -145,9 +145,9 @@ spec: type: object type: object retryOn: - description: 'RetryOn is a flat list of conditions for Consul + description: RetryOn is a flat list of conditions for Consul to retry requests based on the response from an upstream - service. Refer to the valid conditions here: https://developer.hashicorp.com/consul/docs/connect/config-entries/service-router#routes-destination-retryon' + service. items: type: string type: array diff --git a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_apigateways.yaml b/control-plane/config/crd/bases/mesh.consul.hashicorp.com_apigateways.yaml deleted file mode 100644 index 7b0d2a54b9..0000000000 --- a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_apigateways.yaml +++ /dev/null @@ -1,297 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - name: apigateways.mesh.consul.hashicorp.com -spec: - group: mesh.consul.hashicorp.com - names: - kind: APIGateway - listKind: APIGatewayList - plural: apigateways - singular: apigateway - scope: Cluster - versions: - - additionalPrinterColumns: - - description: The sync status of the resource with Consul - jsonPath: .status.conditions[?(@.type=="Synced")].status - name: Synced - type: string - - description: The last successful synced time of the resource with Consul - jsonPath: .status.lastSyncedTime - name: Last Synced - type: date - - description: The age of the resource - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2beta1 - schema: - openAPIV3Schema: - description: APIGateway is the Schema for the API Gateway - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - gatewayClassName: - description: GatewayClassName is the name of the GatewayClass used - by the APIGateway - type: string - listeners: - items: - properties: - hostname: - description: Hostname is the host name that a listener should - be bound to, if unspecified, the listener accepts requests - for all hostnames. - type: string - name: - description: Name is the name of the listener in a given gateway. - This must be unique within a gateway. - type: string - port: - format: int32 - maximum: 65535 - minimum: 0 - type: integer - protocol: - description: Protocol is the protocol that a listener should - use, it must either be "http" or "tcp" - type: string - tls: - description: TLS is the TLS settings for the listener. - properties: - certificates: - description: Certificates is a set of references to certificates - that a gateway listener uses for TLS termination. - items: - description: Reference identifies which resource a condition - relates to, when it is not the core resource itself. - properties: - name: - description: Name is the user-given name of the resource - (e.g. the "billing" service). - type: string - section: - description: Section identifies which part of the - resource the condition relates to. - type: string - tenancy: - description: Tenancy identifies the tenancy units - (i.e. partition, namespace) in which the resource - resides. - properties: - namespace: - description: "Namespace further isolates resources - within a partition. https://developer.hashicorp.com/consul/docs/enterprise/namespaces - \n When using the List and WatchList endpoints, - provide the wildcard value \"*\" to list resources - across all namespaces." - type: string - partition: - description: "Partition is the topmost administrative - boundary within a cluster. https://developer.hashicorp.com/consul/docs/enterprise/admin-partitions - \n When using the List and WatchList endpoints, - provide the wildcard value \"*\" to list resources - across all partitions." - type: string - type: object - type: - description: Type identifies the resource's type. - properties: - group: - description: Group describes the area of functionality - to which this resource type relates (e.g. "catalog", - "authorization"). - type: string - groupVersion: - description: GroupVersion is incremented when - sweeping or backward-incompatible changes are - made to the group's resource types. - type: string - kind: - description: Kind identifies the specific resource - type within the group. - type: string - type: object - type: object - type: array - tlsParameters: - description: TLSParameters contains optional configuration - for running TLS termination. - properties: - cipherSuites: - items: - enum: - - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256 - - TLS_CIPHER_SUITE_AES256_SHA - - TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305 - - TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256 - - TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305 - - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA - - TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA - - TLS_CIPHER_SUITE_AES128_GCM_SHA256 - - TLS_CIPHER_SUITE_AES128_SHA - - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384 - - TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384 - - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA - - TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA - - TLS_CIPHER_SUITE_AES256_GCM_SHA384 - format: int32 - type: string - type: array - maxVersion: - enum: - - TLS_VERSION_AUTO - - TLS_VERSION_1_0 - - TLS_VERSION_1_1 - - TLS_VERSION_1_2 - - TLS_VERSION_1_3 - - TLS_VERSION_INVALID - - TLS_VERSION_UNSPECIFIED - format: int32 - type: string - minVersion: - enum: - - TLS_VERSION_AUTO - - TLS_VERSION_1_0 - - TLS_VERSION_1_1 - - TLS_VERSION_1_2 - - TLS_VERSION_1_3 - - TLS_VERSION_INVALID - - TLS_VERSION_UNSPECIFIED - format: int32 - type: string - type: object - type: object - type: object - minItems: 1 - type: array - type: object - status: - properties: - addresses: - items: - properties: - type: - default: IPAddress - type: string - value: - type: string - required: - - type - - value - type: object - type: array - listeners: - items: - properties: - attachedRoutes: - format: int32 - type: integer - name: - type: string - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. - items: - description: 'Conditions define a readiness condition - for a Consul resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' - properties: - lastTransitionTime: - description: LastTransitionTime is the last time the - condition transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details - about the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, - False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource - successfully synced with Consul. - format: date-time - type: string - type: object - required: - - attachedRoutes - - name - type: object - type: array - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. - items: - description: 'Conditions define a readiness condition for a - Consul resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' - properties: - lastTransitionTime: - description: LastTransitionTime is the last time the condition - transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details - about the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, - Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource successfully - synced with Consul. - format: date-time - type: string - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_gatewayclassconfigs.yaml b/control-plane/config/crd/bases/mesh.consul.hashicorp.com_gatewayclassconfigs.yaml deleted file mode 100644 index e7f560861b..0000000000 --- a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_gatewayclassconfigs.yaml +++ /dev/null @@ -1,1821 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - name: gatewayclassconfigs.mesh.consul.hashicorp.com -spec: - group: mesh.consul.hashicorp.com - names: - kind: GatewayClassConfig - listKind: GatewayClassConfigList - plural: gatewayclassconfigs - singular: gatewayclassconfig - scope: Cluster - versions: - - additionalPrinterColumns: - - description: The age of the resource - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2beta1 - schema: - openAPIV3Schema: - description: GatewayClassConfig is the Schema for the Mesh Gateway API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: GatewayClassConfigSpec specifies the desired state of the - GatewayClassConfig CRD. - properties: - annotations: - description: Annotations are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key included - here will override those in Set if specified on the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included here - will be overridden if present in InheritFromGateway and set - on the Gateway. - type: object - type: object - deployment: - description: Deployment contains config specific to the Deployment - created from this GatewayClass - properties: - affinity: - description: Affinity specifies the affinity to use on the created - Deployment. - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for - the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods - to nodes that satisfy the affinity expressions specified - by this field, but it may choose a node that violates - one or more of the expressions. The node that is most - preferred is the one with the greatest sum of weights, - i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node matches the corresponding matchExpressions; - the node(s) with the highest sum are the most preferred. - items: - description: An empty preferred scheduling term matches - all objects with implicit weight 0 (i.e. it's a no-op). - A null preferred scheduling term matches no objects - (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated with - the corresponding weight. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching the - corresponding nodeSelectorTerm, in the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by - this field are not met at scheduling time, the pod will - not be scheduled onto the node. If the affinity requirements - specified by this field cease to be met at some point - during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from - its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. - The terms are ORed. - items: - description: A null or empty node selector term - matches no objects. The requirements of them are - ANDed. The TopologySelectorTerm type implements - a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - x-kubernetes-map-type: atomic - type: array - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules (e.g. - co-locate this pod in the same node, zone, etc. as some - other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods - to nodes that satisfy the affinity expressions specified - by this field, but it may choose a node that violates - one or more of the expressions. The node that is most - preferred is the one with the greatest sum of weights, - i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node has pods which matches the corresponding - podAffinityTerm; the node(s) with the highest sum are - the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: A label query over the set of namespaces - that the term applies to. The term is applied - to the union of the namespaces selected by - this field and the ones listed in the namespaces - field. null selector and null or empty namespaces - list means "this pod's namespace". An empty - selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list - of namespace names that the term applies to. - The term is applied to the union of the namespaces - listed in this field and the ones selected - by namespaceSelector. null or empty namespaces - list and null namespaceSelector means "this - pod's namespace". - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the - pods matching the labelSelector in the specified - namespaces, where co-located is defined as - running on a node whose value of the label - with key topologyKey matches that of any node - on which any of the selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: weight associated with matching the - corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by - this field are not met at scheduling time, the pod will - not be scheduled onto the node. If the affinity requirements - specified by this field cease to be met at some point - during pod execution (e.g. due to a pod label update), - the system may or may not try to eventually evict the - pod from its node. When there are multiple elements, - the lists of nodes corresponding to each podAffinityTerm - are intersected, i.e. all terms must be satisfied. - items: - description: Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) - that this pod should be co-located (affinity) or not - co-located (anti-affinity) with, where co-located - is defined as running on a node whose value of the - label with key matches that of any node - on which a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: A label query over the set of namespaces - that the term applies to. The term is applied - to the union of the namespaces selected by this - field and the ones listed in the namespaces field. - null selector and null or empty namespaces list - means "this pod's namespace". An empty selector - ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list - of namespace names that the term applies to. The - term is applied to the union of the namespaces - listed in this field and the ones selected by - namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey - matches that of any node on which any of the selected - pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules - (e.g. avoid putting this pod in the same node, zone, etc. - as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods - to nodes that satisfy the anti-affinity expressions - specified by this field, but it may choose a node that - violates one or more of the expressions. The node that - is most preferred is the one with the greatest sum of - weights, i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - anti-affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node has pods which matches the corresponding - podAffinityTerm; the node(s) with the highest sum are - the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: A label query over the set of namespaces - that the term applies to. The term is applied - to the union of the namespaces selected by - this field and the ones listed in the namespaces - field. null selector and null or empty namespaces - list means "this pod's namespace". An empty - selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list - of namespace names that the term applies to. - The term is applied to the union of the namespaces - listed in this field and the ones selected - by namespaceSelector. null or empty namespaces - list and null namespaceSelector means "this - pod's namespace". - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the - pods matching the labelSelector in the specified - namespaces, where co-located is defined as - running on a node whose value of the label - with key topologyKey matches that of any node - on which any of the selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: weight associated with matching the - corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified - by this field are not met at scheduling time, the pod - will not be scheduled onto the node. If the anti-affinity - requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod - label update), the system may or may not try to eventually - evict the pod from its node. When there are multiple - elements, the lists of nodes corresponding to each podAffinityTerm - are intersected, i.e. all terms must be satisfied. - items: - description: Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) - that this pod should be co-located (affinity) or not - co-located (anti-affinity) with, where co-located - is defined as running on a node whose value of the - label with key matches that of any node - on which a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: A label query over the set of namespaces - that the term applies to. The term is applied - to the union of the namespaces selected by this - field and the ones listed in the namespaces field. - null selector and null or empty namespaces list - means "this pod's namespace". An empty selector - ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list - of namespace names that the term applies to. The - term is applied to the union of the namespaces - listed in this field and the ones selected by - namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey - matches that of any node on which any of the selected - pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - annotations: - description: Annotations are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - container: - description: Container contains config specific to the created - Deployment's container. - properties: - consul: - description: Consul specifies configuration for the consul-dataplane - container - properties: - logging: - description: Logging specifies the logging configuration - for Consul Dataplane - properties: - level: - description: Level sets the logging level for Consul - Dataplane (debug, info, etc.) - type: string - type: object - type: object - hostPort: - description: HostPort specifies a port to be exposed to the - external host network - format: int32 - type: integer - portModifier: - description: PortModifier specifies the value to be added - to every port value for listeners on this gateway. This - is generally used to avoid binding to privileged ports in - the container. - format: int32 - type: integer - resources: - description: Resources specifies the resource requirements - for the created Deployment's container - properties: - claims: - description: "Claims lists the names of resources, defined - in spec.resourceClaims, that are used by this container. - \n This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. \n This field - is immutable. It can only be set for containers." - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one entry - in pod.spec.resourceClaims of the Pod where this - field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of - compute resources required. If Requests is omitted for - a container, it defaults to Limits if that is explicitly - specified, otherwise to an implementation-defined value. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' - type: object - type: object - type: object - dnsPolicy: - description: DNSPolicy specifies the dns policy to use. These - are set on a per pod basis. - enum: - - Default - - ClusterFirst - - ClusterFirstWithHostNet - - None - type: string - hostNetwork: - description: HostNetwork specifies whether the gateway pods should - run on the host network. - type: boolean - initContainer: - description: InitContainer contains config specific to the created - Deployment's init container. - properties: - consul: - description: Consul specifies configuration for the consul-k8s-control-plane - init container - properties: - logging: - description: Logging specifies the logging configuration - for Consul Dataplane - properties: - level: - description: Level sets the logging level for Consul - Dataplane (debug, info, etc.) - type: string - type: object - type: object - resources: - description: Resources specifies the resource requirements - for the created Deployment's init container - properties: - claims: - description: "Claims lists the names of resources, defined - in spec.resourceClaims, that are used by this container. - \n This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. \n This field - is immutable. It can only be set for containers." - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one entry - in pod.spec.resourceClaims of the Pod where this - field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of - compute resources required. If Requests is omitted for - a container, it defaults to Limits if that is explicitly - specified, otherwise to an implementation-defined value. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' - type: object - type: object - type: object - labels: - description: Labels are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - nodeSelector: - additionalProperties: - type: string - description: 'NodeSelector is a feature that constrains the scheduling - of a pod to nodes that match specified labels. By defining NodeSelector - in a pod''s configuration, you can ensure that the pod is only - scheduled to nodes with the corresponding labels, providing - a way to influence the placement of workloads based on node - attributes. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' - type: object - priorityClassName: - description: PriorityClassName specifies the priority class name - to use on the created Deployment. - type: string - replicas: - description: Replicas specifies the configuration to control the - number of replicas for the created Deployment. - properties: - default: - description: Default is the number of replicas assigned to - the Deployment when created - format: int32 - type: integer - max: - description: Max is the maximum number of replicas allowed - for a gateway with this class. If the replica count exceeds - this value due to manual or automated scaling, the replica - count will be restored to this value. - format: int32 - type: integer - min: - description: Min is the minimum number of replicas allowed - for a gateway with this class. If the replica count drops - below this value due to manual or automated scaling, the - replica count will be restored to this value. - format: int32 - type: integer - type: object - securityContext: - description: SecurityContext specifies the security context for - the created Deployment's Pod. - properties: - fsGroup: - description: "A special supplemental group that applies to - all containers in a pod. Some volume types allow the Kubelet - to change the ownership of that volume to be owned by the - pod: \n 1. The owning GID will be the FSGroup 2. The setgid - bit is set (new files created in the volume will be owned - by FSGroup) 3. The permission bits are OR'd with rw-rw---- - \n If unset, the Kubelet will not modify the ownership and - permissions of any volume. Note that this field cannot be - set when spec.os.name is windows." - format: int64 - type: integer - fsGroupChangePolicy: - description: 'fsGroupChangePolicy defines behavior of changing - ownership and permission of the volume before being exposed - inside Pod. This field will only apply to volume types which - support fsGroup based ownership(and permissions). It will - have no effect on ephemeral volume types such as: secret, - configmaps and emptydir. Valid values are "OnRootMismatch" - and "Always". If not specified, "Always" is used. Note that - this field cannot be set when spec.os.name is windows.' - type: string - runAsGroup: - description: The GID to run the entrypoint of the container - process. Uses runtime default if unset. May also be set - in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. Note that this field - cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root - user. If true, the Kubelet will validate the image at runtime - to ensure that it does not run as UID 0 (root) and fail - to start the container if it does. If unset or false, no - such validation will be performed. May also be set in SecurityContext. If - set in both SecurityContext and PodSecurityContext, the - value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: The UID to run the entrypoint of the container - process. Defaults to user specified in image metadata if - unspecified. May also be set in SecurityContext. If set - in both SecurityContext and PodSecurityContext, the value - specified in SecurityContext takes precedence for that container. - Note that this field cannot be set when spec.os.name is - windows. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random - SELinux context for each container. May also be set in - SecurityContext. If set in both SecurityContext and PodSecurityContext, - the value specified in SecurityContext takes precedence - for that container. Note that this field cannot be set when - spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies - to the container. - type: string - role: - description: Role is a SELinux role label that applies - to the container. - type: string - type: - description: Type is a SELinux type label that applies - to the container. - type: string - user: - description: User is a SELinux user label that applies - to the container. - type: string - type: object - seccompProfile: - description: The seccomp options to use by the containers - in this pod. Note that this field cannot be set when spec.os.name - is windows. - properties: - localhostProfile: - description: localhostProfile indicates a profile defined - in a file on the node should be used. The profile must - be preconfigured on the node to work. Must be a descending - path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". - type: string - type: - description: "type indicates which kind of seccomp profile - will be applied. Valid options are: \n Localhost - a - profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile - should be used. Unconfined - no profile should be applied." - type: string - required: - - type - type: object - supplementalGroups: - description: A list of groups applied to the first process - run in each container, in addition to the container's primary - GID, the fsGroup (if specified), and group memberships defined - in the container image for the uid of the container process. - If unspecified, no additional groups are added to any container. - Note that group memberships defined in the container image - for the uid of the container process are still effective, - even if they are not included in this list. Note that this - field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - sysctls: - description: Sysctls hold a list of namespaced sysctls used - for the pod. Pods with unsupported sysctls (by the container - runtime) might fail to launch. Note that this field cannot - be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - windowsOptions: - description: The Windows specific settings applied to all - containers. If unspecified, the options within a container's - SecurityContext will be used. If set in both SecurityContext - and PodSecurityContext, the value specified in SecurityContext - takes precedence. Note that this field cannot be set when - spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: GMSACredentialSpec is where the GMSA admission - webhook (https://github.com/kubernetes-sigs/windows-gmsa) - inlines the contents of the GMSA credential spec named - by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the - GMSA credential spec to use. - type: string - hostProcess: - description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components that - enable the WindowsHostProcessContainers feature flag. - Setting this field without the feature flag will result - in errors when validating the Pod. All of a Pod's containers - must have the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: The UserName in Windows to run the entrypoint - of the container process. Defaults to the user specified - in image metadata if unspecified. May also be set in - PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext - takes precedence. - type: string - type: object - type: object - tolerations: - description: Tolerations specifies the tolerations to use on the - created Deployment. - items: - description: The pod this Toleration is attached to tolerates - any taint that matches the triple using - the matching operator . - properties: - effect: - description: Effect indicates the taint effect to match. - Empty means match all taint effects. When specified, allowed - values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies - to. Empty means match all taint keys. If the key is empty, - operator must be Exists; this combination means to match - all values and all keys. - type: string - operator: - description: Operator represents a key's relationship to - the value. Valid operators are Exists and Equal. Defaults - to Equal. Exists is equivalent to wildcard for value, - so that a pod can tolerate all taints of a particular - category. - type: string - tolerationSeconds: - description: TolerationSeconds represents the period of - time the toleration (which must be of effect NoExecute, - otherwise this field is ignored) tolerates the taint. - By default, it is not set, which means tolerate the taint - forever (do not evict). Zero and negative values will - be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: Value is the taint value the toleration matches - to. If the operator is Exists, the value should be empty, - otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: - description: 'TopologySpreadConstraints is a feature that controls - how pods are spead across your topology. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/' - items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. - properties: - labelSelector: - description: LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine - the number of pods in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. - If the operator is In or NotIn, the values array - must be non-empty. If the operator is Exists - or DoesNotExist, the values array must be empty. - This array is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} pairs. - A single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field - is "key", the operator is "In", and the values array - contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to - select the pods over which spreading will be calculated. - The keys are used to lookup values from the incoming pod - labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading - will be calculated for the incoming pod. Keys that don't - exist in the incoming pod labels will be ignored. A null - or empty list means only match against labelSelector. - items: - type: string - type: array - x-kubernetes-list-type: atomic - maxSkew: - description: 'MaxSkew describes the degree to which pods - may be unevenly distributed. When `whenUnsatisfiable=DoNotSchedule`, - it is the maximum permitted difference between the number - of matching pods in the target topology and the global - minimum. The global minimum is the minimum number of matching - pods in an eligible domain or zero if the number of eligible - domains is less than MinDomains. For example, in a 3-zone - cluster, MaxSkew is set to 1, and pods with the same labelSelector - spread as 2/2/1: In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to - zone3 to become 2/2/2; scheduling it onto zone1(zone2) - would make the ActualSkew(3-1) on zone1(zone2) violate - MaxSkew(1). - if MaxSkew is 2, incoming pod can be scheduled - onto any zone. When `whenUnsatisfiable=ScheduleAnyway`, - it is used to give higher precedence to topologies that - satisfy it. It''s a required field. Default value is 1 - and 0 is not allowed.' - format: int32 - type: integer - minDomains: - description: "MinDomains indicates a minimum number of eligible - domains. When the number of eligible domains with matching - topology keys is less than minDomains, Pod Topology Spread - treats \"global minimum\" as 0, and then the calculation - of Skew is performed. And when the number of eligible - domains with matching topology keys equals or greater - than minDomains, this value has no effect on scheduling. - As a result, when the number of eligible domains is less - than minDomains, scheduler won't schedule more than maxSkew - Pods to those domains. If value is nil, the constraint - behaves as if MinDomains is equal to 1. Valid values are - integers greater than 0. When value is not nil, WhenUnsatisfiable - must be DoNotSchedule. \n For example, in a 3-zone cluster, - MaxSkew is set to 2, MinDomains is set to 5 and pods with - the same labelSelector spread as 2/2/2: | zone1 | zone2 - | zone3 | | P P | P P | P P | The number of domains - is less than 5(MinDomains), so \"global minimum\" is treated - as 0. In this situation, new pod with the same labelSelector - cannot be scheduled, because computed skew will be 3(3 - - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. \n This is a beta field and requires - the MinDomainsInPodTopologySpread feature gate to be enabled - (enabled by default)." - format: int32 - type: integer - nodeAffinityPolicy: - description: "NodeAffinityPolicy indicates how we will treat - Pod's nodeAffinity/nodeSelector when calculating pod topology - spread skew. Options are: - Honor: only nodes matching - nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes - are included in the calculations. \n If this value is - nil, the behavior is equivalent to the Honor policy. This - is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread - feature flag." - type: string - nodeTaintsPolicy: - description: "NodeTaintsPolicy indicates how we will treat - node taints when calculating pod topology spread skew. - Options are: - Honor: nodes without taints, along with - tainted nodes for which the incoming pod has a toleration, - are included. - Ignore: node taints are ignored. All nodes - are included. \n If this value is nil, the behavior is - equivalent to the Ignore policy. This is a beta-level - feature default enabled by the NodeInclusionPolicyInPodTopologySpread - feature flag." - type: string - topologyKey: - description: TopologyKey is the key of node labels. Nodes - that have a label with this key and identical values are - considered to be in the same topology. We consider each - as a "bucket", and try to put balanced number - of pods into each bucket. We define a domain as a particular - instance of a topology. Also, we define an eligible domain - as a domain whose nodes meet the requirements of nodeAffinityPolicy - and nodeTaintsPolicy. e.g. If TopologyKey is "kubernetes.io/hostname", - each Node is a domain of that topology. And, if TopologyKey - is "topology.kubernetes.io/zone", each zone is a domain - of that topology. It's a required field. - type: string - whenUnsatisfiable: - description: 'WhenUnsatisfiable indicates how to deal with - a pod if it doesn''t satisfy the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule - it. - ScheduleAnyway tells the scheduler to schedule the - pod in any location, but giving higher precedence to topologies - that would help reduce the skew. A constraint is considered - "Unsatisfiable" for an incoming pod if and only if every - possible node assignment for that pod would violate "MaxSkew" - on some topology. For example, in a 3-zone cluster, MaxSkew - is set to 1, and pods with the same labelSelector spread - as 3/1/1: | zone1 | zone2 | zone3 | | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming - pod can only be scheduled to zone2(zone3) to become 3/2/1(3/1/2) - as ActualSkew(2-1) on zone2(zone3) satisfies MaxSkew(1). - In other words, the cluster can still be imbalanced, but - scheduler won''t make it *more* imbalanced. It''s a required - field.' - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - type: object - labels: - description: Labels are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key included - here will override those in Set if specified on the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included here - will be overridden if present in InheritFromGateway and set - on the Gateway. - type: object - type: object - role: - description: Role contains config specific to the Role created from - this GatewayClass - properties: - annotations: - description: Annotations are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - labels: - description: Labels are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - type: object - roleBinding: - description: RoleBinding contains config specific to the RoleBinding - created from this GatewayClass - properties: - annotations: - description: Annotations are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - labels: - description: Labels are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - type: object - service: - description: Service contains config specific to the Service created - from this GatewayClass - properties: - annotations: - description: Annotations are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - labels: - description: Labels are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - type: - description: Type specifies the type of Service to use (LoadBalancer, - ClusterIP, etc.) - enum: - - ClusterIP - - NodePort - - LoadBalancer - type: string - type: object - serviceAccount: - description: ServiceAccount contains config specific to the corev1.ServiceAccount - created from this GatewayClass - properties: - annotations: - description: Annotations are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - labels: - description: Labels are applied to the created resource - properties: - inheritFromGateway: - description: InheritFromGateway lists the names/keys of annotations - or labels to copy from the Gateway resource. Any name/key - included here will override those in Set if specified on - the Gateway. - items: - type: string - type: array - set: - additionalProperties: - type: string - description: Set lists the names/keys and values of annotations - or labels to set on the resource. Any name/key included - here will be overridden if present in InheritFromGateway - and set on the Gateway. - type: object - type: object - type: object - type: object - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. - items: - description: 'Conditions define a readiness condition for a Consul - resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' - properties: - lastTransitionTime: - description: LastTransitionTime is the last time the condition - transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource successfully - synced with Consul. - format: date-time - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_gatewayclasses.yaml b/control-plane/config/crd/bases/mesh.consul.hashicorp.com_gatewayclasses.yaml deleted file mode 100644 index ca2b05d062..0000000000 --- a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_gatewayclasses.yaml +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - name: gatewayclasses.mesh.consul.hashicorp.com -spec: - group: mesh.consul.hashicorp.com - names: - kind: GatewayClass - listKind: GatewayClassList - plural: gatewayclasses - singular: gatewayclass - scope: Cluster - versions: - - additionalPrinterColumns: - - description: The age of the resource - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2beta1 - schema: - openAPIV3Schema: - description: GatewayClass is the Schema for the Gateway Class API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - controllerName: - description: ControllerName is the name of the Kubernetes controller - that manages Gateways of this class - type: string - description: - description: Description of GatewayClass - type: string - parametersRef: - description: ParametersRef refers to a resource responsible for configuring - the behavior of the GatewayClass. - properties: - group: - description: The Kubernetes Group that the referred object belongs - to - type: string - kind: - description: The Kubernetes Kind that the referred object is - type: string - name: - description: The Name of the referred object - type: string - namespace: - description: The kubernetes namespace that the referred object - is in - type: string - required: - - name - type: object - required: - - controllerName - - parametersRef - type: object - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. - items: - description: 'Conditions define a readiness condition for a Consul - resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' - properties: - lastTransitionTime: - description: LastTransitionTime is the last time the condition - transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource successfully - synced with Consul. - format: date-time - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_grpcroutes.yaml b/control-plane/config/crd/bases/mesh.consul.hashicorp.com_grpcroutes.yaml index ff00bd86e5..fda3e4255e 100644 --- a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_grpcroutes.yaml +++ b/control-plane/config/crd/bases/mesh.consul.hashicorp.com_grpcroutes.yaml @@ -68,10 +68,9 @@ spec: description: 'NOTE: roughly equivalent to structs.ResourceReference' properties: port: - description: "For east/west this is the name of the Consul Service + description: For east/west this is the name of the Consul Service port to direct traffic to or empty to imply all. For north/south - this is TBD. \n For more details on potential values of this - field, see documentation for Service.ServicePort." + this is TBD. type: string ref: description: For east/west configuration, this should point @@ -103,6 +102,13 @@ spec: the wildcard value \"*\" to list resources across all partitions." type: string + peerName: + description: "PeerName identifies which peer the resource + is imported from. https://developer.hashicorp.com/consul/docs/connect/cluster-peering + \n When using the List and WatchList endpoints, provide + the wildcard value \"*\" to list resources across + all peers." + type: string type: object type: description: Type identifies the resource's type. @@ -156,9 +162,7 @@ spec: description: "For east/west this is the name of the Consul Service port to direct traffic to or empty to imply using the same value as the parent ref. - For north/south this is TBD. \n For more details - on potential values of this field, see documentation - for Service.ServicePort." + \n For north/south this is TBD." type: string ref: description: For east/west configuration, this should @@ -191,6 +195,13 @@ spec: provide the wildcard value \"*\" to list resources across all partitions." type: string + peerName: + description: "PeerName identifies which peer + the resource is imported from. https://developer.hashicorp.com/consul/docs/connect/cluster-peering + \n When using the List and WatchList endpoints, + provide the wildcard value \"*\" to list + resources across all peers." + type: string type: object type: description: Type identifies the resource's type. diff --git a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_httproutes.yaml b/control-plane/config/crd/bases/mesh.consul.hashicorp.com_httproutes.yaml index ae41db0016..46bf7162a6 100644 --- a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_httproutes.yaml +++ b/control-plane/config/crd/bases/mesh.consul.hashicorp.com_httproutes.yaml @@ -68,10 +68,9 @@ spec: description: 'NOTE: roughly equivalent to structs.ResourceReference' properties: port: - description: "For east/west this is the name of the Consul Service + description: For east/west this is the name of the Consul Service port to direct traffic to or empty to imply all. For north/south - this is TBD. \n For more details on potential values of this - field, see documentation for Service.ServicePort." + this is TBD. type: string ref: description: For east/west configuration, this should point @@ -103,6 +102,13 @@ spec: the wildcard value \"*\" to list resources across all partitions." type: string + peerName: + description: "PeerName identifies which peer the resource + is imported from. https://developer.hashicorp.com/consul/docs/connect/cluster-peering + \n When using the List and WatchList endpoints, provide + the wildcard value \"*\" to list resources across + all peers." + type: string type: object type: description: Type identifies the resource's type. @@ -159,9 +165,7 @@ spec: description: "For east/west this is the name of the Consul Service port to direct traffic to or empty to imply using the same value as the parent ref. - For north/south this is TBD. \n For more details - on potential values of this field, see documentation - for Service.ServicePort." + \n For north/south this is TBD." type: string ref: description: For east/west configuration, this should @@ -194,6 +198,13 @@ spec: provide the wildcard value \"*\" to list resources across all partitions." type: string + peerName: + description: "PeerName identifies which peer + the resource is imported from. https://developer.hashicorp.com/consul/docs/connect/cluster-peering + \n When using the List and WatchList endpoints, + provide the wildcard value \"*\" to list + resources across all peers." + type: string type: object type: description: Type identifies the resource's type. diff --git a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_meshconfigurations.yaml b/control-plane/config/crd/bases/mesh.consul.hashicorp.com_meshconfigurations.yaml deleted file mode 100644 index eb044ecb6c..0000000000 --- a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_meshconfigurations.yaml +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - name: meshconfigurations.mesh.consul.hashicorp.com -spec: - group: mesh.consul.hashicorp.com - names: - kind: MeshConfiguration - listKind: MeshConfigurationList - plural: meshconfigurations - singular: meshconfiguration - scope: Cluster - versions: - - additionalPrinterColumns: - - description: The sync status of the resource with Consul - jsonPath: .status.conditions[?(@.type=="Synced")].status - name: Synced - type: string - - description: The last successful synced time of the resource with Consul - jsonPath: .status.lastSyncedTime - name: Last Synced - type: date - - description: The age of the resource - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2beta1 - schema: - openAPIV3Schema: - description: MeshConfiguration is the Schema for the Mesh Configuration - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: MeshConfiguration is responsible for configuring the default - behavior of Mesh Gateways. This is a Resource type. - type: object - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. - items: - description: 'Conditions define a readiness condition for a Consul - resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' - properties: - lastTransitionTime: - description: LastTransitionTime is the last time the condition - transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource successfully - synced with Consul. - format: date-time - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_meshgateways.yaml b/control-plane/config/crd/bases/mesh.consul.hashicorp.com_meshgateways.yaml deleted file mode 100644 index 47f2fcfba8..0000000000 --- a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_meshgateways.yaml +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - name: meshgateways.mesh.consul.hashicorp.com -spec: - group: mesh.consul.hashicorp.com - names: - kind: MeshGateway - listKind: MeshGatewayList - plural: meshgateways - singular: meshgateway - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: The sync status of the resource with Consul - jsonPath: .status.conditions[?(@.type=="Synced")].status - name: Synced - type: string - - description: The last successful synced time of the resource with Consul - jsonPath: .status.lastSyncedTime - name: Last Synced - type: date - - description: The age of the resource - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2beta1 - schema: - openAPIV3Schema: - description: MeshGateway is the Schema for the Mesh Gateway API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - gatewayClassName: - description: GatewayClassName is the name of the GatewayClass used - by the MeshGateway - type: string - listeners: - items: - properties: - name: - type: string - port: - format: int32 - maximum: 65535 - minimum: 0 - type: integer - protocol: - enum: - - TCP - type: string - type: object - minItems: 1 - type: array - workloads: - description: Selection of workloads to be configured as mesh gateways - properties: - filter: - type: string - names: - items: - type: string - type: array - prefixes: - items: - type: string - type: array - type: object - type: object - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. - items: - description: 'Conditions define a readiness condition for a Consul - resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' - properties: - lastTransitionTime: - description: LastTransitionTime is the last time the condition - transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource successfully - synced with Consul. - format: date-time - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_proxyconfigurations.yaml b/control-plane/config/crd/bases/mesh.consul.hashicorp.com_proxyconfigurations.yaml index 4a505adeb9..1d15b34111 100644 --- a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_proxyconfigurations.yaml +++ b/control-plane/config/crd/bases/mesh.consul.hashicorp.com_proxyconfigurations.yaml @@ -123,6 +123,24 @@ spec: format: int32 type: string type: object + envoyExtensions: + items: + description: EnvoyExtension has configuration for an extension + that patches Envoy resources. + properties: + arguments: + type: object + x-kubernetes-preserve-unknown-fields: true + consulVersion: + type: string + envoyVersion: + type: string + name: + type: string + required: + type: boolean + type: object + type: array exposeConfig: properties: exposePaths: @@ -156,7 +174,7 @@ spec: format: int32 type: string maxInboundConnections: - format: int32 + format: int64 type: integer type: object listenerTracingJson: diff --git a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_tcproutes.yaml b/control-plane/config/crd/bases/mesh.consul.hashicorp.com_tcproutes.yaml index dbfb0c9b20..21a3a9c5ec 100644 --- a/control-plane/config/crd/bases/mesh.consul.hashicorp.com_tcproutes.yaml +++ b/control-plane/config/crd/bases/mesh.consul.hashicorp.com_tcproutes.yaml @@ -62,10 +62,9 @@ spec: description: 'NOTE: roughly equivalent to structs.ResourceReference' properties: port: - description: "For east/west this is the name of the Consul Service + description: For east/west this is the name of the Consul Service port to direct traffic to or empty to imply all. For north/south - this is TBD. \n For more details on potential values of this - field, see documentation for Service.ServicePort." + this is TBD. type: string ref: description: For east/west configuration, this should point @@ -97,6 +96,13 @@ spec: the wildcard value \"*\" to list resources across all partitions." type: string + peerName: + description: "PeerName identifies which peer the resource + is imported from. https://developer.hashicorp.com/consul/docs/connect/cluster-peering + \n When using the List and WatchList endpoints, provide + the wildcard value \"*\" to list resources across + all peers." + type: string type: object type: description: Type identifies the resource's type. @@ -141,9 +147,7 @@ spec: description: "For east/west this is the name of the Consul Service port to direct traffic to or empty to imply using the same value as the parent ref. - For north/south this is TBD. \n For more details - on potential values of this field, see documentation - for Service.ServicePort." + \n For north/south this is TBD." type: string ref: description: For east/west configuration, this should @@ -176,6 +180,13 @@ spec: provide the wildcard value \"*\" to list resources across all partitions." type: string + peerName: + description: "PeerName identifies which peer + the resource is imported from. https://developer.hashicorp.com/consul/docs/connect/cluster-peering + \n When using the List and WatchList endpoints, + provide the wildcard value \"*\" to list + resources across all peers." + type: string type: object type: description: Type identifies the resource's type. diff --git a/control-plane/config/crd/bases/multicluster.consul.hashicorp.com_exportedservices.yaml b/control-plane/config/crd/bases/multicluster.consul.hashicorp.com_exportedservices.yaml deleted file mode 100644 index 36020e3639..0000000000 --- a/control-plane/config/crd/bases/multicluster.consul.hashicorp.com_exportedservices.yaml +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - name: exportedservices.multicluster.consul.hashicorp.com -spec: - group: multicluster.consul.hashicorp.com - names: - kind: ExportedServices - listKind: ExportedServicesList - plural: exportedservices - singular: exportedservices - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: The sync status of the resource with Consul - jsonPath: .status.conditions[?(@.type=="Synced")].status - name: Synced - type: string - - description: The last successful synced time of the resource with Consul - jsonPath: .status.lastSyncedTime - name: Last Synced - type: date - - description: The age of the resource - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2 - schema: - openAPIV3Schema: - description: ExportedServices is the Schema for the Exported Services API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - consumers: - items: - type: object - x-kubernetes-preserve-unknown-fields: true - type: array - services: - items: - type: string - type: array - type: object - status: - properties: - conditions: - description: Conditions indicate the latest available observations - of a resource's current state. - items: - description: 'Conditions define a readiness condition for a Consul - resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' - properties: - lastTransitionTime: - description: LastTransitionTime is the last time the condition - transitioned from one status to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition. - type: string - required: - - status - - type - type: object - type: array - lastSyncedTime: - description: LastSyncedTime is the last time the resource successfully - synced with Consul. - format: date-time - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/control-plane/config/rbac/role.yaml b/control-plane/config/rbac/role.yaml index c2ad591c4f..cce5208eda 100644 --- a/control-plane/config/rbac/role.yaml +++ b/control-plane/config/rbac/role.yaml @@ -345,46 +345,6 @@ rules: - get - patch - update -- apiGroups: - - mesh.consul.hashicorp.com - resources: - - gatewayclass - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - mesh.consul.hashicorp.com - resources: - - gatewayclass/status - verbs: - - get - - patch - - update -- apiGroups: - - mesh.consul.hashicorp.com - resources: - - gatewayclassconfig - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - mesh.consul.hashicorp.com - resources: - - gatewayclassconfig/status - verbs: - - get - - patch - - update - apiGroups: - mesh.consul.hashicorp.com resources: @@ -425,46 +385,6 @@ rules: - get - patch - update -- apiGroups: - - mesh.consul.hashicorp.com - resources: - - meshconfiguration - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - mesh.consul.hashicorp.com - resources: - - meshconfiguration/status - verbs: - - get - - patch - - update -- apiGroups: - - mesh.consul.hashicorp.com - resources: - - meshgateway - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - mesh.consul.hashicorp.com - resources: - - meshgateway/status - verbs: - - get - - patch - - update - apiGroups: - mesh.consul.hashicorp.com resources: @@ -505,23 +425,3 @@ rules: - get - patch - update -- apiGroups: - - multicluster.consul.hashicorp.com - resources: - - exportedservices - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - multicluster.consul.hashicorp.com - resources: - - exportedservices/status - verbs: - - get - - patch - - update diff --git a/control-plane/config/webhook/manifests.yaml b/control-plane/config/webhook/manifests.yaml index a4b3aaadd0..b5e3bb52fd 100644 --- a/control-plane/config/webhook/manifests.yaml +++ b/control-plane/config/webhook/manifests.yaml @@ -14,19 +14,19 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v2beta1-grpcroute + path: /mutate-v1alpha1-controlplanerequestlimits failurePolicy: Fail - name: mutate-grpcroute.auth.consul.hashicorp.com + name: mutate-controlplanerequestlimits.consul.hashicorp.com rules: - apiGroups: - - auth.consul.hashicorp.com + - consul.hashicorp.com apiVersions: - - v2beta1 + - v1alpha1 operations: - CREATE - UPDATE resources: - - grpcroute + - controlplanerequestlimits sideEffects: None - admissionReviewVersions: - v1beta1 @@ -35,19 +35,19 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v2beta1-httproute + path: /mutate-v1alpha1-exportedservices failurePolicy: Fail - name: mutate-httproute.auth.consul.hashicorp.com + name: mutate-exportedservices.consul.hashicorp.com rules: - apiGroups: - - auth.consul.hashicorp.com + - consul.hashicorp.com apiVersions: - - v2beta1 + - v1alpha1 operations: - CREATE - UPDATE resources: - - httproute + - exportedservices sideEffects: None - admissionReviewVersions: - v1beta1 @@ -56,19 +56,19 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v2beta1-proxyconfiguration + path: /mutate-v1alpha1-ingressgateway failurePolicy: Fail - name: mutate-proxyconfiguration.auth.consul.hashicorp.com + name: mutate-ingressgateway.consul.hashicorp.com rules: - apiGroups: - - auth.consul.hashicorp.com + - consul.hashicorp.com apiVersions: - - v2beta1 + - v1alpha1 operations: - CREATE - UPDATE resources: - - proxyconfiguration + - ingressgateways sideEffects: None - admissionReviewVersions: - v1beta1 @@ -77,19 +77,19 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v2beta1-tcproute + path: /mutate-v1alpha1-jwtprovider failurePolicy: Fail - name: mutate-tcproute.auth.consul.hashicorp.com + name: mutate-jwtprovider.consul.hashicorp.com rules: - apiGroups: - - auth.consul.hashicorp.com + - consul.hashicorp.com apiVersions: - - v2beta1 + - v1alpha1 operations: - CREATE - UPDATE resources: - - tcproute + - jwtproviders sideEffects: None - admissionReviewVersions: - v1beta1 @@ -98,9 +98,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-controlplanerequestlimits + path: /mutate-v1alpha1-mesh failurePolicy: Fail - name: mutate-controlplanerequestlimits.consul.hashicorp.com + name: mutate-mesh.consul.hashicorp.com rules: - apiGroups: - consul.hashicorp.com @@ -110,7 +110,7 @@ webhooks: - CREATE - UPDATE resources: - - controlplanerequestlimits + - mesh sideEffects: None - admissionReviewVersions: - v1beta1 @@ -119,9 +119,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-exportedservices + path: /mutate-v1alpha1-peeringacceptors failurePolicy: Fail - name: mutate-exportedservices.consul.hashicorp.com + name: mutate-peeringacceptors.consul.hashicorp.com rules: - apiGroups: - consul.hashicorp.com @@ -131,7 +131,7 @@ webhooks: - CREATE - UPDATE resources: - - exportedservices + - peeringacceptors sideEffects: None - admissionReviewVersions: - v1beta1 @@ -140,9 +140,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-ingressgateway + path: /mutate-v1alpha1-peeringdialers failurePolicy: Fail - name: mutate-ingressgateway.consul.hashicorp.com + name: mutate-peeringdialers.consul.hashicorp.com rules: - apiGroups: - consul.hashicorp.com @@ -152,7 +152,7 @@ webhooks: - CREATE - UPDATE resources: - - ingressgateways + - peeringdialers sideEffects: None - admissionReviewVersions: - v1beta1 @@ -161,9 +161,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-jwtprovider + path: /mutate-v1alpha1-proxydefaults failurePolicy: Fail - name: mutate-jwtprovider.consul.hashicorp.com + name: mutate-proxydefaults.consul.hashicorp.com rules: - apiGroups: - consul.hashicorp.com @@ -173,7 +173,7 @@ webhooks: - CREATE - UPDATE resources: - - jwtproviders + - proxydefaults sideEffects: None - admissionReviewVersions: - v1beta1 @@ -182,9 +182,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-mesh + path: /mutate-v1alpha1-samenessgroups failurePolicy: Fail - name: mutate-mesh.consul.hashicorp.com + name: mutate-samenessgroup.consul.hashicorp.com rules: - apiGroups: - consul.hashicorp.com @@ -194,7 +194,7 @@ webhooks: - CREATE - UPDATE resources: - - mesh + - samenessgroups sideEffects: None - admissionReviewVersions: - v1beta1 @@ -203,9 +203,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-peeringacceptors + path: /mutate-v1alpha1-servicedefaults failurePolicy: Fail - name: mutate-peeringacceptors.consul.hashicorp.com + name: mutate-servicedefaults.consul.hashicorp.com rules: - apiGroups: - consul.hashicorp.com @@ -215,7 +215,7 @@ webhooks: - CREATE - UPDATE resources: - - peeringacceptors + - servicedefaults sideEffects: None - admissionReviewVersions: - v1beta1 @@ -224,9 +224,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-peeringdialers + path: /mutate-v1alpha1-serviceintentions failurePolicy: Fail - name: mutate-peeringdialers.consul.hashicorp.com + name: mutate-serviceintentions.consul.hashicorp.com rules: - apiGroups: - consul.hashicorp.com @@ -236,7 +236,7 @@ webhooks: - CREATE - UPDATE resources: - - peeringdialers + - serviceintentions sideEffects: None - admissionReviewVersions: - v1beta1 @@ -245,9 +245,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-proxydefaults + path: /mutate-v1alpha1-serviceresolver failurePolicy: Fail - name: mutate-proxydefaults.consul.hashicorp.com + name: mutate-serviceresolver.consul.hashicorp.com rules: - apiGroups: - consul.hashicorp.com @@ -257,7 +257,7 @@ webhooks: - CREATE - UPDATE resources: - - proxydefaults + - serviceresolvers sideEffects: None - admissionReviewVersions: - v1beta1 @@ -266,9 +266,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-samenessgroups + path: /mutate-v1alpha1-servicerouter failurePolicy: Fail - name: mutate-samenessgroup.consul.hashicorp.com + name: mutate-servicerouter.consul.hashicorp.com rules: - apiGroups: - consul.hashicorp.com @@ -278,7 +278,7 @@ webhooks: - CREATE - UPDATE resources: - - samenessgroups + - servicerouters sideEffects: None - admissionReviewVersions: - v1beta1 @@ -287,9 +287,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-servicedefaults + path: /mutate-v1alpha1-servicesplitter failurePolicy: Fail - name: mutate-servicedefaults.consul.hashicorp.com + name: mutate-servicesplitter.consul.hashicorp.com rules: - apiGroups: - consul.hashicorp.com @@ -299,7 +299,7 @@ webhooks: - CREATE - UPDATE resources: - - servicedefaults + - servicesplitters sideEffects: None - admissionReviewVersions: - v1beta1 @@ -308,9 +308,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-serviceintentions + path: /mutate-v1alpha1-terminatinggateway failurePolicy: Fail - name: mutate-serviceintentions.consul.hashicorp.com + name: mutate-terminatinggateway.consul.hashicorp.com rules: - apiGroups: - consul.hashicorp.com @@ -320,7 +320,7 @@ webhooks: - CREATE - UPDATE resources: - - serviceintentions + - terminatinggateways sideEffects: None - admissionReviewVersions: - v1beta1 @@ -329,19 +329,19 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-serviceresolver + path: /mutate-v2beta1-trafficpermissions failurePolicy: Fail - name: mutate-serviceresolver.consul.hashicorp.com + name: mutate-trafficpermissions.auth.consul.hashicorp.com rules: - apiGroups: - - consul.hashicorp.com + - auth.consul.hashicorp.com apiVersions: - - v1alpha1 + - v2beta1 operations: - CREATE - UPDATE resources: - - serviceresolvers + - trafficpermissions sideEffects: None - admissionReviewVersions: - v1beta1 @@ -350,19 +350,19 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-servicerouter + path: /mutate-v2beta1-grpcroute failurePolicy: Fail - name: mutate-servicerouter.consul.hashicorp.com + name: mutate-grpcroute.auth.consul.hashicorp.com rules: - apiGroups: - - consul.hashicorp.com + - auth.consul.hashicorp.com apiVersions: - - v1alpha1 + - v2beta1 operations: - CREATE - UPDATE resources: - - servicerouters + - grpcroute sideEffects: None - admissionReviewVersions: - v1beta1 @@ -371,19 +371,19 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-servicesplitter + path: /mutate-v2beta1-httproute failurePolicy: Fail - name: mutate-servicesplitter.consul.hashicorp.com + name: mutate-httproute.auth.consul.hashicorp.com rules: - apiGroups: - - consul.hashicorp.com + - auth.consul.hashicorp.com apiVersions: - - v1alpha1 + - v2beta1 operations: - CREATE - UPDATE resources: - - servicesplitters + - httproute sideEffects: None - admissionReviewVersions: - v1beta1 @@ -392,19 +392,19 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v1alpha1-terminatinggateway + path: /mutate-v2beta1-proxyconfiguration failurePolicy: Fail - name: mutate-terminatinggateway.consul.hashicorp.com + name: mutate-proxyconfiguration.auth.consul.hashicorp.com rules: - apiGroups: - - consul.hashicorp.com + - auth.consul.hashicorp.com apiVersions: - - v1alpha1 + - v2beta1 operations: - CREATE - UPDATE resources: - - terminatinggateways + - proxyconfiguration sideEffects: None - admissionReviewVersions: - v1beta1 @@ -413,9 +413,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-v2beta1-trafficpermissions + path: /mutate-v2beta1-tcproute failurePolicy: Fail - name: mutate-trafficpermissions.auth.consul.hashicorp.com + name: mutate-tcproute.auth.consul.hashicorp.com rules: - apiGroups: - auth.consul.hashicorp.com @@ -425,7 +425,7 @@ webhooks: - CREATE - UPDATE resources: - - trafficpermissions + - tcproute sideEffects: None --- apiVersion: admissionregistration.k8s.io/v1 diff --git a/control-plane/connect-inject/common/annotation_processor.go b/control-plane/connect-inject/common/annotation_processor.go index f89c6348d0..778f630049 100644 --- a/control-plane/connect-inject/common/annotation_processor.go +++ b/control-plane/connect-inject/common/annotation_processor.go @@ -99,7 +99,7 @@ func processPodLabeledDestination(pod corev1.Pod, rawUpstream string, enablePart service := parts[0] pieces := strings.Split(service, ".") - var portName, datacenter, svcName, namespace, partition string + var portName, datacenter, svcName, namespace, partition, peer string if enablePartitions || enableNamespaces { switch len(pieces) { case 8: @@ -180,6 +180,7 @@ func processPodLabeledDestination(pod corev1.Pod, rawUpstream string, enablePart Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(partition), Namespace: constants.GetNormalizedConsulNamespace(namespace), + PeerName: constants.GetNormalizedConsulPeer(peer), }, Name: svcName, }, @@ -249,6 +250,7 @@ func processPodUnlabeledDestination(pod corev1.Pod, rawUpstream string, enablePa Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(partition), Namespace: constants.GetNormalizedConsulNamespace(namespace), + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: svcName, }, diff --git a/control-plane/connect-inject/common/annotation_processor_test.go b/control-plane/connect-inject/common/annotation_processor_test.go index 77053540e3..223067e6c5 100644 --- a/control-plane/connect-inject/common/annotation_processor_test.go +++ b/control-plane/connect-inject/common/annotation_processor_test.go @@ -51,6 +51,7 @@ func TestProcessUpstreams(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(""), Namespace: constants.GetNormalizedConsulNamespace(""), + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream1", }, @@ -87,6 +88,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: constants.GetNormalizedConsulPartition(""), // Namespace: constants.GetNormalizedConsulNamespace(""), + // PeerName: constants.GetNormalizedConsulPeer(""), // }, // Name: "upstream1", // }, @@ -123,6 +125,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: constants.GetNormalizedConsulPartition(""), // Namespace: constants.GetNormalizedConsulNamespace(""), + // PeerName: "peer1", // }, // Name: "upstream1", // }, @@ -159,6 +162,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: constants.GetNormalizedConsulPartition(""), // Namespace: "ns1", + // PeerName: "peer1", // }, // Name: "upstream1", // }, @@ -193,6 +197,7 @@ func TestProcessUpstreams(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: "part1", Namespace: "ns1", + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream1", }, @@ -229,6 +234,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: constants.GetNormalizedConsulPartition(""), // Namespace: "ns1", + // PeerName: constants.GetNormalizedConsulPeer(""), // }, // Name: "upstream1", // }, @@ -263,6 +269,7 @@ func TestProcessUpstreams(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(""), Namespace: "ns1", + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream1", }, @@ -281,6 +288,7 @@ func TestProcessUpstreams(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(""), Namespace: constants.GetNormalizedConsulNamespace(""), + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream2", }, @@ -299,6 +307,7 @@ func TestProcessUpstreams(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: "ap1", Namespace: "ns1", + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream4", }, @@ -335,6 +344,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: constants.GetNormalizedConsulPartition(""), // Namespace: "ns1", + // PeerName: constants.GetNormalizedConsulPeer(""), // }, // Name: "upstream1", // }, @@ -353,6 +363,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: constants.GetNormalizedConsulPartition(""), // Namespace: constants.GetNormalizedConsulNamespace(""), + // PeerName: constants.GetNormalizedConsulPeer(""), // }, // Name: "upstream2", // }, @@ -371,6 +382,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: constants.GetNormalizedConsulPartition(""), // Namespace: "ns1", + // PeerName: constants.GetNormalizedConsulPeer(""), // }, // Name: "upstream3", // }, @@ -389,6 +401,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: constants.GetNormalizedConsulPartition(""), // Namespace: "ns1", + // PeerName: "peer1", // }, // Name: "upstream4", // }, @@ -573,6 +586,7 @@ func TestProcessUpstreams(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(""), Namespace: "ns1", + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream1", }, @@ -591,6 +605,7 @@ func TestProcessUpstreams(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(""), Namespace: constants.GetNormalizedConsulNamespace(""), + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream2", }, @@ -609,6 +624,7 @@ func TestProcessUpstreams(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: "ap1", Namespace: "ns1", + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream4", }, @@ -643,6 +659,7 @@ func TestProcessUpstreams(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(""), Namespace: constants.GetNormalizedConsulNamespace(""), + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream", }, @@ -677,6 +694,7 @@ func TestProcessUpstreams(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(""), Namespace: "foo", + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream", }, @@ -711,6 +729,7 @@ func TestProcessUpstreams(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: "bar", Namespace: "foo", + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream", }, @@ -745,6 +764,7 @@ func TestProcessUpstreams(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(""), Namespace: constants.GetNormalizedConsulNamespace(""), + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream1", }, @@ -763,6 +783,7 @@ func TestProcessUpstreams(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(""), Namespace: constants.GetNormalizedConsulNamespace(""), + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream2", }, @@ -805,6 +826,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: constants.GetNormalizedConsulPartition(""), // Namespace: constants.GetNormalizedConsulNamespace(""), + // PeerName: constants.GetNormalizedConsulPeer(""), // }, // Name: "upstream1", // }, @@ -823,6 +845,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: constants.GetNormalizedConsulPartition(""), // Namespace: "bar", + // PeerName: constants.GetNormalizedConsulPeer(""), // }, // Name: "upstream2", // }, @@ -841,6 +864,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: "baz", // Namespace: "foo", + // PeerName: constants.GetNormalizedConsulPeer(""), // }, // Name: "upstream3", // }, @@ -883,6 +907,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: constants.GetNormalizedConsulPartition(""), // Namespace: constants.GetNormalizedConsulNamespace(""), + // PeerName: constants.GetNormalizedConsulPeer(""), // }, // Name: "upstream1", // }, @@ -901,6 +926,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: constants.GetNormalizedConsulPartition(""), // Namespace: "bar", + // PeerName: constants.GetNormalizedConsulPeer(""), // }, // Name: "upstream2", // }, @@ -919,6 +945,7 @@ func TestProcessUpstreams(t *testing.T) { // Tenancy: &pbresource.Tenancy{ // Partition: constants.GetNormalizedConsulPartition(""), // Namespace: "foo", + // PeerName: constants.GetNormalizedConsulPeer(""), // }, // Name: "upstream3", // }, diff --git a/control-plane/connect-inject/common/common.go b/control-plane/connect-inject/common/common.go index 569b4d96e6..baf74dabb3 100644 --- a/control-plane/connect-inject/common/common.go +++ b/control-plane/connect-inject/common/common.go @@ -73,20 +73,6 @@ func PortValue(pod corev1.Pod, value string) (int32, error) { return int32(raw), err } -// WorkloadPortName returns the container port's name if it has one, and if not, constructs a name from the port number -// and adds a constant prefix. The port name must be 1-15 characters and must have at least 1 alpha character. -func WorkloadPortName(port *corev1.ContainerPort) string { - name := port.Name - var isNum bool - if _, err := strconv.Atoi(name); err == nil { - isNum = true - } - if name == "" || isNum { - name = constants.UnnamedWorkloadPortNamePrefix + strconv.Itoa(int(port.ContainerPort)) - } - return name -} - // TransparentProxyEnabled returns true if transparent proxy should be enabled for this pod. // It returns an error when the annotation value cannot be parsed by strconv.ParseBool or if we are unable // to read the pod's namespace label when it exists. @@ -206,16 +192,6 @@ func HasBeenMeshInjected(pod corev1.Pod) bool { return false } -func IsGateway(pod corev1.Pod) bool { - if pod.Annotations == nil { - return false - } - if anno, ok := pod.Annotations[constants.AnnotationGatewayKind]; ok && anno != "" { - return true - } - return false -} - // ConsulNamespaceIsNotFound checks the gRPC error code and message to determine // if a namespace does not exist. If the namespace exists this function returns false, true otherwise. func ConsulNamespaceIsNotFound(err error) bool { @@ -226,7 +202,7 @@ func ConsulNamespaceIsNotFound(err error) bool { if !ok { return false } - if codes.InvalidArgument == s.Code() && strings.Contains(s.Message(), "namespace not found") { + if codes.InvalidArgument == s.Code() && strings.Contains(s.Message(), "namespace resource not found") { return true } return false diff --git a/control-plane/connect-inject/common/common_test.go b/control-plane/connect-inject/common/common_test.go index 2c35315b89..3f41c414fb 100644 --- a/control-plane/connect-inject/common/common_test.go +++ b/control-plane/connect-inject/common/common_test.go @@ -23,6 +23,7 @@ import ( "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" + "github.com/hashicorp/consul-k8s/control-plane/consul" "github.com/hashicorp/consul-k8s/control-plane/helper/test" "github.com/hashicorp/consul-k8s/control-plane/namespaces" ) @@ -167,46 +168,6 @@ func TestCommonDetermineAndValidatePort(t *testing.T) { } } -func TestWorkloadPortName(t *testing.T) { - cases := []struct { - Name string - Port *corev1.ContainerPort - Expected string - }{ - { - Name: "named port", - Port: &corev1.ContainerPort{ - Name: "http", - ContainerPort: 8080, - }, - Expected: "http", - }, - { - Name: "unnamed port", - Port: &corev1.ContainerPort{ - Name: "", - ContainerPort: 8080, - }, - Expected: "cslport-8080", - }, - { - Name: "number port name", - Port: &corev1.ContainerPort{ - Name: "8080", - ContainerPort: 8080, - }, - Expected: "cslport-8080", - }, - } - - for _, tt := range cases { - t.Run(tt.Name, func(t *testing.T) { - name := WorkloadPortName(tt.Port) - require.Equal(t, tt.Expected, name) - }) - } -} - func TestPortValue(t *testing.T) { cases := []struct { Name string @@ -546,7 +507,7 @@ func Test_ConsulNamespaceIsNotFound(t *testing.T) { }, { name: "namespace is missing", - input: status.Error(codes.InvalidArgument, "namespace not found"), + input: status.Error(codes.InvalidArgument, "namespace resource not found"), expectMissingNamespace: true, }, } @@ -568,6 +529,8 @@ func Test_ConsulNamespaceIsNotFound_ErrorMsg(t *testing.T) { testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) id := &pbresource.ID{ Name: "foo", @@ -575,6 +538,10 @@ func Test_ConsulNamespaceIsNotFound_ErrorMsg(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.DefaultConsulPartition, Namespace: "i-dont-exist-but-its-ok-we-will-meet-again-someday", + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, } @@ -599,13 +566,13 @@ func Test_ConsulNamespaceIsNotFound_ErrorMsg(t *testing.T) { Data: data, } - _, err := testClient.ResourceClient.Write(context.Background(), &pbresource.WriteRequest{Resource: resource}) + _, err = resourceClient.Write(context.Background(), &pbresource.WriteRequest{Resource: resource}) require.Error(t, err) s, ok := status.FromError(err) require.True(t, ok) require.Equal(t, codes.InvalidArgument, s.Code()) - require.Contains(t, s.Message(), "namespace not found") + require.Contains(t, s.Message(), "namespace resource not found") require.True(t, ConsulNamespaceIsNotFound(err)) } diff --git a/control-plane/connect-inject/constants/constants.go b/control-plane/connect-inject/constants/constants.go index d4d109ade5..dd7cb4d243 100644 --- a/control-plane/connect-inject/constants/constants.go +++ b/control-plane/connect-inject/constants/constants.go @@ -27,10 +27,6 @@ const ( // ProxyDefaultHealthPort is the default HTTP health check port for the proxy. ProxyDefaultHealthPort = 21000 - // MetaGatewayKind is the meta key name for indicating which kind of gateway a Pod is for, if any. - // The value should be one of "mesh", "api", or "terminating". - MetaGatewayKind = "gateway-kind" - // MetaKeyManagedBy is the meta key name for indicating which Kubernetes controller manages a Consul resource. MetaKeyManagedBy = "managed-by" @@ -62,9 +58,6 @@ const ( // DefaultGracefulShutdownPath is the default path that consul-dataplane uses for graceful shutdown. DefaultGracefulShutdownPath = "/graceful_shutdown" - // DefaultWANPort is the default port that consul-dataplane uses for WAN. - DefaultWANPort = 8443 - // ConsulKubernetesCheckType is the type of health check in Consul for Kubernetes readiness status. ConsulKubernetesCheckType = "kubernetes-readiness" @@ -72,16 +65,6 @@ const ( ConsulKubernetesCheckName = "Kubernetes Readiness Check" KubernetesSuccessReasonMsg = "Kubernetes health checks passing" - - // MeshV2VolumePath is the name of the volume that contains the proxy ID. - MeshV2VolumePath = "/consul/mesh-inject" - - UseTLSEnvVar = "CONSUL_USE_TLS" - CACertFileEnvVar = "CONSUL_CACERT_FILE" - CACertPEMEnvVar = "CONSUL_CACERT_PEM" - TLSServerNameEnvVar = "CONSUL_TLS_SERVER_NAME" - - UnnamedWorkloadPortNamePrefix = "cslport-" ) // GetNormalizedConsulNamespace returns the default namespace if the passed namespace diff --git a/control-plane/connect-inject/controllers/endpointsv2/endpoints_controller.go b/control-plane/connect-inject/controllers/endpointsv2/endpoints_controller.go index 82a9904201..82dd583dfc 100644 --- a/control-plane/connect-inject/controllers/endpointsv2/endpoints_controller.go +++ b/control-plane/connect-inject/controllers/endpointsv2/endpoints_controller.go @@ -375,6 +375,7 @@ func getServiceID(name, namespace, partition string) *pbresource.ID { Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + PeerName: constants.DefaultConsulPeer, }, } } @@ -443,7 +444,12 @@ func getEffectiveTargetPort(targetPort intstr.IntOrString, prefixedPods selector targetPortInt := int32(targetPort.IntValue()) var mostPrevalentContainerPort *corev1.ContainerPort maxCount := 0 - effectiveNameForPort := inject.WorkloadPortName + effectiveNameForPort := func(port *corev1.ContainerPort) string { + if port.Name != "" { + return port.Name + } + return targetPort.String() + } for _, podData := range prefixedPods { containerPort := getTargetContainerPort(targetPortInt, podData.samplePod) @@ -487,7 +493,7 @@ func getEffectiveTargetPort(targetPort intstr.IntOrString, prefixedPods selector // If still no match for the target port, fall back to string-ifying the target port name, which // is what the PodController will do when converting unnamed ContainerPorts to Workload ports. - return constants.UnnamedWorkloadPortNamePrefix + targetPort.String() + return targetPort.String() } // getTargetContainerPort returns the pod ContainerPort matching the given numeric port value, or nil if none is found. diff --git a/control-plane/connect-inject/controllers/endpointsv2/endpoints_controller_test.go b/control-plane/connect-inject/controllers/endpointsv2/endpoints_controller_test.go index 93d41f0f11..cfbd7d7cc2 100644 --- a/control-plane/connect-inject/controllers/endpointsv2/endpoints_controller_test.go +++ b/control-plane/connect-inject/controllers/endpointsv2/endpoints_controller_test.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "testing" + "time" mapset "github.com/deckarep/golang-set" logrtest "github.com/go-logr/logr/testr" @@ -32,6 +33,7 @@ import ( "github.com/hashicorp/consul-k8s/control-plane/api/common" inject "github.com/hashicorp/consul-k8s/control-plane/connect-inject/common" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" + "github.com/hashicorp/consul-k8s/control-plane/consul" "github.com/hashicorp/consul-k8s/control-plane/helper/test" ) @@ -58,6 +60,7 @@ type reconcileCase struct { } // TODO(NET-5716): Allow/deny namespaces for reconcile tests +// TODO(NET-5932): Add tests for consistently sorting repeated output fields (getConsulService, getServicePorts) func TestReconcile_CreateService(t *testing.T) { t.Parallel() @@ -228,7 +231,7 @@ func TestReconcile_CreateService(t *testing.T) { Name: "other", Port: 10001, Protocol: "TCP", - TargetPort: intstr.FromString("cslport-10001"), + TargetPort: intstr.FromString("10001"), // no app protocol specified }, }, @@ -259,7 +262,7 @@ func TestReconcile_CreateService(t *testing.T) { }, { VirtualPort: 10001, - TargetPort: "cslport-10001", + TargetPort: "10001", Protocol: pbcatalog.Protocol_PROTOCOL_TCP, }, { @@ -553,12 +556,12 @@ func TestReconcile_CreateService(t *testing.T) { }, { VirtualPort: 9090, - TargetPort: "cslport-6789", // Matches service target number + TargetPort: "6789", // Matches service target number Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, }, { VirtualPort: 10010, - TargetPort: "cslport-10010", // Matches service target number (unmatched by container ports) + TargetPort: "10010", // Matches service target number (unmatched by container ports) Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, }, { @@ -712,7 +715,7 @@ func TestReconcile_CreateService(t *testing.T) { }, { VirtualPort: 9090, - TargetPort: "cslport-6789", // Matches service target number due to unnamed being most common + TargetPort: "6789", // Matches service target number due to unnamed being most common Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, }, { @@ -1268,7 +1271,7 @@ func TestReconcile_UpdateService(t *testing.T) { }, { VirtualPort: 10001, - TargetPort: "unspec-port", //this might need to be changed to "my_unspecified_port" + TargetPort: "10001", Protocol: pbcatalog.Protocol_PROTOCOL_UNSPECIFIED, }, { @@ -1389,7 +1392,7 @@ func TestReconcile_UpdateService(t *testing.T) { Name: "other", Port: 10001, Protocol: "TCP", - TargetPort: intstr.FromString("cslport-10001"), + TargetPort: intstr.FromString("10001"), // no app protocol specified }, }, @@ -1420,7 +1423,7 @@ func TestReconcile_UpdateService(t *testing.T) { }, { VirtualPort: 10001, - TargetPort: "cslport-10001", + TargetPort: "10001", Protocol: pbcatalog.Protocol_PROTOCOL_TCP, }, { @@ -1752,6 +1755,9 @@ func TestEnsureService(t *testing.T) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { // Create the Endpoints controller. @@ -1768,7 +1774,7 @@ func TestEnsureService(t *testing.T) { // Set up test resourceReadWriter rw := struct{ testReadWriter }{} - defaultRw := defaultResourceReadWriter{testClient.ResourceClient} + defaultRw := defaultResourceReadWriter{resourceClient} rw.readFn = defaultRw.Read rw.writeFn = defaultRw.Write if tc.readFn != nil { @@ -1792,7 +1798,7 @@ func TestEnsureService(t *testing.T) { require.NoError(t, err) // Get written resource before additional calls - beforeResource := getAndValidateResource(t, testClient.ResourceClient, id) + beforeResource := getAndValidateResource(t, resourceClient, id) // Call a second time err = ep.ensureService(context.Background(), &rw, tc.afterArgs.k8sUid, id, tc.afterArgs.meta, tc.afterArgs.consulSvc) @@ -1800,26 +1806,26 @@ func TestEnsureService(t *testing.T) { // Check for change on second call to ensureService if tc.expectWrite { - require.NotEqual(t, beforeResource.GetGeneration(), getAndValidateResource(t, testClient.ResourceClient, id).GetGeneration(), + require.NotEqual(t, beforeResource.GetGeneration(), getAndValidateResource(t, resourceClient, id).GetGeneration(), "wanted different version for before and after resources following modification and reconcile") } else { - require.Equal(t, beforeResource.GetGeneration(), getAndValidateResource(t, testClient.ResourceClient, id).GetGeneration(), + require.Equal(t, beforeResource.GetGeneration(), getAndValidateResource(t, resourceClient, id).GetGeneration(), "wanted same version for before and after resources following repeat reconcile") } // Call several additional times for i := 0; i < 5; i++ { // Get written resource before each additional call - beforeResource = getAndValidateResource(t, testClient.ResourceClient, id) + beforeResource = getAndValidateResource(t, resourceClient, id) err := ep.ensureService(context.Background(), &rw, tc.afterArgs.k8sUid, id, tc.afterArgs.meta, tc.afterArgs.consulSvc) require.NoError(t, err) if tc.expectAlwaysWrite { - require.NotEqual(t, beforeResource.GetGeneration(), getAndValidateResource(t, testClient.ResourceClient, id).GetGeneration(), + require.NotEqual(t, beforeResource.GetGeneration(), getAndValidateResource(t, resourceClient, id).GetGeneration(), "wanted different version for before and after resources following modification and reconcile") } else { - require.Equal(t, beforeResource.GetGeneration(), getAndValidateResource(t, testClient.ResourceClient, id).GetGeneration(), + require.Equal(t, beforeResource.GetGeneration(), getAndValidateResource(t, resourceClient, id).GetGeneration(), "wanted same version for before and after resources following repeat reconcile") } } @@ -2190,6 +2196,11 @@ func runReconcileCase(t *testing.T, tc reconcileCase) { c.Experiments = []string{"resource-apis"} }) + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) + // Create the Endpoints controller. ep := &Controller{ Client: fakeClient, @@ -2201,6 +2212,8 @@ func runReconcileCase(t *testing.T, tc reconcileCase) { DenyK8sNamespacesSet: mapset.NewSetWith(), }, } + resourceClient, err := consul.NewResourceServiceClient(ep.ConsulServerConnMgr) + require.NoError(t, err) // Default ns and partition if not specified in test. if tc.targetConsulNs == "" { @@ -2213,9 +2226,9 @@ func runReconcileCase(t *testing.T, tc reconcileCase) { // If existing resource specified, create it and ensure it exists. if tc.existingResource != nil { writeReq := &pbresource.WriteRequest{Resource: tc.existingResource} - _, err := testClient.ResourceClient.Write(context.Background(), writeReq) + _, err = resourceClient.Write(context.Background(), writeReq) require.NoError(t, err) - test.ResourceHasPersisted(t, context.Background(), testClient.ResourceClient, tc.existingResource.Id) + test.ResourceHasPersisted(t, context.Background(), resourceClient, tc.existingResource.Id) } // Run actual reconcile and verify results. @@ -2232,10 +2245,10 @@ func runReconcileCase(t *testing.T, tc reconcileCase) { } require.False(t, resp.Requeue) - expectedServiceMatches(t, testClient.ResourceClient, tc.svcName, tc.targetConsulNs, tc.targetConsulPartition, tc.expectedResource) + expectedServiceMatches(t, resourceClient, tc.svcName, tc.targetConsulNs, tc.targetConsulPartition, tc.expectedResource) if tc.caseFn != nil { - tc.caseFn(t, &tc, ep, testClient.ResourceClient) + tc.caseFn(t, &tc, ep, resourceClient) } } diff --git a/control-plane/connect-inject/controllers/pod/pod_controller.go b/control-plane/connect-inject/controllers/pod/pod_controller.go index 12e2c2124d..4cf7580d5c 100644 --- a/control-plane/connect-inject/controllers/pod/pod_controller.go +++ b/control-plane/connect-inject/controllers/pod/pod_controller.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "regexp" + "strconv" "strings" "github.com/go-logr/logr" @@ -149,7 +150,7 @@ func (r *Controller) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu r.Log.Info("retrieved", "name", pod.Name, "ns", pod.Namespace) - if inject.HasBeenMeshInjected(pod) || inject.IsGateway(pod) { + if inject.HasBeenMeshInjected(pod) { // It is possible the pod was scheduled but doesn't have an allocated IP yet, so safely requeue if pod.Status.PodIP == "" { @@ -335,11 +336,9 @@ func (r *Controller) writeWorkload(ctx context.Context, pod corev1.Pod) error { } data := inject.ToProtoAny(workload) - resourceID := getWorkloadID(pod.GetName(), r.getConsulNamespace(pod.Namespace), r.getPartition()) - r.Log.Info("registering workload with Consul", getLogFieldsForResource(resourceID)...) req := &pbresource.WriteRequest{ Resource: &pbresource.Resource{ - Id: resourceID, + Id: getWorkloadID(pod.GetName(), r.getConsulNamespace(pod.Namespace), r.getPartition()), Metadata: metaFromPod(pod), Data: data, }, @@ -618,7 +617,10 @@ func getWorkloadPorts(pod corev1.Pod) ([]string, map[string]*pbcatalog.WorkloadP for _, container := range pod.Spec.Containers { for _, port := range container.Ports { - name := inject.WorkloadPortName(&port) + name := port.Name + if name == "" { + name = strconv.Itoa(int(port.ContainerPort)) + } // TODO: error check reserved "mesh" keyword and 20000 @@ -662,16 +664,10 @@ func parseLocality(node corev1.Node) *pbcatalog.Locality { func metaFromPod(pod corev1.Pod) map[string]string { // TODO: allow custom workload metadata - meta := map[string]string{ + return map[string]string{ constants.MetaKeyKubeNS: pod.GetNamespace(), constants.MetaKeyManagedBy: constants.ManagedByPodValue, } - - if gatewayKind := pod.Annotations[constants.AnnotationGatewayKind]; gatewayKind != "" { - meta[constants.MetaGatewayKind] = gatewayKind - } - - return meta } // getHealthStatusFromPod checks the Pod for a "Ready" condition that is true. @@ -708,6 +704,10 @@ func getWorkloadID(name, namespace, partition string) *pbresource.ID { Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, } } @@ -719,6 +719,10 @@ func getProxyConfigurationID(name, namespace, partition string) *pbresource.ID { Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, } } @@ -730,6 +734,10 @@ func getHealthStatusID(name, namespace, partition string) *pbresource.ID { Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, } } @@ -741,14 +749,10 @@ func getDestinationsID(name, namespace, partition string) *pbresource.ID { Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, - }, - } -} -func getLogFieldsForResource(id *pbresource.ID) []any { - return []any{ - "name", id.Name, - "ns", id.Tenancy.Namespace, - "partition", id.Tenancy.Partition, + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, + }, } } diff --git a/control-plane/connect-inject/controllers/pod/pod_controller_ent_test.go b/control-plane/connect-inject/controllers/pod/pod_controller_ent_test.go index 614526254e..1c074dc940 100644 --- a/control-plane/connect-inject/controllers/pod/pod_controller_ent_test.go +++ b/control-plane/connect-inject/controllers/pod/pod_controller_ent_test.go @@ -8,6 +8,7 @@ package pod import ( "context" "testing" + "time" mapset "github.com/deckarep/golang-set" logrtest "github.com/go-logr/logr/testr" @@ -26,6 +27,7 @@ import ( "github.com/hashicorp/consul-k8s/control-plane/api/common" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/metrics" + "github.com/hashicorp/consul-k8s/control-plane/consul" "github.com/hashicorp/consul-k8s/control-plane/helper/test" ) @@ -99,7 +101,7 @@ func TestReconcileCreatePodWithMirrorNamespaces(t *testing.T) { expectedConsulNamespace: constants.DefaultConsulNS, expectedWorkload: createWorkload(), expectedHealthStatus: createPassingHealthStatus(), - expectedProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + expectedProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), }, { name: "kitchen sink new pod, non-default ns and partition", @@ -125,7 +127,7 @@ func TestReconcileCreatePodWithMirrorNamespaces(t *testing.T) { expectedConsulNamespace: "bar", expectedWorkload: createWorkload(), expectedHealthStatus: createPassingHealthStatus(), - expectedProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + expectedProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), }, { name: "new pod with namespace prefix", @@ -192,7 +194,7 @@ func TestReconcileCreatePodWithMirrorNamespaces(t *testing.T) { expectedConsulNamespace: constants.DefaultConsulNS, expectedWorkload: createWorkload(), expectedHealthStatus: createPassingHealthStatus(), - expectedProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_DEFAULT), + expectedProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_DEFAULT), expectedDestinations: createDestinations(), }, { @@ -271,12 +273,12 @@ func TestReconcileUpdatePodWithMirrorNamespaces(t *testing.T) { existingConsulNamespace: "bar", existingWorkload: createWorkload(), existingHealthStatus: createPassingHealthStatus(), - existingProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + existingProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), expectedConsulNamespace: "bar", expectedWorkload: createWorkload(), expectedHealthStatus: createPassingHealthStatus(), - expectedProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + expectedProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), }, } @@ -309,7 +311,7 @@ func TestReconcileDeletePodWithMirrorNamespaces(t *testing.T) { existingConsulNamespace: "bar", existingWorkload: createWorkload(), existingHealthStatus: createPassingHealthStatus(), - existingProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + existingProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), expectedConsulNamespace: "bar", }, @@ -328,7 +330,7 @@ func TestReconcileDeletePodWithMirrorNamespaces(t *testing.T) { existingConsulNamespace: "bar", existingWorkload: createWorkload(), existingHealthStatus: createPassingHealthStatus(), - existingProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_DEFAULT), + existingProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_DEFAULT), existingDestinations: createDestinations(), expectedConsulNamespace: "bar", @@ -413,7 +415,7 @@ func TestReconcileCreatePodWithDestinationNamespace(t *testing.T) { expectedConsulNamespace: constants.DefaultConsulNS, expectedWorkload: createWorkload(), expectedHealthStatus: createPassingHealthStatus(), - expectedProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + expectedProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), }, { name: "new pod with explicit destinations, ns and partition", @@ -437,7 +439,7 @@ func TestReconcileCreatePodWithDestinationNamespace(t *testing.T) { expectedConsulNamespace: constants.DefaultConsulNS, expectedWorkload: createWorkload(), expectedHealthStatus: createPassingHealthStatus(), - expectedProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_DEFAULT), + expectedProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_DEFAULT), expectedDestinations: createDestinations(), }, { @@ -464,7 +466,7 @@ func TestReconcileCreatePodWithDestinationNamespace(t *testing.T) { expectedConsulNamespace: "a-penguin-walks-into-a-bar", expectedWorkload: createWorkload(), expectedHealthStatus: createPassingHealthStatus(), - expectedProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + expectedProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), }, { name: "namespace in Consul does not exist", @@ -541,12 +543,12 @@ func TestReconcileUpdatePodWithDestinationNamespace(t *testing.T) { existingConsulNamespace: "a-penguin-walks-into-a-bar", existingWorkload: createWorkload(), existingHealthStatus: createPassingHealthStatus(), - existingProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + existingProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), expectedConsulNamespace: "a-penguin-walks-into-a-bar", expectedWorkload: createWorkload(), expectedHealthStatus: createPassingHealthStatus(), - expectedProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + expectedProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), }, } @@ -579,7 +581,7 @@ func TestReconcileDeletePodWithDestinationNamespace(t *testing.T) { existingConsulNamespace: "a-penguin-walks-into-a-bar", existingWorkload: createWorkload(), existingHealthStatus: createPassingHealthStatus(), - existingProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + existingProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), expectedConsulNamespace: "a-penguin-walks-into-a-bar", }, @@ -598,7 +600,7 @@ func TestReconcileDeletePodWithDestinationNamespace(t *testing.T) { existingConsulNamespace: "a-penguin-walks-into-a-bar", existingWorkload: createWorkload(), existingHealthStatus: createPassingHealthStatus(), - existingProxyConfiguration: createProxyConfiguration(testPodName, true, pbmesh.ProxyMode_PROXY_MODE_DEFAULT), + existingProxyConfiguration: createProxyConfiguration(testPodName, pbmesh.ProxyMode_PROXY_MODE_DEFAULT), existingDestinations: createDestinations(), expectedConsulNamespace: "a-penguin-walks-into-a-bar", @@ -670,6 +672,14 @@ func runControllerTest(t *testing.T, tc testCase) { } }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) + // Create the partition in Consul. if tc.partition != "" { testClient.Cfg.APIClientConfig.Partition = tc.partition @@ -730,10 +740,10 @@ func runControllerTest(t *testing.T, tc testCase) { } workloadID := getWorkloadID(tc.podName, tc.expectedConsulNamespace, tc.partition) - loadResource(t, context.Background(), testClient.ResourceClient, workloadID, tc.existingWorkload, nil) - loadResource(t, context.Background(), testClient.ResourceClient, getHealthStatusID(tc.podName, tc.expectedConsulNamespace, tc.partition), tc.existingHealthStatus, workloadID) - loadResource(t, context.Background(), testClient.ResourceClient, getProxyConfigurationID(tc.podName, tc.expectedConsulNamespace, tc.partition), tc.existingProxyConfiguration, nil) - loadResource(t, context.Background(), testClient.ResourceClient, getDestinationsID(tc.podName, tc.expectedConsulNamespace, tc.partition), tc.existingDestinations, nil) + loadResource(t, context.Background(), resourceClient, workloadID, tc.existingWorkload, nil) + loadResource(t, context.Background(), resourceClient, getHealthStatusID(tc.podName, tc.expectedConsulNamespace, tc.partition), tc.existingHealthStatus, workloadID) + loadResource(t, context.Background(), resourceClient, getProxyConfigurationID(tc.podName, tc.expectedConsulNamespace, tc.partition), tc.existingProxyConfiguration, nil) + loadResource(t, context.Background(), resourceClient, getDestinationsID(tc.podName, tc.expectedConsulNamespace, tc.partition), tc.existingDestinations, nil) namespacedName := types.NamespacedName{ Namespace: podNamespace, @@ -752,14 +762,14 @@ func runControllerTest(t *testing.T, tc testCase) { require.Equal(t, tc.expRequeue, resp.Requeue) wID := getWorkloadID(tc.podName, tc.expectedConsulNamespace, tc.partition) - expectedWorkloadMatches(t, context.Background(), testClient.ResourceClient, wID, tc.expectedWorkload) + expectedWorkloadMatches(t, context.Background(), resourceClient, wID, tc.expectedWorkload) hsID := getHealthStatusID(tc.podName, tc.expectedConsulNamespace, tc.partition) - expectedHealthStatusMatches(t, context.Background(), testClient.ResourceClient, hsID, tc.expectedHealthStatus) + expectedHealthStatusMatches(t, context.Background(), resourceClient, hsID, tc.expectedHealthStatus) pcID := getProxyConfigurationID(tc.podName, tc.expectedConsulNamespace, tc.partition) - expectedProxyConfigurationMatches(t, context.Background(), testClient.ResourceClient, pcID, tc.expectedProxyConfiguration) + expectedProxyConfigurationMatches(t, context.Background(), resourceClient, pcID, tc.expectedProxyConfiguration) uID := getDestinationsID(tc.podName, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedDestinationMatches(t, context.Background(), testClient.ResourceClient, uID, tc.expectedDestinations) + expectedDestinationMatches(t, context.Background(), resourceClient, uID, tc.expectedDestinations) } diff --git a/control-plane/connect-inject/controllers/pod/pod_controller_test.go b/control-plane/connect-inject/controllers/pod/pod_controller_test.go index 489010eeb8..413f9ac49a 100644 --- a/control-plane/connect-inject/controllers/pod/pod_controller_test.go +++ b/control-plane/connect-inject/controllers/pod/pod_controller_test.go @@ -36,6 +36,7 @@ import ( "github.com/hashicorp/consul-k8s/control-plane/api/common" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/metrics" + "github.com/hashicorp/consul-k8s/control-plane/consul" "github.com/hashicorp/consul-k8s/control-plane/helper/test" ) @@ -118,6 +119,13 @@ func TestWorkloadWrite(t *testing.T) { testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) // Create the pod controller. pc := &Controller{ @@ -129,16 +137,16 @@ func TestWorkloadWrite(t *testing.T) { AllowK8sNamespacesSet: mapset.NewSetWith("*"), DenyK8sNamespacesSet: mapset.NewSetWith(), }, - ResourceClient: testClient.ResourceClient, + ResourceClient: resourceClient, } - err := pc.writeWorkload(context.Background(), *tc.pod) + err = pc.writeWorkload(context.Background(), *tc.pod) require.NoError(t, err) req := &pbresource.ReadRequest{ Id: getWorkloadID(tc.pod.GetName(), metav1.NamespaceDefault, constants.DefaultConsulPartition), } - actualRes, err := testClient.ResourceClient.Read(context.Background(), req) + actualRes, err := resourceClient.Read(context.Background(), req) require.NoError(t, err) require.NotNil(t, actualRes) @@ -239,14 +247,14 @@ func TestWorkloadWrite(t *testing.T) { }, expectedWorkload: &pbcatalog.Workload{ Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "10.0.0.1", Ports: []string{"cslport-80", "cslport-8080", "mesh"}}, + {Host: "10.0.0.1", Ports: []string{"80", "8080", "mesh"}}, }, Ports: map[string]*pbcatalog.WorkloadPort{ - "cslport-80": { + "80": { Port: 80, Protocol: pbcatalog.Protocol_PROTOCOL_UNSPECIFIED, }, - "cslport-8080": { + "8080": { Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_UNSPECIFIED, }, @@ -302,6 +310,13 @@ func TestWorkloadDelete(t *testing.T) { testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) // Create the pod controller. pc := &Controller{ @@ -313,7 +328,7 @@ func TestWorkloadDelete(t *testing.T) { AllowK8sNamespacesSet: mapset.NewSetWith("*"), DenyK8sNamespacesSet: mapset.NewSetWith(), }, - ResourceClient: testClient.ResourceClient, + ResourceClient: resourceClient, } workload, err := anypb.New(tc.existingWorkload) @@ -327,9 +342,9 @@ func TestWorkloadDelete(t *testing.T) { }, } - _, err = testClient.ResourceClient.Write(context.Background(), writeReq) + _, err = resourceClient.Write(context.Background(), writeReq) require.NoError(t, err) - test.ResourceHasPersisted(t, context.Background(), testClient.ResourceClient, workloadID) + test.ResourceHasPersisted(t, context.Background(), resourceClient, workloadID) reconcileReq := types.NamespacedName{ Namespace: metav1.NamespaceDefault, @@ -341,7 +356,7 @@ func TestWorkloadDelete(t *testing.T) { readReq := &pbresource.ReadRequest{ Id: getWorkloadID(tc.pod.GetName(), metav1.NamespaceDefault, constants.DefaultConsulPartition), } - _, err = testClient.ResourceClient.Read(context.Background(), readReq) + _, err = resourceClient.Read(context.Background(), readReq) require.Error(t, err) s, ok := status.FromError(err) require.True(t, ok) @@ -384,6 +399,13 @@ func TestHealthStatusWrite(t *testing.T) { testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) // Create the pod controller. pc := &Controller{ @@ -395,7 +417,7 @@ func TestHealthStatusWrite(t *testing.T) { AllowK8sNamespacesSet: mapset.NewSetWith("*"), DenyK8sNamespacesSet: mapset.NewSetWith(), }, - ResourceClient: testClient.ResourceClient, + ResourceClient: resourceClient, } // The owner of a resource is validated, so create a dummy workload for the HealthStatus @@ -409,7 +431,7 @@ func TestHealthStatusWrite(t *testing.T) { Data: workloadData, }, } - _, err = testClient.ResourceClient.Write(context.Background(), writeReq) + _, err = resourceClient.Write(context.Background(), writeReq) require.NoError(t, err) // Test writing the pod to a HealthStatus @@ -419,7 +441,7 @@ func TestHealthStatusWrite(t *testing.T) { req := &pbresource.ReadRequest{ Id: getHealthStatusID(tc.pod.GetName(), metav1.NamespaceDefault, constants.DefaultConsulPartition), } - actualRes, err := testClient.ResourceClient.Read(context.Background(), req) + actualRes, err := resourceClient.Read(context.Background(), req) require.NoError(t, err) require.NotNil(t, actualRes) @@ -498,6 +520,13 @@ func TestProxyConfigurationWrite(t *testing.T) { testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) // Create the pod controller. pc := &Controller{ @@ -512,7 +541,7 @@ func TestProxyConfigurationWrite(t *testing.T) { EnableTransparentProxy: tc.tproxy, TProxyOverwriteProbes: tc.overwriteProbes, EnableTelemetryCollector: tc.telemetry, - ResourceClient: testClient.ResourceClient, + ResourceClient: resourceClient, } if tc.metrics { @@ -523,13 +552,13 @@ func TestProxyConfigurationWrite(t *testing.T) { } // Test writing the pod to a HealthStatus - err := pc.writeProxyConfiguration(context.Background(), *tc.pod) + err = pc.writeProxyConfiguration(context.Background(), *tc.pod) require.NoError(t, err) req := &pbresource.ReadRequest{ Id: getProxyConfigurationID(tc.pod.GetName(), metav1.NamespaceDefault, constants.DefaultConsulPartition), } - actualRes, err := testClient.ResourceClient.Read(context.Background(), req) + actualRes, err := resourceClient.Read(context.Background(), req) if tc.expectedProxyConfiguration == nil { require.Error(t, err) @@ -698,6 +727,13 @@ func TestProxyConfigurationDelete(t *testing.T) { testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) // Create the pod controller. pc := &Controller{ @@ -709,7 +745,7 @@ func TestProxyConfigurationDelete(t *testing.T) { AllowK8sNamespacesSet: mapset.NewSetWith("*"), DenyK8sNamespacesSet: mapset.NewSetWith(), }, - ResourceClient: testClient.ResourceClient, + ResourceClient: resourceClient, } // Create the existing ProxyConfiguration @@ -724,9 +760,9 @@ func TestProxyConfigurationDelete(t *testing.T) { }, } - _, err = testClient.ResourceClient.Write(context.Background(), writeReq) + _, err = resourceClient.Write(context.Background(), writeReq) require.NoError(t, err) - test.ResourceHasPersisted(t, context.Background(), testClient.ResourceClient, pcID) + test.ResourceHasPersisted(t, context.Background(), resourceClient, pcID) reconcileReq := types.NamespacedName{ Namespace: metav1.NamespaceDefault, @@ -738,7 +774,7 @@ func TestProxyConfigurationDelete(t *testing.T) { readReq := &pbresource.ReadRequest{ Id: getProxyConfigurationID(tc.pod.GetName(), metav1.NamespaceDefault, constants.DefaultConsulPartition), } - _, err = testClient.ResourceClient.Read(context.Background(), readReq) + _, err = resourceClient.Read(context.Background(), readReq) require.Error(t, err) s, ok := status.FromError(err) require.True(t, ok) @@ -749,7 +785,7 @@ func TestProxyConfigurationDelete(t *testing.T) { { name: "proxy configuration delete", pod: createPod("foo", "", true, true), - existingProxyConfiguration: createProxyConfiguration("foo", true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + existingProxyConfiguration: createProxyConfiguration("foo", pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), }, } @@ -793,6 +829,7 @@ func TestDestinationsWrite(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(""), Namespace: constants.GetNormalizedConsulNamespace(""), + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream1", }, @@ -866,6 +903,7 @@ func TestDestinationsWrite(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: "part1", Namespace: "ns1", + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream1", }, @@ -912,6 +950,7 @@ func TestDestinationsWrite(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(""), Namespace: constants.GetNormalizedConsulNamespace(""), + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream", }, @@ -947,6 +986,7 @@ func TestDestinationsWrite(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: "bar", Namespace: "foo", + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream", }, @@ -971,6 +1011,13 @@ func TestDestinationsWrite(t *testing.T) { testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) pc := &Controller{ Log: logrtest.New(t), @@ -982,17 +1029,17 @@ func TestDestinationsWrite(t *testing.T) { EnableConsulNamespaces: tt.consulNamespacesEnabled, EnableConsulPartitions: tt.consulPartitionsEnabled, }, - ResourceClient: testClient.ResourceClient, + ResourceClient: resourceClient, } - err := pc.writeDestinations(context.Background(), *tt.pod()) + err = pc.writeDestinations(context.Background(), *tt.pod()) if tt.expErr != "" { require.EqualError(t, err, tt.expErr) } else { require.NoError(t, err) uID := getDestinationsID(tt.pod().Name, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedDestinationMatches(t, context.Background(), testClient.ResourceClient, uID, tt.expected) + expectedDestinationMatches(t, context.Background(), resourceClient, uID, tt.expected) } }) } @@ -1029,6 +1076,7 @@ func TestDestinationsDelete(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(""), Namespace: constants.GetNormalizedConsulNamespace(""), + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "upstream1", }, @@ -1051,6 +1099,13 @@ func TestDestinationsDelete(t *testing.T) { testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) pc := &Controller{ Log: logrtest.New(t), @@ -1058,17 +1113,17 @@ func TestDestinationsDelete(t *testing.T) { AllowK8sNamespacesSet: mapset.NewSetWith("*"), DenyK8sNamespacesSet: mapset.NewSetWith(), }, - ResourceClient: testClient.ResourceClient, + ResourceClient: resourceClient, } // Load in the upstream for us to delete and check that it's there - loadResource(t, context.Background(), testClient.ResourceClient, getDestinationsID(tt.pod().Name, constants.DefaultConsulNS, constants.DefaultConsulPartition), tt.existingDestinations, nil) + loadResource(t, context.Background(), resourceClient, getDestinationsID(tt.pod().Name, constants.DefaultConsulNS, constants.DefaultConsulPartition), tt.existingDestinations, nil) uID := getDestinationsID(tt.pod().Name, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedDestinationMatches(t, context.Background(), testClient.ResourceClient, uID, tt.existingDestinations) + expectedDestinationMatches(t, context.Background(), resourceClient, uID, tt.existingDestinations) // Delete the upstream nn := types.NamespacedName{Name: tt.pod().Name} - err := pc.deleteDestinations(context.Background(), nn) + err = pc.deleteDestinations(context.Background(), nn) // Verify the upstream has been deleted or that an expected error has been returned if tt.expErr != "" { @@ -1076,7 +1131,7 @@ func TestDestinationsDelete(t *testing.T) { } else { require.NoError(t, err) uID := getDestinationsID(tt.pod().Name, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedDestinationMatches(t, context.Background(), testClient.ResourceClient, uID, nil) + expectedDestinationMatches(t, context.Background(), resourceClient, uID, nil) } }) } @@ -1095,6 +1150,20 @@ func TestDeleteACLTokens(t *testing.T) { c.ACL.Tokens.InitialManagement = masterToken c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + // Wait for the ACL system to be bootstraped + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.ACL().PolicyList(nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) + + // Wait for the default partition to be created + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) test.SetupK8sAuthMethodV2(t, testClient.APIClient, serviceName, metav1.NamespaceDefault) token, _, err := testClient.APIClient.ACL().Login(&api.ACLLoginParams{ @@ -1113,7 +1182,7 @@ func TestDeleteACLTokens(t *testing.T) { AllowK8sNamespacesSet: mapset.NewSetWith("*"), DenyK8sNamespacesSet: mapset.NewSetWith(), }, - ResourceClient: testClient.ResourceClient, + ResourceClient: resourceClient, AuthMethod: test.AuthMethod, ConsulClientConfig: testClient.Cfg, ConsulServerConnMgr: testClient.Watcher, @@ -1175,6 +1244,13 @@ func TestReconcileCreatePod(t *testing.T) { testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) // Create the pod controller. pc := &Controller{ @@ -1218,21 +1294,21 @@ func TestReconcileCreatePod(t *testing.T) { require.Equal(t, tc.requeue, resp.Requeue) wID := getWorkloadID(tc.podName, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedWorkloadMatches(t, context.Background(), testClient.ResourceClient, wID, tc.expectedWorkload) + expectedWorkloadMatches(t, context.Background(), resourceClient, wID, tc.expectedWorkload) hsID := getHealthStatusID(tc.podName, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedHealthStatusMatches(t, context.Background(), testClient.ResourceClient, hsID, tc.expectedHealthStatus) + expectedHealthStatusMatches(t, context.Background(), resourceClient, hsID, tc.expectedHealthStatus) pcID := getProxyConfigurationID(tc.podName, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedProxyConfigurationMatches(t, context.Background(), testClient.ResourceClient, pcID, tc.expectedProxyConfiguration) + expectedProxyConfigurationMatches(t, context.Background(), resourceClient, pcID, tc.expectedProxyConfiguration) uID := getDestinationsID(tc.podName, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedDestinationMatches(t, context.Background(), testClient.ResourceClient, uID, tc.expectedDestinations) + expectedDestinationMatches(t, context.Background(), resourceClient, uID, tc.expectedDestinations) } testCases := []testCase{ { - name: "vanilla new mesh-injected pod", + name: "vanilla new pod", podName: "foo", k8sObjects: func() []runtime.Object { pod := createPod("foo", "", true, true) @@ -1246,26 +1322,7 @@ func TestReconcileCreatePod(t *testing.T) { overwriteProbes: true, expectedWorkload: createWorkload(), expectedHealthStatus: createPassingHealthStatus(), - expectedProxyConfiguration: createProxyConfiguration("foo", true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), - }, - { - name: "vanilla new gateway pod (not mesh-injected)", - podName: "foo", - k8sObjects: func() []runtime.Object { - pod := createPod("foo", "", false, true) - pod.Annotations[constants.AnnotationGatewayKind] = "mesh-gateway" - pod.Annotations[constants.AnnotationMeshInject] = "false" - pod.Annotations[constants.AnnotationTransparentProxyOverwriteProbes] = "false" - - return []runtime.Object{pod} - }, - tproxy: true, - telemetry: true, - metrics: true, - overwriteProbes: true, - expectedWorkload: createWorkload(), - expectedHealthStatus: createPassingHealthStatus(), - expectedProxyConfiguration: createProxyConfiguration("foo", false, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + expectedProxyConfiguration: createProxyConfiguration("foo", pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), }, { name: "pod in ignored namespace", @@ -1323,7 +1380,7 @@ func TestReconcileCreatePod(t *testing.T) { overwriteProbes: true, expectedWorkload: createWorkload(), expectedHealthStatus: createPassingHealthStatus(), - expectedProxyConfiguration: createProxyConfiguration("foo", true, pbmesh.ProxyMode_PROXY_MODE_DEFAULT), + expectedProxyConfiguration: createProxyConfiguration("foo", pbmesh.ProxyMode_PROXY_MODE_DEFAULT), expectedDestinations: createDestinations(), }, { @@ -1398,6 +1455,13 @@ func TestReconcileUpdatePod(t *testing.T) { testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) // Create the pod controller. pc := &Controller{ @@ -1426,10 +1490,10 @@ func TestReconcileUpdatePod(t *testing.T) { } workloadID := getWorkloadID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition) - loadResource(t, context.Background(), testClient.ResourceClient, workloadID, tc.existingWorkload, nil) - loadResource(t, context.Background(), testClient.ResourceClient, getHealthStatusID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tc.existingHealthStatus, workloadID) - loadResource(t, context.Background(), testClient.ResourceClient, getProxyConfigurationID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tc.existingProxyConfiguration, nil) - loadResource(t, context.Background(), testClient.ResourceClient, getDestinationsID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tc.existingDestinations, nil) + loadResource(t, context.Background(), resourceClient, workloadID, tc.existingWorkload, nil) + loadResource(t, context.Background(), resourceClient, getHealthStatusID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tc.existingHealthStatus, workloadID) + loadResource(t, context.Background(), resourceClient, getProxyConfigurationID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tc.existingProxyConfiguration, nil) + loadResource(t, context.Background(), resourceClient, getDestinationsID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tc.existingDestinations, nil) namespacedName := types.NamespacedName{ Namespace: namespace, @@ -1447,16 +1511,16 @@ func TestReconcileUpdatePod(t *testing.T) { require.False(t, resp.Requeue) wID := getWorkloadID(tc.podName, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedWorkloadMatches(t, context.Background(), testClient.ResourceClient, wID, tc.expectedWorkload) + expectedWorkloadMatches(t, context.Background(), resourceClient, wID, tc.expectedWorkload) hsID := getHealthStatusID(tc.podName, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedHealthStatusMatches(t, context.Background(), testClient.ResourceClient, hsID, tc.expectedHealthStatus) + expectedHealthStatusMatches(t, context.Background(), resourceClient, hsID, tc.expectedHealthStatus) pcID := getProxyConfigurationID(tc.podName, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedProxyConfigurationMatches(t, context.Background(), testClient.ResourceClient, pcID, tc.expectedProxyConfiguration) + expectedProxyConfigurationMatches(t, context.Background(), resourceClient, pcID, tc.expectedProxyConfiguration) uID := getDestinationsID(tc.podName, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedDestinationMatches(t, context.Background(), testClient.ResourceClient, uID, tc.expectedDestinations) + expectedDestinationMatches(t, context.Background(), resourceClient, uID, tc.expectedDestinations) } testCases := []testCase{ @@ -1572,6 +1636,7 @@ func TestReconcileUpdatePod(t *testing.T) { Tenancy: &pbresource.Tenancy{ Partition: "ap1", Namespace: "ns1", + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "mySVC3", }, @@ -1652,6 +1717,16 @@ func TestReconcileDeletePod(t *testing.T) { } c.Experiments = []string{"resource-apis"} }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) + + if tc.aclsEnabled { + // Wait for the ACL system to be bootstraped + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.ACL().PolicyList(nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) + } ctx := context.Background() if tc.aclsEnabled { @@ -1685,13 +1760,12 @@ func TestReconcileDeletePod(t *testing.T) { } workloadID := getWorkloadID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition) - loadResource(t, ctx, testClient.ResourceClient, workloadID, tc.existingWorkload, nil) - loadResource(t, ctx, testClient.ResourceClient, getHealthStatusID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tc.existingHealthStatus, workloadID) - loadResource(t, ctx, testClient.ResourceClient, getProxyConfigurationID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tc.existingProxyConfiguration, nil) - loadResource(t, ctx, testClient.ResourceClient, getDestinationsID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tc.existingDestinations, nil) + loadResource(t, ctx, resourceClient, workloadID, tc.existingWorkload, nil) + loadResource(t, ctx, resourceClient, getHealthStatusID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tc.existingHealthStatus, workloadID) + loadResource(t, ctx, resourceClient, getProxyConfigurationID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tc.existingProxyConfiguration, nil) + loadResource(t, ctx, resourceClient, getDestinationsID(tc.podName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tc.existingDestinations, nil) var token *api.ACLToken - var err error if tc.aclsEnabled { test.SetupK8sAuthMethodV2(t, testClient.APIClient, tc.podName, metav1.NamespaceDefault) //podName is a standin for the service name token, _, err = testClient.APIClient.ACL().Login(&api.ACLLoginParams{ @@ -1729,16 +1803,16 @@ func TestReconcileDeletePod(t *testing.T) { require.False(t, resp.Requeue) wID := getWorkloadID(tc.podName, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedWorkloadMatches(t, ctx, testClient.ResourceClient, wID, tc.expectedWorkload) + expectedWorkloadMatches(t, ctx, resourceClient, wID, tc.expectedWorkload) hsID := getHealthStatusID(tc.podName, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedHealthStatusMatches(t, ctx, testClient.ResourceClient, hsID, tc.expectedHealthStatus) + expectedHealthStatusMatches(t, ctx, resourceClient, hsID, tc.expectedHealthStatus) pcID := getProxyConfigurationID(tc.podName, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedProxyConfigurationMatches(t, ctx, testClient.ResourceClient, pcID, tc.expectedProxyConfiguration) + expectedProxyConfigurationMatches(t, ctx, resourceClient, pcID, tc.expectedProxyConfiguration) uID := getDestinationsID(tc.podName, metav1.NamespaceDefault, constants.DefaultConsulPartition) - expectedDestinationMatches(t, ctx, testClient.ResourceClient, uID, tc.expectedDestinations) + expectedDestinationMatches(t, ctx, resourceClient, uID, tc.expectedDestinations) if tc.aclsEnabled { _, _, err = testClient.APIClient.ACL().TokenRead(token.AccessorID, nil) @@ -1753,14 +1827,14 @@ func TestReconcileDeletePod(t *testing.T) { podName: "foo", existingWorkload: createWorkload(), existingHealthStatus: createPassingHealthStatus(), - existingProxyConfiguration: createProxyConfiguration("foo", true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + existingProxyConfiguration: createProxyConfiguration("foo", pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), }, { name: "annotated delete pod", podName: "foo", existingWorkload: createWorkload(), existingHealthStatus: createPassingHealthStatus(), - existingProxyConfiguration: createProxyConfiguration("foo", true, pbmesh.ProxyMode_PROXY_MODE_DEFAULT), + existingProxyConfiguration: createProxyConfiguration("foo", pbmesh.ProxyMode_PROXY_MODE_DEFAULT), existingDestinations: createDestinations(), }, { @@ -1768,7 +1842,7 @@ func TestReconcileDeletePod(t *testing.T) { podName: "foo", existingWorkload: createWorkload(), existingHealthStatus: createPassingHealthStatus(), - existingProxyConfiguration: createProxyConfiguration("foo", true, pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), + existingProxyConfiguration: createProxyConfiguration("foo", pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT), aclsEnabled: true, }, } @@ -1915,14 +1989,32 @@ func createCriticalHealthStatus(name string, namespace string) *pbcatalog.Health // createProxyConfiguration creates a proxyConfiguration that matches the pod from createPod, // assuming that metrics, telemetry, and overwrite probes are enabled separately. -func createProxyConfiguration(podName string, overwriteProbes bool, mode pbmesh.ProxyMode) *pbmesh.ProxyConfiguration { +func createProxyConfiguration(podName string, mode pbmesh.ProxyMode) *pbmesh.ProxyConfiguration { mesh := &pbmesh.ProxyConfiguration{ Workloads: &pbcatalog.WorkloadSelector{ Names: []string{podName}, }, DynamicConfig: &pbmesh.DynamicConfig{ - Mode: mode, - ExposeConfig: nil, + Mode: mode, + ExposeConfig: &pbmesh.ExposeConfig{ + ExposePaths: []*pbmesh.ExposePath{ + { + ListenerPort: 20400, + LocalPathPort: 2001, + Path: "/livez", + }, + { + ListenerPort: 20300, + LocalPathPort: 2000, + Path: "/readyz", + }, + { + ListenerPort: 20500, + LocalPathPort: 2002, + Path: "/startupz", + }, + }, + }, }, BootstrapConfig: &pbmesh.BootstrapConfig{ PrometheusBindAddr: "0.0.0.0:1234", @@ -1930,28 +2022,6 @@ func createProxyConfiguration(podName string, overwriteProbes bool, mode pbmesh. }, } - if overwriteProbes { - mesh.DynamicConfig.ExposeConfig = &pbmesh.ExposeConfig{ - ExposePaths: []*pbmesh.ExposePath{ - { - ListenerPort: 20400, - LocalPathPort: 2001, - Path: "/livez", - }, - { - ListenerPort: 20300, - LocalPathPort: 2000, - Path: "/readyz", - }, - { - ListenerPort: 20500, - LocalPathPort: 2002, - Path: "/startupz", - }, - }, - } - } - if mode == pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT { mesh.DynamicConfig.TransparentProxy = &pbmesh.TransparentProxy{ OutboundListenerPort: 15001, @@ -1974,6 +2044,7 @@ func createDestinations() *pbmesh.Destinations { Tenancy: &pbresource.Tenancy{ Partition: constants.GetNormalizedConsulPartition(""), Namespace: constants.GetNormalizedConsulNamespace(""), + PeerName: constants.GetNormalizedConsulPeer(""), }, Name: "mySVC", }, diff --git a/control-plane/connect-inject/controllers/serviceaccount/serviceaccount_controller.go b/control-plane/connect-inject/controllers/serviceaccount/serviceaccount_controller.go index 98e5c949c5..8027995ac9 100644 --- a/control-plane/connect-inject/controllers/serviceaccount/serviceaccount_controller.go +++ b/control-plane/connect-inject/controllers/serviceaccount/serviceaccount_controller.go @@ -155,6 +155,9 @@ func getWorkloadIdentityID(name, namespace, partition string) *pbresource.ID { Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, } } diff --git a/control-plane/connect-inject/controllers/serviceaccount/serviceaccount_controller_test.go b/control-plane/connect-inject/controllers/serviceaccount/serviceaccount_controller_test.go index 27bb909d2c..d2ea94c22d 100644 --- a/control-plane/connect-inject/controllers/serviceaccount/serviceaccount_controller_test.go +++ b/control-plane/connect-inject/controllers/serviceaccount/serviceaccount_controller_test.go @@ -6,6 +6,7 @@ package serviceaccount import ( "context" "testing" + "time" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" @@ -29,6 +30,7 @@ import ( "github.com/hashicorp/consul-k8s/control-plane/api/common" inject "github.com/hashicorp/consul-k8s/control-plane/connect-inject/common" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" + "github.com/hashicorp/consul-k8s/control-plane/consul" "github.com/hashicorp/consul-k8s/control-plane/helper/test" ) @@ -224,6 +226,13 @@ func runReconcileCase(t *testing.T, tc reconcileCase) { DenyK8sNamespacesSet: mapset.NewSetWith(), }, } + resourceClient, err := consul.NewResourceServiceClient(sa.ConsulServerConnMgr) + require.NoError(t, err) + + require.Eventually(t, func() bool { + _, _, err := testClient.APIClient.Partitions().Read(context.Background(), constants.DefaultConsulPartition, nil) + return err == nil + }, 5*time.Second, 500*time.Millisecond) // Default ns and partition if not specified in test. if tc.targetConsulNs == "" { @@ -236,9 +245,9 @@ func runReconcileCase(t *testing.T, tc reconcileCase) { // If existing resource specified, create it and ensure it exists. if tc.existingResource != nil { writeReq := &pbresource.WriteRequest{Resource: tc.existingResource} - _, err := testClient.ResourceClient.Write(context.Background(), writeReq) + _, err = resourceClient.Write(context.Background(), writeReq) require.NoError(t, err) - test.ResourceHasPersisted(t, context.Background(), testClient.ResourceClient, tc.existingResource.Id) + test.ResourceHasPersisted(t, context.Background(), resourceClient, tc.existingResource.Id) } // Run actual reconcile and verify results. @@ -255,7 +264,7 @@ func runReconcileCase(t *testing.T, tc reconcileCase) { } require.False(t, resp.Requeue) - expectedWorkloadIdentityMatches(t, testClient.ResourceClient, tc.svcAccountName, tc.targetConsulNs, tc.targetConsulPartition, tc.expectedResource) + expectedWorkloadIdentityMatches(t, resourceClient, tc.svcAccountName, tc.targetConsulNs, tc.targetConsulPartition, tc.expectedResource) } func expectedWorkloadIdentityMatches(t *testing.T, client pbresource.ResourceServiceClient, name, namespace, partition string, expectedResource *pbresource.Resource) { diff --git a/control-plane/connect-inject/webhook/container_init.go b/control-plane/connect-inject/webhook/container_init.go index 2626b03689..effee89150 100644 --- a/control-plane/connect-inject/webhook/container_init.go +++ b/control-plane/connect-inject/webhook/container_init.go @@ -155,15 +155,15 @@ func (w *MeshWebhook) containerInit(namespace corev1.Namespace, pod corev1.Pod, if w.TLSEnabled { container.Env = append(container.Env, corev1.EnvVar{ - Name: constants.UseTLSEnvVar, + Name: "CONSUL_USE_TLS", Value: "true", }, corev1.EnvVar{ - Name: constants.CACertPEMEnvVar, + Name: "CONSUL_CACERT_PEM", Value: w.ConsulCACert, }, corev1.EnvVar{ - Name: constants.TLSServerNameEnvVar, + Name: "CONSUL_TLS_SERVER_NAME", Value: w.ConsulTLSServerName, }) } diff --git a/control-plane/connect-inject/webhookv2/container_init.go b/control-plane/connect-inject/webhookv2/container_init.go index 7afcaefd33..f393c5ebe0 100644 --- a/control-plane/connect-inject/webhookv2/container_init.go +++ b/control-plane/connect-inject/webhookv2/container_init.go @@ -124,15 +124,15 @@ func (w *MeshWebhook) containerInit(namespace corev1.Namespace, pod corev1.Pod) if w.TLSEnabled { container.Env = append(container.Env, corev1.EnvVar{ - Name: constants.UseTLSEnvVar, + Name: "CONSUL_USE_TLS", Value: "true", }, corev1.EnvVar{ - Name: constants.CACertPEMEnvVar, + Name: "CONSUL_CACERT_PEM", Value: w.ConsulCACert, }, corev1.EnvVar{ - Name: constants.TLSServerNameEnvVar, + Name: "CONSUL_TLS_SERVER_NAME", Value: w.ConsulTLSServerName, }) } diff --git a/control-plane/connect-inject/webhookv2/mesh_webhook.go b/control-plane/connect-inject/webhookv2/mesh_webhook.go index 590608bce7..839b3fd4ab 100644 --- a/control-plane/connect-inject/webhookv2/mesh_webhook.go +++ b/control-plane/connect-inject/webhookv2/mesh_webhook.go @@ -10,7 +10,6 @@ import ( "fmt" "net/http" "strconv" - "strings" mapset "github.com/deckarep/golang-set" "github.com/go-logr/logr" @@ -252,16 +251,6 @@ func (w *MeshWebhook) Handle(ctx context.Context, req admission.Request) admissi w.Log.Info("received pod", "name", req.Name, "ns", req.Namespace) - // Validate that none of the pod ports start with the prefix "cslport-" as that may result in conflicts with ports - // created by the pod controller when creating workloads. - for _, c := range pod.Spec.Containers { - for _, p := range c.Ports { - if strings.HasPrefix(p.Name, constants.UnnamedWorkloadPortNamePrefix) { - return admission.Errored(http.StatusInternalServerError, fmt.Errorf("error creating pod: port names cannot be prefixed with \"cslport-\" as that prefix is reserved")) - } - } - } - // Add our volume that will be shared by the init container and // the sidecar for passing data in the pod. pod.Spec.Volumes = append(pod.Spec.Volumes, w.containerVolume()) diff --git a/control-plane/connect-inject/webhookv2/mesh_webhook_test.go b/control-plane/connect-inject/webhookv2/mesh_webhook_test.go index 8bb6dc7a2f..ee68db5c14 100644 --- a/control-plane/connect-inject/webhookv2/mesh_webhook_test.go +++ b/control-plane/connect-inject/webhookv2/mesh_webhook_test.go @@ -1164,115 +1164,6 @@ func TestHandlerHandle_ValidateOverwriteProbes(t *testing.T) { } } -func TestHandlerValidatePorts(t *testing.T) { - cases := []struct { - Name string - Pod *corev1.Pod - Err string - }{ - { - "basic pod, with ports", - &corev1.Pod{ - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "web", - Ports: []corev1.ContainerPort{ - { - Name: "http", - ContainerPort: 8080, - }, - }, - }, - { - Name: "web-side", - }, - }, - }, - }, - "", - }, - { - "basic pod, with unnamed ports", - &corev1.Pod{ - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "web", - Ports: []corev1.ContainerPort{ - { - ContainerPort: 8080, - }, - }, - }, - { - Name: "web-side", - }, - }, - }, - }, - "", - }, - { - "basic pod, with invalid prefix name", - &corev1.Pod{ - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "web", - Ports: []corev1.ContainerPort{ - { - Name: "cslport-8080", - ContainerPort: 8080, - }, - }, - }, - { - Name: "web-side", - }, - }, - }, - }, - "error creating pod: port names cannot be prefixed with \"cslport-\" as that prefix is reserved", - }, - } - for _, tt := range cases { - t.Run(tt.Name, func(t *testing.T) { - s := runtime.NewScheme() - s.AddKnownTypes(schema.GroupVersion{ - Group: "", - Version: "v1", - }, &corev1.Pod{}) - decoder, err := admission.NewDecoder(s) - require.NoError(t, err) - - w := MeshWebhook{ - Log: logrtest.New(t), - AllowK8sNamespacesSet: mapset.NewSetWith("*"), - DenyK8sNamespacesSet: mapset.NewSet(), - EnableTransparentProxy: true, - TProxyOverwriteProbes: true, - decoder: decoder, - ConsulConfig: &consul.Config{HTTPPort: 8500}, - Clientset: defaultTestClientWithNamespace(), - } - req := admission.Request{ - AdmissionRequest: admissionv1.AdmissionRequest{ - Namespace: namespaces.DefaultNamespace, - Object: encodeRaw(t, tt.Pod), - }, - } - resp := w.Handle(context.Background(), req) - if tt.Err == "" { - require.True(t, resp.Allowed) - } else { - require.False(t, resp.Allowed) - require.Contains(t, resp.Result.Message, tt.Err) - } - - }) - } -} func TestHandlerDefaultAnnotations(t *testing.T) { cases := []struct { Name string diff --git a/control-plane/consul/dataplane_client_test.go b/control-plane/consul/dataplane_client_test.go index 233000cee8..9463839dda 100644 --- a/control-plane/consul/dataplane_client_test.go +++ b/control-plane/consul/dataplane_client_test.go @@ -116,6 +116,7 @@ func createWorkload(t *testing.T, watcher ServerConnectionManager, name string) Tenancy: &pbresource.Tenancy{ Partition: "default", Namespace: "default", + PeerName: "local", }, } @@ -156,6 +157,7 @@ func createProxyConfiguration(t *testing.T, watcher ServerConnectionManager, nam Tenancy: &pbresource.Tenancy{ Partition: "default", Namespace: "default", + PeerName: "local", }, } diff --git a/control-plane/consul/resource_client_test.go b/control-plane/consul/resource_client_test.go index f1d28b27da..0dbecc9798 100644 --- a/control-plane/consul/resource_client_test.go +++ b/control-plane/consul/resource_client_test.go @@ -100,6 +100,7 @@ func createWriteRequest(t *testing.T, name string) *pbresource.WriteRequest { Tenancy: &pbresource.Tenancy{ Namespace: constants.DefaultConsulNS, Partition: constants.DefaultConsulPartition, + PeerName: constants.DefaultConsulPeer, }, }, Data: proto, diff --git a/control-plane/controllers/resources/api-gateway-controller.go b/control-plane/controllers/resources/api-gateway-controller.go deleted file mode 100644 index 87333beb6f..0000000000 --- a/control-plane/controllers/resources/api-gateway-controller.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package resources - -import ( - "context" - - "github.com/go-logr/logr" - k8serr "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - "github.com/hashicorp/consul-k8s/control-plane/gateways" -) - -// APIGatewayController reconciles a APIGateway object. -type APIGatewayController struct { - client.Client - Log logr.Logger - Scheme *runtime.Scheme - Controller *ConsulResourceController - GatewayConfig gateways.GatewayConfig -} - -// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=tcproute,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=tcproute/status,verbs=get;update;patch - -func (r *APIGatewayController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - logger := r.Logger(req.NamespacedName) - logger.Info("Reconciling APIGateway") - - resource := &meshv2beta1.APIGateway{} - if err := r.Get(ctx, req.NamespacedName, resource); k8serr.IsNotFound(err) { - return ctrl.Result{}, client.IgnoreNotFound(err) - } else if err != nil { - logger.Error(err, "retrieving resource") - return ctrl.Result{}, err - } - - // Call hooks - if !resource.GetDeletionTimestamp().IsZero() { - logger.Info("deletion event") - - if err := onDelete(ctx, req, r.Client, resource); err != nil { - return ctrl.Result{}, err - } - } else { - // Fetch GatewayClassConfig for the gateway - if resource.Namespace == "" { - resource.Namespace = "default" - } - - gcc, err := getGatewayClassConfigByGatewayClassName(ctx, r.Client, resource.Spec.GatewayClassName) - if err != nil { - r.Log.Error(err, "unable to get gatewayclassconfig for gateway: %s gatewayclass: %s", resource.Name, resource.Spec.GatewayClassName) - return ctrl.Result{}, err - } - - if err := onCreateUpdate(ctx, r.Client, gatewayConfigs{ - gcc: gcc, - gatewayConfig: r.GatewayConfig, - }, resource, gateways.APIGatewayAnnotationKind); err != nil { - logger.Error(err, "unable to create/update gateway") - return ctrl.Result{}, err - } - } - - return r.Controller.ReconcileResource(ctx, r, req, &meshv2beta1.APIGateway{}) -} - -func (r *APIGatewayController) Logger(name types.NamespacedName) logr.Logger { - return r.Log.WithValues("request", name) -} - -func (r *APIGatewayController) UpdateStatus(ctx context.Context, obj client.Object, opts ...client.SubResourceUpdateOption) error { - return r.Status().Update(ctx, obj, opts...) -} - -func (r *APIGatewayController) SetupWithManager(mgr ctrl.Manager) error { - return setupGatewayControllerWithManager[*meshv2beta1.APIGatewayList](mgr, &meshv2beta1.APIGateway{}, r.Client, r, APIGateway_GatewayClassIndex) -} diff --git a/control-plane/controllers/resources/api-gateway-controller_test.go b/control-plane/controllers/resources/api-gateway-controller_test.go deleted file mode 100644 index 6b907647ec..0000000000 --- a/control-plane/controllers/resources/api-gateway-controller_test.go +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package resources - -import ( - "context" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" - "github.com/hashicorp/consul-k8s/control-plane/helper/test" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/testing/protocmp" - - logrtest "github.com/go-logr/logr/testr" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client/fake" -) - -func TestAPIGatewayController_ReconcileResourceExists(t *testing.T) { - t.Parallel() - ctx := context.Background() - - s := runtime.NewScheme() - require.NoError(t, corev1.AddToScheme(s)) - require.NoError(t, appsv1.AddToScheme(s)) - require.NoError(t, rbacv1.AddToScheme(s)) - require.NoError(t, v2beta1.AddMeshToScheme(s)) - s.AddKnownTypes( - schema.GroupVersion{ - Group: "mesh.consul.hashicorp.com", - Version: pbmesh.Version, - }, - &v2beta1.APIGateway{}, - &v2beta1.GatewayClass{}, - &v2beta1.GatewayClassConfig{}, - ) - - apiGW := &v2beta1.APIGateway{ - ObjectMeta: metav1.ObjectMeta{ - Name: "api-gateway", - Namespace: metav1.NamespaceDefault, - }, - Spec: pbmesh.APIGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.APIGatewayListener{ - { - Name: "http-listener", - Port: 9090, - Protocol: "http", - }, - }, - }, - } - - fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(apiGW).Build() - - testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { - c.Experiments = []string{"resource-apis"} - }) - - gwCtrl := APIGatewayController{ - Client: fakeClient, - Log: logrtest.New(t), - Scheme: s, - Controller: &ConsulResourceController{ - ConsulClientConfig: testClient.Cfg, - ConsulServerConnMgr: testClient.Watcher, - }, - } - - // ensure the resource is not in consul yet - { - req := &pbresource.ReadRequest{Id: apiGW.ResourceID(constants.DefaultConsulNS, constants.DefaultConsulPartition)} - _, err := testClient.ResourceClient.Read(ctx, req) - require.Error(t, err) - } - - // now reconcile the resource - { - namespacedName := types.NamespacedName{ - Namespace: metav1.NamespaceDefault, - Name: apiGW.KubernetesName(), - } - - // First get it, so we have the latest revision number. - err := fakeClient.Get(ctx, namespacedName, apiGW) - require.NoError(t, err) - - resp, err := gwCtrl.Reconcile(ctx, ctrl.Request{ - NamespacedName: namespacedName, - }) - - require.NoError(t, err) - require.False(t, resp.Requeue) - } - - // now check that the object in Consul is as expected. - { - expectedResource := &pbmesh.APIGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.APIGatewayListener{ - { - Name: "http-listener", - Port: 9090, - Protocol: "http", - }, - }, - } - req := &pbresource.ReadRequest{Id: apiGW.ResourceID(constants.DefaultConsulNS, constants.DefaultConsulPartition)} - res, err := testClient.ResourceClient.Read(ctx, req) - require.NoError(t, err) - require.NotNil(t, res) - require.Equal(t, apiGW.GetName(), res.GetResource().GetId().GetName()) - - data := res.GetResource().Data - actual := &pbmesh.APIGateway{} - require.NoError(t, data.UnmarshalTo(actual)) - - opts := append([]cmp.Option{protocmp.IgnoreFields(&pbresource.Resource{}, "status", "generation", "version")}, test.CmpProtoIgnoreOrder()...) - diff := cmp.Diff(expectedResource, actual, opts...) - require.Equal(t, "", diff, "APIGateway does not match") - } -} - -func TestAPIGatewayController_ReconcileAPIGWDoesNotExistInK8s(t *testing.T) { - t.Parallel() - ctx := context.Background() - - s := runtime.NewScheme() - s.AddKnownTypes(schema.GroupVersion{ - Group: "mesh.consul.hashicorp.com", - Version: pbmesh.Version, - }, &v2beta1.APIGateway{}, &v2beta1.APIGatewayList{}) - - fakeClient := fake.NewClientBuilder().WithScheme(s).Build() - - testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { - c.Experiments = []string{"resource-apis"} - }) - - gwCtrl := APIGatewayController{ - Client: fakeClient, - Log: logrtest.New(t), - Scheme: s, - Controller: &ConsulResourceController{ - ConsulClientConfig: testClient.Cfg, - ConsulServerConnMgr: testClient.Watcher, - }, - } - - // now reconcile the resource - { - namespacedName := types.NamespacedName{ - Namespace: metav1.NamespaceDefault, - Name: "api-gateway", - } - - resp, err := gwCtrl.Reconcile(ctx, ctrl.Request{ - NamespacedName: namespacedName, - }) - - require.NoError(t, err) - require.False(t, resp.Requeue) - require.Equal(t, ctrl.Result{}, resp) - } - - // ensure the resource is not in consul - { - req := &pbresource.ReadRequest{Id: &pbresource.ID{ - Name: "api-gateway", - Type: pbmesh.APIGatewayType, - Tenancy: &pbresource.Tenancy{ - Namespace: constants.DefaultConsulNS, - Partition: constants.DefaultConsulPartition, - }, - }} - - _, err := testClient.ResourceClient.Read(ctx, req) - require.Error(t, err) - } -} diff --git a/control-plane/controllers/resources/consul_resource_controller_ent_test.go b/control-plane/controllers/resources/consul_resource_controller_ent_test.go deleted file mode 100644 index 56cb6c9b49..0000000000 --- a/control-plane/controllers/resources/consul_resource_controller_ent_test.go +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -//go:build enterprise - -package resources - -import ( - "context" - "testing" - - "github.com/go-logr/logr" - logrtest "github.com/go-logr/logr/testr" - "github.com/google/go-cmp/cmp" - "github.com/hashicorp/consul-k8s/control-plane/api/auth/v2beta1" - "github.com/hashicorp/consul-k8s/control-plane/api/common" - "github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1" - "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" - "github.com/hashicorp/consul-k8s/control-plane/consul" - "github.com/hashicorp/consul-k8s/control-plane/helper/test" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/testing/protocmp" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" -) - -// TestConsulResourceController_UpdatesConsulResourceEnt tests is a mirror of the CE test which also tests the -// enterprise traffic permissions deny action. -func TestConsulResourceController_UpdatesConsulResourceEnt(t *testing.T) { - t.Parallel() - - cases := []struct { - name string - resource common.ConsulResource - expected *pbauth.TrafficPermissions - reconciler func(client.Client, *consul.Config, consul.ServerConnectionManager, logr.Logger) testReconciler - updateF func(config common.ConsulResource) - unmarshal func(t *testing.T, consul *pbresource.Resource) proto.Message - }{ - { - name: "TrafficPermissions", - resource: &v2beta1.TrafficPermissions{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-traffic-permission", - Namespace: metav1.NamespaceDefault, - }, - Spec: pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "destination-identity", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Namespace: "the space namespace space", - }, - { - IdentityName: "source-identity", - }, - }, - // TODO: enable this when L7 traffic permissions are supported - //DestinationRules: []*pbauth.DestinationRule{ - // { - // PathExact: "/hello", - // Methods: []string{"GET", "POST"}, - // PortNames: []string{"web", "admin"}, - // }, - //}, - }, - }, - }, - }, - expected: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "destination-identity", - }, - Action: pbauth.Action_ACTION_DENY, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Namespace: "the space namespace space", - Partition: common.DefaultConsulPartition, - Peer: constants.DefaultConsulPeer, - }, - }, - //DestinationRules: []*pbauth.DestinationRule{ - // { - // PathExact: "/hello", - // Methods: []string{"GET", "POST"}, - // PortNames: []string{"web", "admin"}, - // }, - //}, - }, - }, - }, - reconciler: func(client client.Client, cfg *consul.Config, watcher consul.ServerConnectionManager, logger logr.Logger) testReconciler { - return &TrafficPermissionsController{ - Client: client, - Log: logger, - Controller: &ConsulResourceController{ - ConsulClientConfig: cfg, - ConsulServerConnMgr: watcher, - }, - } - }, - updateF: func(resource common.ConsulResource) { - trafficPermissions := resource.(*v2beta1.TrafficPermissions) - trafficPermissions.Spec.Action = pbauth.Action_ACTION_DENY - trafficPermissions.Spec.Permissions[0].Sources = trafficPermissions.Spec.Permissions[0].Sources[:1] - }, - unmarshal: func(t *testing.T, resource *pbresource.Resource) proto.Message { - data := resource.Data - - trafficPermission := &pbauth.TrafficPermissions{} - require.NoError(t, data.UnmarshalTo(trafficPermission)) - return trafficPermission - }, - }, - } - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - ctx := context.Background() - - s := runtime.NewScheme() - s.AddKnownTypes(v1alpha1.GroupVersion, c.resource) - fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(c.resource).Build() - - testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { - c.Experiments = []string{"resource-apis"} - }) - - // We haven't run reconcile yet, so we must create the resource - // in Consul ourselves. - { - resource := c.resource.Resource(constants.DefaultConsulNS, constants.DefaultConsulPartition) - req := &pbresource.WriteRequest{Resource: resource} - _, err := testClient.ResourceClient.Write(ctx, req) - require.NoError(t, err) - } - - // Now run reconcile which should update the entry in Consul. - { - namespacedName := types.NamespacedName{ - Namespace: metav1.NamespaceDefault, - Name: c.resource.KubernetesName(), - } - // First get it, so we have the latest revision number. - err := fakeClient.Get(ctx, namespacedName, c.resource) - require.NoError(t, err) - - // Update the entry in Kube and run reconcile. - c.updateF(c.resource) - err = fakeClient.Update(ctx, c.resource) - require.NoError(t, err) - r := c.reconciler(fakeClient, testClient.Cfg, testClient.Watcher, logrtest.New(t)) - resp, err := r.Reconcile(ctx, ctrl.Request{ - NamespacedName: namespacedName, - }) - require.NoError(t, err) - require.False(t, resp.Requeue) - - // Now check that the object in Consul is as expected. - req := &pbresource.ReadRequest{Id: c.resource.ResourceID(constants.DefaultConsulNS, constants.DefaultConsulPartition)} - res, err := testClient.ResourceClient.Read(ctx, req) - require.NoError(t, err) - require.NotNil(t, res) - require.Equal(t, c.resource.GetName(), res.GetResource().GetId().GetName()) - - actual := c.unmarshal(t, res.GetResource()) - opts := append([]cmp.Option{protocmp.IgnoreFields(&pbresource.Resource{}, "status", "generation", "version")}, test.CmpProtoIgnoreOrder()...) - diff := cmp.Diff(c.expected, actual, opts...) - require.Equal(t, "", diff, "TrafficPermissions do not match") - } - }) - } -} diff --git a/control-plane/controllers/resources/exported_services_controller.go b/control-plane/controllers/resources/exported_services_controller.go deleted file mode 100644 index 9690942194..0000000000 --- a/control-plane/controllers/resources/exported_services_controller.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package resources - -import ( - "context" - - "github.com/go-logr/logr" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - multiclusterv2 "github.com/hashicorp/consul-k8s/control-plane/api/multicluster/v2" - "github.com/hashicorp/consul-k8s/control-plane/gateways" -) - -// ExportedServicesController reconciles a MeshGateway object. -type ExportedServicesController struct { - client.Client - Log logr.Logger - Scheme *runtime.Scheme - Controller *ConsulResourceController - GatewayConfig gateways.GatewayConfig -} - -// +kubebuilder:rbac:groups=multicluster.consul.hashicorp.com,resources=exportedservices,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=multicluster.consul.hashicorp.com,resources=exportedservices/status,verbs=get;update;patch - -func (r *ExportedServicesController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - return r.Controller.ReconcileResource(ctx, r, req, &multiclusterv2.ExportedServices{}) -} - -func (r *ExportedServicesController) Logger(name types.NamespacedName) logr.Logger { - return r.Log.WithValues("request", name) -} - -func (r *ExportedServicesController) UpdateStatus(ctx context.Context, obj client.Object, opts ...client.SubResourceUpdateOption) error { - return r.Status().Update(ctx, obj, opts...) -} - -func (r *ExportedServicesController) SetupWithManager(mgr ctrl.Manager) error { - return setupWithManager(mgr, &multiclusterv2.ExportedServices{}, r) -} diff --git a/control-plane/controllers/resources/gateway_class_config_controller.go b/control-plane/controllers/resources/gateway_class_config_controller.go deleted file mode 100644 index 22084bbc56..0000000000 --- a/control-plane/controllers/resources/gateway_class_config_controller.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package resources - -import ( - "context" - - "github.com/go-logr/logr" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" -) - -// GatewayClassConfigController reconciles a GatewayClassConfig object. -type GatewayClassConfigController struct { - client.Client - Log logr.Logger - Scheme *runtime.Scheme - Controller *ConsulResourceController -} - -// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=gatewayclassconfig,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=gatewayclassconfig/status,verbs=get;update;patch - -func (r *GatewayClassConfigController) Reconcile(_ context.Context, _ ctrl.Request) (ctrl.Result, error) { - // GatewayClassConfig is not synced into Consul because Consul has no use for it. - // Consul is only aware of the resource for the sake of Kubernetes CRD generation. - return ctrl.Result{}, nil -} - -func (r *GatewayClassConfigController) Logger(name types.NamespacedName) logr.Logger { - return r.Log.WithValues("request", name) -} - -func (r *GatewayClassConfigController) UpdateStatus(ctx context.Context, obj client.Object, opts ...client.SubResourceUpdateOption) error { - return r.Status().Update(ctx, obj, opts...) -} - -func (r *GatewayClassConfigController) SetupWithManager(mgr ctrl.Manager) error { - return setupWithManager(mgr, &meshv2beta1.GatewayClassConfig{}, r) -} diff --git a/control-plane/controllers/resources/gateway_class_controller.go b/control-plane/controllers/resources/gateway_class_controller.go deleted file mode 100644 index 5f2bc91ebe..0000000000 --- a/control-plane/controllers/resources/gateway_class_controller.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package resources - -import ( - "context" - - "github.com/go-logr/logr" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" -) - -// GatewayClassController reconciles a MeshGateway object. -type GatewayClassController struct { - client.Client - Log logr.Logger - Scheme *runtime.Scheme - Controller *ConsulResourceController -} - -// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=gatewayclass,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=gatewayclass/status,verbs=get;update;patch - -func (r *GatewayClassController) Reconcile(_ context.Context, _ ctrl.Request) (ctrl.Result, error) { - // GatewayClass is not synced into Consul because Consul has no use for it. - // Consul is only aware of the resource for the sake of Kubernetes CRD generation. - return ctrl.Result{}, nil -} - -func (r *GatewayClassController) Logger(name types.NamespacedName) logr.Logger { - return r.Log.WithValues("request", name) -} - -func (r *GatewayClassController) UpdateStatus(ctx context.Context, obj client.Object, opts ...client.SubResourceUpdateOption) error { - return r.Status().Update(ctx, obj, opts...) -} - -func (r *GatewayClassController) SetupWithManager(mgr ctrl.Manager) error { - return setupWithManager(mgr, &meshv2beta1.GatewayClass{}, r) -} diff --git a/control-plane/controllers/resources/gateway_controller_crud.go b/control-plane/controllers/resources/gateway_controller_crud.go deleted file mode 100644 index a2eae79811..0000000000 --- a/control-plane/controllers/resources/gateway_controller_crud.go +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package resources - -import ( - "context" - "fmt" - - "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - "github.com/hashicorp/consul-k8s/control-plane/gateways" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - k8serr "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" -) - -type gatewayConfigs struct { - gcc *meshv2beta1.GatewayClassConfig - gatewayConfig gateways.GatewayConfig -} - -// onCreateUpdate is responsible for creating/updating all K8s resources that -// are required in order to run a meshv2beta1.XGateway. These are created/updated -// in dependency order. -// 1. ServiceAccount -// 2. Deployment -// 3. Service -// 4. Role -// 5. RoleBinding -func onCreateUpdate[T gateways.Gateway](ctx context.Context, k8sClient client.Client, cfg gatewayConfigs, resource T, gatewayKind string) error { - builder := gateways.NewGatewayBuilder[T](resource, cfg.gatewayConfig, cfg.gcc, gatewayKind) - - // Create ServiceAccount - desiredAccount := builder.ServiceAccount() - existingAccount := &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Namespace: desiredAccount.Namespace, Name: desiredAccount.Name}} - - upsertOp := func(ctx context.Context, _, object client.Object) error { - _, err := controllerutil.CreateOrUpdate(ctx, k8sClient, object, func() error { return nil }) - return err - } - - err := opIfNewOrOwned(ctx, resource, k8sClient, existingAccount, desiredAccount, upsertOp) - if err != nil { - return fmt.Errorf("unable to create service account: %w", err) - } - - // Create Role - desiredRole := builder.Role() - existingRole := &rbacv1.Role{ObjectMeta: metav1.ObjectMeta{Namespace: desiredRole.Namespace, Name: desiredRole.Name}} - - err = opIfNewOrOwned(ctx, resource, k8sClient, existingRole, desiredRole, upsertOp) - if err != nil { - return fmt.Errorf("unable to create role: %w", err) - } - - // Create RoleBinding - desiredBinding := builder.RoleBinding() - existingBinding := &rbacv1.RoleBinding{ObjectMeta: metav1.ObjectMeta{Namespace: desiredBinding.Namespace, Name: desiredBinding.Name}} - - err = opIfNewOrOwned(ctx, resource, k8sClient, existingBinding, desiredBinding, upsertOp) - if err != nil { - return fmt.Errorf("unable to create role binding: %w", err) - } - - // Create Service - desiredService := builder.Service() - existingService := &corev1.Service{ObjectMeta: metav1.ObjectMeta{Namespace: desiredService.Namespace, Name: desiredService.Name}} - - mergeServiceOp := func(ctx context.Context, existingObj, desiredObj client.Object) error { - existing := existingObj.(*corev1.Service) - desired := desiredObj.(*corev1.Service) - - _, err := controllerutil.CreateOrUpdate(ctx, k8sClient, existing, func() error { - gateways.MergeService(existing, desired) - return nil - }) - return err - } - - err = opIfNewOrOwned(ctx, resource, k8sClient, existingService, desiredService, mergeServiceOp) - if err != nil { - return fmt.Errorf("unable to create service: %w", err) - } - - // Create Deployment - desiredDeployment, err := builder.Deployment() - if err != nil { - return fmt.Errorf("unable to create deployment: %w", err) - } - existingDeployment := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Namespace: desiredDeployment.Namespace, Name: desiredDeployment.Name}} - - mergeDeploymentOp := func(ctx context.Context, existingObj, desiredObj client.Object) error { - existing := existingObj.(*appsv1.Deployment) - desired := desiredObj.(*appsv1.Deployment) - - _, err = controllerutil.CreateOrUpdate(ctx, k8sClient, existing, func() error { - gateways.MergeDeployment(existing, desired) - return nil - }) - return err - } - - err = opIfNewOrOwned(ctx, resource, k8sClient, existingDeployment, desiredDeployment, mergeDeploymentOp) - if err != nil { - return fmt.Errorf("unable to create deployment: %w", err) - } - - return nil -} - -// onDelete is responsible for cleaning up any side effects of onCreateUpdate. -// We only clean up side effects because all resources that we create explicitly -// have an owner reference and will thus be cleaned up by the K8s garbage collector -// once the owning meshv2beta1.XGateway is deleted. -func onDelete[T gateways.Gateway](ctx context.Context, req ctrl.Request, k8sClient client.Client, resource T) error { - // TODO NET-6392 NET-6393 - return nil -} - -// ownedObjectOp represents an operation that needs to be applied -// only if the newObject does not yet exist or if the existingObject -// has an owner reference pointing to the XGateway being reconciled. -// -// The existing and new object are available in case any merging needs -// to occur, such as unknown annotations and values from the existing object -// that need to be carried forward onto the new object. -type ownedObjectOp func(ctx context.Context, existing, desired client.Object) error - -// opIfNewOrOwned runs a given ownedObjectOp to create, update, or delete a resource. -// The purpose of opIfNewOrOwned is to ensure that we aren't updating or deleting a -// resource that was not created by us. If this scenario is encountered, we error. -func opIfNewOrOwned(ctx context.Context, gateway client.Object, k8sClient client.Client, existing, desired client.Object, op ownedObjectOp) error { - // Ensure owner reference is always set on objects that we write - if err := ctrl.SetControllerReference(gateway, desired, k8sClient.Scheme()); err != nil { - return err - } - - key := client.ObjectKey{ - Namespace: existing.GetNamespace(), - Name: existing.GetName(), - } - - exists := false - if err := k8sClient.Get(ctx, key, existing); err != nil { - // We failed to fetch the object in a way that doesn't tell us about its existence - if !k8serr.IsNotFound(err) { - return err - } - } else { - // We successfully fetched the object, so it exists - exists = true - } - - // None exists, so we need only execute the operation - if !exists { - return op(ctx, existing, desired) - } - - // Ensure the existing object was put there by us so that we don't overwrite random objects - owned := false - for _, reference := range existing.GetOwnerReferences() { - if reference.UID == gateway.GetUID() && reference.Name == gateway.GetName() { - owned = true - break - } - } - if !owned { - return errResourceNotOwned - } - return op(ctx, existing, desired) -} - -func getGatewayClassConfigByGatewayClassName(ctx context.Context, k8sClient client.Client, className string) (*meshv2beta1.GatewayClassConfig, error) { - gatewayClass, err := getGatewayClassByName(ctx, k8sClient, className) - if err != nil { - return nil, err - } - - if gatewayClass == nil { - return nil, nil - } - - gatewayClassConfig := &meshv2beta1.GatewayClassConfig{} - if ref := gatewayClass.Spec.ParametersRef; ref != nil { - if ref.Group != meshv2beta1.MeshGroup || ref.Kind != v2beta1.KindGatewayClassConfig { - // TODO @Gateway-Management additionally check for controller name when available - return nil, nil - } - - if err := k8sClient.Get(ctx, types.NamespacedName{Name: ref.Name}, gatewayClassConfig); err != nil { - return nil, client.IgnoreNotFound(err) - } - } - return gatewayClassConfig, nil -} - -func getGatewayClassByName(ctx context.Context, k8sClient client.Client, className string) (*meshv2beta1.GatewayClass, error) { - var gatewayClass meshv2beta1.GatewayClass - - if err := k8sClient.Get(ctx, types.NamespacedName{Name: className}, &gatewayClass); err != nil { - return nil, client.IgnoreNotFound(err) - } - return &gatewayClass, nil -} diff --git a/control-plane/controllers/resources/gateway_controller_setup.go b/control-plane/controllers/resources/gateway_controller_setup.go deleted file mode 100644 index 43f120a23c..0000000000 --- a/control-plane/controllers/resources/gateway_controller_setup.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package resources - -import ( - "context" - - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - "k8s.io/apimachinery/pkg/fields" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/source" -) - -type gatewayList interface { - *meshv2beta1.MeshGatewayList | *meshv2beta1.APIGatewayList - client.ObjectList - ReconcileRequests() []reconcile.Request -} - -func setupGatewayControllerWithManager[L gatewayList](mgr ctrl.Manager, obj client.Object, k8sClient client.Client, gwc reconcile.Reconciler, index indexName) error { - return ctrl.NewControllerManagedBy(mgr). - For(obj). - Owns(&appsv1.Deployment{}). - Owns(&rbacv1.Role{}). - Owns(&rbacv1.RoleBinding{}). - Owns(&corev1.Service{}). - Owns(&corev1.ServiceAccount{}). - Watches( - source.NewKindWithCache(&meshv2beta1.GatewayClass{}, mgr.GetCache()), - handler.EnqueueRequestsFromMapFunc(func(o client.Object) []reconcile.Request { - gc := o.(*meshv2beta1.GatewayClass) - if gc == nil { - return nil - } - - gateways, err := getGatewaysReferencingGatewayClass[L](context.Background(), k8sClient, gc.Name, index) - if err != nil { - return nil - } - - return gateways.ReconcileRequests() - })). - Watches( - source.NewKindWithCache(&meshv2beta1.GatewayClassConfig{}, mgr.GetCache()), - handler.EnqueueRequestsFromMapFunc(func(o client.Object) []reconcile.Request { - gcc := o.(*meshv2beta1.GatewayClassConfig) - if gcc == nil { - return nil - } - - classes, err := getGatewayClassesReferencingGatewayClassConfig(context.Background(), k8sClient, gcc.Name) - if err != nil { - return nil - } - - var requests []reconcile.Request - for _, class := range classes.Items { - if class == nil { - continue - } - - gateways, err := getGatewaysReferencingGatewayClass[L](context.Background(), k8sClient, class.Name, index) - if err != nil { - continue - } - - requests = append(requests, gateways.ReconcileRequests()...) - } - - return requests - })). - Complete(gwc) -} - -// getGatewayClassesReferencingGatewayClassConfig queries all GatewayClass resources in the -// cluster and returns any that reference the given GatewayClassConfig by name. -func getGatewayClassesReferencingGatewayClassConfig(ctx context.Context, k8sClient client.Client, configName string) (*meshv2beta1.GatewayClassList, error) { - allClasses := &meshv2beta1.GatewayClassList{} - if err := k8sClient.List(ctx, allClasses, &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(string(GatewayClass_GatewayClassConfigIndex), configName), - }); err != nil { - return nil, client.IgnoreNotFound(err) - } - - return allClasses, nil -} - -// getGatewaysReferencingGatewayClass queries all xGateway resources in the cluster -// and returns any that reference the given GatewayClass by name. -func getGatewaysReferencingGatewayClass[T gatewayList](ctx context.Context, k8sClient client.Client, className string, index indexName) (T, error) { - var allGateways T - if err := k8sClient.List(ctx, allGateways, &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(string(index), className), - }); err != nil { - return nil, client.IgnoreNotFound(err) - } - - return allGateways, nil -} diff --git a/control-plane/controllers/resources/gateway_indices.go b/control-plane/controllers/resources/gateway_indices.go deleted file mode 100644 index 29e221d191..0000000000 --- a/control-plane/controllers/resources/gateway_indices.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package resources - -import ( - "context" - - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" -) - -type indexName string - -const ( - // Naming convention: TARGET_REFERENCE. - GatewayClass_GatewayClassConfigIndex indexName = "__v2_gatewayclass_referencing_gatewayclassconfig" - - APIGateway_GatewayClassIndex indexName = "__v2_api_gateway_referencing_gatewayclass" - MeshGateway_GatewayClassIndex indexName = "__v2_mesh_gateway_referencing_gatewayclass" -) - -// RegisterGatewayFieldIndexes registers all of the field indexes for the xGateway controllers. -// These indexes are similar to indexes used in databases to speed up queries. -// They allow us to quickly find objects based on a field value. -func RegisterGatewayFieldIndexes(ctx context.Context, mgr ctrl.Manager) error { - for _, index := range indexes { - if err := mgr.GetFieldIndexer().IndexField(ctx, index.target, string(index.name), index.indexerFunc); err != nil { - return err - } - } - return nil -} - -type index struct { - name indexName - target client.Object - indexerFunc client.IndexerFunc -} - -var indexes = []index{ - { - name: GatewayClass_GatewayClassConfigIndex, - target: &meshv2beta1.GatewayClass{}, - indexerFunc: func(o client.Object) []string { - gc := o.(*meshv2beta1.GatewayClass) - - pr := gc.Spec.ParametersRef - if pr != nil && pr.Kind == v2beta1.KindGatewayClassConfig { - return []string{pr.Name} - } - - return []string{} - }, - }, - { - name: APIGateway_GatewayClassIndex, - target: &meshv2beta1.APIGateway{}, - indexerFunc: func(o client.Object) []string { - g := o.(*meshv2beta1.APIGateway) - return []string{string(g.Spec.GatewayClassName)} - }, - }, - { - name: MeshGateway_GatewayClassIndex, - target: &meshv2beta1.MeshGateway{}, - indexerFunc: func(o client.Object) []string { - g := o.(*meshv2beta1.MeshGateway) - return []string{string(g.Spec.GatewayClassName)} - }, - }, -} diff --git a/control-plane/controllers/resources/mesh_configuration_controller.go b/control-plane/controllers/resources/mesh_configuration_controller.go deleted file mode 100644 index d5813294e9..0000000000 --- a/control-plane/controllers/resources/mesh_configuration_controller.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package resources - -import ( - "context" - - "github.com/go-logr/logr" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" -) - -// MeshConfigurationController reconciles a MeshConfiguration object. -type MeshConfigurationController struct { - client.Client - Log logr.Logger - Scheme *runtime.Scheme - Controller *ConsulResourceController -} - -// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=meshconfiguration,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=meshconfiguration/status,verbs=get;update;patch - -func (r *MeshConfigurationController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - return r.Controller.ReconcileResource(ctx, r, req, &meshv2beta1.MeshConfiguration{}) -} - -func (r *MeshConfigurationController) Logger(name types.NamespacedName) logr.Logger { - return r.Log.WithValues("request", name) -} - -func (r *MeshConfigurationController) UpdateStatus(ctx context.Context, obj client.Object, opts ...client.SubResourceUpdateOption) error { - return r.Status().Update(ctx, obj, opts...) -} - -func (r *MeshConfigurationController) SetupWithManager(mgr ctrl.Manager) error { - return setupWithManager(mgr, &meshv2beta1.MeshConfiguration{}, r) -} diff --git a/control-plane/controllers/resources/mesh_gateway_controller.go b/control-plane/controllers/resources/mesh_gateway_controller.go deleted file mode 100644 index 71bd4e3d46..0000000000 --- a/control-plane/controllers/resources/mesh_gateway_controller.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package resources - -import ( - "context" - "errors" - - "github.com/go-logr/logr" - k8serr "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - "github.com/hashicorp/consul-k8s/control-plane/gateways" -) - -// errResourceNotOwned indicates that a resource the controller would have -// updated or deleted does not have an owner reference pointing to the MeshGateway. -var errResourceNotOwned = errors.New("existing resource not owned by controller") - -// MeshGatewayController reconciles a MeshGateway object. -type MeshGatewayController struct { - client.Client - Log logr.Logger - Scheme *runtime.Scheme - Controller *ConsulResourceController - GatewayConfig gateways.GatewayConfig -} - -// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=meshgateway,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=meshgateway/status,verbs=get;update;patch - -func (r *MeshGatewayController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - logger := r.Logger(req.NamespacedName) - - // Fetch the resource being reconciled - resource := &meshv2beta1.MeshGateway{} - if err := r.Get(ctx, req.NamespacedName, resource); k8serr.IsNotFound(err) { - return ctrl.Result{}, client.IgnoreNotFound(err) - } else if err != nil { - logger.Error(err, "retrieving resource") - return ctrl.Result{}, err - } - - // Call hooks - if !resource.GetDeletionTimestamp().IsZero() { - logger.Info("deletion event") - - if err := onDelete(ctx, req, r.Client, resource); err != nil { - return ctrl.Result{}, err - } - } else { - // Fetch GatewayClassConfig for the gateway - gcc, err := getGatewayClassConfigByGatewayClassName(ctx, r.Client, resource.Spec.GatewayClassName) - if err != nil { - r.Log.Error(err, "unable to get gatewayclassconfig for gateway: %s gatewayclass: %s", resource.Name, resource.Spec.GatewayClassName) - return ctrl.Result{}, err - } - - if err := onCreateUpdate(ctx, r.Client, gatewayConfigs{ - gcc: gcc, - gatewayConfig: r.GatewayConfig, - }, resource, gateways.MeshGatewayAnnotationKind); err != nil { - return ctrl.Result{}, err - } - } - - return r.Controller.ReconcileResource(ctx, r, req, &meshv2beta1.MeshGateway{}) -} - -func (r *MeshGatewayController) Logger(name types.NamespacedName) logr.Logger { - return r.Log.WithValues("request", name) -} - -func (r *MeshGatewayController) UpdateStatus(ctx context.Context, obj client.Object, opts ...client.SubResourceUpdateOption) error { - return r.Status().Update(ctx, obj, opts...) -} - -func (r *MeshGatewayController) SetupWithManager(mgr ctrl.Manager) error { - return setupGatewayControllerWithManager[*meshv2beta1.MeshGatewayList](mgr, &meshv2beta1.MeshGateway{}, r.Client, r, MeshGateway_GatewayClassIndex) -} diff --git a/control-plane/controllers/resources/mesh_gateway_controller_test.go b/control-plane/controllers/resources/mesh_gateway_controller_test.go deleted file mode 100644 index 63f38624f0..0000000000 --- a/control-plane/controllers/resources/mesh_gateway_controller_test.go +++ /dev/null @@ -1,601 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package resources - -import ( - "context" - "testing" - - logrtest "github.com/go-logr/logr/testr" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/sdk/testutil" - - "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - "github.com/hashicorp/consul-k8s/control-plane/helper/test" -) - -func TestMeshGatewayController_Reconcile(t *testing.T) { - t.Parallel() - - testCases := []struct { - name string - // k8sObjects is the list of Kubernetes resources that will be present in the cluster at runtime - k8sObjects []runtime.Object - // request is the request that will be provided to MeshGatewayController.Reconcile - request ctrl.Request - // expectedErr is the error we expect MeshGatewayController.Reconcile to return - expectedErr error - // expectedResult is the result we expect MeshGatewayController.Reconcile to return - expectedResult ctrl.Result - // postReconcile runs some set of assertions on the state of k8s after Reconcile is called - postReconcile func(*testing.T, client.Client) - }{ - // ServiceAccount - { - name: "MeshGateway created with no existing ServiceAccount", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "consul", - Name: "mesh-gateway", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "consul", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - postReconcile: func(t *testing.T, c client.Client) { - // Verify ServiceAccount was created - key := client.ObjectKey{Namespace: "consul", Name: "mesh-gateway"} - assert.NoError(t, c.Get(context.Background(), key, &corev1.ServiceAccount{})) - }, - }, - { - name: "MeshGateway created with existing ServiceAccount not owned by gateway", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - &corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - expectedErr: errResourceNotOwned, - }, - // Role - { - name: "MeshGateway created with no existing Role", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "consul", - Name: "mesh-gateway", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "consul", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - postReconcile: func(t *testing.T, c client.Client) { - // Verify Role was created - key := client.ObjectKey{Namespace: "consul", Name: "mesh-gateway"} - assert.NoError(t, c.Get(context.Background(), key, &rbacv1.Role{})) - }, - }, - { - name: "MeshGateway created with existing Role not owned by gateway", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - expectedErr: errResourceNotOwned, - }, - { - name: "MeshGateway created with existing Role owned by gateway", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - UID: "abc123", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - OwnerReferences: []metav1.OwnerReference{ - { - UID: "abc123", - Name: "mesh-gateway", - }, - }, - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - expectedErr: nil, // The Reconcile should be a no-op - }, - // RoleBinding - { - name: "MeshGateway created with no existing RoleBinding", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "consul", - Name: "mesh-gateway", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "consul", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - postReconcile: func(t *testing.T, c client.Client) { - // Verify RoleBinding was created - key := client.ObjectKey{Namespace: "consul", Name: "mesh-gateway"} - assert.NoError(t, c.Get(context.Background(), key, &rbacv1.RoleBinding{})) - }, - }, - { - name: "MeshGateway created with existing RoleBinding not owned by gateway", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - expectedErr: errResourceNotOwned, - }, - { - name: "MeshGateway created with existing RoleBinding owned by gateway", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - UID: "abc123", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - OwnerReferences: []metav1.OwnerReference{ - { - UID: "abc123", - Name: "mesh-gateway", - }, - }, - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - expectedErr: nil, // The Reconcile should be a no-op - }, - // Deployment - { - name: "MeshGateway created with no existing Deployment", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "consul", - Name: "mesh-gateway", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "consul", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - postReconcile: func(t *testing.T, c client.Client) { - // Verify Deployment was created - key := client.ObjectKey{Namespace: "consul", Name: "mesh-gateway"} - assert.NoError(t, c.Get(context.Background(), key, &appsv1.Deployment{})) - }, - }, - { - name: "MeshGateway created with existing Deployment not owned by gateway", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - expectedErr: errResourceNotOwned, - }, - { - name: "MeshGateway created with existing Deployment owned by gateway", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - UID: "abc123", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - OwnerReferences: []metav1.OwnerReference{ - { - UID: "abc123", - Name: "mesh-gateway", - }, - }, - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - expectedErr: nil, // The Reconcile should be a no-op - }, - // Service - { - name: "MeshGateway created with no existing Service", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "consul", - Name: "mesh-gateway", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "consul", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - postReconcile: func(t *testing.T, c client.Client) { - // Verify Service was created - key := client.ObjectKey{Namespace: "consul", Name: "mesh-gateway"} - assert.NoError(t, c.Get(context.Background(), key, &corev1.Service{})) - }, - }, - { - name: "MeshGateway created with existing Service not owned by gateway", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - expectedErr: errResourceNotOwned, - }, - { - name: "MeshGateway created with existing Service owned by gateway", - k8sObjects: []runtime.Object{ - &v2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - UID: "abc123", - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "consul", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 8443, - Protocol: "tcp", - }, - }, - }, - }, - &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - OwnerReferences: []metav1.OwnerReference{ - { - UID: "abc123", - Name: "mesh-gateway", - }, - }, - }, - }, - }, - request: ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, - expectedResult: ctrl.Result{}, - expectedErr: nil, // The Reconcile should be a no-op - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - consulClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { - c.Experiments = []string{"resource-apis"} - }) - - s := runtime.NewScheme() - require.NoError(t, corev1.AddToScheme(s)) - require.NoError(t, appsv1.AddToScheme(s)) - require.NoError(t, rbacv1.AddToScheme(s)) - require.NoError(t, v2beta1.AddMeshToScheme(s)) - s.AddKnownTypes(v2beta1.MeshGroupVersion, &v2beta1.MeshGateway{}, &v2beta1.GatewayClass{}, &v2beta1.GatewayClassConfig{}) - fakeClient := fake.NewClientBuilder().WithScheme(s). - WithRuntimeObjects(testCase.k8sObjects...). - Build() - - controller := MeshGatewayController{ - Client: fakeClient, - Log: logrtest.New(t), - Scheme: s, - Controller: &ConsulResourceController{ - ConsulClientConfig: consulClient.Cfg, - ConsulServerConnMgr: consulClient.Watcher, - }, - } - - res, err := controller.Reconcile(context.Background(), testCase.request) - if testCase.expectedErr != nil { - // require.EqualError(t, err, testCase.expectedErr.Error()) - require.ErrorIs(t, err, testCase.expectedErr) - } else { - require.NoError(t, err) - } - assert.Equal(t, testCase.expectedResult, res) - - if testCase.postReconcile != nil { - testCase.postReconcile(t, fakeClient) - } - }) - } -} diff --git a/control-plane/gateways/builder.go b/control-plane/gateways/builder.go deleted file mode 100644 index 35e8384b3f..0000000000 --- a/control-plane/gateways/builder.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -import ( - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - corev1 "k8s.io/api/core/v1" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -type Gateway interface { - *meshv2beta1.MeshGateway | *meshv2beta1.APIGateway - client.Object - ListenersToServicePorts(int32) []corev1.ServicePort - ListenersToContainerPorts(int32, int32) []corev1.ContainerPort -} - -// gatewayBuilder is a helper struct for building the Kubernetes resources for a mesh gateway. -// This includes Deployment, Role, Service, and ServiceAccount resources. -// Configuration is combined from the MeshGateway, GatewayConfig, and GatewayClassConfig. -type gatewayBuilder[T Gateway] struct { - gateway T - gcc *meshv2beta1.GatewayClassConfig - config GatewayConfig - gatewayKind string -} - -// NewGatewayBuilder returns a new meshGatewayBuilder for the given MeshGateway, -// GatewayConfig, and GatewayClassConfig. -func NewGatewayBuilder[T Gateway](gateway T, gatewayConfig GatewayConfig, gatewayClassConfig *meshv2beta1.GatewayClassConfig, gatewayKind string) *gatewayBuilder[T] { - return &gatewayBuilder[T]{ - gateway: gateway, - config: gatewayConfig, - gcc: gatewayClassConfig, - gatewayKind: gatewayKind, - } -} diff --git a/control-plane/gateways/constants.go b/control-plane/gateways/constants.go deleted file mode 100644 index ac0242bd2d..0000000000 --- a/control-plane/gateways/constants.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -const ( - // General environment variables. - envPodName = "POD_NAME" - envPodNamespace = "POD_NAMESPACE" - envNodeName = "NODE_NAME" - envTmpDir = "TMPDIR" - - // Dataplane Configuration Environment variables. - envDPProxyId = "DP_PROXY_ID" - envDPCredentialLoginMeta = "DP_CREDENTIAL_LOGIN_META" - - // Init Container Configuration Environment variables. - envConsulAddresses = "CONSUL_ADDRESSES" - envConsulGRPCPort = "CONSUL_GRPC_PORT" - envConsulHTTPPort = "CONSUL_HTTP_PORT" - envConsulAPITimeout = "CONSUL_API_TIMEOUT" - envConsulNodeName = "CONSUL_NODE_NAME" - envConsulLoginAuthMethod = "CONSUL_LOGIN_AUTH_METHOD" - envConsulLoginBearerTokenFile = "CONSUL_LOGIN_BEARER_TOKEN_FILE" - envConsulLoginMeta = "CONSUL_LOGIN_META" - envConsulLoginPartition = "CONSUL_LOGIN_PARTITION" - envConsulNamespace = "CONSUL_NAMESPACE" - envConsulPartition = "CONSUL_PARTITION" - - // defaultBearerTokenFile is the default location where the init container will store the bearer token for the dataplane container to read. - defaultBearerTokenFile = "/var/run/secrets/kubernetes.io/serviceaccount/token" -) diff --git a/control-plane/gateways/deployment.go b/control-plane/gateways/deployment.go deleted file mode 100644 index 5bab84dec8..0000000000 --- a/control-plane/gateways/deployment.go +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -import ( - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/pointer" - - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" -) - -const ( - globalDefaultInstances int32 = 1 - MeshGatewayAnnotationKind = "mesh-gateway" - APIGatewayAnnotationKind = "api-gateway" -) - -func (b *gatewayBuilder[T]) Deployment() (*appsv1.Deployment, error) { - spec, err := b.deploymentSpec() - return &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: b.gateway.GetName(), - Namespace: b.gateway.GetNamespace(), - Labels: b.labelsForDeployment(), - Annotations: b.annotationsForDeployment(), - }, - Spec: *spec, - }, err -} - -func (b *gatewayBuilder[T]) deploymentSpec() (*appsv1.DeploymentSpec, error) { - var ( - deploymentConfig meshv2beta1.GatewayClassDeploymentConfig - containerConfig meshv2beta1.GatewayClassContainerConfig - ) - - // If GatewayClassConfig is not nil, use it to override the defaults for - // the deployment and container configs. - if b.gcc != nil { - deploymentConfig = b.gcc.Spec.Deployment - if deploymentConfig.Container != nil { - containerConfig = *b.gcc.Spec.Deployment.Container - } - } - - initContainer, err := b.initContainer() - if err != nil { - return nil, err - } - - container, err := b.consulDataplaneContainer(containerConfig) - if err != nil { - return nil, err - } - - return &appsv1.DeploymentSpec{ - Replicas: deploymentReplicaCount(deploymentConfig.Replicas, nil), - Selector: &metav1.LabelSelector{ - MatchLabels: b.labelsForDeployment(), - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: b.labelsForDeployment(), - Annotations: map[string]string{ - // Indicate that this pod is a mesh gateway pod so that the Pod controller, - // consul-k8s CLI, etc. can key off of it - constants.AnnotationGatewayKind: b.gatewayKind, - // It's not logical to add a proxy sidecar since our workload is itself a proxy - constants.AnnotationMeshInject: "false", - // This functionality only applies when proxy sidecars are used - constants.AnnotationTransparentProxyOverwriteProbes: "false", - // This annotation determines which source to use to set the - // WAN address and WAN port for the Mesh Gateway service registration. - constants.AnnotationGatewayWANSource: b.gateway.GetAnnotations()[constants.AnnotationGatewayWANSource], - // This annotation determines the WAN port for the Mesh Gateway service registration. - constants.AnnotationGatewayWANPort: b.gateway.GetAnnotations()[constants.AnnotationGatewayWANPort], - // This annotation determines the address for the gateway when the source annotation is "Static". - constants.AnnotationGatewayWANAddress: b.gateway.GetAnnotations()[constants.AnnotationGatewayWANAddress], - }, - }, - Spec: corev1.PodSpec{ - Volumes: []corev1.Volume{ - { - Name: volumeName, - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{Medium: corev1.StorageMediumMemory}, - }, - }, - }, - InitContainers: []corev1.Container{ - initContainer, - }, - Containers: []corev1.Container{ - container, - }, - Affinity: deploymentConfig.Affinity, - NodeSelector: deploymentConfig.NodeSelector, - PriorityClassName: deploymentConfig.PriorityClassName, - TopologySpreadConstraints: deploymentConfig.TopologySpreadConstraints, - HostNetwork: deploymentConfig.HostNetwork, - Tolerations: deploymentConfig.Tolerations, - ServiceAccountName: b.serviceAccountName(), - DNSPolicy: deploymentConfig.DNSPolicy, - }, - }, - }, nil -} - -// areDeploymentsEqual determines whether two Deployments are the same in -// the ways that we care about. This specifically ignores valid out-of-band -// changes such as initContainer injection. -func areDeploymentsEqual(a, b *appsv1.Deployment) bool { - // since K8s adds a bunch of defaults when we create a deployment, check that - // they don't differ by the things that we may actually change, namely container - // ports - if len(b.Spec.Template.Spec.Containers) != len(a.Spec.Template.Spec.Containers) { - return false - } - for i, container := range a.Spec.Template.Spec.Containers { - otherPorts := b.Spec.Template.Spec.Containers[i].Ports - if len(container.Ports) != len(otherPorts) { - return false - } - for j, port := range container.Ports { - otherPort := otherPorts[j] - if port.ContainerPort != otherPort.ContainerPort { - return false - } - if port.Protocol != otherPort.Protocol { - return false - } - } - } - - if b.Spec.Replicas == nil && a.Spec.Replicas == nil { - return true - } else if b.Spec.Replicas == nil { - return false - } else if a.Spec.Replicas == nil { - return false - } - - return *b.Spec.Replicas == *a.Spec.Replicas -} - -func deploymentReplicaCount(replicas *meshv2beta1.GatewayClassReplicasConfig, currentReplicas *int32) *int32 { - // if we have the replicas config, use it - if replicas != nil && replicas.Default != nil && currentReplicas == nil { - return replicas.Default - } - - // if we have the replicas config and the current replicas, use the min/max to ensure - // the current replicas are within the min/max range - if replicas != nil && currentReplicas != nil { - if replicas.Max != nil && *currentReplicas > *replicas.Max { - return replicas.Max - } - - if replicas.Min != nil && *currentReplicas < *replicas.Min { - return replicas.Min - } - - return currentReplicas - } - - // if we don't have the replicas config, use the current replicas if we have them - if currentReplicas != nil { - return currentReplicas - } - - // otherwise use the global default - return pointer.Int32(globalDefaultInstances) -} - -// MergeDeployment is used to update an appsv1.Deployment without overwriting any -// existing annotations or labels that were placed there by other vendors. -// -// based on https://github.com/kubernetes-sigs/controller-runtime/blob/4000e996a202917ad7d40f02ed8a2079a9ce25e9/pkg/controller/controllerutil/example_test.go -func MergeDeployment(existing, desired *appsv1.Deployment) { - // Only overwrite fields if the Deployment doesn't exist yet - if existing.ObjectMeta.CreationTimestamp.IsZero() { - existing.ObjectMeta.OwnerReferences = desired.ObjectMeta.OwnerReferences - existing.Spec = desired.Spec - existing.Annotations = desired.Annotations - existing.Labels = desired.Labels - return - } - - // Make sure we don't reconcile forever by overwriting valid out-of-band - // changes such as init container injection. If the deployments are - // sufficiently equal, we only update the annotations. - if !areDeploymentsEqual(existing, desired) { - desired.Spec.Replicas = deploymentReplicaCount(nil, existing.Spec.Replicas) - existing.Spec = desired.Spec - } - - // If the Deployment already exists, add any desired annotations + labels to existing set - for k, v := range desired.ObjectMeta.Annotations { - existing.ObjectMeta.Annotations[k] = v - } - for k, v := range desired.ObjectMeta.Labels { - existing.ObjectMeta.Labels[k] = v - } -} diff --git a/control-plane/gateways/deployment_dataplane_container.go b/control-plane/gateways/deployment_dataplane_container.go deleted file mode 100644 index 630e337ad5..0000000000 --- a/control-plane/gateways/deployment_dataplane_container.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -import ( - "fmt" - "strconv" - - "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/utils/pointer" - - "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" - "github.com/hashicorp/consul-k8s/control-plane/namespaces" - - corev1 "k8s.io/api/core/v1" -) - -const ( - allCapabilities = "ALL" - netBindCapability = "NET_BIND_SERVICE" - consulDataplaneDNSBindHost = "127.0.0.1" - consulDataplaneDNSBindPort = 8600 - defaultPrometheusScrapePath = "/metrics" - defaultEnvoyProxyConcurrency = "1" - volumeName = "consul-mesh-inject-data" -) - -func (b *gatewayBuilder[T]) consulDataplaneContainer(containerConfig v2beta1.GatewayClassContainerConfig) (corev1.Container, error) { - // Extract the service account token's volume mount. - var ( - err error - bearerTokenFile string - ) - - resources := containerConfig.Resources - - if b.config.AuthMethod != "" { - bearerTokenFile = "/var/run/secrets/kubernetes.io/serviceaccount/token" - } - - args, err := b.dataplaneArgs(bearerTokenFile) - if err != nil { - return corev1.Container{}, err - } - - probe := &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - HTTPGet: &corev1.HTTPGetAction{ - Port: intstr.FromInt(constants.ProxyDefaultHealthPort), - Path: "/ready", - }, - }, - InitialDelaySeconds: 1, - } - - container := corev1.Container{ - Name: b.gateway.GetName(), - Image: b.config.ImageDataplane, - - // We need to set tmp dir to an ephemeral volume that we're mounting so that - // consul-dataplane can write files to it. Otherwise, it wouldn't be able to - // because we set file system to be read-only. - - // TODO(nathancoleman): I don't believe consul-dataplane needs to write anymore, investigate. - Env: []corev1.EnvVar{ - { - Name: envDPProxyId, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, - }, - }, - { - Name: envPodNamespace, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, - }, - }, - { - Name: envTmpDir, - Value: constants.MeshV2VolumePath, - }, - { - Name: envNodeName, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: envDPCredentialLoginMeta, - Value: "pod=$(POD_NAMESPACE)/$(DP_PROXY_ID)", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: volumeName, - MountPath: constants.MeshV2VolumePath, - }, - }, - Args: args, - ReadinessProbe: probe, - } - - // Configure the Readiness Address for the proxy's health check to be the Pod IP. - container.Env = append(container.Env, corev1.EnvVar{ - Name: "DP_ENVOY_READY_BIND_ADDRESS", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{FieldPath: "status.podIP"}, - }, - }) - // Configure the port on which the readiness probe will query the proxy for its health. - container.Ports = append(container.Ports, corev1.ContainerPort{ - Name: "proxy-health", - ContainerPort: int32(constants.ProxyDefaultHealthPort), - }) - - container.Ports = append(container.Ports, b.gateway.ListenersToContainerPorts(containerConfig.PortModifier, containerConfig.HostPort)...) - - // Configure the resource requests and limits for the proxy if they are set. - if resources != nil { - container.Resources = *resources - } - - container.SecurityContext = &corev1.SecurityContext{ - AllowPrivilegeEscalation: pointer.Bool(false), - // Drop any Linux capabilities you'd get other than NET_BIND_SERVICE. - // FUTURE: We likely require some additional capability in order to support - // MeshGateway's host network option. - Capabilities: &corev1.Capabilities{ - Add: []corev1.Capability{netBindCapability}, - Drop: []corev1.Capability{allCapabilities}, - }, - ReadOnlyRootFilesystem: pointer.Bool(true), - RunAsNonRoot: pointer.Bool(true), - } - - return container, nil -} - -func (b *gatewayBuilder[T]) dataplaneArgs(bearerTokenFile string) ([]string, error) { - args := []string{ - "-addresses", b.config.ConsulConfig.Address, - "-grpc-port=" + strconv.Itoa(b.config.ConsulConfig.GRPCPort), - "-log-level=" + b.logLevelForDataplaneContainer(), - "-log-json=" + strconv.FormatBool(b.config.LogJSON), - "-envoy-concurrency=" + defaultEnvoyProxyConcurrency, - } - - consulNamespace := namespaces.ConsulNamespace(b.gateway.GetNamespace(), b.config.ConsulTenancyConfig.EnableConsulNamespaces, b.config.ConsulTenancyConfig.ConsulDestinationNamespace, b.config.ConsulTenancyConfig.EnableConsulNamespaces, b.config.ConsulTenancyConfig.NSMirroringPrefix) - - if b.config.AuthMethod != "" { - args = append(args, - "-credential-type=login", - "-login-auth-method="+b.config.AuthMethod, - "-login-bearer-token-path="+bearerTokenFile, - "-login-meta="+fmt.Sprintf("gateway=%s/%s", b.gateway.GetNamespace(), b.gateway.GetName()), - ) - if b.config.ConsulTenancyConfig.ConsulPartition != "" { - args = append(args, "-login-partition="+b.config.ConsulTenancyConfig.ConsulPartition) - } - } - if b.config.SkipServerWatch { - args = append(args, "-server-watch-disabled=true") - } - if b.config.ConsulTenancyConfig.EnableConsulNamespaces { - args = append(args, "-proxy-namespace="+consulNamespace) - } - if b.config.ConsulTenancyConfig.ConsulPartition != "" { - args = append(args, "-proxy-partition="+b.config.ConsulTenancyConfig.ConsulPartition) - } - - args = append(args, buildTLSArgs(b.config)...) - - // Configure the readiness port on the dataplane sidecar if proxy health checks are enabled. - args = append(args, fmt.Sprintf("%s=%d", "-envoy-ready-bind-port", constants.ProxyDefaultHealthPort)) - - args = append(args, fmt.Sprintf("-envoy-admin-bind-port=%d", 19000)) - - return args, nil -} - -func buildTLSArgs(config GatewayConfig) []string { - if !config.TLSEnabled { - return []string{"-tls-disabled"} - } - tlsArgs := make([]string, 0, 2) - - if config.ConsulTLSServerName != "" { - tlsArgs = append(tlsArgs, fmt.Sprintf("-tls-server-name=%s", config.ConsulTLSServerName)) - } - if config.ConsulCACert != "" { - tlsArgs = append(tlsArgs, fmt.Sprintf("-ca-certs=%s", constants.ConsulCAFile)) - } - - return tlsArgs -} diff --git a/control-plane/gateways/deployment_init_container.go b/control-plane/gateways/deployment_init_container.go deleted file mode 100644 index beb7267005..0000000000 --- a/control-plane/gateways/deployment_init_container.go +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -import ( - "bytes" - "strconv" - "strings" - "text/template" - - corev1 "k8s.io/api/core/v1" - - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" - "github.com/hashicorp/consul-k8s/control-plane/namespaces" -) - -const ( - injectInitContainerName = "consul-mesh-init" - initContainersUserAndGroupID = 5996 -) - -var tpl = template.Must(template.New("root").Parse(strings.TrimSpace(initContainerCommandTpl))) - -type initContainerCommandData struct { - ServiceName string - ServiceAccountName string - AuthMethod string - - // Log settings for the connect-init command. - LogLevel string - LogJSON bool -} - -// initContainer returns the init container spec for connect-init that polls for the service and the connect proxy service to be registered -// so that it can save the proxy service id to the shared volume and boostrap Envoy with the proxy-id. -func (b *gatewayBuilder[T]) initContainer() (corev1.Container, error) { - data := initContainerCommandData{ - AuthMethod: b.config.AuthMethod, - LogLevel: b.logLevelForInitContainer(), - LogJSON: b.config.LogJSON, - ServiceName: b.gateway.GetName(), - ServiceAccountName: b.serviceAccountName(), - } - // Render the command - var buf bytes.Buffer - if err := tpl.Execute(&buf, &data); err != nil { - return corev1.Container{}, err - } - - // Create expected volume mounts - volMounts := []corev1.VolumeMount{ - { - Name: volumeName, - MountPath: constants.MeshV2VolumePath, - }, - } - - var bearerTokenFile string - if b.config.AuthMethod != "" { - bearerTokenFile = defaultBearerTokenFile - } - - consulNamespace := namespaces.ConsulNamespace(b.gateway.GetNamespace(), b.config.ConsulTenancyConfig.EnableConsulNamespaces, b.config.ConsulTenancyConfig.ConsulDestinationNamespace, b.config.ConsulTenancyConfig.EnableConsulNamespaces, b.config.ConsulTenancyConfig.NSMirroringPrefix) - - initContainerName := injectInitContainerName - container := corev1.Container{ - Name: initContainerName, - Image: b.config.ImageConsulK8S, - - Env: []corev1.EnvVar{ - { - Name: envPodName, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, - }, - }, - { - Name: envPodNamespace, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, - }, - }, - { - Name: envNodeName, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: envConsulAddresses, - Value: b.config.ConsulConfig.Address, - }, - { - Name: envConsulGRPCPort, - Value: strconv.Itoa(b.config.ConsulConfig.GRPCPort), - }, - { - Name: envConsulHTTPPort, - Value: strconv.Itoa(b.config.ConsulConfig.HTTPPort), - }, - { - Name: envConsulAPITimeout, - Value: b.config.ConsulConfig.APITimeout.String(), - }, - { - Name: envConsulNodeName, - Value: "$(NODE_NAME)-virtual", - }, - }, - VolumeMounts: volMounts, - Command: []string{"/bin/sh", "-ec", buf.String()}, - Resources: initContainerResourcesOrDefault(b.gcc), - } - - if b.config.AuthMethod != "" { - container.Env = append(container.Env, - corev1.EnvVar{ - Name: envConsulLoginAuthMethod, - Value: b.config.AuthMethod, - }, - corev1.EnvVar{ - Name: envConsulLoginBearerTokenFile, - Value: bearerTokenFile, - }, - corev1.EnvVar{ - Name: envConsulLoginMeta, - Value: "pod=$(POD_NAMESPACE)/$(POD_NAME)", - }) - - if b.config.ConsulTenancyConfig.ConsulPartition != "" { - container.Env = append(container.Env, corev1.EnvVar{ - Name: envConsulLoginPartition, - Value: b.config.ConsulTenancyConfig.ConsulPartition, - }) - } - } - container.Env = append(container.Env, - corev1.EnvVar{ - Name: envConsulNamespace, - Value: consulNamespace, - }) - - if b.config.TLSEnabled { - container.Env = append(container.Env, - corev1.EnvVar{ - Name: constants.UseTLSEnvVar, - Value: "true", - }, - corev1.EnvVar{ - Name: constants.CACertPEMEnvVar, - Value: b.config.ConsulCACert, - }, - corev1.EnvVar{ - Name: constants.TLSServerNameEnvVar, - Value: b.config.ConsulTLSServerName, - }) - } - - if b.config.ConsulTenancyConfig.ConsulPartition != "" { - container.Env = append(container.Env, - corev1.EnvVar{ - Name: envConsulPartition, - Value: b.config.ConsulTenancyConfig.ConsulPartition, - }) - } - - return container, nil -} - -func initContainerResourcesOrDefault(gcc *meshv2beta1.GatewayClassConfig) corev1.ResourceRequirements { - if gcc != nil && gcc.Spec.Deployment.InitContainer != nil && gcc.Spec.Deployment.InitContainer.Resources != nil { - return *gcc.Spec.Deployment.InitContainer.Resources - } - - return corev1.ResourceRequirements{} -} - -// initContainerCommandTpl is the template for the command executed by -// the init container. -// TODO @GatewayManagement parametrize gateway kind. -const initContainerCommandTpl = ` -consul-k8s-control-plane mesh-init \ - -proxy-name=${POD_NAME} \ - -namespace=${POD_NAMESPACE} \ - {{- with .LogLevel }} - -log-level={{ . }} \ - {{- end }} - -log-json={{ .LogJSON }} -` diff --git a/control-plane/gateways/deployment_test.go b/control-plane/gateways/deployment_test.go deleted file mode 100644 index 24e5fa67a2..0000000000 --- a/control-plane/gateways/deployment_test.go +++ /dev/null @@ -1,1262 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/utils/pointer" - - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" -) - -const testCert = `-----BEGIN CERTIFICATE----- │ -MIIDQjCCAuigAwIBAgIUZGIigQ4IKLoCh4XrXyi/c89B7ZgwCgYIKoZIzj0EAwIw │ -gZExCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5j │ -aXNjbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1 │ -MRcwFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjEYMBYGA1UEAxMPQ29uc3VsIEFnZW50 │ -IENBMB4XDTI0MDEwMzE4NTYyOVoXDTMzMTIzMTE4NTcyOVowgZExCzAJBgNVBAYT │ -AlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEaMBgGA1UE │ -CRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcwFQYDVQQKEw5I │ -YXNoaUNvcnAgSW5jLjEYMBYGA1UEAxMPQ29uc3VsIEFnZW50IENBMFkwEwYHKoZI │ -zj0CAQYIKoZIzj0DAQcDQgAEcbkdpZxlDOEuT3ZCcZ8H9j0Jad8ncDYk/Y0IbHPC │ -OKfFcpldEFPRv16WgSTHg38kK9WgEuK291+joBTHry3y06OCARowggEWMA4GA1Ud │ -DwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0T │ -AQH/BAUwAwEB/zBoBgNVHQ4EYQRfZGY6MzA6YWE6NzI6ZTQ6ZTI6NzI6Y2Y6NTg6 │ -NDU6Zjk6YjU6NTA6N2I6ZDQ6MDI6MTE6ZjM6YzY6ZjE6NTc6NTE6MTg6NGU6OGU6 │ -ZjE6MmE6ZTE6MzI6NmY6ZTU6YjMwagYDVR0jBGMwYYBfZGY6MzA6YWE6NzI6ZTQ6 │ -ZTI6NzI6Y2Y6NTg6NDU6Zjk6YjU6NTA6N2I6ZDQ6MDI6MTE6ZjM6YzY6ZjE6NTc6 │ -NTE6MTg6NGU6OGU6ZjE6MmE6ZTE6MzI6NmY6ZTU6YjMwCgYIKoZIzj0EAwIDSAAw │ -RQIgXg8YtejEgGNxswtyXsvqzhLpt7k44L7TJMUhfIw0lUECIQCIxKNowmv0/XVz │ -nRnYLmGy79EZ2Y+CZS9nSm9Es6QNwg== │ ------END CERTIFICATE-----` - -func Test_gatewayBuilder_Deployment(t *testing.T) { - type fields struct { - gateway *meshv2beta1.MeshGateway - config GatewayConfig - gcc *meshv2beta1.GatewayClassConfig - } - tests := []struct { - name string - fields fields - want *appsv1.Deployment - wantErr bool - }{ - { - name: "happy path", - fields: fields{ - gateway: &meshv2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - constants.AnnotationGatewayWANSource: "Service", - constants.AnnotationGatewayWANPort: "443", - constants.AnnotationGatewayWANAddress: "", - }, - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "test-gateway-class", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 443, - Protocol: "tcp", - }, - }, - }, - }, - config: GatewayConfig{}, - gcc: &meshv2beta1.GatewayClassConfig{ - Spec: meshv2beta1.GatewayClassConfigSpec{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Labels: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - Set: map[string]string{ - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - }, - Annotations: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - Set: map[string]string{ - "a": "b", - }, - }, - }, - Deployment: meshv2beta1.GatewayClassDeploymentConfig{ - Affinity: &corev1.Affinity{ - PodAntiAffinity: &corev1.PodAntiAffinity{ - PreferredDuringSchedulingIgnoredDuringExecution: []corev1.WeightedPodAffinityTerm{ - { - Weight: 1, - PodAffinityTerm: corev1.PodAffinityTerm{ - LabelSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - }, - TopologyKey: "kubernetes.io/hostname", - }, - }, - }, - }, - }, - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Labels: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - Set: map[string]string{ - "foo": "bar", - }, - }, - Annotations: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - Set: map[string]string{ - "baz": "qux", - }, - }, - }, - Container: &meshv2beta1.GatewayClassContainerConfig{ - HostPort: 8080, - PortModifier: 8000, - Consul: meshv2beta1.GatewayClassConsulConfig{ - Logging: meshv2beta1.GatewayClassConsulLoggingConfig{ - Level: "debug", - }, - }, - }, - NodeSelector: map[string]string{"beta.kubernetes.io/arch": "amd64"}, - Replicas: &meshv2beta1.GatewayClassReplicasConfig{ - Default: pointer.Int32(1), - Min: pointer.Int32(1), - Max: pointer.Int32(8), - }, - PriorityClassName: "priorityclassname", - TopologySpreadConstraints: []corev1.TopologySpreadConstraint{ - { - MaxSkew: 1, - TopologyKey: "key", - WhenUnsatisfiable: "DoNotSchedule", - }, - }, - InitContainer: &meshv2beta1.GatewayClassInitContainerConfig{ - Resources: &corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "cpu": resource.MustParse("100m"), - "memory": resource.MustParse("128Mi"), - }, - Limits: corev1.ResourceList{ - "cpu": resource.MustParse("200m"), - "memory": resource.MustParse("228Mi"), - }, - }, - Consul: meshv2beta1.GatewayClassConsulConfig{ - Logging: meshv2beta1.GatewayClassConsulLoggingConfig{ - Level: "debug", - }, - }, - }, - }, - }, - }, - }, - want: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - "foo": "bar", - }, - Annotations: map[string]string{ - "a": "b", - "baz": "qux", - }, - }, - Spec: appsv1.DeploymentSpec{ - Replicas: pointer.Int32(1), - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - "foo": "bar", - }, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "foo": "bar", - "release": "consul", - }, - Annotations: map[string]string{ - constants.AnnotationGatewayKind: MeshGatewayAnnotationKind, - constants.AnnotationMeshInject: "false", - constants.AnnotationTransparentProxyOverwriteProbes: "false", - constants.AnnotationGatewayWANSource: "Service", - constants.AnnotationGatewayWANPort: "443", - constants.AnnotationGatewayWANAddress: "", - }, - }, - Spec: corev1.PodSpec{ - Volumes: []corev1.Volume{ - { - Name: "consul-mesh-inject-data", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{ - Medium: "Memory", - }, - }, - }, - }, - InitContainers: []corev1.Container{ - { - Name: "consul-mesh-init", - Command: []string{ - "/bin/sh", - "-ec", - "consul-k8s-control-plane mesh-init \\\n -proxy-name=${POD_NAME} \\\n -namespace=${POD_NAMESPACE} \\\n -log-level=debug \\\n -log-json=false", - }, - Env: []corev1.EnvVar{ - { - Name: "POD_NAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "metadata.name", - }, - }, - }, - { - Name: "POD_NAMESPACE", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "NODE_NAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "CONSUL_ADDRESSES", - Value: "", - }, - { - Name: "CONSUL_GRPC_PORT", - Value: "0", - }, - { - Name: "CONSUL_HTTP_PORT", - Value: "0", - }, - { - Name: "CONSUL_API_TIMEOUT", - Value: "0s", - }, - { - Name: "CONSUL_NODE_NAME", - Value: "$(NODE_NAME)-virtual", - }, - { - Name: "CONSUL_NAMESPACE", - Value: "", - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "cpu": resource.MustParse("100m"), - "memory": resource.MustParse("128Mi"), - }, - Limits: corev1.ResourceList{ - "cpu": resource.MustParse("200m"), - "memory": resource.MustParse("228Mi"), - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "consul-mesh-inject-data", - ReadOnly: false, - MountPath: "/consul/mesh-inject", - }, - }, - }, - }, - Containers: []corev1.Container{ - { - Args: []string{ - "-addresses", - "", - "-grpc-port=0", - "-log-level=debug", - "-log-json=false", - "-envoy-concurrency=1", - "-tls-disabled", - "-envoy-ready-bind-port=21000", - "-envoy-admin-bind-port=19000", - }, - Ports: []corev1.ContainerPort{ - { - Name: "proxy-health", - ContainerPort: 21000, - }, - { - Name: "wan", - ContainerPort: 8443, - HostPort: 8080, - Protocol: "tcp", - }, - }, - Env: []corev1.EnvVar{ - { - Name: "DP_PROXY_ID", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "metadata.name", - }, - }, - }, - { - Name: "POD_NAMESPACE", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "TMPDIR", - Value: "/consul/mesh-inject", - }, - { - Name: "NODE_NAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "DP_CREDENTIAL_LOGIN_META", - Value: "pod=$(POD_NAMESPACE)/$(DP_PROXY_ID)", - }, - { - Name: "DP_ENVOY_READY_BIND_ADDRESS", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "status.podIP", - }, - }, - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "consul-mesh-inject-data", - MountPath: "/consul/mesh-inject", - }, - }, - ReadinessProbe: &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "/ready", - Port: intstr.IntOrString{ - Type: 0, - IntVal: 21000, - StrVal: "", - }, - }, - }, - InitialDelaySeconds: 1, - }, - SecurityContext: &corev1.SecurityContext{ - Capabilities: &corev1.Capabilities{ - Add: []corev1.Capability{ - "NET_BIND_SERVICE", - }, - Drop: []corev1.Capability{ - "ALL", - }, - }, - RunAsNonRoot: pointer.Bool(true), - ReadOnlyRootFilesystem: pointer.Bool(true), - AllowPrivilegeEscalation: pointer.Bool(false), - ProcMount: nil, - SeccompProfile: nil, - }, - Stdin: false, - StdinOnce: false, - TTY: false, - }, - }, - NodeSelector: map[string]string{"beta.kubernetes.io/arch": "amd64"}, - PriorityClassName: "priorityclassname", - TopologySpreadConstraints: []corev1.TopologySpreadConstraint{ - { - MaxSkew: 1, - TopologyKey: "key", - WhenUnsatisfiable: "DoNotSchedule", - }, - }, - Affinity: &corev1.Affinity{ - NodeAffinity: nil, - PodAffinity: nil, - PodAntiAffinity: &corev1.PodAntiAffinity{ - PreferredDuringSchedulingIgnoredDuringExecution: []corev1.WeightedPodAffinityTerm{ - { - Weight: 1, - PodAffinityTerm: corev1.PodAffinityTerm{ - LabelSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - }, - TopologyKey: "kubernetes.io/hostname", - }, - }, - }, - }, - }, - }, - }, - Strategy: appsv1.DeploymentStrategy{}, - MinReadySeconds: 0, - RevisionHistoryLimit: nil, - Paused: false, - ProgressDeadlineSeconds: nil, - }, - Status: appsv1.DeploymentStatus{}, - }, - wantErr: false, - }, - { - name: "happy path tls enabled", - fields: fields{ - gateway: &meshv2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - constants.AnnotationGatewayWANSource: "Service", - constants.AnnotationGatewayWANPort: "443", - constants.AnnotationGatewayWANAddress: "", - }, - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "test-gateway-class", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 443, - Protocol: "tcp", - }, - }, - }, - }, - config: GatewayConfig{ - TLSEnabled: true, - ConsulCACert: testCert, - }, - gcc: &meshv2beta1.GatewayClassConfig{ - Spec: meshv2beta1.GatewayClassConfigSpec{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Labels: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - Set: map[string]string{ - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - }, - }, - Deployment: meshv2beta1.GatewayClassDeploymentConfig{ - Affinity: &corev1.Affinity{ - PodAntiAffinity: &corev1.PodAntiAffinity{ - PreferredDuringSchedulingIgnoredDuringExecution: []corev1.WeightedPodAffinityTerm{ - { - Weight: 1, - PodAffinityTerm: corev1.PodAffinityTerm{ - LabelSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - }, - TopologyKey: "kubernetes.io/hostname", - }, - }, - }, - }, - }, - Container: &meshv2beta1.GatewayClassContainerConfig{ - HostPort: 8080, - PortModifier: 8000, - Consul: meshv2beta1.GatewayClassConsulConfig{ - Logging: meshv2beta1.GatewayClassConsulLoggingConfig{ - Level: "debug", - }, - }, - }, - NodeSelector: map[string]string{"beta.kubernetes.io/arch": "amd64"}, - Replicas: &meshv2beta1.GatewayClassReplicasConfig{ - Default: pointer.Int32(1), - Min: pointer.Int32(1), - Max: pointer.Int32(8), - }, - PriorityClassName: "priorityclassname", - TopologySpreadConstraints: []corev1.TopologySpreadConstraint{ - { - MaxSkew: 1, - TopologyKey: "key", - WhenUnsatisfiable: "DoNotSchedule", - }, - }, - InitContainer: &meshv2beta1.GatewayClassInitContainerConfig{ - Resources: &corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "cpu": resource.MustParse("100m"), - "memory": resource.MustParse("128Mi"), - }, - Limits: corev1.ResourceList{ - "cpu": resource.MustParse("200m"), - "memory": resource.MustParse("228Mi"), - }, - }, - Consul: meshv2beta1.GatewayClassConsulConfig{ - Logging: meshv2beta1.GatewayClassConsulLoggingConfig{ - Level: "debug", - }, - }, - }, - }, - }, - }, - }, - want: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - - Annotations: map[string]string{}, - }, - Spec: appsv1.DeploymentSpec{ - Replicas: pointer.Int32(1), - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - Annotations: map[string]string{ - constants.AnnotationGatewayKind: MeshGatewayAnnotationKind, - constants.AnnotationMeshInject: "false", - constants.AnnotationTransparentProxyOverwriteProbes: "false", - constants.AnnotationGatewayWANSource: "Service", - constants.AnnotationGatewayWANPort: "443", - constants.AnnotationGatewayWANAddress: "", - }, - }, - Spec: corev1.PodSpec{ - Volumes: []corev1.Volume{ - { - Name: "consul-mesh-inject-data", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{ - Medium: "Memory", - }, - }, - }, - }, - InitContainers: []corev1.Container{ - { - Name: "consul-mesh-init", - Command: []string{ - "/bin/sh", - "-ec", - "consul-k8s-control-plane mesh-init \\\n -proxy-name=${POD_NAME} \\\n -namespace=${POD_NAMESPACE} \\\n -log-level=debug \\\n -log-json=false", - }, - Env: []corev1.EnvVar{ - { - Name: "POD_NAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "metadata.name", - }, - }, - }, - { - Name: "POD_NAMESPACE", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "NODE_NAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "CONSUL_ADDRESSES", - Value: "", - }, - { - Name: "CONSUL_GRPC_PORT", - Value: "0", - }, - { - Name: "CONSUL_HTTP_PORT", - Value: "0", - }, - { - Name: "CONSUL_API_TIMEOUT", - Value: "0s", - }, - { - Name: "CONSUL_NODE_NAME", - Value: "$(NODE_NAME)-virtual", - }, - { - Name: "CONSUL_NAMESPACE", - Value: "", - }, - { - Name: "CONSUL_USE_TLS", - Value: "true", - }, - { - Name: "CONSUL_CACERT_PEM", - Value: testCert, - }, - { - Name: "CONSUL_TLS_SERVER_NAME", - Value: "", - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "cpu": resource.MustParse("100m"), - "memory": resource.MustParse("128Mi"), - }, - Limits: corev1.ResourceList{ - "cpu": resource.MustParse("200m"), - "memory": resource.MustParse("228Mi"), - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "consul-mesh-inject-data", - ReadOnly: false, - MountPath: "/consul/mesh-inject", - }, - }, - }, - }, - Containers: []corev1.Container{ - { - Args: []string{ - "-addresses", - "", - "-grpc-port=0", - "-log-level=debug", - "-log-json=false", - "-envoy-concurrency=1", - "-ca-certs=/consul/mesh-inject/consul-ca.pem", - "-envoy-ready-bind-port=21000", - "-envoy-admin-bind-port=19000", - }, - Ports: []corev1.ContainerPort{ - { - Name: "proxy-health", - ContainerPort: 21000, - }, - { - Name: "wan", - ContainerPort: 8443, - HostPort: 8080, - Protocol: "tcp", - }, - }, - Env: []corev1.EnvVar{ - { - Name: "DP_PROXY_ID", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "metadata.name", - }, - }, - }, - { - Name: "POD_NAMESPACE", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "TMPDIR", - Value: "/consul/mesh-inject", - }, - { - Name: "NODE_NAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "DP_CREDENTIAL_LOGIN_META", - Value: "pod=$(POD_NAMESPACE)/$(DP_PROXY_ID)", - }, - { - Name: "DP_ENVOY_READY_BIND_ADDRESS", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "status.podIP", - }, - }, - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "consul-mesh-inject-data", - MountPath: "/consul/mesh-inject", - }, - }, - ReadinessProbe: &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "/ready", - Port: intstr.IntOrString{ - Type: 0, - IntVal: 21000, - StrVal: "", - }, - }, - }, - InitialDelaySeconds: 1, - }, - SecurityContext: &corev1.SecurityContext{ - Capabilities: &corev1.Capabilities{ - Add: []corev1.Capability{ - "NET_BIND_SERVICE", - }, - Drop: []corev1.Capability{ - "ALL", - }, - }, - RunAsNonRoot: pointer.Bool(true), - ReadOnlyRootFilesystem: pointer.Bool(true), - AllowPrivilegeEscalation: pointer.Bool(false), - ProcMount: nil, - SeccompProfile: nil, - }, - Stdin: false, - StdinOnce: false, - TTY: false, - }, - }, - NodeSelector: map[string]string{"beta.kubernetes.io/arch": "amd64"}, - PriorityClassName: "priorityclassname", - TopologySpreadConstraints: []corev1.TopologySpreadConstraint{ - { - MaxSkew: 1, - TopologyKey: "key", - WhenUnsatisfiable: "DoNotSchedule", - }, - }, - Affinity: &corev1.Affinity{ - NodeAffinity: nil, - PodAffinity: nil, - PodAntiAffinity: &corev1.PodAntiAffinity{ - PreferredDuringSchedulingIgnoredDuringExecution: []corev1.WeightedPodAffinityTerm{ - { - Weight: 1, - PodAffinityTerm: corev1.PodAffinityTerm{ - LabelSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - }, - TopologyKey: "kubernetes.io/hostname", - }, - }, - }, - }, - }, - }, - }, - Strategy: appsv1.DeploymentStrategy{}, - MinReadySeconds: 0, - RevisionHistoryLimit: nil, - Paused: false, - ProgressDeadlineSeconds: nil, - }, - Status: appsv1.DeploymentStatus{}, - }, - wantErr: false, - }, - { - name: "nil gatewayclassconfig - (notfound)", - fields: fields{ - gateway: &meshv2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - constants.AnnotationGatewayWANSource: "Service", - constants.AnnotationGatewayWANPort: "443", - constants.AnnotationGatewayWANAddress: "", - }, - }, - Spec: pbmesh.MeshGateway{ - GatewayClassName: "test-gateway-class", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 443, - Protocol: "tcp", - }, - }, - }, - }, - config: GatewayConfig{}, - gcc: nil, - }, - want: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Labels: defaultLabels, - Annotations: map[string]string{}, - }, - Spec: appsv1.DeploymentSpec{ - Replicas: pointer.Int32(1), - Selector: &metav1.LabelSelector{ - MatchLabels: defaultLabels, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: defaultLabels, - Annotations: map[string]string{ - constants.AnnotationGatewayKind: MeshGatewayAnnotationKind, - constants.AnnotationMeshInject: "false", - constants.AnnotationTransparentProxyOverwriteProbes: "false", - constants.AnnotationGatewayWANSource: "Service", - constants.AnnotationGatewayWANPort: "443", - constants.AnnotationGatewayWANAddress: "", - }, - }, - Spec: corev1.PodSpec{ - Volumes: []corev1.Volume{ - { - Name: "consul-mesh-inject-data", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{ - Medium: "Memory", - }, - }, - }, - }, - InitContainers: []corev1.Container{ - { - Name: "consul-mesh-init", - Command: []string{ - "/bin/sh", - "-ec", - "consul-k8s-control-plane mesh-init \\\n -proxy-name=${POD_NAME} \\\n -namespace=${POD_NAMESPACE} \\\n -log-json=false", - }, - Env: []corev1.EnvVar{ - { - Name: "POD_NAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "metadata.name", - }, - }, - }, - { - Name: "POD_NAMESPACE", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "NODE_NAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "CONSUL_ADDRESSES", - Value: "", - }, - { - Name: "CONSUL_GRPC_PORT", - Value: "0", - }, - { - Name: "CONSUL_HTTP_PORT", - Value: "0", - }, - { - Name: "CONSUL_API_TIMEOUT", - Value: "0s", - }, - { - Name: "CONSUL_NODE_NAME", - Value: "$(NODE_NAME)-virtual", - }, - { - Name: "CONSUL_NAMESPACE", - Value: "", - }, - }, - Resources: corev1.ResourceRequirements{}, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "consul-mesh-inject-data", - ReadOnly: false, - MountPath: "/consul/mesh-inject", - }, - }, - }, - }, - Containers: []corev1.Container{ - { - Args: []string{ - "-addresses", - "", - "-grpc-port=0", - "-log-level=", - "-log-json=false", - "-envoy-concurrency=1", - "-tls-disabled", - "-envoy-ready-bind-port=21000", - "-envoy-admin-bind-port=19000", - }, - Ports: []corev1.ContainerPort{ - { - Name: "proxy-health", - ContainerPort: 21000, - }, - { - Name: "wan", - ContainerPort: 443, - Protocol: "tcp", - }, - }, - Env: []corev1.EnvVar{ - { - Name: "DP_PROXY_ID", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "metadata.name", - }, - }, - }, - { - Name: "POD_NAMESPACE", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "TMPDIR", - Value: "/consul/mesh-inject", - }, - { - Name: "NODE_NAME", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "DP_CREDENTIAL_LOGIN_META", - Value: "pod=$(POD_NAMESPACE)/$(DP_PROXY_ID)", - }, - { - Name: "DP_ENVOY_READY_BIND_ADDRESS", - Value: "", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "", - FieldPath: "status.podIP", - }, - }, - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "consul-mesh-inject-data", - MountPath: "/consul/mesh-inject", - }, - }, - ReadinessProbe: &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "/ready", - Port: intstr.IntOrString{ - Type: 0, - IntVal: 21000, - StrVal: "", - }, - }, - }, - InitialDelaySeconds: 1, - }, - SecurityContext: &corev1.SecurityContext{ - Capabilities: &corev1.Capabilities{ - Add: []corev1.Capability{ - "NET_BIND_SERVICE", - }, - Drop: []corev1.Capability{ - "ALL", - }, - }, - RunAsNonRoot: pointer.Bool(true), - ReadOnlyRootFilesystem: pointer.Bool(true), - AllowPrivilegeEscalation: pointer.Bool(false), - ProcMount: nil, - SeccompProfile: nil, - }, - Stdin: false, - StdinOnce: false, - TTY: false, - }, - }, - }, - }, - Strategy: appsv1.DeploymentStrategy{}, - MinReadySeconds: 0, - RevisionHistoryLimit: nil, - Paused: false, - ProgressDeadlineSeconds: nil, - }, - Status: appsv1.DeploymentStatus{}, - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - b := &gatewayBuilder[*meshv2beta1.MeshGateway]{ - gateway: tt.fields.gateway, - config: tt.fields.config, - gcc: tt.fields.gcc, - gatewayKind: MeshGatewayAnnotationKind, - } - got, err := b.Deployment() - if !tt.wantErr && (err != nil) { - assert.Errorf(t, err, "Error") - } - assert.Equalf(t, tt.want, got, "Deployment()") - }) - } -} - -func Test_MergeDeployment(t *testing.T) { - testCases := []struct { - name string - a, b *appsv1.Deployment - assertFn func(*testing.T, *appsv1.Deployment) - }{ - { - name: "new deployment gets desired annotations + labels + containers", - a: &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "deployment"}}, - b: &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "deployment", - Annotations: map[string]string{"b": "b"}, - Labels: map[string]string{"b": "b"}, - }}, - assertFn: func(t *testing.T, result *appsv1.Deployment) { - assert.Equal(t, map[string]string{"b": "b"}, result.Annotations) - assert.Equal(t, map[string]string{"b": "b"}, result.Labels) - }, - }, - { - name: "existing deployment keeps existing annotations + labels and gains desired annotations + labels + containers", - a: &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "deployment", - CreationTimestamp: metav1.Now(), - Annotations: map[string]string{"a": "a"}, - Labels: map[string]string{"a": "a"}, - }}, - b: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "deployment", - Annotations: map[string]string{"b": "b"}, - Labels: map[string]string{"b": "b"}, - }, - Spec: appsv1.DeploymentSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - Containers: []corev1.Container{{Name: "b"}}, - }, - }, - }, - }, - assertFn: func(t *testing.T, result *appsv1.Deployment) { - assert.Equal(t, map[string]string{"a": "a", "b": "b"}, result.Annotations) - assert.Equal(t, map[string]string{"a": "a", "b": "b"}, result.Labels) - - require.Len(t, result.Spec.Template.Spec.Containers, 1) - assert.Equal(t, "b", result.Spec.Template.Spec.Containers[0].Name) - }, - }, - { - name: "existing deployment with injected initContainer retains it", - a: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "deployment", - CreationTimestamp: metav1.Now(), - Annotations: map[string]string{"a": "a"}, - Labels: map[string]string{"a": "a"}, - }, - Spec: appsv1.DeploymentSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - InitContainers: []corev1.Container{{Name: "b"}}, - Containers: []corev1.Container{{Name: "b"}}, - }, - }, - }, - }, - b: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "deployment", - Annotations: map[string]string{"b": "b"}, - Labels: map[string]string{"b": "b"}, - }, - Spec: appsv1.DeploymentSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - Containers: []corev1.Container{{Name: "b"}}, - }, - }, - }, - }, - assertFn: func(t *testing.T, result *appsv1.Deployment) { - assert.Equal(t, map[string]string{"a": "a", "b": "b"}, result.Annotations) - assert.Equal(t, map[string]string{"a": "a", "b": "b"}, result.Labels) - - require.Len(t, result.Spec.Template.Spec.InitContainers, 1) - assert.Equal(t, "b", result.Spec.Template.Spec.InitContainers[0].Name) - - require.Len(t, result.Spec.Template.Spec.Containers, 1) - assert.Equal(t, "b", result.Spec.Template.Spec.Containers[0].Name) - }, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - MergeDeployment(testCase.a, testCase.b) - testCase.assertFn(t, testCase.a) - }) - } -} diff --git a/control-plane/gateways/gateway_config.go b/control-plane/gateways/gateway_config.go deleted file mode 100644 index de3202e29e..0000000000 --- a/control-plane/gateways/gateway_config.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -import ( - "github.com/hashicorp/consul-k8s/control-plane/api/common" - "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" -) - -// GatewayConfig is a combination of settings relevant to Gateways. -type GatewayConfig struct { - // ImageDataplane is the Consul Dataplane image to use in gateway deployments. - ImageDataplane string - // ImageConsulK8S is the Consul Kubernetes Control Plane image to use in gateway deployments. - ImageConsulK8S string - // AuthMethod method used to authenticate with Consul Server. - AuthMethod string - - // ConsulTenancyConfig is the configuration for the Consul Tenancy feature. - ConsulTenancyConfig common.ConsulTenancyConfig - - // LogLevel is the logging level of the deployed Consul Dataplanes. - LogLevel string - // LogJSON if JSONLogging has been enabled. - LogJSON bool - // TLSEnabled is the value of whether or not TLS has been enabled in Consul. - TLSEnabled bool - // PeeringEnabled toggles whether or not Peering is enabled in Consul. - PeeringEnabled bool - // ConsulTLSServerName the name of the server running TLS. - ConsulTLSServerName string - // ConsulCACert contains the Consul Certificate Authority. - ConsulCACert string - // ConsulConfig configuration for the consul server address. - ConsulConfig common.ConsulConfig - - // EnableOpenShift indicates whether we're deploying into an OpenShift environment - EnableOpenShift bool - - // MapPrivilegedServicePorts is the value which Consul will add to privileged container port values (ports < 1024) - // defined on a Gateway. - MapPrivilegedServicePorts int - - // TODO(nathancoleman) Add doc - SkipServerWatch bool -} - -// GatewayResources is a collection of Kubernetes resources for a Gateway. -type GatewayResources struct { - // GatewayClassConfigs is a list of GatewayClassConfig resources which are - // responsible for defining configuration shared across all gateway kinds. - GatewayClassConfigs []*v2beta1.GatewayClassConfig `json:"gatewayClassConfigs"` - // MeshGateways is a list of MeshGateway resources which are responsible for - // defining the configuration for a specific mesh gateway. - // Deployments of mesh gateways have a one-to-one relationship with MeshGateway resources. - MeshGateways []*v2beta1.MeshGateway `json:"meshGateways"` -} diff --git a/control-plane/gateways/metadata.go b/control-plane/gateways/metadata.go deleted file mode 100644 index 4581efc232..0000000000 --- a/control-plane/gateways/metadata.go +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -import ( - "golang.org/x/exp/slices" - - "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" -) - -const labelManagedBy = "mesh.consul.hashicorp.com/managed-by" - -var defaultLabels = map[string]string{labelManagedBy: "consul-k8s"} - -func (b *gatewayBuilder[T]) annotationsForDeployment() map[string]string { - if b.gcc == nil { - return map[string]string{} - } - return computeAnnotationsOrLabels(b.gateway.GetAnnotations(), b.gcc.Spec.Deployment.Annotations, b.gcc.Spec.Annotations) -} - -func (b *gatewayBuilder[T]) annotationsForRole() map[string]string { - if b.gcc == nil { - return map[string]string{} - } - return computeAnnotationsOrLabels(b.gateway.GetAnnotations(), b.gcc.Spec.Role.Annotations, b.gcc.Spec.Annotations) -} - -func (b *gatewayBuilder[T]) annotationsForRoleBinding() map[string]string { - if b.gcc == nil { - return map[string]string{} - } - return computeAnnotationsOrLabels(b.gateway.GetAnnotations(), b.gcc.Spec.RoleBinding.Annotations, b.gcc.Spec.Annotations) -} - -func (b *gatewayBuilder[T]) annotationsForService() map[string]string { - if b.gcc == nil { - return map[string]string{} - } - return computeAnnotationsOrLabels(b.gateway.GetAnnotations(), b.gcc.Spec.Service.Annotations, b.gcc.Spec.Annotations) -} - -func (b *gatewayBuilder[T]) annotationsForServiceAccount() map[string]string { - if b.gcc == nil { - return map[string]string{} - } - return computeAnnotationsOrLabels(b.gateway.GetAnnotations(), b.gcc.Spec.ServiceAccount.Annotations, b.gcc.Spec.Annotations) -} - -func (b *gatewayBuilder[T]) labelsForDeployment() map[string]string { - if b.gcc == nil { - return defaultLabels - } - - labels := computeAnnotationsOrLabels(b.gateway.GetLabels(), b.gcc.Spec.Deployment.Labels, b.gcc.Spec.Labels) - for k, v := range defaultLabels { - labels[k] = v - } - return labels -} - -func (b *gatewayBuilder[T]) logLevelForDataplaneContainer() string { - if b.config.LogLevel != "" { - return b.config.LogLevel - } - - if b.gcc == nil || b.gcc.Spec.Deployment.Container == nil { - return "" - } - - return b.gcc.Spec.Deployment.Container.Consul.Logging.Level -} - -func (b *gatewayBuilder[T]) logLevelForInitContainer() string { - if b.config.LogLevel != "" { - return b.config.LogLevel - } - - if b.gcc == nil || b.gcc.Spec.Deployment.InitContainer == nil { - return "" - } - - return b.gcc.Spec.Deployment.InitContainer.Consul.Logging.Level -} - -func (b *gatewayBuilder[T]) labelsForRole() map[string]string { - if b.gcc == nil { - return defaultLabels - } - - labels := computeAnnotationsOrLabels(b.gateway.GetLabels(), b.gcc.Spec.Role.Labels, b.gcc.Spec.Labels) - for k, v := range defaultLabels { - labels[k] = v - } - return labels -} - -func (b *gatewayBuilder[T]) labelsForRoleBinding() map[string]string { - if b.gcc == nil { - return defaultLabels - } - - labels := computeAnnotationsOrLabels(b.gateway.GetLabels(), b.gcc.Spec.RoleBinding.Labels, b.gcc.Spec.Labels) - for k, v := range defaultLabels { - labels[k] = v - } - return labels -} - -func (b *gatewayBuilder[T]) labelsForService() map[string]string { - if b.gcc == nil { - return defaultLabels - } - - labels := computeAnnotationsOrLabels(b.gateway.GetLabels(), b.gcc.Spec.Service.Labels, b.gcc.Spec.Labels) - for k, v := range defaultLabels { - labels[k] = v - } - return labels -} - -func (b *gatewayBuilder[T]) labelsForServiceAccount() map[string]string { - if b.gcc == nil { - return defaultLabels - } - - labels := computeAnnotationsOrLabels(b.gateway.GetLabels(), b.gcc.Spec.ServiceAccount.Labels, b.gcc.Spec.Labels) - for k, v := range defaultLabels { - labels[k] = v - } - return labels -} - -// computeAnnotationsOrLabels compiles a set of annotations or labels -// using the following priority, highest to lowest: -// 1. inherited keys specified on the primary -// 2. added key-values specified on the primary -// 3. inherited keys specified on the secondary -// 4. added key-values specified on the secondary -func computeAnnotationsOrLabels(inheritFrom map[string]string, primary, secondary v2beta1.GatewayClassAnnotationsLabelsConfig) map[string]string { - out := map[string]string{} - - // Add key-values specified on the secondary - for k, v := range secondary.Set { - out[k] = v - } - - // Inherit keys specified on the secondary - for k, v := range inheritFrom { - if slices.Contains(secondary.InheritFromGateway, k) { - out[k] = v - } - } - - // Add key-values specified on the primary - for k, v := range primary.Set { - out[k] = v - } - - // Inherit keys specified on the primary - for k, v := range inheritFrom { - if slices.Contains(primary.InheritFromGateway, k) { - out[k] = v - } - } - - return out -} diff --git a/control-plane/gateways/metadata_test.go b/control-plane/gateways/metadata_test.go deleted file mode 100644 index 5b4861c1d0..0000000000 --- a/control-plane/gateways/metadata_test.go +++ /dev/null @@ -1,341 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -import ( - "testing" - - "github.com/stretchr/testify/assert" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" -) - -func TestGatewayBuilder_Annotations(t *testing.T) { - gateway := &meshv2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - "gateway-annotation": "true", // Will be inherited by all resources - "gateway-deployment-annotation": "true", // Will be inherited by Deployment - "gateway-role-annotation": "true", // Will be inherited by Role - "gateway-role-binding-annotation": "true", // Will be inherited by RoleBinding - "gateway-service-annotation": "true", // Will be inherited by Service - "gateway-service-account-annotation": "true", // Will be inherited by ServiceAccount - }, - }, - } - - gatewayClassConfig := &meshv2beta1.GatewayClassConfig{ - Spec: meshv2beta1.GatewayClassConfigSpec{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Annotations: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{"gateway-annotation"}, - Set: map[string]string{"global-set": "true"}, - }, - }, - Deployment: meshv2beta1.GatewayClassDeploymentConfig{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Annotations: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{"gateway-deployment-annotation"}, - Set: map[string]string{"deployment-set": "true"}, - }, - }, - }, - Role: meshv2beta1.GatewayClassRoleConfig{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Annotations: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{"gateway-role-annotation"}, - Set: map[string]string{"role-set": "true"}, - }, - }, - }, - RoleBinding: meshv2beta1.GatewayClassRoleBindingConfig{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Annotations: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{"gateway-role-binding-annotation"}, - Set: map[string]string{"role-binding-set": "true"}, - }, - }, - }, - Service: meshv2beta1.GatewayClassServiceConfig{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Annotations: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{"gateway-service-annotation"}, - Set: map[string]string{"service-set": "true"}, - }, - }, - }, - ServiceAccount: meshv2beta1.GatewayClassServiceAccountConfig{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Annotations: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{"gateway-service-account-annotation"}, - Set: map[string]string{"service-account-set": "true"}, - }, - }, - }, - }, - } - - b := NewGatewayBuilder[*meshv2beta1.MeshGateway](gateway, GatewayConfig{}, gatewayClassConfig, MeshGatewayAnnotationKind) - - for _, testCase := range []struct { - Actual map[string]string - Expected map[string]string - }{ - { - Actual: b.annotationsForDeployment(), - Expected: map[string]string{ - "gateway-annotation": "true", - "global-set": "true", - "gateway-deployment-annotation": "true", - "deployment-set": "true", - }, - }, - { - Actual: b.annotationsForRole(), - Expected: map[string]string{ - "gateway-annotation": "true", - "global-set": "true", - "gateway-role-annotation": "true", - "role-set": "true", - }, - }, - { - Actual: b.annotationsForRoleBinding(), - Expected: map[string]string{ - "gateway-annotation": "true", - "global-set": "true", - "gateway-role-binding-annotation": "true", - "role-binding-set": "true", - }, - }, - { - Actual: b.annotationsForService(), - Expected: map[string]string{ - "gateway-annotation": "true", - "global-set": "true", - "gateway-service-annotation": "true", - "service-set": "true", - }, - }, - { - Actual: b.annotationsForServiceAccount(), - Expected: map[string]string{ - "gateway-annotation": "true", - "global-set": "true", - "gateway-service-account-annotation": "true", - "service-account-set": "true", - }, - }, - } { - assert.Equal(t, testCase.Expected, testCase.Actual) - } -} - -func TestGatewayBuilder_Labels(t *testing.T) { - gateway := &meshv2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "gateway-label": "true", // Will be inherited by all resources - "gateway-deployment-label": "true", // Will be inherited by Deployment - "gateway-role-label": "true", // Will be inherited by Role - "gateway-role-binding-label": "true", // Will be inherited by RoleBinding - "gateway-service-label": "true", // Will be inherited by Service - "gateway-service-account-label": "true", // Will be inherited by ServiceAccount - }, - }, - } - - gatewayClassConfig := &meshv2beta1.GatewayClassConfig{ - Spec: meshv2beta1.GatewayClassConfigSpec{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Labels: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{"gateway-label"}, - Set: map[string]string{"global-set": "true"}, - }, - }, - Deployment: meshv2beta1.GatewayClassDeploymentConfig{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Labels: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{"gateway-deployment-label"}, - Set: map[string]string{"deployment-set": "true"}, - }, - }, - }, - Role: meshv2beta1.GatewayClassRoleConfig{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Labels: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{"gateway-role-label"}, - Set: map[string]string{"role-set": "true"}, - }, - }, - }, - RoleBinding: meshv2beta1.GatewayClassRoleBindingConfig{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Labels: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{"gateway-role-binding-label"}, - Set: map[string]string{"role-binding-set": "true"}, - }, - }, - }, - Service: meshv2beta1.GatewayClassServiceConfig{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Labels: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{"gateway-service-label"}, - Set: map[string]string{"service-set": "true"}, - }, - }, - }, - ServiceAccount: meshv2beta1.GatewayClassServiceAccountConfig{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Labels: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{"gateway-service-account-label"}, - Set: map[string]string{"service-account-set": "true"}, - }, - }, - }, - }, - } - - b := NewGatewayBuilder[*meshv2beta1.MeshGateway](gateway, GatewayConfig{}, gatewayClassConfig, MeshGatewayAnnotationKind) - - for _, testCase := range []struct { - Actual map[string]string - Expected map[string]string - }{ - { - Actual: b.labelsForDeployment(), - Expected: map[string]string{ - "mesh.consul.hashicorp.com/managed-by": "consul-k8s", - "gateway-label": "true", - "global-set": "true", - "gateway-deployment-label": "true", - "deployment-set": "true", - }, - }, - { - Actual: b.labelsForRole(), - Expected: map[string]string{ - "mesh.consul.hashicorp.com/managed-by": "consul-k8s", - "gateway-label": "true", - "global-set": "true", - "gateway-role-label": "true", - "role-set": "true", - }, - }, - { - Actual: b.labelsForRoleBinding(), - Expected: map[string]string{ - "mesh.consul.hashicorp.com/managed-by": "consul-k8s", - "gateway-label": "true", - "global-set": "true", - "gateway-role-binding-label": "true", - "role-binding-set": "true", - }, - }, - { - Actual: b.labelsForService(), - Expected: map[string]string{ - "mesh.consul.hashicorp.com/managed-by": "consul-k8s", - "gateway-label": "true", - "global-set": "true", - "gateway-service-label": "true", - "service-set": "true", - }, - }, - { - Actual: b.labelsForServiceAccount(), - Expected: map[string]string{ - "mesh.consul.hashicorp.com/managed-by": "consul-k8s", - "gateway-label": "true", - "global-set": "true", - "gateway-service-account-label": "true", - "service-account-set": "true", - }, - }, - } { - assert.Equal(t, testCase.Expected, testCase.Actual) - } -} - -// The LogLevel for deployment containers may be set on the Gateway Class Config or the Gateway Config. -// If it is set on both, the Gateway Config takes precedence. -func TestGatewayBuilder_LogLevel(t *testing.T) { - debug := "debug" - info := "info" - - testCases := map[string]struct { - GatewayLogLevel string - GCCLogLevel string - }{ - "Set on Gateway": { - GatewayLogLevel: debug, - GCCLogLevel: "", - }, - "Set on GCC": { - GatewayLogLevel: "", - GCCLogLevel: debug, - }, - "Set on both": { - GatewayLogLevel: debug, - GCCLogLevel: info, - }, - } - - for name, testCase := range testCases { - t.Run(name, func(t *testing.T) { - gcc := &meshv2beta1.GatewayClassConfig{ - Spec: meshv2beta1.GatewayClassConfigSpec{ - Deployment: meshv2beta1.GatewayClassDeploymentConfig{ - Container: &meshv2beta1.GatewayClassContainerConfig{ - Consul: meshv2beta1.GatewayClassConsulConfig{ - Logging: meshv2beta1.GatewayClassConsulLoggingConfig{ - Level: testCase.GCCLogLevel, - }, - }, - }, - }, - }, - } - b := NewGatewayBuilder(&meshv2beta1.MeshGateway{}, GatewayConfig{LogLevel: testCase.GatewayLogLevel}, gcc, MeshGatewayAnnotationKind) - - assert.Equal(t, debug, b.logLevelForDataplaneContainer()) - }) - } -} - -func Test_computeAnnotationsOrLabels(t *testing.T) { - gatewaySet := map[string]string{ - "service.beta.kubernetes.io/aws-load-balancer-internal": "true", // Will not be inherited - "service.beta.kubernetes.io/aws-load-balancer-name": "my-lb", // Will be inherited - } - - primary := meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{ - "service.beta.kubernetes.io/aws-load-balancer-name", - }, - Set: map[string]string{ - "created-by": "nathancoleman", // Only exists in primary - "owning-team": "consul-gateway-management", // Will override secondary - }, - } - - secondary := meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - InheritFromGateway: []string{}, - Set: map[string]string{ - "created-on": "kubernetes", // Only exists in secondary - "owning-team": "consul", // Will be overridden by primary - }, - } - - actual := computeAnnotationsOrLabels(gatewaySet, primary, secondary) - expected := map[string]string{ - "created-by": "nathancoleman", // Set by primary - "created-on": "kubernetes", // Set by secondary - "owning-team": "consul-gateway-management", // Set by primary, overrode secondary - "service.beta.kubernetes.io/aws-load-balancer-name": "my-lb", // Inherited from gateway - } - - assert.Equal(t, expected, actual) -} diff --git a/control-plane/gateways/role.go b/control-plane/gateways/role.go deleted file mode 100644 index 0cec287b5b..0000000000 --- a/control-plane/gateways/role.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -import ( - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func (b *gatewayBuilder[T]) Role() *rbacv1.Role { - return &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: b.gateway.GetName(), - Namespace: b.gateway.GetNamespace(), - Labels: b.labelsForRole(), - Annotations: b.annotationsForRole(), - }, - Rules: []rbacv1.PolicyRule{}, - } -} - -func (b *gatewayBuilder[T]) RoleBinding() *rbacv1.RoleBinding { - return &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: b.gateway.GetName(), - Namespace: b.gateway.GetNamespace(), - Labels: b.labelsForRoleBinding(), - Annotations: b.annotationsForRoleBinding(), - }, - Subjects: []rbacv1.Subject{ - { - APIGroup: "", - Kind: rbacv1.ServiceAccountKind, - Name: b.gateway.GetName(), - Namespace: b.gateway.GetNamespace(), - }, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: b.Role().Name, - }, - } -} diff --git a/control-plane/gateways/service.go b/control-plane/gateways/service.go deleted file mode 100644 index b60cc42019..0000000000 --- a/control-plane/gateways/service.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -import ( - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" -) - -func (b *gatewayBuilder[T]) Service() *corev1.Service { - var ( - containerConfig *meshv2beta1.GatewayClassContainerConfig - portModifier = int32(0) - serviceType = corev1.ServiceType("") - ) - - if b.gcc != nil { - containerConfig = b.gcc.Spec.Deployment.Container - portModifier = containerConfig.PortModifier - serviceType = *b.gcc.Spec.Service.Type - } - - return &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: b.gateway.GetName(), - Namespace: b.gateway.GetNamespace(), - Labels: b.labelsForService(), - Annotations: b.annotationsForService(), - }, - Spec: corev1.ServiceSpec{ - Selector: b.labelsForDeployment(), - Type: serviceType, - Ports: b.gateway.ListenersToServicePorts(portModifier), - }, - } -} - -// MergeService is used to update a corev1.Service without overwriting any -// existing annotations or labels that were placed there by other vendors. -// -// based on https://github.com/kubernetes-sigs/controller-runtime/blob/4000e996a202917ad7d40f02ed8a2079a9ce25e9/pkg/controller/controllerutil/example_test.go -func MergeService(existing, desired *corev1.Service) { - existing.Spec = desired.Spec - - // Only overwrite fields if the Service doesn't exist yet - if existing.ObjectMeta.CreationTimestamp.IsZero() { - existing.ObjectMeta.OwnerReferences = desired.ObjectMeta.OwnerReferences - existing.Annotations = desired.Annotations - existing.Labels = desired.Labels - return - } - - // If the Service already exists, add any desired annotations + labels to existing set - for k, v := range desired.ObjectMeta.Annotations { - existing.ObjectMeta.Annotations[k] = v - } - for k, v := range desired.ObjectMeta.Labels { - existing.ObjectMeta.Labels[k] = v - } -} diff --git a/control-plane/gateways/service_test.go b/control-plane/gateways/service_test.go deleted file mode 100644 index 19e9a0e71d..0000000000 --- a/control-plane/gateways/service_test.go +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -import ( - "testing" - - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" - - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" -) - -func Test_gatewayBuilder_meshGateway_Service(t *testing.T) { - lbType := corev1.ServiceTypeLoadBalancer - - type fields struct { - gateway *meshv2beta1.MeshGateway - config GatewayConfig - gcc *meshv2beta1.GatewayClassConfig - } - tests := []struct { - name string - fields fields - want *corev1.Service - }{ - { - name: "service resource crd created - happy path", - fields: fields{ - gateway: &meshv2beta1.MeshGateway{ - Spec: pbmesh.MeshGateway{ - GatewayClassName: "test-gateway-class", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 443, - Protocol: "TCP", - }, - }, - }, - }, - config: GatewayConfig{}, - gcc: &meshv2beta1.GatewayClassConfig{ - Spec: meshv2beta1.GatewayClassConfigSpec{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Labels: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - Set: map[string]string{ - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - }, - }, - Deployment: meshv2beta1.GatewayClassDeploymentConfig{ - Container: &meshv2beta1.GatewayClassContainerConfig{ - PortModifier: 8000, - }, - }, - Service: meshv2beta1.GatewayClassServiceConfig{ - Type: &lbType, - }, - }, - }, - }, - want: &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - Annotations: map[string]string{}, - }, - Spec: corev1.ServiceSpec{ - Selector: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - Type: corev1.ServiceTypeLoadBalancer, - Ports: []corev1.ServicePort{ - { - Name: "wan", - Port: int32(443), - TargetPort: intstr.IntOrString{ - IntVal: int32(8443), - }, - Protocol: "TCP", - }, - }, - }, - Status: corev1.ServiceStatus{}, - }, - }, - { - name: "create service resource crd - gcc is nil", - fields: fields{ - gateway: &meshv2beta1.MeshGateway{ - Spec: pbmesh.MeshGateway{ - GatewayClassName: "test-gateway-class", - Listeners: []*pbmesh.MeshGatewayListener{ - { - Name: "wan", - Port: 443, - Protocol: "TCP", - }, - }, - }, - }, - config: GatewayConfig{}, - gcc: nil, - }, - want: &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Labels: defaultLabels, - Annotations: map[string]string{}, - }, - Spec: corev1.ServiceSpec{ - Selector: defaultLabels, - Type: "", - Ports: []corev1.ServicePort{ - { - Name: "wan", - Port: int32(443), - TargetPort: intstr.IntOrString{ - IntVal: int32(443), - }, - Protocol: "TCP", - }, - }, - }, - Status: corev1.ServiceStatus{}, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - b := &gatewayBuilder[*meshv2beta1.MeshGateway]{ - gateway: tt.fields.gateway, - config: tt.fields.config, - gcc: tt.fields.gcc, - } - result := b.Service() - assert.Equalf(t, tt.want, result, "Service()") - }) - } -} - -func Test_MergeService(t *testing.T) { - testCases := []struct { - name string - a, b *corev1.Service - assertFn func(*testing.T, *corev1.Service) - }{ - { - name: "new service gets desired annotations + labels", - a: &corev1.Service{ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "service"}}, - b: &corev1.Service{ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "service", - Annotations: map[string]string{"b": "b"}, - Labels: map[string]string{"b": "b"}, - }}, - assertFn: func(t *testing.T, result *corev1.Service) { - assert.Equal(t, map[string]string{"b": "b"}, result.Annotations) - assert.Equal(t, map[string]string{"b": "b"}, result.Labels) - }, - }, - { - name: "existing service keeps existing annotations + labels and gains desired annotations + labels + type", - a: &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "service", - CreationTimestamp: metav1.Now(), - Annotations: map[string]string{"a": "a"}, - Labels: map[string]string{"a": "a"}, - }, - Spec: corev1.ServiceSpec{ - Type: corev1.ServiceTypeClusterIP, - }, - }, - b: &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "service", - Annotations: map[string]string{"b": "b"}, - Labels: map[string]string{"b": "b"}, - }, - Spec: corev1.ServiceSpec{ - Type: corev1.ServiceTypeLoadBalancer, - }, - }, - assertFn: func(t *testing.T, result *corev1.Service) { - assert.Equal(t, map[string]string{"a": "a", "b": "b"}, result.Annotations) - assert.Equal(t, map[string]string{"a": "a", "b": "b"}, result.Labels) - - assert.Equal(t, corev1.ServiceTypeLoadBalancer, result.Spec.Type) - }, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - MergeService(testCase.a, testCase.b) - testCase.assertFn(t, testCase.a) - }) - } -} - -func Test_gatewayBuilder_apiGateway_Service(t *testing.T) { - lbType := corev1.ServiceTypeLoadBalancer - - type fields struct { - gateway *meshv2beta1.APIGateway - config GatewayConfig - gcc *meshv2beta1.GatewayClassConfig - } - tests := []struct { - name string - fields fields - want *corev1.Service - }{ - { - name: "service resource crd created - happy path", - fields: fields{ - gateway: &meshv2beta1.APIGateway{ - Spec: pbmesh.APIGateway{ - GatewayClassName: "test-gateway-class", - Listeners: []*pbmesh.APIGatewayListener{ - { - Name: "http-listener", - Port: 80, - Protocol: "http", - }, - }, - }, - }, - config: GatewayConfig{}, - gcc: &meshv2beta1.GatewayClassConfig{ - Spec: meshv2beta1.GatewayClassConfigSpec{ - GatewayClassAnnotationsAndLabels: meshv2beta1.GatewayClassAnnotationsAndLabels{ - Labels: meshv2beta1.GatewayClassAnnotationsLabelsConfig{ - Set: map[string]string{ - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - }, - }, - Deployment: meshv2beta1.GatewayClassDeploymentConfig{ - Container: &meshv2beta1.GatewayClassContainerConfig{ - PortModifier: 8000, - }, - }, - Service: meshv2beta1.GatewayClassServiceConfig{ - Type: &lbType, - }, - }, - }, - }, - want: &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - Annotations: map[string]string{}, - }, - Spec: corev1.ServiceSpec{ - Selector: map[string]string{ - labelManagedBy: "consul-k8s", - "app": "consul", - "chart": "consul-helm", - "heritage": "Helm", - "release": "consul", - }, - Type: corev1.ServiceTypeLoadBalancer, - Ports: []corev1.ServicePort{ - { - Name: "http-listener", - Port: int32(80), - TargetPort: intstr.IntOrString{ - IntVal: int32(8080), - }, - Protocol: "http", - }, - }, - }, - Status: corev1.ServiceStatus{}, - }, - }, - { - name: "create service resource crd - gcc is nil", - fields: fields{ - gateway: &meshv2beta1.APIGateway{ - Spec: pbmesh.APIGateway{ - GatewayClassName: "test-gateway-class", - Listeners: []*pbmesh.APIGatewayListener{ - { - Name: "http-listener", - Port: 80, - Protocol: "http", - }, - }, - }, - }, - config: GatewayConfig{}, - gcc: nil, - }, - want: &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Labels: defaultLabels, - Annotations: map[string]string{}, - }, - Spec: corev1.ServiceSpec{ - Selector: defaultLabels, - Type: "", - Ports: []corev1.ServicePort{ - { - Name: "http-listener", - Port: int32(80), - TargetPort: intstr.IntOrString{ - IntVal: int32(80), - }, - Protocol: "http", - }, - }, - }, - Status: corev1.ServiceStatus{}, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - b := &gatewayBuilder[*meshv2beta1.APIGateway]{ - gateway: tt.fields.gateway, - config: tt.fields.config, - gcc: tt.fields.gcc, - } - result := b.Service() - assert.Equalf(t, tt.want, result, "Service()") - }) - } -} diff --git a/control-plane/gateways/serviceaccount.go b/control-plane/gateways/serviceaccount.go deleted file mode 100644 index 8b740cbd76..0000000000 --- a/control-plane/gateways/serviceaccount.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -import ( - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func (b *gatewayBuilder[T]) ServiceAccount() *corev1.ServiceAccount { - return &corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: b.serviceAccountName(), - Namespace: b.gateway.GetNamespace(), - Labels: b.labelsForServiceAccount(), - Annotations: b.annotationsForServiceAccount(), - }, - } -} - -func (b *gatewayBuilder[T]) serviceAccountName() string { - return b.gateway.GetName() -} diff --git a/control-plane/gateways/serviceaccount_test.go b/control-plane/gateways/serviceaccount_test.go deleted file mode 100644 index 7436beb683..0000000000 --- a/control-plane/gateways/serviceaccount_test.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package gateways - -import ( - "testing" - - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" -) - -func TestNewMeshGatewayBuilder_ServiceAccount(t *testing.T) { - b := NewGatewayBuilder(&meshv2beta1.MeshGateway{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - }, - }, GatewayConfig{}, nil, MeshGatewayAnnotationKind) - - expected := &corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "mesh-gateway", - Labels: defaultLabels, - Annotations: map[string]string{}, - }, - } - - assert.Equal(t, expected, b.ServiceAccount()) -} diff --git a/control-plane/go.mod b/control-plane/go.mod index f51b417f48..40895f68c4 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -1,11 +1,5 @@ module github.com/hashicorp/consul-k8s/control-plane -// TODO: Remove this when the next version of the submodule is released. -// We need to use a replace directive instead of directly pinning because `api` requires version `0.5.1` and will clobber the pin, but not the replace directive. -replace github.com/hashicorp/consul/proto-public => github.com/hashicorp/consul/proto-public v0.1.2-0.20240207215339-2456fe5148bd - -replace github.com/hashicorp/consul/sdk => github.com/hashicorp/consul/sdk v0.4.1-0.20231213150639-123bc95e1a3f - require ( github.com/cenkalti/backoff v2.2.1+incompatible github.com/containernetworking/cni v1.1.2 @@ -17,7 +11,7 @@ require ( github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20230825213844-4ea04860c5ed github.com/hashicorp/consul-server-connection-manager v0.1.6 - github.com/hashicorp/consul/api v1.10.1-0.20240122152324-758ddf84e9c9 + github.com/hashicorp/consul/api v1.10.1-0.20240122160221-1c7e9443cbcd github.com/hashicorp/consul/proto-public v0.5.1 github.com/hashicorp/consul/sdk v0.15.0 github.com/hashicorp/go-bexpr v0.1.11 @@ -43,15 +37,14 @@ require ( gomodules.xyz/jsonpatch/v2 v2.3.0 google.golang.org/grpc v1.58.3 google.golang.org/protobuf v1.31.0 - gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.26.12 - k8s.io/apimachinery v0.26.12 - k8s.io/client-go v0.26.12 + gopkg.in/yaml.v2 v2.4.0 + k8s.io/api v0.26.10 + k8s.io/apimachinery v0.26.10 + k8s.io/client-go v0.26.10 k8s.io/klog/v2 v2.100.1 - k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 + k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 sigs.k8s.io/controller-runtime v0.14.7 sigs.k8s.io/gateway-api v0.7.1 - sigs.k8s.io/yaml v1.3.0 ) require ( @@ -169,12 +162,13 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/resty.v1 v1.12.0 // 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/apiextensions-apiserver v0.26.10 // indirect k8s.io/component-base v0.26.10 // indirect k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) go 1.20 diff --git a/control-plane/go.sum b/control-plane/go.sum index 5d66eb73e7..69275b0ccb 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -273,12 +273,12 @@ github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20230825213844-4ea04860 github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20230825213844-4ea04860c5ed/go.mod h1:mwODEC+VTCA1LY/m2RUG4S2c5lNRvBcsvqaMJtMLLos= github.com/hashicorp/consul-server-connection-manager v0.1.6 h1:ktj8Fi+dRXn9hhM+FXsfEJayhzzgTqfH08Ne5M6Fmug= github.com/hashicorp/consul-server-connection-manager v0.1.6/go.mod h1:HngMIv57MT+pqCVeRQMa1eTB5dqnyMm8uxjyv+Hn8cs= -github.com/hashicorp/consul/api v1.10.1-0.20240122152324-758ddf84e9c9 h1:qaS6rE768dt5hGPl2y4DIABXF4eA23BNSmWFpEr3kWQ= -github.com/hashicorp/consul/api v1.10.1-0.20240122152324-758ddf84e9c9/go.mod h1:gInwZGrnWlE1Vvq6rSD5pUf6qwNa69NTLLknbdwQRUk= -github.com/hashicorp/consul/proto-public v0.1.2-0.20240207215339-2456fe5148bd h1:xNTNL7j7qNNhH68bxHabcsS3GKL6T1OEMYDbbxJ42qI= -github.com/hashicorp/consul/proto-public v0.1.2-0.20240207215339-2456fe5148bd/go.mod h1:JF6983XNCzvw4wDNOLEwLqOq2IPw7iyT+pkswHSz08U= -github.com/hashicorp/consul/sdk v0.4.1-0.20231213150639-123bc95e1a3f h1:GKsa7bfoL7xgvCkzYJMF9eYYNfLWQyk8QuRZZl4nMTo= -github.com/hashicorp/consul/sdk v0.4.1-0.20231213150639-123bc95e1a3f/go.mod h1:r/OmRRPbHOe0yxNahLw7G9x5WG17E1BIECMtCjcPSNo= +github.com/hashicorp/consul/api v1.10.1-0.20240122160221-1c7e9443cbcd h1:M98X+hMQSPtK5xpAFuSGlgh4eE2py9UNmB1S6w6/a6c= +github.com/hashicorp/consul/api v1.10.1-0.20240122160221-1c7e9443cbcd/go.mod h1:gInwZGrnWlE1Vvq6rSD5pUf6qwNa69NTLLknbdwQRUk= +github.com/hashicorp/consul/proto-public v0.5.1 h1:g4xHZ7rJ56iktDi1uThKp+IbvHrP6nveZeGVt2Qw5x0= +github.com/hashicorp/consul/proto-public v0.5.1/go.mod h1:SayEhfXS3DQDnW/vKSZXvkwDObg7XK60KTfrJcp0wrg= +github.com/hashicorp/consul/sdk v0.15.0 h1:2qK9nDrr4tiJKRoxPGhm6B7xJjLVIQqkjiab2M4aKjU= +github.com/hashicorp/consul/sdk v0.15.0/go.mod h1:r/OmRRPbHOe0yxNahLw7G9x5WG17E1BIECMtCjcPSNo= 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= @@ -966,22 +966,22 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh 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.12 h1:jJm3s5ot05SUN3tPGg3b+XWuBE7rO/X0+dnVMhxyd5o= -k8s.io/api v0.26.12/go.mod h1:N+HUXukmtXNOKDngxXrEPbZWggWx01tH/N0nG4nV0oo= +k8s.io/api v0.26.10 h1:skTnrDR0r8dg4MMLf6YZIzugxNM0BjFsWKPkNc5kOvk= +k8s.io/api v0.26.10/go.mod h1:ou/H3yviqrHtP/DSPVTfsc7qNfmU06OhajytJfYXkXw= k8s.io/apiextensions-apiserver v0.26.10 h1:wAriTUc6l7gUqJKOxhmXnYo/VNJzk4oh4QLCUR4Uq+k= k8s.io/apiextensions-apiserver v0.26.10/go.mod h1:N2qhlxkhJLSoC4f0M1/1lNG627b45SYqnOPEVFoQXw4= -k8s.io/apimachinery v0.26.12 h1:y+OgufxqLIZtyXIydRhjLBGzrYLF+qwiDdCFXYOjeN4= -k8s.io/apimachinery v0.26.12/go.mod h1:2/HZp0l6coXtS26du1Bk36fCuAEr/lVs9Q9NbpBtd1Y= -k8s.io/client-go v0.26.12 h1:kPpTpIeFNqwo4UyvoqzNp3DNK2mbGcdGv23eS1U8VMo= -k8s.io/client-go v0.26.12/go.mod h1:V7thEnIFroyNZOU30dKLiiVeqQmJz45shJG1mu7nONQ= +k8s.io/apimachinery v0.26.10 h1:aE+J2KIbjctFqPp3Y0q4Wh2PD+l1p2g3Zp4UYjSvtGU= +k8s.io/apimachinery v0.26.10/go.mod h1:iT1ZP4JBP34wwM+ZQ8ByPEQ81u043iqAcsJYftX9amM= +k8s.io/client-go v0.26.10 h1:4mDzl+1IrfRxh4Ro0s65JRGJp14w77gSMUTjACYWVRo= +k8s.io/client-go v0.26.10/go.mod h1:sh74ig838gCckU4ElYclWb24lTesPdEDPnlyg5vcbkA= k8s.io/component-base v0.26.10 h1:vl3Gfe5aC09mNxfnQtTng7u3rnBVrShOK3MAkqEleb0= k8s.io/component-base v0.26.10/go.mod h1:/IDdENUHG5uGxqcofZajovYXE9KSPzJ4yQbkYQt7oN0= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= -k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= -k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +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= diff --git a/control-plane/helper/test/test_util.go b/control-plane/helper/test/test_util.go index df51927e4c..3a80232a23 100644 --- a/control-plane/helper/test/test_util.go +++ b/control-plane/helper/test/test_util.go @@ -20,31 +20,24 @@ import ( "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/sdk/testutil" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/exp/slices" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/protobuf/testing/protocmp" - "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" "github.com/hashicorp/consul-k8s/control-plane/consul" "github.com/hashicorp/consul-k8s/control-plane/helper/cert" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" ) const ( componentAuthMethod = "consul-k8s-component-auth-method" - eventuallyWaitFor = 5 * time.Second - eventuallyTickEvery = 100 * time.Millisecond ) type TestServerClient struct { - TestServer *testutil.TestServer - APIClient *api.Client - Cfg *consul.Config - Watcher consul.ServerConnectionManager - ResourceClient pbresource.ResourceServiceClient + TestServer *testutil.TestServer + APIClient *api.Client + Cfg *consul.Config + Watcher consul.ServerConnectionManager } func TestServerWithMockConnMgrWatcher(t *testing.T, callback testutil.ServerConfigCallback) *TestServerClient { @@ -73,24 +66,11 @@ func TestServerWithMockConnMgrWatcher(t *testing.T, callback testutil.ServerConf client, err := api.NewClient(consulConfig.APIClientConfig) require.NoError(t, err) - requireACLBootstrapped(t, cfg, client) - watcher := MockConnMgrForIPAndPort(t, "127.0.0.1", cfg.Ports.GRPC, true) - - // Create a gRPC resource service client when the resource-apis experiment is enabled. - var resourceClient pbresource.ResourceServiceClient - if slices.Contains(cfg.Experiments, "resource-apis") { - resourceClient, err = consul.NewResourceServiceClient(watcher) - require.NoError(t, err) - } - - requireTenancyBuiltins(t, cfg, client, resourceClient) - return &TestServerClient{ - TestServer: consulServer, - APIClient: client, - Cfg: consulConfig, - Watcher: watcher, - ResourceClient: resourceClient, + TestServer: consulServer, + APIClient: client, + Cfg: consulConfig, + Watcher: MockConnMgrForIPAndPort(t, "127.0.0.1", cfg.Ports.GRPC, true), } } @@ -417,69 +397,3 @@ w7/VeA7lzmj3TQRE/W0U0ZGeoAxn9b6JtT0iMucYvP0hXKTPBWlnzIijamU50r2Y Z23jGuk6rn9DUHC2xPj3wCTmd8SGEJoV31noJV5dVeQ90wusXz3vTG7ficKnvHFS xtr5PSwH1DusYfVaGH2O -----END CERTIFICATE-----` - -func requireTenancyBuiltins(t *testing.T, cfg *testutil.TestServerConfig, client *api.Client, resourceClient pbresource.ResourceServiceClient) { - t.Helper() - - // There is a window of time post-leader election on startup where v2 tenancy builtins - // (default partition and namespace) have not yet been created. - // Wait for them to exist before considering the server "open for business". - // Only check for default namespace existence since it implies the default partition exists. - if slices.Contains(cfg.Experiments, "v2tenancy") { - require.EventuallyWithT(t, func(c *assert.CollectT) { - _, err := resourceClient.Read(context.Background(), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Name: constants.DefaultConsulNS, - Type: pbtenancy.NamespaceType, - Tenancy: &pbresource.Tenancy{Partition: constants.DefaultConsulPartition}, - }, - }) - assert.NoError(c, err) - }, - eventuallyWaitFor, - eventuallyTickEvery, - "failed to eventually read v2 builtin default namespace", - ) - } else { - // Do the same for V1 counterparts in ent only to prevent known test flakes. - require.Eventually(t, - func() bool { - self, err := client.Agent().Self() - if err != nil { - return false - } - if self["DebugConfig"]["VersionMetadata"] != "ent" { - return true - } - - // Check for the default partition instead of the default namespace since this is a thing: - // error="Namespaces are currently disabled until all servers in the datacenter supports the feature" - partition, _, err := client.Partitions().Read( - context.Background(), - constants.DefaultConsulPartition, - nil, - ) - return err == nil && partition != nil - }, - eventuallyWaitFor, - eventuallyTickEvery, - "failed to eventually read v1 builtin default partition") - } -} - -func requireACLBootstrapped(t *testing.T, cfg *testutil.TestServerConfig, client *api.Client) { - t.Helper() - - // Prevent test flakes due to "ACL system must be bootstrapped before ..." error - // by requiring successful retrieval of the initial mgmt token. - if cfg.ACL.Enabled && cfg.ACL.Tokens.InitialManagement != "" { - require.EventuallyWithT(t, func(c *assert.CollectT) { - _, _, err := client.ACL().TokenReadSelf(nil) - assert.NoError(c, err) - }, - eventuallyWaitFor, - eventuallyTickEvery, - "failed to eventually read self token as a proxy for the ACL system bootstrap completion", - ) - } -} diff --git a/control-plane/subcommand/create-federation-secret/command_test.go b/control-plane/subcommand/create-federation-secret/command_test.go index 954882e7f0..29fe3b3d61 100644 --- a/control-plane/subcommand/create-federation-secret/command_test.go +++ b/control-plane/subcommand/create-federation-secret/command_test.go @@ -993,7 +993,7 @@ func TestRun_ConsulClientDelay(t *testing.T) { timer := &retry.Timer{Timeout: 10 * time.Second, Wait: 500 * time.Millisecond} retry.RunWith(timer, t, func(r *retry.R) { var err error - testserver, err = testutil.NewTestServerConfigT(r, func(cfg *testutil.TestServerConfig) { + testserver, err = testutil.NewTestServerConfigT(t, func(cfg *testutil.TestServerConfig) { cfg.CAFile = caFile cfg.CertFile = certFile cfg.KeyFile = keyFile diff --git a/control-plane/subcommand/flags/consul.go b/control-plane/subcommand/flags/consul.go index e155013258..9368b95b3d 100644 --- a/control-plane/subcommand/flags/consul.go +++ b/control-plane/subcommand/flags/consul.go @@ -11,7 +11,6 @@ import ( "strings" "time" - "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" "github.com/hashicorp/consul-k8s/control-plane/consul" "github.com/hashicorp/consul-server-connection-manager/discovery" "github.com/hashicorp/consul/api" @@ -27,6 +26,11 @@ const ( PartitionEnvVar = "CONSUL_PARTITION" DatacenterEnvVar = "CONSUL_DATACENTER" + UseTLSEnvVar = "CONSUL_USE_TLS" + CACertFileEnvVar = "CONSUL_CACERT_FILE" + CACertPEMEnvVar = "CONSUL_CACERT_PEM" + TLSServerNameEnvVar = "CONSUL_TLS_SERVER_NAME" + ACLTokenEnvVar = "CONSUL_ACL_TOKEN" ACLTokenFileEnvVar = "CONSUL_ACL_TOKEN_FILE" @@ -89,7 +93,7 @@ func (f *ConsulFlags) Flags() *flag.FlagSet { // behave as if that env variable is not provided. grpcPort, _ := strconv.Atoi(os.Getenv(GRPCPortEnvVar)) httpPort, _ := strconv.Atoi(os.Getenv(HTTPPortEnvVar)) - useTLS, _ := strconv.ParseBool(os.Getenv(constants.UseTLSEnvVar)) + useTLS, _ := strconv.ParseBool(os.Getenv(UseTLSEnvVar)) skipServerWatch, _ := strconv.ParseBool(os.Getenv(SkipServerWatchEnvVar)) consulLoginMetaFromEnv := os.Getenv(LoginMetaEnvVar) if consulLoginMetaFromEnv != "" { @@ -138,11 +142,11 @@ func (f *ConsulFlags) Flags() *flag.FlagSet { "[Enterprise only] Consul admin partition. Default to \"default\" if Admin Partitions are enabled.") fs.StringVar(&f.Datacenter, "datacenter", os.Getenv(DatacenterEnvVar), "Consul datacenter.") - fs.StringVar(&f.CACertFile, "ca-cert-file", os.Getenv(constants.CACertFileEnvVar), + fs.StringVar(&f.CACertFile, "ca-cert-file", os.Getenv(CACertFileEnvVar), "Path to a CA certificate to use for TLS when communicating with Consul.") - fs.StringVar(&f.CACertPEM, "ca-cert-pem", os.Getenv(constants.CACertPEMEnvVar), + fs.StringVar(&f.CACertPEM, "ca-cert-pem", os.Getenv(CACertPEMEnvVar), "CA certificate PEM to use for TLS when communicating with Consul.") - fs.StringVar(&f.TLSServerName, "tls-server-name", os.Getenv(constants.TLSServerNameEnvVar), + fs.StringVar(&f.TLSServerName, "tls-server-name", os.Getenv(TLSServerNameEnvVar), "The server name to use as the SNI host when connecting via TLS. "+ "This can also be specified via the CONSUL_TLS_SERVER_NAME environment variable.") fs.BoolVar(&f.UseTLS, "use-tls", useTLS, "If true, use TLS for connections to Consul.") diff --git a/control-plane/subcommand/flags/consul_test.go b/control-plane/subcommand/flags/consul_test.go index e51860024c..7f35dc8575 100644 --- a/control-plane/subcommand/flags/consul_test.go +++ b/control-plane/subcommand/flags/consul_test.go @@ -9,7 +9,6 @@ import ( "testing" "time" - "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" "github.com/hashicorp/consul-server-connection-manager/discovery" "github.com/hashicorp/consul/api" "github.com/stretchr/testify/require" @@ -30,10 +29,10 @@ func TestConsulFlags_Flags(t *testing.T) { DatacenterEnvVar: "test-dc", APITimeoutEnvVar: "10s", - constants.UseTLSEnvVar: "true", - constants.CACertFileEnvVar: "path/to/ca.pem", - constants.CACertPEMEnvVar: "test-ca-pem", - constants.TLSServerNameEnvVar: "server.consul", + UseTLSEnvVar: "true", + CACertFileEnvVar: "path/to/ca.pem", + CACertPEMEnvVar: "test-ca-pem", + TLSServerNameEnvVar: "server.consul", ACLTokenEnvVar: "test-token", ACLTokenFileEnvVar: "/path/to/token", @@ -90,7 +89,7 @@ func TestConsulFlags_Flags(t *testing.T) { HTTPPortEnvVar: "not-int-http-port", APITimeoutEnvVar: "10sec", - constants.UseTLSEnvVar: "not-a-bool", + UseTLSEnvVar: "not-a-bool", LoginMetaEnvVar: "key1:value1;key2:value2", }, diff --git a/control-plane/subcommand/gateway-cleanup/command.go b/control-plane/subcommand/gateway-cleanup/command.go index 709f925c66..583b153d01 100644 --- a/control-plane/subcommand/gateway-cleanup/command.go +++ b/control-plane/subcommand/gateway-cleanup/command.go @@ -8,8 +8,6 @@ import ( "errors" "flag" "fmt" - "io" - "os" "sync" "time" @@ -21,38 +19,26 @@ import ( clientgoscheme "k8s.io/client-go/kubernetes/scheme" "sigs.k8s.io/controller-runtime/pkg/client" gwv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - k8syaml "sigs.k8s.io/yaml" - "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" "github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1" - "github.com/hashicorp/consul-k8s/control-plane/gateways" "github.com/hashicorp/consul-k8s/control-plane/subcommand" "github.com/hashicorp/consul-k8s/control-plane/subcommand/flags" ) -const ( - gatewayConfigFilename = "/consul/config/config.yaml" - resourceConfigFilename = "/consul/config/resources.json" -) - type Command struct { UI cli.Ui flags *flag.FlagSet k8s *flags.K8SFlags - flagGatewayClassName string - flagGatewayClassConfigName string - flagGatewayConfigLocation string - flagResourceConfigFileLocation string + flagGatewayClassName string + flagGatewayClassConfigName string k8sClient client.Client once sync.Once help string - gatewayConfig gateways.GatewayResources - ctx context.Context } @@ -64,12 +50,6 @@ func (c *Command) init() { c.flags.StringVar(&c.flagGatewayClassConfigName, "gateway-class-config-name", "", "Name of Kubernetes GatewayClassConfig to delete.") - c.flags.StringVar(&c.flagGatewayConfigLocation, "gateway-config-file-location", gatewayConfigFilename, - "specify a different location for where the gateway config file is") - - c.flags.StringVar(&c.flagResourceConfigFileLocation, "resource-config-file-location", resourceConfigFilename, - "specify a different location for where the gateway resource config file is") - c.k8s = &flags.K8SFlags{} flags.Merge(c.flags, c.k8s.Flags()) c.help = flags.Usage(help, c.flags) @@ -113,11 +93,6 @@ func (c *Command) Run(args []string) int { return 1 } - if err := v2beta1.AddMeshToScheme(s); err != nil { - c.UI.Error(fmt.Sprintf("Could not add consul-k8s schema: %s", err)) - return 1 - } - c.k8sClient, err = client.New(config, client.Options{Scheme: s}) if err != nil { c.UI.Error(fmt.Sprintf("Error initializing Kubernetes client: %s", err)) @@ -127,66 +102,32 @@ func (c *Command) Run(args []string) int { // do the cleanup - //V1 Cleanup - err = c.deleteV1GatewayClassAndGatewayClasConfig() - if err != nil { - c.UI.Error(err.Error()) - return 1 - } - - //V2 Cleanup - err = c.loadGatewayConfigs() - if err != nil { - - c.UI.Error(err.Error()) - return 1 - } - err = c.deleteV2GatewayClassAndClassConfigs(c.ctx) - if err != nil { - c.UI.Error(err.Error()) - - return 1 - } - - err = c.deleteV2MeshGateways(c.ctx) - if err != nil { - c.UI.Error(err.Error()) - - return 1 - } - - return 0 -} - -func (c *Command) deleteV1GatewayClassAndGatewayClasConfig() error { // find the class config and mark it for deletion first so that we // can do an early return if the gateway class isn't found config := &v1alpha1.GatewayClassConfig{} - err := c.k8sClient.Get(context.Background(), types.NamespacedName{Name: c.flagGatewayClassConfigName}, config) + err = c.k8sClient.Get(context.Background(), types.NamespacedName{Name: c.flagGatewayClassConfigName}, config) if err != nil { - if k8serrors.IsNotFound(err) { // no gateway class config, just ignore and return - return nil + return 0 } c.UI.Error(err.Error()) - return err + return 1 } // ignore any returned errors _ = c.k8sClient.Delete(context.Background(), config) // find the gateway class - gatewayClass := &gwv1beta1.GatewayClass{} err = c.k8sClient.Get(context.Background(), types.NamespacedName{Name: c.flagGatewayClassName}, gatewayClass) if err != nil { if k8serrors.IsNotFound(err) { // no gateway class, just ignore and return - return nil + return 0 } c.UI.Error(err.Error()) - return err + return 1 } // ignore any returned errors @@ -210,7 +151,8 @@ func (c *Command) deleteV1GatewayClassAndGatewayClasConfig() error { // if we failed, return 0 anyway after logging the error // since we don't want to block someone from uninstallation } - return nil + + return 0 } func (c *Command) validateFlags() error { @@ -250,106 +192,3 @@ func exponentialBackoffWithMaxIntervalAndTime() *backoff.ExponentialBackOff { backoff.Reset() return backoff } - -// loadGatewayConfigs reads and loads the configs from `/consul/config/config.yaml`, if this file does not exist nothing is done. -func (c *Command) loadGatewayConfigs() error { - file, err := os.Open(c.flagGatewayConfigLocation) - if err != nil { - if os.IsNotExist(err) { - c.UI.Warn(fmt.Sprintf("gateway configuration file not found, skipping gateway configuration, filename: %s", c.flagGatewayConfigLocation)) - return nil - } - c.UI.Error(fmt.Sprintf("Error opening gateway configuration file %s: %s", c.flagGatewayConfigLocation, err)) - return err - } - - config, err := io.ReadAll(file) - if err != nil { - c.UI.Error(fmt.Sprintf("Error reading gateway configuration file %s: %s", c.flagGatewayConfigLocation, err)) - return err - } - - err = k8syaml.Unmarshal(config, &c.gatewayConfig) - if err != nil { - c.UI.Error(fmt.Sprintf("Error decoding gateway config file: %s", err)) - return err - } - - if err := file.Close(); err != nil { - return err - } - return nil -} - -func (c *Command) deleteV2GatewayClassAndClassConfigs(ctx context.Context) error { - for _, gcc := range c.gatewayConfig.GatewayClassConfigs { - - // find the class config and mark it for deletion first so that we - // can do an early return if the gateway class isn't found - config := &v2beta1.GatewayClassConfig{} - err := c.k8sClient.Get(ctx, types.NamespacedName{Name: gcc.Name, Namespace: gcc.Namespace}, config) - if err != nil { - if k8serrors.IsNotFound(err) { - // no gateway class config, just ignore and continue - continue - } - return err - } - - // ignore any returned errors - _ = c.k8sClient.Delete(context.Background(), config) - - // find the gateway class - gatewayClass := &v2beta1.GatewayClass{} - //TODO: NET-6838 To pull the GatewayClassName from the Configmap - err = c.k8sClient.Get(ctx, types.NamespacedName{Name: gcc.Name, Namespace: gcc.Namespace}, gatewayClass) - if err != nil { - if k8serrors.IsNotFound(err) { - // no gateway class, just ignore and continue - continue - } - return err - } - - // ignore any returned errors - _ = c.k8sClient.Delete(context.Background(), gatewayClass) - - // make sure they're gone - if err := backoff.Retry(func() error { - err = c.k8sClient.Get(context.Background(), types.NamespacedName{Name: gcc.Name, Namespace: gcc.Namespace}, config) - if err == nil || !k8serrors.IsNotFound(err) { - return errors.New("gateway class config still exists") - } - - err = c.k8sClient.Get(context.Background(), types.NamespacedName{Name: gcc.Name, Namespace: gcc.Namespace}, gatewayClass) - if err == nil || !k8serrors.IsNotFound(err) { - return errors.New("gateway class still exists") - } - - return nil - }, exponentialBackoffWithMaxIntervalAndTime()); err != nil { - c.UI.Error(err.Error()) - // if we failed, return 0 anyway after logging the error - // since we don't want to block someone from uninstallation - } - } - - return nil -} - -func (c *Command) deleteV2MeshGateways(ctx context.Context) error { - for _, meshGw := range c.gatewayConfig.MeshGateways { - _ = c.k8sClient.Delete(ctx, meshGw) - - err := c.k8sClient.Get(ctx, types.NamespacedName{Name: meshGw.Name, Namespace: meshGw.Namespace}, meshGw) - if err != nil { - if k8serrors.IsNotFound(err) { - // no gateway, just ignore and continue - continue - } - return err - } - - } - return nil -} diff --git a/control-plane/subcommand/gateway-cleanup/command_test.go b/control-plane/subcommand/gateway-cleanup/command_test.go index 69c626db6c..038c5b5667 100644 --- a/control-plane/subcommand/gateway-cleanup/command_test.go +++ b/control-plane/subcommand/gateway-cleanup/command_test.go @@ -4,9 +4,6 @@ package gatewaycleanup import ( - "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - corev1 "k8s.io/api/core/v1" - "os" "testing" "github.com/mitchellh/cli" @@ -55,7 +52,6 @@ func TestRun(t *testing.T) { s := runtime.NewScheme() require.NoError(t, gwv1beta1.Install(s)) require.NoError(t, v1alpha1.AddToScheme(s)) - require.NoError(t, v2beta1.AddMeshToScheme(s)) objs := []client.Object{} if tt.gatewayClass != nil { @@ -86,165 +82,3 @@ func TestRun(t *testing.T) { }) } } - -func TestRunV2Resources(t *testing.T) { - t.Parallel() - - for name, tt := range map[string]struct { - gatewayClassConfig []*v2beta1.GatewayClassConfig - gatewayClass []*v2beta1.GatewayClass - configMapData string - }{ - - "v2 resources exists": { - gatewayClassConfig: []*v2beta1.GatewayClassConfig{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gateway", - }, - }, - }, - gatewayClass: []*v2beta1.GatewayClass{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gateway", - }, - }, - }, - configMapData: `gatewayClassConfigs: -- apiVersion: mesh.consul.hashicorp.com/v2beta1 - kind: GatewayClassConfig - metadata: - name: test-gateway - spec: - deployment: - container: - resources: - requests: - cpu: 200m - memory: 200Mi - limits: - cpu: 200m - memory: 200Mi -`, - }, - "multiple v2 resources exists": { - gatewayClassConfig: []*v2beta1.GatewayClassConfig{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gateway", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gateway2", - }, - }, - }, - gatewayClass: []*v2beta1.GatewayClass{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gateway", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gateway2", - }, - }, - }, - configMapData: `gatewayClassConfigs: -- apiVersion: mesh.consul.hashicorp.com/v2beta1 - kind: GatewayClassConfig - metadata: - name: test-gateway - spec: - deployment: - container: - resources: - requests: - cpu: 200m - memory: 200Mi - limits: - cpu: 200m - memory: 200Mi -- apiVersion: mesh.consul.hashicorp.com/v2beta1 - kind: GatewayClassConfig - metadata: - name: test-gateway2 - spec: - deployment: - container: - resources: - requests: - cpu: 200m - memory: 200Mi - limits: - cpu: 200m - memory: 200Mi -`, - }, - "v2 emptyconfigmap": { - configMapData: "", - }, - } { - t.Run(name, func(t *testing.T) { - tt := tt - - t.Parallel() - - s := runtime.NewScheme() - require.NoError(t, gwv1beta1.Install(s)) - require.NoError(t, v2beta1.AddMeshToScheme(s)) - require.NoError(t, corev1.AddToScheme(s)) - require.NoError(t, v1alpha1.AddToScheme(s)) - - objs := []client.Object{} - for _, gatewayClass := range tt.gatewayClass { - objs = append(objs, gatewayClass) - } - for _, gatewayClassConfig := range tt.gatewayClassConfig { - objs = append(objs, gatewayClassConfig) - } - - path := createGatewayConfigFile(t, tt.configMapData, "config.yaml") - - client := fake.NewClientBuilder().WithScheme(s).WithObjects(objs...).Build() - - ui := cli.NewMockUi() - cmd := Command{ - UI: ui, - k8sClient: client, - flagGatewayClassName: "gateway-class", - flagGatewayClassConfigName: "gateway-class-config", - flagGatewayConfigLocation: path, - } - - code := cmd.Run([]string{ - "-gateway-class-config-name", "gateway-class-config", - "-gateway-class-name", "gateway-class", - "-gateway-config-file-location", path, - }) - - require.Equal(t, 0, code) - }) - } -} - -func createGatewayConfigFile(t *testing.T, fileContent, filename string) string { - t.Helper() - - // create a temp file to store configuration yaml - tmpdir := t.TempDir() - file, err := os.CreateTemp(tmpdir, filename) - if err != nil { - t.Fatal(err) - } - defer file.Close() - - _, err = file.WriteString(fileContent) - if err != nil { - t.Fatal(err) - } - return file.Name() -} diff --git a/control-plane/subcommand/gateway-resources/command.go b/control-plane/subcommand/gateway-resources/command.go index 911fb0afd9..ea4338f2d3 100644 --- a/control-plane/subcommand/gateway-resources/command.go +++ b/control-plane/subcommand/gateway-resources/command.go @@ -16,8 +16,9 @@ import ( "github.com/cenkalti/backoff" "github.com/mitchellh/cli" - "gopkg.in/yaml.v3" + "gopkg.in/yaml.v2" corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -25,24 +26,13 @@ import ( clientgoscheme "k8s.io/client-go/kubernetes/scheme" "sigs.k8s.io/controller-runtime/pkg/client" gwv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - k8syaml "sigs.k8s.io/yaml" - - authv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/auth/v2beta1" "github.com/hashicorp/consul-k8s/control-plane/api-gateway/common" - "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" "github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1" - "github.com/hashicorp/consul-k8s/control-plane/gateways" "github.com/hashicorp/consul-k8s/control-plane/subcommand" "github.com/hashicorp/consul-k8s/control-plane/subcommand/flags" ) -const ( - gatewayConfigFilename = "/consul/config/config.yaml" - resourceConfigFilename = "/consul/config/resources.json" - meshGatewayComponent = "consul-mesh-gateway" -) - // this dupes the Kubernetes tolerations // struct with yaml tags for validation. type toleration struct { @@ -83,9 +73,6 @@ type Command struct { flagDeploymentMaxInstances int flagDeploymentMinInstances int - flagResourceConfigFileLocation string - flagGatewayConfigLocation string - flagNodeSelector string // this is a yaml multiline string map flagTolerations string // this is a multiline yaml string matching the tolerations array flagServiceAnnotations string // this is a multiline yaml string array of annotations to allow @@ -103,7 +90,6 @@ type Command struct { tolerations []corev1.Toleration serviceAnnotations []string resources corev1.ResourceRequirements - gatewayConfig gateways.GatewayResources ctx context.Context } @@ -156,12 +142,6 @@ func (c *Command) init() { "gateway container.", ) - c.flags.StringVar(&c.flagGatewayConfigLocation, "gateway-config-file-location", gatewayConfigFilename, - "specify a different location for where the gateway config file is") - - c.flags.StringVar(&c.flagResourceConfigFileLocation, "resource-config-file-location", resourceConfigFilename, - "specify a different location for where the gateway resource config file is") - c.k8s = &flags.K8SFlags{} flags.Merge(c.flags, c.k8s.Flags()) c.help = flags.Usage(help, c.flags) @@ -179,15 +159,9 @@ func (c *Command) Run(args []string) int { return 1 } - // Load apigw resource config from the configmap. - if c.resources, err = c.loadResourceConfig(c.flagResourceConfigFileLocation); err != nil { - c.UI.Error(fmt.Sprintf("Error loading api-gateway resource config: %s", err)) - return 1 - } - - // Load gateway config from the configmap. - if err := c.loadGatewayConfigs(); err != nil { - c.UI.Error(fmt.Sprintf("Error loading gateway config: %s", err)) + // Load config from the configmap. + if err := c.loadConfig(); err != nil { + c.UI.Error(fmt.Sprintf("Error loading config: %s", err)) return 1 } @@ -217,16 +191,6 @@ func (c *Command) Run(args []string) int { return 1 } - if err := authv2beta1.AddAuthToScheme(s); err != nil { - c.UI.Error(fmt.Sprintf("Could not add authv2beta schema: %s", err)) - return 1 - } - - if err := v2beta1.AddMeshToScheme(s); err != nil { - c.UI.Error(fmt.Sprintf("Could not add meshv2 schema: %s", err)) - return 1 - } - c.k8sClient, err = client.New(config, client.Options{Scheme: s}) if err != nil { c.UI.Error(fmt.Sprintf("Error initializing Kubernetes client: %s", err)) @@ -235,6 +199,7 @@ func (c *Command) Run(args []string) int { } // do the creation + labels := map[string]string{ "app": c.flagApp, "chart": c.flagChart, @@ -274,31 +239,15 @@ func (c *Command) Run(args []string) int { }, } - if err := forceV1ClassConfig(context.Background(), c.k8sClient, classConfig); err != nil { + if err := forceClassConfig(context.Background(), c.k8sClient, classConfig); err != nil { c.UI.Error(err.Error()) return 1 } - if err := forceV1Class(context.Background(), c.k8sClient, class); err != nil { + if err := forceClass(context.Background(), c.k8sClient, class); err != nil { c.UI.Error(err.Error()) return 1 } - if len(c.gatewayConfig.GatewayClassConfigs) > 0 { - err = c.createV2GatewayClassAndClassConfigs(context.Background(), meshGatewayComponent, "consul-mesh-gateway-controller") - if err != nil { - c.UI.Error(err.Error()) - return 1 - } - } - - if len(c.gatewayConfig.MeshGateways) > 0 { - err = c.createV2MeshGateways(context.Background(), meshGatewayComponent) - if err != nil { - c.UI.Error(err.Error()) - return 1 - } - } - return 0 } @@ -339,7 +288,11 @@ func (c *Command) validateFlags() error { return fmt.Errorf("error decoding node selector: %w", err) } } - + if c.flagNodeSelector != "" { + if err := yaml.Unmarshal([]byte(c.flagNodeSelector), &c.nodeSelector); err != nil { + return fmt.Errorf("error decoding node selector: %w", err) + } + } if c.flagServiceAnnotations != "" { if err := yaml.Unmarshal([]byte(c.flagServiceAnnotations), &c.serviceAnnotations); err != nil { return fmt.Errorf("error decoding service annotations: %w", err) @@ -349,138 +302,43 @@ func (c *Command) validateFlags() error { return nil } -func (c *Command) loadResourceConfig(filename string) (corev1.ResourceRequirements, error) { +func (c *Command) loadConfig() error { // Load resources.json - file, err := os.Open(filename) + file, err := os.Open("/consul/config/resources.json") if err != nil { if !os.IsNotExist(err) { - return corev1.ResourceRequirements{}, err + return err } c.UI.Info("No resources.json found, using defaults") - return defaultResourceRequirements, nil + c.resources = defaultResourceRequirements() + return nil } resources, err := io.ReadAll(file) if err != nil { c.UI.Error(fmt.Sprintf("Unable to read resources.json, using defaults: %s", err)) - return defaultResourceRequirements, err - } - - reqs := corev1.ResourceRequirements{} - if err := json.Unmarshal(resources, &reqs); err != nil { - return corev1.ResourceRequirements{}, err - } - - if err := file.Close(); err != nil { - return corev1.ResourceRequirements{}, err - } - return reqs, nil -} - -// loadGatewayConfigs reads and loads the configs from `/consul/config/config.yaml`, if this file does not exist nothing is done. -func (c *Command) loadGatewayConfigs() error { - file, err := os.Open(c.flagGatewayConfigLocation) - if err != nil { - if os.IsNotExist(err) { - c.UI.Warn(fmt.Sprintf("gateway configuration file not found, skipping gateway configuration, filename: %s", c.flagGatewayConfigLocation)) - return nil - } - c.UI.Error(fmt.Sprintf("Error opening gateway configuration file %s: %s", c.flagGatewayConfigLocation, err)) + c.resources = defaultResourceRequirements() return err } - config, err := io.ReadAll(file) - if err != nil { - c.UI.Error(fmt.Sprintf("Error reading gateway configuration file %s: %s", c.flagGatewayConfigLocation, err)) - return err - } - - err = k8syaml.Unmarshal(config, &c.gatewayConfig) - if err != nil { - c.UI.Error(fmt.Sprintf("Error decoding gateway config file: %s", err)) + if err := json.Unmarshal(resources, &c.resources); err != nil { return err } - // ensure default resources requirements are set - for idx := range c.gatewayConfig.MeshGateways { - if c.gatewayConfig.GatewayClassConfigs[idx].Spec.Deployment.Container == nil { - c.gatewayConfig.GatewayClassConfigs[idx].Spec.Deployment.Container = &v2beta1.GatewayClassContainerConfig{Resources: &defaultResourceRequirements} - } - } if err := file.Close(); err != nil { return err } return nil } -// createV2GatewayClassAndClassConfigs utilizes the configuration loaded from the gateway config file to -// create the GatewayClassConfig and GatewayClass for the gateway. -func (c *Command) createV2GatewayClassAndClassConfigs(ctx context.Context, component, controllerName string) error { - labels := map[string]string{ - "app": c.flagApp, - "chart": c.flagChart, - "heritage": c.flagHeritage, - "release": c.flagRelease, - "component": component, - } - - for _, cfg := range c.gatewayConfig.GatewayClassConfigs { - err := forceV2ClassConfig(ctx, c.k8sClient, cfg) - if err != nil { - return err - } - - class := &v2beta1.GatewayClass{ - ObjectMeta: metav1.ObjectMeta{Name: cfg.Name, Labels: labels}, - TypeMeta: metav1.TypeMeta{Kind: v2beta1.KindGatewayClass}, - Spec: v2beta1.GatewayClassSpec{ - ControllerName: controllerName, - ParametersRef: &v2beta1.ParametersReference{ - Group: v2beta1.MeshGroup, - Kind: v2beta1.KindGatewayClassConfig, - Namespace: &cfg.Namespace, - Name: cfg.Name, - }, - }, - } - - err = forceV2Class(ctx, c.k8sClient, class) - if err != nil { - return err - } - } - - return nil -} - -func (c *Command) createV2MeshGateways(ctx context.Context, component string) error { - labels := map[string]string{ - "app": c.flagApp, - "chart": c.flagChart, - "heritage": c.flagHeritage, - "release": c.flagRelease, - "component": component, - } - for _, meshGw := range c.gatewayConfig.MeshGateways { - meshGw.Labels = labels - err := forceV2MeshGateway(ctx, c.k8sClient, meshGw) - if err != nil { - return err - } - - } - return nil -} - func (c *Command) Synopsis() string { return synopsis } func (c *Command) Help() string { c.once.Do(c.init) return c.help } -const ( - synopsis = "Create managed gateway resources after installation/upgrade." - help = ` +const synopsis = "Create managed gateway resources after installation/upgrade." +const help = ` Usage: consul-k8s-control-plane gateway-resources [options] Installs managed gateway class and configuration resources @@ -488,20 +346,22 @@ Usage: consul-k8s-control-plane gateway-resources [options] dependencies of CRDs being in-place prior to resource creation. ` -) -var defaultResourceRequirements = corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("100Mi"), - corev1.ResourceCPU: resource.MustParse("100m"), - }, - Limits: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("100Mi"), - corev1.ResourceCPU: resource.MustParse("100m"), - }, +func defaultResourceRequirements() v1.ResourceRequirements { + // This is a fallback. The resource.json file should be present unless explicitly removed. + return v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceMemory: resource.MustParse("100Mi"), + v1.ResourceCPU: resource.MustParse("100m"), + }, + Limits: v1.ResourceList{ + v1.ResourceMemory: resource.MustParse("100Mi"), + v1.ResourceCPU: resource.MustParse("100m"), + }, + } } -func forceV1ClassConfig(ctx context.Context, k8sClient client.Client, o *v1alpha1.GatewayClassConfig) error { +func forceClassConfig(ctx context.Context, k8sClient client.Client, o *v1alpha1.GatewayClassConfig) error { return backoff.Retry(func() error { var existing v1alpha1.GatewayClassConfig err := k8sClient.Get(ctx, client.ObjectKeyFromObject(o), &existing) @@ -520,7 +380,7 @@ func forceV1ClassConfig(ctx context.Context, k8sClient client.Client, o *v1alpha }, exponentialBackoffWithMaxIntervalAndTime()) } -func forceV1Class(ctx context.Context, k8sClient client.Client, o *gwv1beta1.GatewayClass) error { +func forceClass(ctx context.Context, k8sClient client.Client, o *gwv1beta1.GatewayClass) error { return backoff.Retry(func() error { var existing gwv1beta1.GatewayClass err := k8sClient.Get(ctx, client.ObjectKeyFromObject(o), &existing) @@ -539,63 +399,6 @@ func forceV1Class(ctx context.Context, k8sClient client.Client, o *gwv1beta1.Gat }, exponentialBackoffWithMaxIntervalAndTime()) } -func forceV2ClassConfig(ctx context.Context, k8sClient client.Client, o *v2beta1.GatewayClassConfig) error { - return backoff.Retry(func() error { - var existing v2beta1.GatewayClassConfig - err := k8sClient.Get(ctx, client.ObjectKeyFromObject(o), &existing) - if err != nil && !k8serrors.IsNotFound(err) { - return err - } - - if k8serrors.IsNotFound(err) { - return k8sClient.Create(ctx, o) - } - - existing.Spec = *o.Spec.DeepCopy() - existing.Labels = o.Labels - - return k8sClient.Update(ctx, &existing) - }, exponentialBackoffWithMaxIntervalAndTime()) -} - -func forceV2Class(ctx context.Context, k8sClient client.Client, o *v2beta1.GatewayClass) error { - return backoff.Retry(func() error { - var existing v2beta1.GatewayClass - err := k8sClient.Get(ctx, client.ObjectKeyFromObject(o), &existing) - if err != nil && !k8serrors.IsNotFound(err) { - return err - } - - if k8serrors.IsNotFound(err) { - return k8sClient.Create(ctx, o) - } - - existing.Spec = *o.Spec.DeepCopy() - existing.Labels = o.Labels - - return k8sClient.Update(ctx, &existing) - }, exponentialBackoffWithMaxIntervalAndTime()) -} - -func forceV2MeshGateway(ctx context.Context, k8sClient client.Client, o *v2beta1.MeshGateway) error { - return backoff.Retry(func() error { - var existing v2beta1.MeshGateway - err := k8sClient.Get(ctx, client.ObjectKeyFromObject(o), &existing) - if err != nil && !k8serrors.IsNotFound(err) { - return err - } - - if k8serrors.IsNotFound(err) { - return k8sClient.Create(ctx, o) - } - - existing.Spec = *o.Spec.DeepCopy() - existing.Labels = o.Labels - - return k8sClient.Update(ctx, &existing) - }, exponentialBackoffWithMaxIntervalAndTime()) -} - func exponentialBackoffWithMaxIntervalAndTime() *backoff.ExponentialBackOff { backoff := backoff.NewExponentialBackOff() backoff.MaxElapsedTime = 10 * time.Second diff --git a/control-plane/subcommand/gateway-resources/command_test.go b/control-plane/subcommand/gateway-resources/command_test.go index 70eb1e3d90..8455c1a315 100644 --- a/control-plane/subcommand/gateway-resources/command_test.go +++ b/control-plane/subcommand/gateway-resources/command_test.go @@ -4,22 +4,16 @@ package gatewayresources import ( - "os" "testing" "github.com/mitchellh/cli" "github.com/stretchr/testify/require" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" gwv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - meshv2beta1 "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - - "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" "github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1" ) @@ -199,22 +193,18 @@ func TestRun(t *testing.T) { for name, tt := range map[string]struct { existingGatewayClass bool existingGatewayClassConfig bool - meshGWConfigFileExists bool }{ "both exist": { existingGatewayClass: true, existingGatewayClassConfig: true, }, - "api gateway class config doesn't exist": { + "gateway class config doesn't exist": { existingGatewayClass: true, }, - "api gateway class doesn't exist": { + "gateway class doesn't exist": { existingGatewayClassConfig: true, }, "neither exist": {}, - "mesh gw config file exists": { - meshGWConfigFileExists: true, - }, } { t.Run(name, func(t *testing.T) { tt := tt @@ -232,11 +222,6 @@ func TestRun(t *testing.T) { require.NoError(t, gwv1beta1.Install(s)) require.NoError(t, v1alpha1.AddToScheme(s)) - configFileName := gatewayConfigFilename - if tt.meshGWConfigFileExists { - configFileName = createGatewayConfigFile(t, validGWConfigurationKitchenSink, "config.yaml") - } - objs := []client.Object{} if tt.existingGatewayClass { objs = append(objs, existingGatewayClass) @@ -249,9 +234,8 @@ func TestRun(t *testing.T) { ui := cli.NewMockUi() cmd := Command{ - UI: ui, - k8sClient: client, - flagGatewayConfigLocation: configFileName, + UI: ui, + k8sClient: client, } code := cmd.Run([]string{ @@ -270,379 +254,3 @@ func TestRun(t *testing.T) { }) } } - -var validResourceConfiguration = `{ - "requests": { - "memory": "200Mi", - "cpu": "200m" - }, - "limits": { - "memory": "200Mi", - "cpu": "200m" - } -} -` - -var invalidResourceConfiguration = `{"resources": -{ - "memory": "100Mi" - "cpu": "100m" - }, - "limits": { - "memory": "100Mi" - "cpu": "100m" - }, -} -` - -func TestRun_loadResourceConfig(t *testing.T) { - filename := createGatewayConfigFile(t, validResourceConfiguration, "resource.json") - // setup k8s client - s := runtime.NewScheme() - require.NoError(t, gwv1beta1.Install(s)) - require.NoError(t, v1alpha1.AddToScheme(s)) - - client := fake.NewClientBuilder().WithScheme(s).Build() - - ui := cli.NewMockUi() - cmd := Command{ - UI: ui, - k8sClient: client, - } - - expectedResources := corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("200Mi"), - corev1.ResourceCPU: resource.MustParse("200m"), - }, - Limits: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("200Mi"), - corev1.ResourceCPU: resource.MustParse("200m"), - }, - } - - resources, err := cmd.loadResourceConfig(filename) - require.NoError(t, err) - require.Equal(t, resources, expectedResources) -} - -func TestRun_loadResourceConfigInvalidConfigFile(t *testing.T) { - filename := createGatewayConfigFile(t, invalidResourceConfiguration, "resource.json") - // setup k8s client - s := runtime.NewScheme() - require.NoError(t, gwv1beta1.Install(s)) - require.NoError(t, v1alpha1.AddToScheme(s)) - - client := fake.NewClientBuilder().WithScheme(s).Build() - - ui := cli.NewMockUi() - cmd := Command{ - UI: ui, - k8sClient: client, - } - - _, err := cmd.loadResourceConfig(filename) - require.Error(t, err) -} - -func TestRun_loadResourceConfigFileWhenConfigFileDoesNotExist(t *testing.T) { - filename := "./consul/config/resources.json" - s := runtime.NewScheme() - require.NoError(t, gwv1beta1.Install(s)) - require.NoError(t, v1alpha1.AddToScheme(s)) - - client := fake.NewClientBuilder().WithScheme(s).Build() - - ui := cli.NewMockUi() - cmd := Command{ - UI: ui, - k8sClient: client, - } - - resources, err := cmd.loadResourceConfig(filename) - require.NoError(t, err) - require.Equal(t, resources, defaultResourceRequirements) // should be using defaults - require.Contains(t, string(ui.OutputWriter.Bytes()), "No resources.json found, using defaults") -} - -var validGWConfigurationKitchenSink = `gatewayClassConfigs: -- apiVersion: mesh.consul.hashicorp.com/v2beta1 - kind: GatewayClassConfig - metadata: - name: consul-mesh-gateway - spec: - deployment: - hostNetwork: true - dnsPolicy: ClusterFirst - replicas: - min: 3 - default: 3 - max: 3 - nodeSelector: - beta.kubernetes.io/arch: amd64 - beta.kubernetes.io/os: linux - affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: - app: consul - release: consul-helm - component: mesh-gateway - topologyKey: kubernetes.io/hostname - tolerations: - - key: "key1" - operator: "Equal" - value: "value1" - effect: "NoSchedule" - container: - portModifier: 8000 - resources: - requests: - cpu: 200m - memory: 200Mi - limits: - cpu: 200m - memory: 200Mi -meshGateways: -- apiVersion: mesh.consul.hashicorp.com/v2beta1 - kind: MeshGateway - metadata: - name: mesh-gateway - namespace: consul - spec: - gatewayClassName: consul-mesh-gateway -` - -var validGWConfigurationMinimal = `gatewayClassConfigs: -- apiVersion: mesh.consul.hashicorp.com/v2beta1 - kind: GatewayClassConfig - metadata: - name: consul-mesh-gateway - spec: - deployment: -meshGateways: -- apiVersion: mesh.consul.hashicorp.com/v2beta1 - kind: MeshGateway - metadata: - name: mesh-gateway - namespace: consul - spec: - gatewayClassName: consul-mesh-gateway -` - -var invalidGWConfiguration = ` -gatewayClassConfigs: -iVersion= mesh.consul.hashicorp.com/v2beta1 - kind: gatewayClassConfig - metadata: - name: consul-mesh-gateway - namespace: namespace - spec: - deployment: - resources: - requests: - cpu: 100m -meshGateways: -- name: mesh-gateway - spec: - gatewayClassName: consul-mesh-gateway -` - -func TestRun_loadGatewayConfigs(t *testing.T) { - var replicasCount int32 = 3 - testCases := map[string]struct { - config string - filename string - expectedDeployment v2beta1.GatewayClassDeploymentConfig - }{ - "kitchen sink": { - config: validGWConfigurationKitchenSink, - filename: "kitchenSinkConfig.yaml", - expectedDeployment: v2beta1.GatewayClassDeploymentConfig{ - HostNetwork: true, - DNSPolicy: "ClusterFirst", - NodeSelector: map[string]string{ - "beta.kubernetes.io/arch": "amd64", - "beta.kubernetes.io/os": "linux", - }, - Replicas: &v2beta1.GatewayClassReplicasConfig{ - Default: &replicasCount, - Min: &replicasCount, - Max: &replicasCount, - }, - Tolerations: []corev1.Toleration{ - { - Key: "key1", - Operator: "Equal", - Value: "value1", - Effect: "NoSchedule", - }, - }, - - Affinity: &corev1.Affinity{ - PodAntiAffinity: &corev1.PodAntiAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: []corev1.PodAffinityTerm{ - { - LabelSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app": "consul", - "release": "consul-helm", - "component": "mesh-gateway", - }, - }, - TopologyKey: "kubernetes.io/hostname", - }, - }, - }, - }, - Container: &v2beta1.GatewayClassContainerConfig{ - Resources: &corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("200Mi"), - corev1.ResourceCPU: resource.MustParse("200m"), - }, - Limits: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("200Mi"), - corev1.ResourceCPU: resource.MustParse("200m"), - }, - }, - PortModifier: 8000, - }, - }, - }, - "minimal configuration": { - config: validGWConfigurationMinimal, - filename: "minimalConfig.yaml", - expectedDeployment: v2beta1.GatewayClassDeploymentConfig{ - Container: &v2beta1.GatewayClassContainerConfig{ - Resources: &defaultResourceRequirements, - }, - }, - }, - } - - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - filename := createGatewayConfigFile(t, tc.config, tc.filename) - // setup k8s client - s := runtime.NewScheme() - require.NoError(t, gwv1beta1.Install(s)) - require.NoError(t, v1alpha1.AddToScheme(s)) - - client := fake.NewClientBuilder().WithScheme(s).Build() - - ui := cli.NewMockUi() - cmd := Command{ - UI: ui, - k8sClient: client, - flagGatewayConfigLocation: filename, - } - - err := cmd.loadGatewayConfigs() - require.NoError(t, err) - require.NotEmpty(t, cmd.gatewayConfig.GatewayClassConfigs) - require.NotEmpty(t, cmd.gatewayConfig.MeshGateways) - - // we only created one class config - classConfig := cmd.gatewayConfig.GatewayClassConfigs[0].DeepCopy() - - expectedClassConfig := v2beta1.GatewayClassConfig{ - TypeMeta: metav1.TypeMeta{ - APIVersion: v2beta1.MeshGroupVersion.String(), - Kind: v2beta1.KindGatewayClassConfig, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "consul-mesh-gateway", - }, - Spec: v2beta1.GatewayClassConfigSpec{ - Deployment: tc.expectedDeployment, - }, - Status: v2beta1.Status{}, - } - require.Equal(t, expectedClassConfig.DeepCopy(), classConfig) - - // check mesh gateway, we only created one of these - actualMeshGateway := cmd.gatewayConfig.MeshGateways[0] - - expectedMeshGateway := &v2beta1.MeshGateway{ - TypeMeta: metav1.TypeMeta{ - Kind: "MeshGateway", - APIVersion: v2beta1.MeshGroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "mesh-gateway", - Namespace: "consul", - }, - Spec: meshv2beta1.MeshGateway{ - GatewayClassName: "consul-mesh-gateway", - }, - } - - require.Equal(t, expectedMeshGateway.DeepCopy(), actualMeshGateway) - }) - } -} - -func TestRun_loadGatewayConfigsWithInvalidFile(t *testing.T) { - filename := createGatewayConfigFile(t, invalidGWConfiguration, "config.yaml") - // setup k8s client - s := runtime.NewScheme() - require.NoError(t, gwv1beta1.Install(s)) - require.NoError(t, v1alpha1.AddToScheme(s)) - - client := fake.NewClientBuilder().WithScheme(s).Build() - - ui := cli.NewMockUi() - cmd := Command{ - UI: ui, - k8sClient: client, - flagGatewayConfigLocation: filename, - } - - err := cmd.loadGatewayConfigs() - require.Error(t, err) - require.Empty(t, cmd.gatewayConfig.GatewayClassConfigs) - require.Empty(t, cmd.gatewayConfig.MeshGateways) -} - -func TestRun_loadGatewayConfigsWhenConfigFileDoesNotExist(t *testing.T) { - filename := "./consul/config/config.yaml" - s := runtime.NewScheme() - require.NoError(t, gwv1beta1.Install(s)) - require.NoError(t, v1alpha1.AddToScheme(s)) - - client := fake.NewClientBuilder().WithScheme(s).Build() - - ui := cli.NewMockUi() - cmd := Command{ - UI: ui, - k8sClient: client, - flagGatewayConfigLocation: filename, - } - - err := cmd.loadGatewayConfigs() - require.NoError(t, err) - require.Empty(t, cmd.gatewayConfig.GatewayClassConfigs) - require.Empty(t, cmd.gatewayConfig.MeshGateways) - require.Contains(t, string(ui.ErrorWriter.Bytes()), "gateway configuration file not found, skipping gateway configuration") -} - -func createGatewayConfigFile(t *testing.T, fileContent, filename string) string { - t.Helper() - - // create a temp file to store configuration yaml - tmpdir := t.TempDir() - file, err := os.CreateTemp(tmpdir, filename) - if err != nil { - t.Fatal(err) - } - defer file.Close() - - _, err = file.WriteString(fileContent) - if err != nil { - t.Fatal(err) - } - - return file.Name() -} diff --git a/control-plane/subcommand/inject-connect/command.go b/control-plane/subcommand/inject-connect/command.go index e0c05933b8..ea8e41b40e 100644 --- a/control-plane/subcommand/inject-connect/command.go +++ b/control-plane/subcommand/inject-connect/command.go @@ -32,7 +32,6 @@ import ( authv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/auth/v2beta1" meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" - multiclusterv2 "github.com/hashicorp/consul-k8s/control-plane/api/multicluster/v2" "github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" "github.com/hashicorp/consul-k8s/control-plane/subcommand/common" @@ -58,7 +57,6 @@ type Command struct { flagLogLevel string flagLogJSON bool flagResourceAPIs bool // Use V2 APIs - flagV2Tenancy bool // Use V2 partitions (ent only) and namespaces instead of V1 counterparts flagAllowK8sNamespacesList []string // K8s namespaces to explicitly inject flagDenyK8sNamespacesList []string // K8s namespaces to deny injection (has precedence) @@ -171,9 +169,8 @@ func init() { // V2 resources utilruntime.Must(authv2beta1.AddAuthToScheme(scheme)) utilruntime.Must(meshv2beta1.AddMeshToScheme(scheme)) - utilruntime.Must(multiclusterv2.AddMultiClusterToScheme(scheme)) - // +kubebuilder:scaffold:scheme + //+kubebuilder:scaffold:scheme } func (c *Command) init() { @@ -241,8 +238,6 @@ func (c *Command) init() { "Enable or disable JSON output format for logging.") c.flagSet.BoolVar(&c.flagResourceAPIs, "enable-resource-apis", false, "Enable or disable Consul V2 Resource APIs.") - c.flagSet.BoolVar(&c.flagV2Tenancy, "enable-v2tenancy", false, - "Enable or disable Consul V2 tenancy.") // Proxy sidecar resource setting flags. c.flagSet.StringVar(&c.flagDefaultSidecarProxyCPURequest, "default-sidecar-proxy-cpu-request", "", "Default sidecar proxy CPU request.") @@ -431,19 +426,6 @@ func (c *Command) validateFlags() error { return errors.New("-consul-dataplane-image must be set") } - // In Consul 1.17, multiport beta shipped with v2 catalog + mesh resources backed by v1 tenancy - // and acls (experiments=[resource-apis]). - // - // With Consul 1.18, we built out v2 tenancy with no support for acls, hence need to be explicit - // about which combination of v1 + v2 features are enabled. - // - // To summarize: - // - experiments=[resource-apis] => v2 catalog and mesh + v1 tenancy and acls - // - experiments=[resource-apis, v2tenancy] => v2 catalog and mesh + v2 tenancy + acls disabled - if c.flagV2Tenancy && !c.flagResourceAPIs { - return errors.New("-enable-resource-apis must be set to 'true' if -enable-v2tenancy is set") - } - if c.flagEnablePartitions && c.consul.Partition == "" { return errors.New("-partition must set if -enable-partitions is set to 'true'") } diff --git a/control-plane/subcommand/inject-connect/command_test.go b/control-plane/subcommand/inject-connect/command_test.go index e7ca3f12cd..9c64020376 100644 --- a/control-plane/subcommand/inject-connect/command_test.go +++ b/control-plane/subcommand/inject-connect/command_test.go @@ -132,15 +132,6 @@ func TestRun_FlagValidation(t *testing.T) { }, expErr: "-default-envoy-proxy-concurrency must be >= 0 if set", }, - { - flags: []string{ - "-consul-k8s-image", "hashicorp/consul-k8s", - "-consul-image", "hashicorp/consul", - "-consul-dataplane-image", "hashicorp/consul-dataplane", - "-enable-v2tenancy", "true", - }, - expErr: "-enable-resource-apis must be set to 'true' if -enable-v2tenancy is set", - }, } for _, c := range cases { diff --git a/control-plane/subcommand/inject-connect/v1controllers.go b/control-plane/subcommand/inject-connect/v1controllers.go index 3dfa99bc48..0081935199 100644 --- a/control-plane/subcommand/inject-connect/v1controllers.go +++ b/control-plane/subcommand/inject-connect/v1controllers.go @@ -17,12 +17,12 @@ import ( gatewaycontrollers "github.com/hashicorp/consul-k8s/control-plane/api-gateway/controllers" apicommon "github.com/hashicorp/consul-k8s/control-plane/api/common" "github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1" + "github.com/hashicorp/consul-k8s/control-plane/config-entries/controllers" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/controllers/endpoints" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/controllers/peering" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/lifecycle" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/metrics" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/webhook" - controllers "github.com/hashicorp/consul-k8s/control-plane/controllers/configentries" webhookconfiguration "github.com/hashicorp/consul-k8s/control-plane/helper/webhook-configuration" "github.com/hashicorp/consul-k8s/control-plane/subcommand/flags" ) diff --git a/control-plane/subcommand/inject-connect/v2controllers.go b/control-plane/subcommand/inject-connect/v2controllers.go index fce6968ad6..abe4b38c53 100644 --- a/control-plane/subcommand/inject-connect/v2controllers.go +++ b/control-plane/subcommand/inject-connect/v2controllers.go @@ -6,6 +6,7 @@ package connectinject import ( "context" + "github.com/hashicorp/consul-server-connection-manager/discovery" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/manager" ctrlRuntimeWebhook "sigs.k8s.io/controller-runtime/pkg/webhook" @@ -13,6 +14,7 @@ import ( authv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/auth/v2beta1" "github.com/hashicorp/consul-k8s/control-plane/api/common" meshv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1" + "github.com/hashicorp/consul-k8s/control-plane/config-entries/controllersv2" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/controllers/endpointsv2" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/controllers/pod" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/controllers/serviceaccount" @@ -21,11 +23,7 @@ import ( "github.com/hashicorp/consul-k8s/control-plane/connect-inject/namespace" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/webhook" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/webhookv2" - resourceControllers "github.com/hashicorp/consul-k8s/control-plane/controllers/resources" - "github.com/hashicorp/consul-k8s/control-plane/gateways" "github.com/hashicorp/consul-k8s/control-plane/subcommand/flags" - namespacev2 "github.com/hashicorp/consul-k8s/control-plane/tenancy/namespace" - "github.com/hashicorp/consul-server-connection-manager/discovery" ) func (c *Command) configureV2Controllers(ctx context.Context, mgr manager.Manager, watcher *discovery.Watcher) error { @@ -110,183 +108,76 @@ func (c *Command) configureV2Controllers(ctx context.Context, mgr manager.Manage return err } - if c.flagV2Tenancy { - // V2 tenancy implies non-default namespaces in CE, so we don't observe flagEnableNamespaces - err := (&namespacev2.Controller{ - Client: mgr.GetClient(), - ConsulServerConnMgr: watcher, - K8sNamespaceConfig: k8sNsConfig, - ConsulTenancyConfig: consulTenancyConfig, - Log: ctrl.Log.WithName("controller").WithName("namespacev2"), + if c.flagEnableNamespaces { + err := (&namespace.Controller{ + Client: mgr.GetClient(), + ConsulClientConfig: consulConfig, + ConsulServerConnMgr: watcher, + AllowK8sNamespacesSet: allowK8sNamespaces, + DenyK8sNamespacesSet: denyK8sNamespaces, + ConsulDestinationNamespace: c.flagConsulDestinationNamespace, + EnableNSMirroring: c.flagEnableK8SNSMirroring, + NSMirroringPrefix: c.flagK8SNSMirroringPrefix, + CrossNamespaceACLPolicy: c.flagCrossNamespaceACLPolicy, + Log: ctrl.Log.WithName("controller").WithName("namespace"), }).SetupWithManager(mgr) if err != nil { - setupLog.Error(err, "unable to create controller", "controller", "namespacev2") + setupLog.Error(err, "unable to create controller", "controller", namespace.Controller{}) return err } - } else { - if c.flagEnableNamespaces { - err := (&namespace.Controller{ - Client: mgr.GetClient(), - ConsulClientConfig: consulConfig, - ConsulServerConnMgr: watcher, - AllowK8sNamespacesSet: allowK8sNamespaces, - DenyK8sNamespacesSet: denyK8sNamespaces, - ConsulDestinationNamespace: c.flagConsulDestinationNamespace, - EnableNSMirroring: c.flagEnableK8SNSMirroring, - NSMirroringPrefix: c.flagK8SNSMirroringPrefix, - CrossNamespaceACLPolicy: c.flagCrossNamespaceACLPolicy, - Log: ctrl.Log.WithName("controller").WithName("namespace"), - }).SetupWithManager(mgr) - if err != nil { - setupLog.Error(err, "unable to create controller", "controller", namespace.Controller{}) - return err - } - } } - consulResourceController := &resourceControllers.ConsulResourceController{ + meshConfigReconciler := &controllersv2.MeshConfigController{ ConsulClientConfig: consulConfig, ConsulServerConnMgr: watcher, ConsulTenancyConfig: consulTenancyConfig, } - - if err := (&resourceControllers.TrafficPermissionsController{ - Controller: consulResourceController, - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controller").WithName(common.TrafficPermissions), - Scheme: mgr.GetScheme(), + if err := (&controllersv2.TrafficPermissionsController{ + MeshConfigController: meshConfigReconciler, + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controller").WithName(common.TrafficPermissions), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", common.TrafficPermissions) return err } - - if err := (&resourceControllers.GRPCRouteController{ - Controller: consulResourceController, - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controller").WithName(common.GRPCRoute), - Scheme: mgr.GetScheme(), + if err := (&controllersv2.GRPCRouteController{ + MeshConfigController: meshConfigReconciler, + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controller").WithName(common.GRPCRoute), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", common.GRPCRoute) return err } - - if err := (&resourceControllers.HTTPRouteController{ - Controller: consulResourceController, - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controller").WithName(common.HTTPRoute), - Scheme: mgr.GetScheme(), + if err := (&controllersv2.HTTPRouteController{ + MeshConfigController: meshConfigReconciler, + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controller").WithName(common.HTTPRoute), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", common.HTTPRoute) return err } - - if err := (&resourceControllers.TCPRouteController{ - Controller: consulResourceController, - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controller").WithName(common.TCPRoute), - Scheme: mgr.GetScheme(), + if err := (&controllersv2.TCPRouteController{ + MeshConfigController: meshConfigReconciler, + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controller").WithName(common.TCPRoute), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", common.TCPRoute) return err } - - if err := (&resourceControllers.ProxyConfigurationController{ - Controller: consulResourceController, - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controller").WithName(common.ProxyConfiguration), - Scheme: mgr.GetScheme(), + if err := (&controllersv2.ProxyConfigurationController{ + MeshConfigController: meshConfigReconciler, + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controller").WithName(common.ProxyConfiguration), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", common.ProxyConfiguration) return err } - if err := resourceControllers.RegisterGatewayFieldIndexes(ctx, mgr); err != nil { - setupLog.Error(err, "unable to register field indexes") - return err - } - - if err := (&resourceControllers.MeshConfigurationController{ - Controller: consulResourceController, - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controller").WithName(common.MeshConfiguration), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", common.MeshConfiguration) - return err - } - - gatewayConfig := gateways.GatewayConfig{ - ConsulConfig: common.ConsulConfig{ - Address: c.consul.Addresses, - GRPCPort: consulConfig.GRPCPort, - HTTPPort: consulConfig.HTTPPort, - APITimeout: consulConfig.APITimeout, - }, - ImageDataplane: c.flagConsulDataplaneImage, - ImageConsulK8S: c.flagConsulK8sImage, - ConsulTenancyConfig: consulTenancyConfig, - PeeringEnabled: c.flagEnablePeering, - EnableOpenShift: c.flagEnableOpenShift, - AuthMethod: c.consul.ConsulLogin.AuthMethod, - LogLevel: c.flagLogLevel, - LogJSON: c.flagLogJSON, - TLSEnabled: c.consul.UseTLS, - ConsulTLSServerName: c.consul.TLSServerName, - ConsulCACert: string(c.caCertPem), - SkipServerWatch: c.consul.SkipServerWatch, - } - - if err := (&resourceControllers.MeshGatewayController{ - Controller: consulResourceController, - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controller").WithName(common.MeshGateway), - Scheme: mgr.GetScheme(), - GatewayConfig: gatewayConfig, - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", common.MeshGateway) - return err - } - - if err := (&resourceControllers.APIGatewayController{ - Controller: consulResourceController, - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controller").WithName(common.APIGateway), - Scheme: mgr.GetScheme(), - GatewayConfig: gatewayConfig, - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", common.APIGateway) - return err - } - - if err := (&resourceControllers.GatewayClassConfigController{ - Controller: consulResourceController, - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controller").WithName(common.GatewayClassConfig), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", common.GatewayClassConfig) - return err - } - - if err := (&resourceControllers.GatewayClassController{ - Controller: consulResourceController, - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controller").WithName(common.GatewayClass), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", common.GatewayClass) - return err - } - - if err := (&resourceControllers.ExportedServicesController{ - Controller: consulResourceController, - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controller").WithName(common.ExportedServices), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", common.ExportedServices) - return err - } - mgr.GetWebhookServer().CertDir = c.flagCertDir mgr.GetWebhookServer().Register("/mutate", diff --git a/control-plane/subcommand/mesh-init/command.go b/control-plane/subcommand/mesh-init/command.go index ea03577848..2a6b6ccebd 100644 --- a/control-plane/subcommand/mesh-init/command.go +++ b/control-plane/subcommand/mesh-init/command.go @@ -34,7 +34,6 @@ import ( const ( // The number of times to attempt to read this proxy registration (120s). defaultMaxPollingRetries = 120 - defaultProxyIDFile = "/consul/mesh-inject/proxyid" ) type Command struct { @@ -73,7 +72,6 @@ func (c *Command) init() { c.flagSet.StringVar(&c.flagLogLevel, "log-level", "info", "Log verbosity level. Supported values (in order of detail) are \"trace\", "+ "\"debug\", \"info\", \"warn\", and \"error\".") - c.flagSet.BoolVar(&c.flagLogJSON, "log-json", false, "Enable or disable JSON output format for logging.") @@ -212,8 +210,8 @@ func (c *Command) Help() string { func (c *Command) getBootstrapParams( client pbdataplane.DataplaneServiceClient, - bootstrapConfig *pbmesh.BootstrapConfig, -) backoff.Operation { + bootstrapConfig *pbmesh.BootstrapConfig) backoff.Operation { + return func() error { req := &pbdataplane.GetEnvoyBootstrapParamsRequest{ ProxyId: c.flagProxyName, @@ -236,6 +234,7 @@ func (c *Command) getBootstrapParams( // https://github.com/hashicorp/consul/blob/fe2d41ddad9ba2b8ff86cbdebbd8f05855b1523c/command/connect/redirecttraffic/redirect_traffic.go#L136. func (c *Command) applyTrafficRedirectionRules(config *pbmesh.BootstrapConfig) error { + err := json.Unmarshal([]byte(c.flagRedirectTrafficConfig), &c.iptablesConfig) if err != nil { return err @@ -275,13 +274,11 @@ func (c *Command) applyTrafficRedirectionRules(config *pbmesh.BootstrapConfig) e return nil } -const ( - synopsis = "Inject mesh init command." - help = ` +const synopsis = "Inject mesh init command." +const help = ` Usage: consul-k8s-control-plane mesh-init [options] Bootstraps mesh-injected pod components. Uses V2 Consul Catalog APIs. Not intended for stand-alone use. ` -) diff --git a/control-plane/subcommand/mesh-init/command_ent_test.go b/control-plane/subcommand/mesh-init/command_ent_test.go index 59c710f6eb..ad3ea8c87d 100644 --- a/control-plane/subcommand/mesh-init/command_ent_test.go +++ b/control-plane/subcommand/mesh-init/command_ent_test.go @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/require" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" + "github.com/hashicorp/consul-k8s/control-plane/consul" "github.com/hashicorp/consul-k8s/control-plane/helper/test" "github.com/hashicorp/consul-k8s/control-plane/namespaces" ) @@ -51,8 +52,10 @@ func TestRun_WithNamespaces(t *testing.T) { c.Experiments = []string{"resource-apis"} serverCfg = c }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) - _, err := EnsurePartitionExists(testClient.APIClient, c.consulPartition) + _, err = EnsurePartitionExists(testClient.APIClient, c.consulPartition) require.NoError(t, err) partitionedCfg := testClient.Cfg.APIClientConfig @@ -65,7 +68,7 @@ func TestRun_WithNamespaces(t *testing.T) { require.NoError(t, err) // Register Consul workload. - loadResource(t, testClient.ResourceClient, getWorkloadID(testPodName, c.consulNamespace, c.consulPartition), getWorkload(), nil) + loadResource(t, resourceClient, getWorkloadID(testPodName, c.consulNamespace, c.consulPartition), getWorkload(), nil) ui := cli.NewMockUi() cmd := Command{ diff --git a/control-plane/subcommand/mesh-init/command_test.go b/control-plane/subcommand/mesh-init/command_test.go index 3567b36102..85b68adc65 100644 --- a/control-plane/subcommand/mesh-init/command_test.go +++ b/control-plane/subcommand/mesh-init/command_test.go @@ -24,6 +24,7 @@ import ( "google.golang.org/protobuf/types/known/anypb" "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" + "github.com/hashicorp/consul-k8s/control-plane/consul" "github.com/hashicorp/consul-k8s/control-plane/helper/test" ) @@ -99,9 +100,11 @@ func TestRun_MeshServices(t *testing.T) { c.Experiments = []string{"resource-apis"} serverCfg = c }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) - loadResource(t, testClient.ResourceClient, getWorkloadID(testPodName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tt.workload, nil) - loadResource(t, testClient.ResourceClient, getProxyConfigurationID(testPodName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tt.proxyConfiguration, nil) + loadResource(t, resourceClient, getWorkloadID(testPodName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tt.workload, nil) + loadResource(t, resourceClient, getProxyConfigurationID(testPodName, constants.DefaultConsulNS, constants.DefaultConsulPartition), tt.proxyConfiguration, nil) ui := cli.NewMockUi() cmd := Command{ @@ -111,8 +114,7 @@ func TestRun_MeshServices(t *testing.T) { // We build the consul-addr because normally it's defined by the init container setting // CONSUL_HTTP_ADDR when it processes the command template. - flags := []string{ - "-proxy-name", testPodName, + flags := []string{"-proxy-name", testPodName, "-addresses", "127.0.0.1", "-http-port", strconv.Itoa(serverCfg.Ports.HTTP), "-grpc-port", strconv.Itoa(serverCfg.Ports.GRPC), @@ -161,6 +163,8 @@ func TestRun_RetryServicePolling(t *testing.T) { c.Experiments = []string{"resource-apis"} serverCfg = c }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) // Start the consul service registration in a go func and delay it so that it runs // after the cmd.Run() starts. @@ -171,7 +175,7 @@ func TestRun_RetryServicePolling(t *testing.T) { // Wait a moment, this ensures that we are already in the retry logic. time.Sleep(time.Second * 2) // Register counting service. - loadResource(t, testClient.ResourceClient, getWorkloadID(testPodName, constants.DefaultConsulNS, constants.DefaultConsulPartition), getWorkload(), nil) + loadResource(t, resourceClient, getWorkloadID(testPodName, constants.DefaultConsulNS, constants.DefaultConsulPartition), getWorkload(), nil) }() ui := cli.NewMockUi() @@ -179,7 +183,6 @@ func TestRun_RetryServicePolling(t *testing.T) { UI: ui, maxPollingAttempts: 10, } - flags := []string{ "-proxy-name", testPodName, "-addresses", "127.0.0.1", @@ -229,20 +232,23 @@ func TestRun_TrafficRedirection(t *testing.T) { for name, c := range cases { t.Run(name, func(t *testing.T) { + // Start Consul server. var serverCfg *testutil.TestServerConfig testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { c.Experiments = []string{"resource-apis"} serverCfg = c }) + resourceClient, err := consul.NewResourceServiceClient(testClient.Watcher) + require.NoError(t, err) // Add additional proxy configuration either to a config entry or to the service itself. if c.registerProxyConfiguration { - loadResource(t, testClient.ResourceClient, getProxyConfigurationID(testPodName, constants.DefaultConsulNS, constants.DefaultConsulPartition), getProxyConfiguration(), nil) + loadResource(t, resourceClient, getProxyConfigurationID(testPodName, constants.DefaultConsulNS, constants.DefaultConsulPartition), getProxyConfiguration(), nil) } // Register Consul workload. - loadResource(t, testClient.ResourceClient, getWorkloadID(testPodName, constants.DefaultConsulNS, constants.DefaultConsulPartition), getWorkload(), nil) + loadResource(t, resourceClient, getWorkloadID(testPodName, constants.DefaultConsulNS, constants.DefaultConsulPartition), getWorkload(), nil) iptablesProvider := &fakeIptablesProvider{} iptablesCfg := iptables.Config{ @@ -259,7 +265,6 @@ func TestRun_TrafficRedirection(t *testing.T) { } iptablesCfgJSON, err := json.Marshal(iptablesCfg) require.NoError(t, err) - flags := []string{ "-proxy-name", testPodName, "-addresses", "127.0.0.1", @@ -314,6 +319,10 @@ func getWorkloadID(name, namespace, partition string) *pbresource.ID { Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, } } @@ -351,6 +360,10 @@ func getProxyConfigurationID(name, namespace, partition string) *pbresource.ID { Tenancy: &pbresource.Tenancy{ Partition: partition, Namespace: namespace, + + // Because we are explicitly defining NS/partition, this will not default and must be explicit. + // At a future point, this will move out of the Tenancy block. + PeerName: constants.DefaultConsulPeer, }, } } diff --git a/control-plane/subcommand/partition-init/command.go b/control-plane/subcommand/partition-init/command.go index 19bb1bc6f5..0aa8cdc724 100644 --- a/control-plane/subcommand/partition-init/command.go +++ b/control-plane/subcommand/partition-init/command.go @@ -11,16 +11,10 @@ import ( "sync" "time" - "github.com/hashicorp/go-hclog" - "github.com/mitchellh/cli" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/types/known/anypb" - "github.com/hashicorp/consul-server-connection-manager/discovery" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" + "github.com/hashicorp/go-hclog" + "github.com/mitchellh/cli" "github.com/hashicorp/consul-k8s/control-plane/consul" "github.com/hashicorp/consul-k8s/control-plane/subcommand/common" @@ -33,10 +27,9 @@ type Command struct { flags *flag.FlagSet consul *flags.ConsulFlags - flagLogLevel string - flagLogJSON bool - flagTimeout time.Duration - flagV2Tenancy bool + flagLogLevel string + flagLogJSON bool + flagTimeout time.Duration // ctx is cancelled when the command timeout is reached. ctx context.Context @@ -59,8 +52,6 @@ func (c *Command) init() { "\"debug\", \"info\", \"warn\", and \"error\".") c.flags.BoolVar(&c.flagLogJSON, "log-json", false, "Enable or disable JSON output format for logging.") - c.flags.BoolVar(&c.flagV2Tenancy, "enable-v2tenancy", false, - "Enable V2 tenancy.") c.consul = &flags.ConsulFlags{} flags.Merge(c.flags, c.consul.Flags()) @@ -79,106 +70,6 @@ func (c *Command) Help() string { return c.help } -func (c *Command) ensureV2Partition(scm consul.ServerConnectionManager) error { - client, err := consul.NewResourceServiceClient(scm) - if err != nil { - c.UI.Error(fmt.Sprintf("unable to create grpc client: %s", err)) - return err - } - - for { - id := &pbresource.ID{ - Name: c.consul.Partition, - Type: pbtenancy.PartitionType, - } - - _, err = client.Read(c.ctx, &pbresource.ReadRequest{Id: id}) - switch { - - // found -> done - case err == nil: - c.log.Info("Admin Partition already exists", "name", c.consul.Partition) - return nil - - // not found -> create - case status.Code(err) == codes.NotFound: - data, err := anypb.New(&pbtenancy.Partition{Description: "Created by Helm installation"}) - if err != nil { - continue - } - _, err = client.Write(c.ctx, &pbresource.WriteRequest{Resource: &pbresource.Resource{ - Id: id, - Data: data, - }}) - if err == nil { - c.log.Info("Successfully created Admin Partition", "name", c.consul.Partition) - return nil - } - - // unexpected error -> retry - default: - c.log.Error("Error reading Partition from Consul", "name", c.consul.Partition, "error", err.Error()) - } - - // Wait on either the retry duration (in which case we continue) or the - // overall command timeout. - c.log.Info("Retrying in " + c.retryDuration.String()) - select { - case <-time.After(c.retryDuration): - continue - case <-c.ctx.Done(): - c.log.Error("Timed out attempting to ensure partition exists", "name", c.consul.Partition) - return err - } - } -} - -func (c *Command) ensureV1Partition(scm consul.ServerConnectionManager) error { - state, err := scm.State() - if err != nil { - c.UI.Error(fmt.Sprintf("unable to get Consul server addresses from watcher: %s", err)) - return err - } - - consulClient, err := consul.NewClientFromConnMgrState(c.consul.ConsulClientConfig(), state) - if err != nil { - c.UI.Error(fmt.Sprintf("unable to create Consul client: %s", err)) - return err - } - - for { - partition, _, err := consulClient.Partitions().Read(c.ctx, c.consul.Partition, nil) - // The API does not return an error if the Partition does not exist. It returns a nil Partition. - if err != nil { - c.log.Error("Error reading Partition from Consul", "name", c.consul.Partition, "error", err.Error()) - } else if partition == nil { - // Retry Admin Partition creation until it succeeds, or we reach the command timeout. - _, _, err = consulClient.Partitions().Create(c.ctx, &api.Partition{ - Name: c.consul.Partition, - Description: "Created by Helm installation", - }, nil) - if err == nil { - c.log.Info("Successfully created Admin Partition", "name", c.consul.Partition) - return nil - } - c.log.Error("Error creating partition", "name", c.consul.Partition, "error", err.Error()) - } else { - c.log.Info("Admin Partition already exists", "name", c.consul.Partition) - return nil - } - // Wait on either the retry duration (in which case we continue) or the - // overall command timeout. - c.log.Info("Retrying in " + c.retryDuration.String()) - select { - case <-time.After(c.retryDuration): - continue - case <-c.ctx.Done(): - c.log.Error("Timed out attempting to create partition", "name", c.consul.Partition) - return fmt.Errorf("") - } - } -} - // Run bootstraps Admin Partitions on Consul servers. // The function will retry its tasks until success, or it exceeds its timeout. func (c *Command) Run(args []string) int { @@ -224,15 +115,49 @@ func (c *Command) Run(args []string) int { go watcher.Run() defer watcher.Stop() - if c.flagV2Tenancy { - err = c.ensureV2Partition(watcher) - } else { - err = c.ensureV1Partition(watcher) + state, err := watcher.State() + if err != nil { + c.UI.Error(fmt.Sprintf("unable to get Consul server addresses from watcher: %s", err)) + return 1 } + + consulClient, err := consul.NewClientFromConnMgrState(c.consul.ConsulClientConfig(), state) if err != nil { + c.UI.Error(fmt.Sprintf("unable to create Consul client: %s", err)) return 1 } - return 0 + + for { + partition, _, err := consulClient.Partitions().Read(c.ctx, c.consul.Partition, nil) + // The API does not return an error if the Partition does not exist. It returns a nil Partition. + if err != nil { + c.log.Error("Error reading Partition from Consul", "name", c.consul.Partition, "error", err.Error()) + } else if partition == nil { + // Retry Admin Partition creation until it succeeds, or we reach the command timeout. + _, _, err = consulClient.Partitions().Create(c.ctx, &api.Partition{ + Name: c.consul.Partition, + Description: "Created by Helm installation", + }, nil) + if err == nil { + c.log.Info("Successfully created Admin Partition", "name", c.consul.Partition) + return 0 + } + c.log.Error("Error creating partition", "name", c.consul.Partition, "error", err.Error()) + } else { + c.log.Info("Admin Partition already exists", "name", c.consul.Partition) + return 0 + } + // Wait on either the retry duration (in which case we continue) or the + // overall command timeout. + c.log.Info("Retrying in " + c.retryDuration.String()) + select { + case <-time.After(c.retryDuration): + continue + case <-c.ctx.Done(): + c.log.Error("Timed out attempting to create partition", "name", c.consul.Partition) + return 1 + } + } } func (c *Command) validateFlags() error { diff --git a/control-plane/subcommand/partition-init/command_ent_test.go b/control-plane/subcommand/partition-init/command_ent_test.go index 21972a5a7a..182412c8aa 100644 --- a/control-plane/subcommand/partition-init/command_ent_test.go +++ b/control-plane/subcommand/partition-init/command_ent_test.go @@ -7,21 +7,14 @@ package partition_init import ( "context" - "strconv" + "strings" "testing" "time" - "github.com/mitchellh/cli" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" "github.com/hashicorp/consul/sdk/testutil" - - "github.com/hashicorp/consul-k8s/control-plane/helper/test" + "github.com/mitchellh/cli" + "github.com/stretchr/testify/require" ) func TestRun_FlagValidation(t *testing.T) { @@ -41,10 +34,7 @@ func TestRun_FlagValidation(t *testing.T) { }, { flags: []string{ - "-addresses", "foo", - "-partition", "bar", - "-api-timeout", "0s", - }, + "-addresses", "foo", "-partition", "bar", "-api-timeout", "0s"}, expErr: "-api-timeout must be set to a value greater than 0", }, { @@ -71,227 +61,103 @@ func TestRun_FlagValidation(t *testing.T) { func TestRun_PartitionCreate(t *testing.T) { partitionName := "test-partition" - type testCase struct { - v2tenancy bool - experiments []string - requirePartitionCreated func(testClient *test.TestServerClient) - } + server, err := testutil.NewTestServerConfigT(t, nil) + require.NoError(t, err) + server.WaitForLeader(t) + defer server.Stop() - testCases := map[string]testCase{ - "v2tenancy false": { - v2tenancy: false, - experiments: []string{}, - requirePartitionCreated: func(testClient *test.TestServerClient) { - consul, err := api.NewClient(testClient.Cfg.APIClientConfig) - require.NoError(t, err) + consul, err := api.NewClient(&api.Config{ + Address: server.HTTPAddr, + }) + require.NoError(t, err) - partition, _, err := consul.Partitions().Read(context.Background(), partitionName, nil) - require.NoError(t, err) - require.NotNil(t, partition) - require.Equal(t, partitionName, partition.Name) - }, - }, - "v2tenancy true": { - v2tenancy: true, - experiments: []string{"resource-apis", "v2tenancy"}, - requirePartitionCreated: func(testClient *test.TestServerClient) { - _, err := testClient.ResourceClient.Read(context.Background(), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Name: partitionName, - Type: pbtenancy.PartitionType, - }, - }) - require.NoError(t, err, "expected partition to be created") - }, - }, + ui := cli.NewMockUi() + cmd := Command{ + UI: ui, + } + cmd.init() + args := []string{ + "-addresses=" + "127.0.0.1", + "-http-port=" + strings.Split(server.HTTPAddr, ":")[1], + "-grpc-port=" + strings.Split(server.GRPCAddr, ":")[1], + "-partition", partitionName, } - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - var serverCfg *testutil.TestServerConfig - testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { - c.Experiments = tc.experiments - serverCfg = c - }) + responseCode := cmd.Run(args) - ui := cli.NewMockUi() - cmd := Command{ - UI: ui, - } - cmd.init() - args := []string{ - "-addresses=" + "127.0.0.1", - "-http-port", strconv.Itoa(serverCfg.Ports.HTTP), - "-grpc-port", strconv.Itoa(serverCfg.Ports.GRPC), - "-partition", partitionName, - "-timeout", "1m", - "-enable-v2tenancy=" + strconv.FormatBool(tc.v2tenancy), - } + require.Equal(t, 0, responseCode) - responseCode := cmd.Run(args) - require.Equal(t, 0, responseCode) - tc.requirePartitionCreated(testClient) - }) - } + partition, _, err := consul.Partitions().Read(context.Background(), partitionName, nil) + require.NoError(t, err) + require.NotNil(t, partition) + require.Equal(t, partitionName, partition.Name) } func TestRun_PartitionExists(t *testing.T) { partitionName := "test-partition" - partitionDesc := "Created before test" - - type testCase struct { - v2tenancy bool - experiments []string - preCreatePartition func(testClient *test.TestServerClient) - requirePartitionNotCreated func(testClient *test.TestServerClient) - } - - testCases := map[string]testCase{ - "v2tenancy false": { - v2tenancy: false, - experiments: []string{}, - - preCreatePartition: func(testClient *test.TestServerClient) { - consul, err := api.NewClient(testClient.Cfg.APIClientConfig) - require.NoError(t, err) - _, _, err = consul.Partitions().Create(context.Background(), &api.Partition{ - Name: partitionName, - Description: partitionDesc, - }, nil) - require.NoError(t, err) - }, - requirePartitionNotCreated: func(testClient *test.TestServerClient) { - consul, err := api.NewClient(testClient.Cfg.APIClientConfig) - require.NoError(t, err) + server, err := testutil.NewTestServerConfigT(t, nil) + require.NoError(t, err) + server.WaitForLeader(t) + defer server.Stop() - partition, _, err := consul.Partitions().Read(context.Background(), partitionName, nil) - require.NoError(t, err) - require.NotNil(t, partition) - require.Equal(t, partitionName, partition.Name) - require.Equal(t, partitionDesc, partition.Description) - }, - }, - "v2tenancy true": { - v2tenancy: true, - experiments: []string{"resource-apis", "v2tenancy"}, - preCreatePartition: func(testClient *test.TestServerClient) { - data, err := anypb.New(&pbtenancy.Partition{Description: partitionDesc}) - require.NoError(t, err) + consul, err := api.NewClient(&api.Config{ + Address: server.HTTPAddr, + }) + require.NoError(t, err) - _, err = testClient.ResourceClient.Write(context.Background(), &pbresource.WriteRequest{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Name: partitionName, - Type: pbtenancy.PartitionType, - }, - Data: data, - }, - }) - require.NoError(t, err) - }, - requirePartitionNotCreated: func(testClient *test.TestServerClient) { - rsp, err := testClient.ResourceClient.Read(context.Background(), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Name: partitionName, - Type: pbtenancy.PartitionType, - }, - }) - require.NoError(t, err) + // Create the Admin Partition before the test runs. + _, _, err = consul.Partitions().Create(context.Background(), &api.Partition{Name: partitionName, Description: "Created before test"}, nil) + require.NoError(t, err) - partition := &pbtenancy.Partition{} - err = anypb.UnmarshalTo(rsp.Resource.Data, partition, proto.UnmarshalOptions{}) - require.NoError(t, err) - require.Equal(t, partitionDesc, partition.Description) - }, - }, + ui := cli.NewMockUi() + cmd := Command{ + UI: ui, + } + cmd.init() + args := []string{ + "-addresses=" + "127.0.0.1", + "-http-port=" + strings.Split(server.HTTPAddr, ":")[1], + "-grpc-port=" + strings.Split(server.GRPCAddr, ":")[1], + "-partition", partitionName, } - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - var serverCfg *testutil.TestServerConfig - testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { - c.Experiments = tc.experiments - serverCfg = c - }) - - // Create the Admin Partition before the test runs. - tc.preCreatePartition(testClient) + responseCode := cmd.Run(args) - ui := cli.NewMockUi() - cmd := Command{ - UI: ui, - } - cmd.init() - args := []string{ - "-addresses=" + "127.0.0.1", - "-http-port", strconv.Itoa(serverCfg.Ports.HTTP), - "-grpc-port", strconv.Itoa(serverCfg.Ports.GRPC), - "-partition", partitionName, - "-enable-v2tenancy=" + strconv.FormatBool(tc.v2tenancy), - } + require.Equal(t, 0, responseCode) - responseCode := cmd.Run(args) - require.Equal(t, 0, responseCode) - - // Verify that the Admin Partition was not overwritten. - tc.requirePartitionNotCreated(testClient) - }) - } + partition, _, err := consul.Partitions().Read(context.Background(), partitionName, nil) + require.NoError(t, err) + require.NotNil(t, partition) + require.Equal(t, partitionName, partition.Name) + require.Equal(t, "Created before test", partition.Description) } func TestRun_ExitsAfterTimeout(t *testing.T) { partitionName := "test-partition" - type testCase struct { - v2tenancy bool - experiments []string - } + server, err := testutil.NewTestServerConfigT(t, nil) + require.NoError(t, err) - testCases := map[string]testCase{ - "v2tenancy false": { - v2tenancy: false, - experiments: []string{}, - }, - "v2tenancy true": { - v2tenancy: true, - experiments: []string{"resource-apis", "v2tenancy"}, - }, + ui := cli.NewMockUi() + cmd := Command{ + UI: ui, } - - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - var serverCfg *testutil.TestServerConfig - testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { - c.Experiments = tc.experiments - serverCfg = c - }) - - ui := cli.NewMockUi() - cmd := Command{ - UI: ui, - } - cmd.init() - - timeout := 500 * time.Millisecond - args := []string{ - "-addresses=" + "127.0.0.1", - "-http-port", strconv.Itoa(serverCfg.Ports.HTTP), - "-grpc-port", strconv.Itoa(serverCfg.Ports.GRPC), - "-timeout", timeout.String(), - "-partition", partitionName, - "-enable-v2tenancy=" + strconv.FormatBool(tc.v2tenancy), - } - - testClient.TestServer.Stop() - startTime := time.Now() - responseCode := cmd.Run(args) - completeTime := time.Now() - require.Equal(t, 1, responseCode) - - // While the timeout is 500ms, adding a buffer of 500ms ensures we account for - // some buffer time required for the task to run and assignments to occur. - require.WithinDuration(t, completeTime, startTime, timeout+500*time.Millisecond) - }) + cmd.init() + args := []string{ + "-addresses=" + "127.0.0.1", + "-http-port=" + strings.Split(server.HTTPAddr, ":")[1], + "-grpc-port=" + strings.Split(server.GRPCAddr, ":")[1], + "-timeout", "500ms", + "-partition", partitionName, } + server.Stop() + startTime := time.Now() + responseCode := cmd.Run(args) + completeTime := time.Now() + + require.Equal(t, 1, responseCode) + // While the timeout is 500ms, adding a buffer of 500ms ensures we account for + // some buffer time required for the task to run and assignments to occur. + require.WithinDuration(t, completeTime, startTime, 1*time.Second) } diff --git a/control-plane/subcommand/server-acl-init/command_ent_test.go b/control-plane/subcommand/server-acl-init/command_ent_test.go index e28af9ef35..b33e4beb60 100644 --- a/control-plane/subcommand/server-acl-init/command_ent_test.go +++ b/control-plane/subcommand/server-acl-init/command_ent_test.go @@ -1449,7 +1449,9 @@ func partitionedSetup(t *testing.T, bootToken string, partitionName string) *tes server.Cfg.APIClientConfig.Token = bootToken serverAPIClient, err := consul.NewClient(server.Cfg.APIClientConfig, 5*time.Second) require.NoError(t, err) + _, _, err = serverAPIClient.Partitions().Create(context.Background(), &api.Partition{Name: partitionName}, &api.WriteOptions{}) require.NoError(t, err) + return server.TestServer } diff --git a/control-plane/subcommand/sync-catalog/command_test.go b/control-plane/subcommand/sync-catalog/command_test.go index 9b7365e801..fdabb957f7 100644 --- a/control-plane/subcommand/sync-catalog/command_test.go +++ b/control-plane/subcommand/sync-catalog/command_test.go @@ -557,14 +557,14 @@ func TestRun_ToConsulChangingFlags(t *testing.T) { require.Len(r, instances, 1) require.Equal(r, instances[0].ServiceName, svcName) } - r.Log("existing services verified") + tt.Log("existing services verified") for _, svcName := range c.SecondRunExpDeletedServices { instances, _, err := consulClient.Catalog().Service(svcName, "k8s", nil) require.NoError(r, err) require.Len(r, instances, 0) } - r.Log("deleted services verified") + tt.Log("deleted services verified") }) } }) diff --git a/control-plane/tenancy/namespace/namespace.go b/control-plane/tenancy/namespace/namespace.go deleted file mode 100644 index 55950bba1d..0000000000 --- a/control-plane/tenancy/namespace/namespace.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package namespace - -import ( - "context" - "fmt" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul-k8s/control-plane/api/common" - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" -) - -// DeletionTimestampKey is the key in a resource's metadata that stores the timestamp -// when a resource was marked for deletion. This only applies to resources with finalizers. -const DeletionTimestampKey = "deletionTimestamp" - -// EnsureDeleted ensures a Consul namespace with name ns in partition ap is deleted or is in the -// process of being deleted. If neither, it will mark it for deletion. -func EnsureDeleted(ctx context.Context, client pbresource.ResourceServiceClient, ap, ns string) error { - if ns == common.WildcardNamespace || ns == common.DefaultNamespaceName { - return nil - } - - // Check if the Consul namespace exists. - rsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: &pbresource.ID{ - Name: ns, - Type: pbtenancy.NamespaceType, - Tenancy: &pbresource.Tenancy{Partition: ap}, - }}) - - switch { - case status.Code(err) == codes.NotFound: - // Nothing to do - return nil - case err != nil: - // Unexpected error - return fmt.Errorf("namespace read failed: %w", err) - case isMarkedForDeletion(rsp.Resource): - // Deletion already in progress, nothing to do - return nil - default: - // Namespace found, so non-CAS delete it. - _, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: rsp.Resource.Id, Version: ""}) - if err != nil { - return fmt.Errorf("namespace delete failed: %w", err) - } - return nil - } -} - -// EnsureExists ensures a Consul namespace with name ns exists and is not marked -// for deletion. If it doesn't, exist it will create it. If it is marked for deletion, -// returns an error. -// -// Boolean return value indicates if the namespace was created by this call. -func EnsureExists(ctx context.Context, client pbresource.ResourceServiceClient, ap, ns string) (bool, error) { - if ns == common.WildcardNamespace || ns == common.DefaultNamespaceName { - return false, nil - } - - // Check if the Consul namespace exists. - rsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: &pbresource.ID{ - Name: ns, - Type: pbtenancy.NamespaceType, - Tenancy: &pbresource.Tenancy{Partition: ap}, - }}) - - switch { - case err == nil && isMarkedForDeletion(rsp.Resource): - // Found, but delete in progress - return false, fmt.Errorf("consul namespace %q deletion in progress", ns) - case err == nil: - // Found and not marked for deletion, nothing to do - return false, nil - case status.Code(err) != codes.NotFound: - // Unexpected error - return false, fmt.Errorf("consul namespace read failed: %w", err) - } - - // Consul namespace not found, so create it - // TODO: Handle creation of crossNSACLPolicy when V2 ACLs are supported - nsData, err := anypb.New(&pbtenancy.Namespace{Description: "Auto-generated by consul-k8s"}) - if err != nil { - return false, err - } - - _, err = client.Write(ctx, &pbresource.WriteRequest{Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Name: ns, - Type: pbtenancy.NamespaceType, - Tenancy: &pbresource.Tenancy{Partition: ap}, - }, - Metadata: map[string]string{"external-source": "kubernetes"}, - Data: nsData, - }}) - - if err != nil { - return false, fmt.Errorf("consul namespace creation failed: %w", err) - } - return true, nil -} - -// isMarkedForDeletion returns true if a resource has been marked for deletion, -// false otherwise. -func isMarkedForDeletion(res *pbresource.Resource) bool { - if res.Metadata == nil { - return false - } - _, ok := res.Metadata[DeletionTimestampKey] - return ok -} diff --git a/control-plane/tenancy/namespace/namespace_controller.go b/control-plane/tenancy/namespace/namespace_controller.go deleted file mode 100644 index e08951b61c..0000000000 --- a/control-plane/tenancy/namespace/namespace_controller.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package namespace - -import ( - "context" - "fmt" - - "github.com/go-logr/logr" - corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/hashicorp/consul-k8s/control-plane/api/common" - injectcommon "github.com/hashicorp/consul-k8s/control-plane/connect-inject/common" - "github.com/hashicorp/consul-k8s/control-plane/consul" -) - -// Namespace syncing between K8s and Consul is vastly simplified when V2 tenancy is enabled. -// Put simply, a K8s namespace maps 1:1 to a Consul namespace of the same name and that is -// the only supported behavior. -// -// The plethora of configuration options available when using V1 tenancy have been removed -// to simplify the user experience and mapping rules. -// -// Hence, the following V1 tenancy namespace helm configuration values are ignored: -// - global.enableConsulNamespaces -// - connectInject.consulNamespaces.consulDestinationNamespace -// - connectInject.consulNamespaces.mirroringK8S -// - connectInject.consulNamespaces.mirroringK8SPrefix. -type Controller struct { - client.Client - // ConsulServerConnMgr is the watcher for the Consul server addresses. - ConsulServerConnMgr consul.ServerConnectionManager - // K8sNamespaceConfig manages allow/deny Kubernetes namespaces. - common.K8sNamespaceConfig - // ConsulTenancyConfig contains the destination partition. - common.ConsulTenancyConfig - Log logr.Logger -} - -// Reconcile reads a Kubernetes Namespace and reconciles the mapped namespace in Consul. -func (r *Controller) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - var namespace corev1.Namespace - - // Ignore the request if the namespace should not be synced to consul. - if injectcommon.ShouldIgnore(req.Name, r.DenyK8sNamespacesSet, r.AllowK8sNamespacesSet) { - return ctrl.Result{}, nil - } - - // Create a gRPC resource service client - resourceClient, err := consul.NewResourceServiceClient(r.ConsulServerConnMgr) - if err != nil { - r.Log.Error(err, "failed to create Consul resource service client", "name", req.Name) - return ctrl.Result{}, err - } - - // Target consul tenancy - consulAP := r.ConsulPartition - consulNS := req.Name - - // Re-read the k8s namespace object - err = r.Client.Get(ctx, req.NamespacedName, &namespace) - - // If the namespace object has been deleted (we get an IsNotFound error), - // we need to remove the Namespace from Consul. - if k8serrors.IsNotFound(err) { - if err := EnsureDeleted(ctx, resourceClient, consulAP, consulNS); err != nil { - return ctrl.Result{}, fmt.Errorf("error deleting consul namespace: %w", err) - } - - return ctrl.Result{}, nil - } else if err != nil { - r.Log.Error(err, "failed to get k8s namespace", "name", req.Name) - return ctrl.Result{}, err - } - - // k8s namespace found, so make sure it is mapped correctly and exists in Consul. - r.Log.Info("retrieved", "k8s namespace", namespace.GetName()) - - if _, err := EnsureExists(ctx, resourceClient, consulAP, consulNS); err != nil { - r.Log.Error(err, "error checking or creating consul namespace", "namespace", consulNS) - return ctrl.Result{}, fmt.Errorf("error checking or creating consul namespace: %w", err) - } - return ctrl.Result{}, nil -} - -// SetupWithManager registers this controller with the manager. -func (r *Controller) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(&corev1.Namespace{}). - Complete(r) -} diff --git a/control-plane/tenancy/namespace/namespace_controller_ent_test.go b/control-plane/tenancy/namespace/namespace_controller_ent_test.go deleted file mode 100644 index 997164d638..0000000000 --- a/control-plane/tenancy/namespace/namespace_controller_ent_test.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -//go:build enterprise - -package namespace - -import ( - "testing" -) - -func TestReconcileCreateNamespace_ENT(t *testing.T) { - testCases := []createTestCase{ - { - name: "consul namespace is ap1/ns1", - kubeNamespace: "ns1", - partition: "ap1", - expectedConsulNamespace: "ns1", - }, - } - testReconcileCreateNamespace(t, testCases) -} - -func TestReconcileDeleteNamespace_ENT(t *testing.T) { - testCases := []deleteTestCase{ - { - name: "non-default partition", - kubeNamespace: "ns1", - partition: "ap1", - existingConsulNamespace: "ns1", - expectNamespaceDeleted: "ns1", - }, - } - testReconcileDeleteNamespace(t, testCases) -} diff --git a/control-plane/tenancy/namespace/namespace_controller_test.go b/control-plane/tenancy/namespace/namespace_controller_test.go deleted file mode 100644 index b9d1cd8728..0000000000 --- a/control-plane/tenancy/namespace/namespace_controller_test.go +++ /dev/null @@ -1,301 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package namespace - -import ( - "context" - "testing" - "time" - - mapset "github.com/deckarep/golang-set" - logrtest "github.com/go-logr/logr/testr" - "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - - "github.com/hashicorp/consul-k8s/control-plane/api/common" - "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" - "github.com/hashicorp/consul-k8s/control-plane/helper/test" - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestReconcileCreateNamespace(t *testing.T) { - testCases := []createTestCase{ - { - name: "consul namespace is default/ns1", - kubeNamespace: "ns1", - partition: constants.DefaultConsulPartition, - expectedConsulNamespace: "ns1", - }, - } - testReconcileCreateNamespace(t, testCases) -} - -type createTestCase struct { - name string - kubeNamespace string - partition string - expectedConsulNamespace string -} - -// testReconcileCreateNamespace ensures that a new k8s namespace is reconciled to a -// Consul namespace. The actual namespace in Consul depends on if the controller -// is configured with a destination namespace or mirroring enabled. -func testReconcileCreateNamespace(t *testing.T, testCases []createTestCase) { - run := func(t *testing.T, tc createTestCase) { - // Create the default kube namespace and kube namespace under test. - kubeNS := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: tc.kubeNamespace}} - kubeDefaultNS := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: metav1.NamespaceDefault}} - kubeObjects := []runtime.Object{ - &kubeNS, - &kubeDefaultNS, - } - fakeClient := fake.NewClientBuilder().WithRuntimeObjects(kubeObjects...).Build() - - // Fire up consul server with v2tenancy enabled - testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { - c.Experiments = []string{"resource-apis", "v2tenancy"} - }) - - // Create partition if needed - testClient.Cfg.APIClientConfig.Partition = tc.partition - if tc.partition != "" && tc.partition != "default" { - _, err := testClient.ResourceClient.Write(context.Background(), &pbresource.WriteRequest{Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Name: tc.partition, - Type: pbtenancy.PartitionType, - }, - }}) - require.NoError(t, err, "failed to create partition") - } - - // Create the namespace controller injecting config from tc - nc := &Controller{ - Client: fakeClient, - ConsulServerConnMgr: testClient.Watcher, - K8sNamespaceConfig: common.K8sNamespaceConfig{ - AllowK8sNamespacesSet: mapset.NewSetWith("*"), - DenyK8sNamespacesSet: mapset.NewSetWith(), - }, - ConsulTenancyConfig: common.ConsulTenancyConfig{ - ConsulPartition: tc.partition, - }, - Log: logrtest.New(t), - } - - // Reconcile the kube namespace under test - resp, err := nc.Reconcile(context.Background(), ctrl.Request{ - NamespacedName: types.NamespacedName{ - Name: tc.kubeNamespace, - }, - }) - require.NoError(t, err) - require.False(t, resp.Requeue) - - // Verify consul namespace exists or was created during reconciliation - _, err = testClient.ResourceClient.Read(context.Background(), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Name: tc.expectedConsulNamespace, - Type: pbtenancy.NamespaceType, - Tenancy: &pbresource.Tenancy{Partition: tc.partition}, - }, - }) - require.NoError(t, err, "expected partition/namespace %s/%s to exist", tc.partition, tc.expectedConsulNamespace) - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestReconcileDeleteNamespace(t *testing.T) { - testCases := []deleteTestCase{ - { - name: "consul namespace ns1", - kubeNamespace: "ns1", - partition: "default", - existingConsulNamespace: "ns1", - expectNamespaceDeleted: "ns1", - }, - { - name: "consul default namespace does not get deleted", - kubeNamespace: metav1.NamespaceDefault, - partition: "default", - existingConsulNamespace: "", - expectNamespaceExists: "default", - }, - { - name: "namespace is already removed from Consul", - kubeNamespace: "ns1", - partition: "default", - existingConsulNamespace: "", // don't pre-create consul namespace - expectNamespaceDeleted: "ns1", // read as "was never created" - }, - } - testReconcileDeleteNamespace(t, testCases) -} - -type deleteTestCase struct { - name string - kubeNamespace string - partition string - existingConsulNamespace string // If non-empty, this namespace is created in consul pre-reconcile - - // Pick one - expectNamespaceExists string // If non-empty, this namespace should exist in consul post-reconcile - expectNamespaceDeleted string // If non-empty, this namespace should not exist in consul post-reconcile -} - -// Tests deleting a Namespace object, with and without matching Consul namespace. -func testReconcileDeleteNamespace(t *testing.T, testCases []deleteTestCase) { - run := func(t *testing.T, tc deleteTestCase) { - // Don't seed with any kube namespaces since we're testing deletion. - fakeClient := fake.NewClientBuilder().WithRuntimeObjects().Build() - - // Fire up consul server with v2tenancy enabled - testClient := test.TestServerWithMockConnMgrWatcher(t, func(c *testutil.TestServerConfig) { - c.Experiments = []string{"resource-apis", "v2tenancy"} - }) - - // Create partition if needed - testClient.Cfg.APIClientConfig.Partition = tc.partition - if tc.partition != "" && tc.partition != "default" { - _, err := testClient.ResourceClient.Write(context.Background(), &pbresource.WriteRequest{Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Name: tc.partition, - Type: pbtenancy.PartitionType, - }, - }}) - require.NoError(t, err, "failed to create partition") - } - - // Create the consul namespace if needed - if tc.existingConsulNamespace != "" && tc.existingConsulNamespace != "default" { - id := &pbresource.ID{ - Name: tc.existingConsulNamespace, - Type: pbtenancy.NamespaceType, - Tenancy: &pbresource.Tenancy{Partition: tc.partition}, - } - - rsp, err := testClient.ResourceClient.Write(context.Background(), &pbresource.WriteRequest{Resource: &pbresource.Resource{Id: id}}) - require.NoError(t, err, "failed to create namespace") - - // TODO: Remove after https://hashicorp.atlassian.net/browse/NET-6719 implemented - requireEventuallyAccepted(t, testClient.ResourceClient, rsp.Resource.Id) - } - - // Create the namespace controller. - nc := &Controller{ - Client: fakeClient, - ConsulServerConnMgr: testClient.Watcher, - K8sNamespaceConfig: common.K8sNamespaceConfig{ - AllowK8sNamespacesSet: mapset.NewSetWith("*"), - DenyK8sNamespacesSet: mapset.NewSetWith(), - }, - ConsulTenancyConfig: common.ConsulTenancyConfig{ - ConsulPartition: tc.partition, - }, - Log: logrtest.New(t), - } - - // Reconcile the kube namespace under test - imagine it has just been deleted - resp, err := nc.Reconcile(context.Background(), ctrl.Request{ - NamespacedName: types.NamespacedName{ - Name: tc.kubeNamespace, - }, - }) - require.NoError(t, err) - require.False(t, resp.Requeue) - - // Verify appropriate action was taken on the counterpart consul namespace - if tc.expectNamespaceExists != "" { - // Verify consul namespace was not deleted - _, err = testClient.ResourceClient.Read(context.Background(), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Name: tc.expectNamespaceExists, - Type: pbtenancy.NamespaceType, - Tenancy: &pbresource.Tenancy{Partition: tc.partition}, - }, - }) - require.NoError(t, err, "expected partition/namespace %s/%s to exist", tc.partition, tc.expectNamespaceExists) - } else if tc.expectNamespaceDeleted != "" { - // Verify consul namespace was deleted - id := &pbresource.ID{ - Name: tc.expectNamespaceDeleted, - Type: pbtenancy.NamespaceType, - Tenancy: &pbresource.Tenancy{Partition: tc.partition}, - } - requireEventuallyNotFound(t, testClient.ResourceClient, id) - } else { - panic("tc.expectedNamespaceExists or tc.expectedNamespaceDeleted must be set") - } - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - run(t, tc) - }) - } -} - -// RequireStatusAccepted waits for a recently created resource to have a resource status of accepted so that -// attempts to delete it by the single-shot controller under test's reconcile will not fail with a CAS error. -// -// Remove refs to this after https://hashicorp.atlassian.net/browse/NET-6719 is implemented. -func requireEventuallyAccepted(t *testing.T, resourceClient pbresource.ResourceServiceClient, id *pbresource.ID) { - require.Eventuallyf(t, - func() bool { - rsp, err := resourceClient.Read(context.Background(), &pbresource.ReadRequest{Id: id}) - if err != nil { - return false - } - if rsp.Resource.Status == nil || len(rsp.Resource.Status) == 0 { - return false - } - - for _, status := range rsp.Resource.Status { - for _, condition := range status.Conditions { - // common.ConditionAccepted in consul namespace controller - if condition.Type == "accepted" && condition.State == pbresource.Condition_STATE_TRUE { - return true - } - } - } - return false - }, - time.Second*5, - time.Millisecond*100, - "timed out out waiting for %s to have status accepted", - id, - ) -} - -func requireEventuallyNotFound(t *testing.T, resourceClient pbresource.ResourceServiceClient, id *pbresource.ID) { - // allow both "not found" and "marked for deletion" so we're not waiting around unnecessarily - require.Eventuallyf(t, func() bool { - rsp, err := resourceClient.Read(context.Background(), &pbresource.ReadRequest{Id: id}) - if err == nil { - return isMarkedForDeletion(rsp.Resource) - } - if status.Code(err) == codes.NotFound { - return true - } - return false - }, - time.Second*5, - time.Millisecond*100, - "timed out waiting for %s to not be found", - id, - ) -} diff --git a/control-plane/version/version.go b/control-plane/version/version.go index f68d1632a6..feb168fbe4 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -17,7 +17,7 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "1.5.0" + Version = "1.3.4" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release diff --git a/hack/copy-crds-to-chart/main.go b/hack/copy-crds-to-chart/main.go index 7835a6244a..435918c53d 100644 --- a/hack/copy-crds-to-chart/main.go +++ b/hack/copy-crds-to-chart/main.go @@ -18,13 +18,6 @@ var ( "consul.hashicorp.com_peeringacceptors.yaml": {}, "consul.hashicorp.com_peeringdialers.yaml": {}, } - - // includeV1Suffix is used to add a ...-v1.yaml suffix for types that exist in - // v1 and v2 APIs with the same name and would otherwise result in last man wins - includeV1Suffix = map[string]struct{}{ - "consul.hashicorp.com_exportedservices.yaml": {}, - "consul.hashicorp.com_gatewayclassconfigs.yaml": {}, - } ) func main() { @@ -95,20 +88,14 @@ func realMain(helmPath string) error { withLabels := append(splitOnNewlines[0:split], append(labelLines, splitOnNewlines[split:]...)...) contents = strings.Join(withLabels, "\n") - suffix := "" - if _, ok := includeV1Suffix[info.Name()]; ok { - suffix = "-v1" - } - var crdName string if dir == "bases" { // Construct the destination filename. filenameSplit := strings.Split(info.Name(), "_") - filenameSplit = strings.Split(filenameSplit[1], ".") - crdName = filenameSplit[0] + suffix + ".yaml" + crdName = filenameSplit[1] } else if dir == "external" { filenameSplit := strings.Split(info.Name(), ".") - crdName = filenameSplit[0] + suffix + "-external.yaml" + crdName = filenameSplit[0] + "-external.yaml" } destinationPath := filepath.Join(helmPath, "templates", fmt.Sprintf("crd-%s", crdName))