From 19badf7ac0472b7cc3a8577940f78cb10a08b088 Mon Sep 17 00:00:00 2001 From: Ashesh Vidyut <134911583+absolutelightning@users.noreply.github.com> Date: Wed, 25 Oct 2023 16:02:48 +0530 Subject: [PATCH] Add the consul_config_entry_service_defaults resource (#366) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ashesh Vidyut Co-authored-by: RĂ©mi Lapeyre --- .github/workflows/test.yaml | 4 +- ...ce_consul_config_entry_service_defaults.go | 899 ++++++++++++++++++ ...l_config_entry_service_defaults_ce_test.go | 308 ++++++ ...l_config_entry_service_defaults_ee_test.go | 316 ++++++ consul/resource_provider.go | 1 + .../config_entry_service_defaults.md | 199 ++++ 6 files changed, 1726 insertions(+), 1 deletion(-) create mode 100644 consul/resource_consul_config_entry_service_defaults.go create mode 100644 consul/resource_consul_config_entry_service_defaults_ce_test.go create mode 100644 consul/resource_consul_config_entry_service_defaults_ee_test.go create mode 100644 docs/resources/config_entry_service_defaults.md diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 2160d20e..43ef980d 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -45,7 +45,9 @@ jobs: sudo unzip tfplugindocs_0.16.0_linux_amd64.zip tfplugindocs -d /usr/local/bin rm -f tfplugindocs_0.16.0_linux_amd64.zip - name: Generate the documentation - run: tfplugindocs generate --ignore-deprecated true + run: | + terraform fmt -recursive . + tfplugindocs generate --ignore-deprecated true - name: Fail if repository has changes run: | git status --short diff --git a/consul/resource_consul_config_entry_service_defaults.go b/consul/resource_consul_config_entry_service_defaults.go new file mode 100644 index 00000000..ab0c2a96 --- /dev/null +++ b/consul/resource_consul_config_entry_service_defaults.go @@ -0,0 +1,899 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "fmt" + "time" + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +type serviceDefaults struct{} + +func (s *serviceDefaults) GetKind() string { + return consulapi.ServiceDefaults +} + +func (s *serviceDefaults) GetDescription() string { + return "The `consul_config_entry_service_defaults` resource configures a [service defaults](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-defaults) config entry that contains common configuration settings for service mesh services, such as upstreams and gateways." +} + +func (s *serviceDefaults) GetSchema() map[string]*schema.Schema { + upstreamConfigSchemaOverrides := &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the name of the service you are setting the defaults for.", + }, + "partition": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the name of the name of the Consul admin partition that the configuration entry applies to.", + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the namespace containing the upstream service that the configuration applies to.", + }, + "peer": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the peer name of the upstream service that the configuration applies to.", + }, + "envoy_listener_json": { + Type: schema.TypeString, + Optional: true, + }, + "protocol": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the default protocol for the service.", + }, + "connect_timeout_ms": { + Type: schema.TypeInt, + Optional: true, + }, + "limits": { + Type: schema.TypeSet, + Optional: true, + Description: "Map that specifies a set of limits to apply to when connecting upstream services.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "max_connections": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the maximum number of connections a service instance can establish against the upstream.", + }, + "max_pending_requests": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the maximum number of requests that are queued while waiting for a connection to establish.", + }, + "max_concurrent_requests": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the maximum number of concurrent requests.", + }, + }, + }, + }, + "passive_health_check": { + Type: schema.TypeSet, + Optional: true, + Description: "Map that specifies a set of rules that enable Consul to remove hosts from the upstream cluster that are unreachable or that return errors.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "interval": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the time between checks.", + }, + "max_failures": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the number of consecutive failures allowed per check interval. If exceeded, Consul removes the host from the load balancer.", + }, + "enforcing_consecutive_5xx": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies a percentage that indicates how many times out of 100 that Consul ejects the host when it detects an outlier status.", + }, + "max_ejection_percent": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the maximum percentage of an upstream cluster that Consul ejects when the proxy reports an outlier.", + }, + "base_ejection_time": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the minimum amount of time that an ejected host must remain outside the cluster before rejoining.", + }, + }, + }, + }, + "mesh_gateway": { + Type: schema.TypeSet, + Optional: true, + Description: "Specifies the default mesh gateway mode field for all upstreams.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "balance_outbound_connections": { + Type: schema.TypeString, + Optional: true, + Description: "Sets the strategy for allocating outbound connections from upstreams across Envoy proxy threads.", + }, + }, + } + upstreamConfigSchemaDefaults := &schema.Resource{ + Schema: map[string]*schema.Schema{ + "protocol": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the default protocol for the service.", + }, + "connect_timeout_ms": { + Type: schema.TypeInt, + Optional: true, + }, + "limits": { + Type: schema.TypeSet, + Optional: true, + Description: "Map that specifies a set of limits to apply to when connecting upstream services.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "max_connections": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the maximum number of connections a service instance can establish against the upstream.", + }, + "max_pending_requests": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the maximum number of requests that are queued while waiting for a connection to establish.", + }, + "max_concurrent_requests": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the maximum number of concurrent requests.", + }, + }, + }, + }, + "passive_health_check": { + Type: schema.TypeSet, + Optional: true, + Description: "Map that specifies a set of rules that enable Consul to remove hosts from the upstream cluster that are unreachable or that return errors.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "interval": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the time between checks.", + }, + "max_failures": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the number of consecutive failures allowed per check interval. If exceeded, Consul removes the host from the load balancer.", + }, + "enforcing_consecutive_5xx": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies a percentage that indicates how many times out of 100 that Consul ejects the host when it detects an outlier status.", + }, + "max_ejection_percent": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the maximum percentage of an upstream cluster that Consul ejects when the proxy reports an outlier.", + }, + "base_ejection_time": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the minimum amount of time that an ejected host must remain outside the cluster before rejoining.", + }, + }, + }, + }, + "mesh_gateway": { + Type: schema.TypeSet, + Optional: true, + Description: "Specifies the default mesh gateway mode field for all upstreams.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "balance_outbound_connections": { + Type: schema.TypeString, + Optional: true, + Description: "Sets the strategy for allocating outbound connections from upstreams across Envoy proxy threads.", + }, + }, + } + return map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Specifies the name of the service you are setting the defaults for.", + }, + "namespace": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Specifies the Consul namespace that the configuration entry applies to.", + }, + "partition": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Specifies the name of the name of the Consul admin partition that the configuration entry applies to. Refer to Admin Partitions for additional information.", + }, + "meta": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Specifies a set of custom key-value pairs to add to the Consul KV store.", + }, + "protocol": { + Type: schema.TypeString, + Required: true, + Description: "Specifies the default protocol for the service.", + }, + "balance_inbound_connections": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the strategy for allocating inbound connections to the service across Envoy proxy threads.", + }, + "mode": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies a mode for how the service directs inbound and outbound traffic.", + }, + "upstream_config": { + Type: schema.TypeSet, + Optional: true, + Description: "Controls default upstream connection settings and custom overrides for individual upstream services.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "overrides": { + Type: schema.TypeList, + Optional: true, + Elem: upstreamConfigSchemaOverrides, + Description: "Specifies options that override the default upstream configurations for individual upstreams.", + }, + "defaults": { + Type: schema.TypeSet, + Optional: true, + Elem: upstreamConfigSchemaDefaults, + Description: "Specifies configurations that set default upstream settings. For information about overriding the default configurations for in for individual upstreams, refer to UpstreamConfig.Overrides.", + }, + }, + }, + }, + "transparent_proxy": { + Type: schema.TypeSet, + Optional: true, + Description: "Controls configurations specific to proxies in transparent mode. Refer to Transparent Proxy Mode for additional information.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "outbound_listener_port": { + Required: true, + Type: schema.TypeInt, + }, + "dialed_directly": { + Required: true, + Type: schema.TypeBool, + }, + }, + }, + }, + "mutual_tls_mode": { + Type: schema.TypeString, + Optional: true, + Description: "Controls whether mutual TLS is required for incoming connections to this service. This setting is only supported for services with transparent proxy enabled.", + }, + "envoy_extensions": { + Type: schema.TypeList, + Optional: true, + Description: "List of extensions to modify Envoy proxy configuration.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + }, + "required": { + Type: schema.TypeBool, + Optional: true, + }, + "arguments": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "consul_version": { + Type: schema.TypeString, + Optional: true, + }, + "envoy_version": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "destination": { + Type: schema.TypeSet, + Optional: true, + Description: "Configures the destination for service traffic through terminating gateways.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "port": { + Type: schema.TypeInt, + Required: true, + }, + "addresses": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "local_connect_timeout_ms": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the number of milliseconds allowed for establishing connections to the local application instance before timing out.", + }, + "max_inbound_connections": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the maximum number of concurrent inbound connections to each service instance.", + }, + "local_request_timeout_ms": { + Type: schema.TypeInt, + Optional: true, + Description: "Specifies the timeout for HTTP requests to the local application instance.", + }, + "mesh_gateway": { + Type: schema.TypeSet, + Optional: true, + Description: "Specifies the default mesh gateway mode field for the service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Required: true, + Type: schema.TypeString, + }, + }, + }, + }, + "external_sni": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the TLS server name indication (SNI) when federating with an external system.", + }, + "expose": { + Type: schema.TypeSet, + Required: true, + Description: "Specifies default configurations for exposing HTTP paths through Envoy.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "checks": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + }, + "paths": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "path": { + Type: schema.TypeString, + Optional: true, + }, + "local_path_port": { + Type: schema.TypeInt, + Optional: true, + }, + "listener_port": { + Type: schema.TypeInt, + Optional: true, + }, + "protocol": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + } +} + +func (s *serviceDefaults) Decode(d *schema.ResourceData) (consulapi.ConfigEntry, error) { + configEntry := &consulapi.ServiceConfigEntry{ + Kind: consulapi.ServiceDefaults, + Name: d.Get("name").(string), + Partition: d.Get("partition").(string), + } + if d.Get("namespace") != nil { + configEntry.Namespace = d.Get("namespace").(string) + } + if d.Get("protocol") != nil { + configEntry.Protocol = d.Get("protocol").(string) + } + if d.Get("balance_inbound_connections") != nil { + configEntry.BalanceInboundConnections = d.Get("balance_inbound_connections").(string) + } + if d.Get("local_connect_timeout_ms") != nil { + configEntry.LocalConnectTimeoutMs = d.Get("local_connect_timeout_ms").(int) + } + if d.Get("max_inbound_connections") != nil { + configEntry.MaxInboundConnections = d.Get("max_inbound_connections").(int) + } + if d.Get("local_request_timeout_ms") != nil { + configEntry.LocalRequestTimeoutMs = d.Get("local_request_timeout_ms").(int) + } + if d.Get("external_sni") != nil { + configEntry.ExternalSNI = d.Get("external_sni").(string) + } + if d.Get("mode") != nil { + configEntry.Mode = consulapi.ProxyMode(d.Get("mode").(string)) + } + if d.Get("mutual_tls_mode") != nil { + configEntry.MutualTLSMode = consulapi.MutualTLSMode(d.Get("mutual_tls_mode").(string)) + } + configEntry.Meta = map[string]string{} + + if d.Get("meta") != nil { + for k, v := range d.Get("meta").(map[string]interface{}) { + configEntry.Meta[k] = v.(string) + } + } + + getLimits := func(limitsMap map[string]interface{}) *consulapi.UpstreamLimits { + intPtr := func(i int) *int { + if i == 0 { + return nil + } + return &i + } + return &consulapi.UpstreamLimits{ + MaxPendingRequests: intPtr(limitsMap["max_pending_requests"].(int)), + MaxConnections: intPtr(limitsMap["max_connections"].(int)), + MaxConcurrentRequests: intPtr(limitsMap["max_concurrent_requests"].(int)), + } + } + + getPassiveHealthCheck := func(passiveHealthCheckSet interface{}) (*consulapi.PassiveHealthCheck, error) { + passiveHealthCheck := passiveHealthCheckSet.(*schema.Set).List() + if len(passiveHealthCheck) > 0 { + passiveHealthCheckMap := passiveHealthCheck[0].(map[string]interface{}) + uint32Ptr := func(i int) *uint32 { + if i == 0 { + return nil + } + ui := uint32(i) + return &ui + } + passiveHealthCheck := &consulapi.PassiveHealthCheck{ + MaxFailures: uint32(passiveHealthCheckMap["max_failures"].(int)), + EnforcingConsecutive5xx: uint32Ptr(passiveHealthCheckMap["enforcing_consecutive_5xx"].(int)), + MaxEjectionPercent: uint32Ptr(passiveHealthCheckMap["max_ejection_percent"].(int)), + } + duration, err := time.ParseDuration(passiveHealthCheckMap["interval"].(string)) + if err != nil { + return nil, fmt.Errorf("failed to parse interval: %w", err) + } + passiveHealthCheck.Interval = duration + baseEjectionTime, err := time.ParseDuration(passiveHealthCheckMap["base_ejection_time"].(string)) + if err != nil { + return nil, fmt.Errorf("failed to parse base_ejection_time: %w", err) + } + passiveHealthCheck.BaseEjectionTime = &baseEjectionTime + return passiveHealthCheck, nil + } + return nil, nil + } + + getMeshGateway := func(meshGateway interface{}) *consulapi.MeshGatewayConfig { + meshGatewayList := meshGateway.(*schema.Set).List() + if len(meshGatewayList) > 0 { + meshGatewayData := meshGatewayList[0].(map[string]interface{}) + return &consulapi.MeshGatewayConfig{ + Mode: consulapi.MeshGatewayMode(meshGatewayData["mode"].(string)), + } + } + return nil + } + + getUpstreamConfigOverrides := func(upstreamConfigMap map[string]interface{}) (*consulapi.UpstreamConfig, error) { + upstreamConfig := &consulapi.UpstreamConfig{} + if upstreamConfigMap["name"] != nil { + upstreamConfig.Name = upstreamConfigMap["name"].(string) + } + if upstreamConfigMap["partition"] != nil { + upstreamConfig.Partition = upstreamConfigMap["partition"].(string) + } + if upstreamConfigMap["namespace"] != nil { + upstreamConfig.Namespace = upstreamConfigMap["namespace"].(string) + } + if upstreamConfigMap["peer"] != nil { + upstreamConfig.Peer = upstreamConfigMap["peer"].(string) + } + if upstreamConfigMap["protocol"] != nil { + upstreamConfig.Protocol = upstreamConfigMap["protocol"].(string) + } + if upstreamConfigMap["connect_timeout_ms"] != nil { + upstreamConfig.ConnectTimeoutMs = upstreamConfigMap["connect_timeout_ms"].(int) + } + if upstreamConfigMap["limits"] != nil && len(upstreamConfigMap["limits"].(*schema.Set).List()) > 0 { + upstreamConfig.Limits = getLimits(upstreamConfigMap["limits"].(*schema.Set).List()[0].(map[string]interface{})) + } + if upstreamConfigMap["passive_health_check"] != nil { + passiveHealthCheck, err := getPassiveHealthCheck(upstreamConfigMap["passive_health_check"]) + if err != nil { + return nil, err + } + upstreamConfig.PassiveHealthCheck = passiveHealthCheck + } + if upstreamConfigMap["mesh_gateway"] != nil { + upstreamConfig.MeshGateway = *getMeshGateway(upstreamConfigMap["mesh_gateway"]) + } + if upstreamConfigMap["balance_outbound_connections"] != nil { + upstreamConfig.BalanceOutboundConnections = upstreamConfigMap["balance_outbound_connections"].(string) + } + return upstreamConfig, nil + } + + getUpstreamConfigDefaults := func(upstreamConfigMap map[string]interface{}) (*consulapi.UpstreamConfig, error) { + upstreamConfig := &consulapi.UpstreamConfig{} + if upstreamConfigMap["protocol"] != nil { + upstreamConfig.Protocol = upstreamConfigMap["protocol"].(string) + } + if upstreamConfigMap["connect_timeout_ms"] != nil { + upstreamConfig.ConnectTimeoutMs = upstreamConfigMap["connect_timeout_ms"].(int) + } + if upstreamConfigMap["limits"] != nil && len(upstreamConfigMap["limits"].(*schema.Set).List()) > 0 { + upstreamConfig.Limits = getLimits(upstreamConfigMap["limits"].(*schema.Set).List()[0].(map[string]interface{})) + } + if upstreamConfigMap["passive_health_check"] != nil { + passiveHealthCheck, err := getPassiveHealthCheck(upstreamConfigMap["passive_health_check"]) + if err != nil { + return nil, err + } + upstreamConfig.PassiveHealthCheck = passiveHealthCheck + } + if upstreamConfigMap["mesh_gateway"] != nil { + upstreamConfig.MeshGateway = *getMeshGateway(upstreamConfigMap["mesh_gateway"]) + } + if upstreamConfigMap["balance_outbound_connections"] != nil { + upstreamConfig.BalanceOutboundConnections = upstreamConfigMap["balance_outbound_connections"].(string) + } + return upstreamConfig, nil + } + + getTransparentProxy := func(transparentProxy map[string]interface{}) *consulapi.TransparentProxyConfig { + transparentProxyConfig := &consulapi.TransparentProxyConfig{} + if transparentProxy["outbound_listener_port"] != nil { + transparentProxyConfig.OutboundListenerPort = transparentProxy["outbound_listener_port"].(int) + } + if transparentProxy["dialed_directly"] != nil { + transparentProxyConfig.DialedDirectly = transparentProxy["dialed_directly"].(bool) + } + return transparentProxyConfig + } + + getEnvoyExtension := func(envoyExtensionMap map[string]interface{}) consulapi.EnvoyExtension { + envoyExtension := consulapi.EnvoyExtension{} + if envoyExtensionMap["name"] != nil { + envoyExtension.Name = envoyExtensionMap["name"].(string) + } + if envoyExtensionMap["required"] != nil { + envoyExtension.Required = envoyExtensionMap["required"].(bool) + } + if envoyExtensionMap["arguments"] != nil { + envoyExtension.Arguments = envoyExtensionMap["arguments"].(map[string]interface{}) + } + if envoyExtensionMap["consul_version"] != nil { + envoyExtension.ConsulVersion = envoyExtensionMap["consul_version"].(string) + } + if envoyExtensionMap["envoy_version"] != nil { + envoyExtension.EnvoyVersion = envoyExtensionMap["envoy_version"].(string) + } + return envoyExtension + } + + getDestination := func(destinationMap map[string]interface{}) *consulapi.DestinationConfig { + if destinationMap != nil { + destination := &consulapi.DestinationConfig{} + if destinationMap["port"] != nil { + destination.Port = destinationMap["port"].(int) + } + if destinationMap["addresses"] != nil { + for _, addr := range destinationMap["addresses"].([]interface{}) { + destination.Addresses = append(destination.Addresses, addr.(string)) + } + } + return destination + } + return nil + } + + getExposePath := func(exposePathMap map[string]interface{}) *consulapi.ExposePath { + exposePath := &consulapi.ExposePath{} + if exposePathMap["path"] != nil { + exposePath.Path = exposePathMap["path"].(string) + } + if exposePathMap["local_path_port"] != nil { + exposePath.LocalPathPort = exposePathMap["local_path_port"].(int) + } + if exposePathMap["listener_port"] != nil { + exposePath.ListenerPort = exposePathMap["listener_port"].(int) + } + if exposePathMap["protocol"] != nil { + exposePath.Protocol = exposePathMap["protocol"].(string) + } + return exposePath + } + + getExpose := func(exposeMap map[string]interface{}) consulapi.ExposeConfig { + exposeConfig := consulapi.ExposeConfig{} + if exposeMap["checks"] != nil { + exposeConfig.Checks = exposeMap["checks"].(bool) + } + if exposeMap["paths"] != nil { + for _, elem := range exposeMap["paths"].([]interface{}) { + exposeConfig.Paths = append(exposeConfig.Paths, *getExposePath(elem.(map[string]interface{}))) + } + } + return exposeConfig + } + + upstreamConfigList := d.Get("upstream_config").(*schema.Set).List() + if len(upstreamConfigList) > 0 { + configEntry.UpstreamConfig = &consulapi.UpstreamConfiguration{} + upstreamConfigMap := upstreamConfigList[0].(map[string]interface{}) + if upstreamConfigMap["defaults"] != nil { + defaultsUpstreamConfigMapList := upstreamConfigMap["defaults"].(*schema.Set).List() + if len(defaultsUpstreamConfigMapList) > 0 { + defaultsUpstreamConfig, err := getUpstreamConfigDefaults(defaultsUpstreamConfigMapList[0].(map[string]interface{})) + if err != nil { + return nil, err + } + configEntry.UpstreamConfig.Defaults = defaultsUpstreamConfig + } + } + + if upstreamConfigMap["overrides"] != nil { + overrideUpstreamConfigList := upstreamConfigMap["overrides"].([]interface{}) + var overrideUpstreamConfig []*consulapi.UpstreamConfig + for _, elem := range overrideUpstreamConfigList { + overrideUpstreamConfigElem, err := getUpstreamConfigOverrides(elem.(map[string]interface{})) + if err != nil { + return nil, err + } + overrideUpstreamConfig = append(overrideUpstreamConfig, overrideUpstreamConfigElem) + } + configEntry.UpstreamConfig.Overrides = overrideUpstreamConfig + } + } + + if d.Get("transparent_proxy") != nil { + transparentProxyList := d.Get("transparent_proxy").(*schema.Set).List() + if len(transparentProxyList) > 0 { + transparentProxy := transparentProxyList[0].(map[string]interface{}) + configEntry.TransparentProxy = getTransparentProxy(transparentProxy) + } + } + + if d.Get("envoy_extensions") != nil { + for _, elem := range d.Get("envoy_extensions").([]interface{}) { + envoyExtensionMap := elem.(map[string]interface{}) + configEntry.EnvoyExtensions = append(configEntry.EnvoyExtensions, getEnvoyExtension(envoyExtensionMap)) + } + } + + if d.Get("destination") != nil { + destinationList := d.Get("destination").(*schema.Set).List() + if len(destinationList) > 0 { + configEntry.Destination = getDestination(destinationList[0].(map[string]interface{})) + } + } + + if d.Get("mesh_gateway") != nil { + if v := getMeshGateway(d.Get("mesh_gateway")); v != nil { + configEntry.MeshGateway = *v + } + } + + if d.Get("expose") != nil { + exposeList := d.Get("expose").(*schema.Set).List() + if len(exposeList) > 0 { + configEntry.Expose = getExpose(exposeList[0].(map[string]interface{})) + } + } + + return configEntry, nil +} + +func (s *serviceDefaults) Write(ce consulapi.ConfigEntry, d *schema.ResourceData, sw *stateWriter) error { + sd, ok := ce.(*consulapi.ServiceConfigEntry) + if !ok { + return fmt.Errorf("expected '%s' but got '%s'", consulapi.ServiceDefaults, ce.GetKind()) + } + + sw.set("name", sd.Name) + sw.set("partition", sd.Partition) + sw.set("namespace", sd.Namespace) + + meta := make(map[string]interface{}) + for k, v := range sd.Meta { + meta[k] = v + } + sw.set("meta", meta) + + sw.set("protocol", sd.Protocol) + sw.set("balance_inbound_connections", sd.BalanceInboundConnections) + sw.set("mode", sd.Mode) + + getUpstreamConfigOverrides := func(elem *consulapi.UpstreamConfig) map[string]interface{} { + upstreamConfig := make(map[string]interface{}) + upstreamConfig["name"] = elem.Name + upstreamConfig["partition"] = elem.Partition + upstreamConfig["namespace"] = elem.Namespace + upstreamConfig["peer"] = elem.Peer + upstreamConfig["protocol"] = elem.Protocol + upstreamConfig["connect_timeout_ms"] = elem.ConnectTimeoutMs + limits := make([]map[string]interface{}, 1) + limits[0] = make(map[string]interface{}) + limits[0]["max_connections"] = elem.Limits.MaxConnections + limits[0]["max_pending_requests"] = elem.Limits.MaxPendingRequests + limits[0]["max_concurrent_requests"] = elem.Limits.MaxConcurrentRequests + upstreamConfig["limits"] = limits + passiveHealthCheck := make([]map[string]interface{}, 1) + passiveHealthCheck[0] = make(map[string]interface{}) + passiveHealthCheck[0]["interval"] = elem.PassiveHealthCheck.Interval.String() + passiveHealthCheck[0]["max_failures"] = elem.PassiveHealthCheck.MaxFailures + passiveHealthCheck[0]["enforcing_consecutive_5xx"] = elem.PassiveHealthCheck.EnforcingConsecutive5xx + passiveHealthCheck[0]["max_ejection_percent"] = elem.PassiveHealthCheck.MaxEjectionPercent + passiveHealthCheck[0]["base_ejection_time"] = elem.PassiveHealthCheck.BaseEjectionTime.String() + upstreamConfig["passive_health_check"] = passiveHealthCheck + + meshGateway := make([]map[string]interface{}, 1) + meshGateway[0] = make(map[string]interface{}) + meshGateway[0]["mode"] = elem.MeshGateway.Mode + upstreamConfig["mesh_gateway"] = meshGateway + + upstreamConfig["balance_outbound_connections"] = elem.BalanceOutboundConnections + return upstreamConfig + } + + getUpstreamConfigDefaults := func(elem *consulapi.UpstreamConfig) map[string]interface{} { + upstreamConfig := make(map[string]interface{}) + upstreamConfig["protocol"] = elem.Protocol + upstreamConfig["connect_timeout_ms"] = elem.ConnectTimeoutMs + limits := make([]map[string]interface{}, 1) + limits[0] = make(map[string]interface{}) + limits[0]["max_connections"] = elem.Limits.MaxConnections + limits[0]["max_pending_requests"] = elem.Limits.MaxPendingRequests + limits[0]["max_concurrent_requests"] = elem.Limits.MaxConcurrentRequests + upstreamConfig["limits"] = limits + passiveHealthCheck := make([]map[string]interface{}, 1) + passiveHealthCheck[0] = make(map[string]interface{}) + passiveHealthCheck[0]["interval"] = elem.PassiveHealthCheck.Interval.String() + passiveHealthCheck[0]["max_failures"] = elem.PassiveHealthCheck.MaxFailures + passiveHealthCheck[0]["enforcing_consecutive_5xx"] = elem.PassiveHealthCheck.EnforcingConsecutive5xx + passiveHealthCheck[0]["max_ejection_percent"] = elem.PassiveHealthCheck.MaxEjectionPercent + passiveHealthCheck[0]["base_ejection_time"] = elem.PassiveHealthCheck.BaseEjectionTime.String() + upstreamConfig["passive_health_check"] = passiveHealthCheck + + meshGateway := make([]map[string]interface{}, 1) + meshGateway[0] = make(map[string]interface{}) + meshGateway[0]["mode"] = elem.MeshGateway.Mode + upstreamConfig["mesh_gateway"] = meshGateway + + upstreamConfig["balance_outbound_connections"] = elem.BalanceOutboundConnections + return upstreamConfig + } + + if sd.UpstreamConfig != nil { + var overrides []interface{} + for _, elem := range sd.UpstreamConfig.Overrides { + overrides = append(overrides, getUpstreamConfigOverrides(elem)) + } + + upstreamConfig := make(map[string]interface{}) + upstreamConfig["overrides"] = overrides + defaultsSlice := make([]map[string]interface{}, 1) + defaultsSlice[0] = getUpstreamConfigDefaults(sd.UpstreamConfig.Defaults) + upstreamConfig["defaults"] = defaultsSlice + upstreamConfigSlice := make([]map[string]interface{}, 1) + upstreamConfigSlice[0] = upstreamConfig + sw.set("upstream_config", upstreamConfigSlice) + } + + transparentProxy := make([]map[string]interface{}, 1) + transparentProxy[0] = make(map[string]interface{}) + transparentProxy[0]["outbound_listener_port"] = sd.TransparentProxy.OutboundListenerPort + transparentProxy[0]["dialed_directly"] = sd.TransparentProxy.DialedDirectly + sw.set("transparent_proxy", transparentProxy) + + sw.set("mutual_tls_mode", sd.MutualTLSMode) + + getEnvoyExtension := func(elem consulapi.EnvoyExtension) map[string]interface{} { + envoyExtension := make(map[string]interface{}) + envoyExtension["name"] = elem.Name + envoyExtension["required"] = elem.Required + arguments := make(map[string]interface{}) + for k, v := range elem.Arguments { + arguments[k] = v + } + envoyExtension["arguments"] = arguments + envoyExtension["consul_version"] = elem.ConsulVersion + envoyExtension["envoy_version"] = elem.EnvoyVersion + return envoyExtension + } + + var envoyExtensions []map[string]interface{} + for _, elem := range sd.EnvoyExtensions { + envoyExtensions = append(envoyExtensions, getEnvoyExtension(elem)) + } + sw.set("envoy_extensions", envoyExtensions) + + destination := make([]map[string]interface{}, 1) + if sd.Destination != nil { + destination[0] = make(map[string]interface{}) + destination[0]["port"] = sd.Destination.Port + destination[0]["addresses"] = sd.Destination.Addresses + sw.set("destination", destination) + } + + sw.set("local_connect_timeout_ms", sd.LocalConnectTimeoutMs) + sw.set("max_inbound_connections", sd.MaxInboundConnections) + sw.set("local_request_timeout_ms", sd.LocalRequestTimeoutMs) + + meshGateway := make([]map[string]interface{}, 1) + meshGateway[0] = make(map[string]interface{}) + meshGateway[0]["mode"] = sd.MeshGateway.Mode + sw.set("mesh_gateway", meshGateway) + + sw.set("external_sni", sd.ExternalSNI) + + expose := make([]map[string]interface{}, 1) + expose[0] = make(map[string]interface{}) + expose[0]["checks"] = sd.Expose.Checks + var paths []map[string]interface{} + for _, elem := range sd.Expose.Paths { + path := make(map[string]interface{}) + path["path"] = elem.Path + path["local_path_port"] = elem.LocalPathPort + path["listener_port"] = elem.ListenerPort + path["protocol"] = elem.Protocol + paths = append(paths, path) + } + expose[0]["paths"] = paths + sw.set("expose", expose) + + return nil +} diff --git a/consul/resource_consul_config_entry_service_defaults_ce_test.go b/consul/resource_consul_config_entry_service_defaults_ce_test.go new file mode 100644 index 00000000..7c21ce2c --- /dev/null +++ b/consul/resource_consul_config_entry_service_defaults_ce_test.go @@ -0,0 +1,308 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "testing" +) + +func TestAccConsulServiceDefaultsConfigCEEntryTest(t *testing.T) { + providers, _ := startTestServer(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipTestOnConsulEnterpriseEdition(t) }, + Providers: providers, + Steps: []resource.TestStep{ + { + Config: testConsulServiceDefaultsConfigEntryWithDestination, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "name", "service-defaults-test-1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "balance_inbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "mode", "test"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "transparent_proxy.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "transparent_proxy.3186228498.outbound_listener_port", "1001"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "transparent_proxy.3186228498.dialed_directly", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "mutual_tls_mode", "strict"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "envoy_extensions.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "envoy_extensions.0.name", "builtin/aws/lambda"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "envoy_extensions.0.required", "false"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "envoy_extensions.0.arguments.ARN", "some-arn"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "envoy_extensions.0.consul_version", "1.16"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "envoy_extensions.0.envoy_version", "1.2"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "destination.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "destination.2840622507.addresses.0", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "destination.2840622507.addresses.1", "10.0.0.2"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "destination.2840622507.port", "1000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "max_inbound_connections", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "local_connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "local_request_timeout_ms", "15"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "mesh_gateway.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "mesh_gateway.2285830552.mode", "mode"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "external_sni", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.checks", "false"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.0.listener_port", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.0.local_path_port", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.0.path", "/local/dir"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.0.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.1.listener_port", "20"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.1.local_path_port", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.1.path", "/test"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.1.protocol", "http"), + ), + }, + { + Config: testConsulServiceDefaultsConfigEntryWithUpstreamConfig, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "name", "service-defaults-test-2"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "balance_inbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "mode", "test"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.name", "backend"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.connect_timeout_ms", "500"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.passive_health_check.3595791510.interval", "19s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.passive_health_check.3595791510.max_failures", "8"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.passive_health_check.3595791510.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.passive_health_check.3595791510.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.passive_health_check.3595791510.base_ejection_time", "30s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.name", "frontend"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.passive_health_check.3595791510.interval", "19s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.passive_health_check.3595791510.max_failures", "8"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.passive_health_check.3595791510.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.passive_health_check.3595791510.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.passive_health_check.3595791510.base_ejection_time", "30s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.limits.3460439324.max_connections", "1000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.limits.3460439324.max_pending_requests", "9000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.limits.3460439324.max_concurrent_requests", "2900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.passive_health_check.2909148994.interval", "6h38m20s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.passive_health_check.2909148994.max_failures", "29030"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.passive_health_check.2909148994.enforcing_consecutive_5xx", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.passive_health_check.2909148994.max_ejection_percent", "12"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.passive_health_check.2909148994.base_ejection_time", "8h25m9s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "transparent_proxy.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "transparent_proxy.3186228498.outbound_listener_port", "1001"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "transparent_proxy.3186228498.dialed_directly", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "mutual_tls_mode", "strict"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "envoy_extensions.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "envoy_extensions.0.name", "builtin/aws/lambda"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "envoy_extensions.0.required", "false"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "envoy_extensions.0.arguments.ARN", "some-arn"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "envoy_extensions.0.consul_version", "1.16"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "envoy_extensions.0.envoy_version", "1.2"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "max_inbound_connections", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "local_connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "local_request_timeout_ms", "15"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "mesh_gateway.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "mesh_gateway.3963046091.mode", "strict"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "external_sni", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.checks", "false"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.0.listener_port", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.0.local_path_port", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.0.path", "/local/dir"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.0.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.1.listener_port", "20"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.1.local_path_port", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.1.path", "/test"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.1.protocol", "http"), + ), + }, + }, + }) +} + +// Destination and Upstream Config are exclusive. +const testConsulServiceDefaultsConfigEntryWithDestination = ` +resource "consul_config_entry_service_defaults" "foo" { + name = "service-defaults-test-1" + meta = { + key = "value" + } + protocol = "tcp" + balance_inbound_connections = "exact_balance" + mode = "test" + transparent_proxy { + outbound_listener_port = 1001 + dialed_directly = true + } + mutual_tls_mode = "strict" # only supported when services are in transparent proxy mode + envoy_extensions { + name = "builtin/aws/lambda" + required = false + arguments = { + "ARN" = "some-arn" + } + consul_version = "1.16" + envoy_version = "1.2" + } + destination { + addresses = [ + "10.0.0.1", + "10.0.0.2" + ] + port = 1000 + } + max_inbound_connections = 0 + local_connect_timeout_ms = 5000 + local_request_timeout_ms = 15 + mesh_gateway { + mode = "mode" + } + external_sni = "10.0.0.1" + + expose { + checks = false + paths { + path = "/local/dir" + local_path_port = 0 + listener_port = 0 + protocol = "http" + } + paths { + path = "/test" + local_path_port = 10 + listener_port = 20 + protocol = "http" + } + } +} +` + +const testConsulServiceDefaultsConfigEntryWithUpstreamConfig = ` +resource "consul_config_entry_service_defaults" "bar" { + name = "service-defaults-test-2" + meta = { + key = "value" + } + protocol = "tcp" + balance_inbound_connections = "exact_balance" + mode = "test" + upstream_config { + overrides { + name = "backend" + protocol = "tcp" + connect_timeout_ms = 500 + mesh_gateway { + mode = "tcp" + } + balance_outbound_connections = "exact_balance" + limits { + max_connections = 1900 + max_pending_requests = 1900 + max_concurrent_requests = 9399 + } + passive_health_check { + interval = "19s" + max_failures = 8 + enforcing_consecutive_5xx = 10 + max_ejection_percent = 10 + base_ejection_time = "30s" + } + } + overrides { + name = "frontend" + protocol = "tcp" + connect_timeout_ms = 5000 + mesh_gateway { + mode = "tcp" + } + balance_outbound_connections = "exact_balance" + limits { + max_connections = 1900 + max_pending_requests = 1900 + max_concurrent_requests = 9399 + } + passive_health_check { + interval = "19s" + max_failures = 8 + enforcing_consecutive_5xx = 10 + max_ejection_percent = 10 + base_ejection_time = "30s" + } + } + defaults { + protocol = "http" + connect_timeout_ms = 5000 + mesh_gateway { + mode = "tcp" + } + balance_outbound_connections = "exact_balance" + limits { + max_connections = 1000 + max_pending_requests = 9000 + max_concurrent_requests = 2900 + } + passive_health_check { + interval = "6h38m20s" + max_failures = 29030 + enforcing_consecutive_5xx = 1 + max_ejection_percent = 12 + base_ejection_time = "8h25m9s" + } + } + } + transparent_proxy { + outbound_listener_port = 1001 + dialed_directly = true + } + mutual_tls_mode = "strict" # only supported when services are in transparent proxy mode + envoy_extensions { + name = "builtin/aws/lambda" + required = false + arguments = { + "ARN" = "some-arn" + } + consul_version = "1.16" + envoy_version = "1.2" + } + max_inbound_connections = 0 + local_connect_timeout_ms = 5000 + local_request_timeout_ms = 15 + mesh_gateway { + mode = "strict" + } + external_sni = "10.0.0.1" + + expose { + checks = false + paths { + path = "/local/dir" + local_path_port = 0 + listener_port = 0 + protocol = "http" + } + paths { + path = "/test" + local_path_port = 10 + listener_port = 20 + protocol = "http" + } + } +} +` diff --git a/consul/resource_consul_config_entry_service_defaults_ee_test.go b/consul/resource_consul_config_entry_service_defaults_ee_test.go new file mode 100644 index 00000000..a5949cfc --- /dev/null +++ b/consul/resource_consul_config_entry_service_defaults_ee_test.go @@ -0,0 +1,316 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package consul + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "testing" +) + +func TestAccConsulServiceDefaultsConfigEEEntryTest(t *testing.T) { + providers, _ := startTestServer(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipTestOnConsulCommunityEdition(t) }, + Providers: providers, + Steps: []resource.TestStep{ + { + Config: testConsulServiceDefaultsConfigEntryWithDestinationEE, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "name", "service-defaults-test-1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "namespace", "namespace1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "partition", "partition1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "balance_inbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "mode", "test"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "transparent_proxy.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "transparent_proxy.3186228498.outbound_listener_port", "1001"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "transparent_proxy.3186228498.dialed_directly", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "mutual_tls_mode", "strict"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "envoy_extensions.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "envoy_extensions.0.name", "builtin/aws/lambda"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "envoy_extensions.0.required", "false"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "envoy_extensions.0.arguments.ARN", "some-arn"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "envoy_extensions.0.consul_version", "1.16"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "envoy_extensions.0.envoy_version", "1.2"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "destination.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "destination.2840622507.addresses.0", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "destination.2840622507.addresses.1", "10.0.0.2"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "destination.2840622507.port", "1000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "max_inbound_connections", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "local_connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "local_request_timeout_ms", "15"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "mesh_gateway.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "mesh_gateway.2285830552.mode", "mode"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "external_sni", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.checks", "false"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.0.listener_port", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.0.local_path_port", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.0.path", "/local/dir"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.0.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.1.listener_port", "20"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.1.local_path_port", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.1.path", "/test"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.foo", "expose.539725082.paths.1.protocol", "http"), + ), + }, + { + Config: testConsulServiceDefaultsConfigEntryWithUpstreamConfigEE, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "name", "service-defaults-test-2"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "namespace", "namespace2"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "partition", "partition2"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "meta.key", "value"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "balance_inbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "mode", "test"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.name", "backend"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.connect_timeout_ms", "500"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.passive_health_check.3595791510.interval", "19s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.passive_health_check.3595791510.max_failures", "8"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.passive_health_check.3595791510.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.passive_health_check.3595791510.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.0.passive_health_check.3595791510.base_ejection_time", "30s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.name", "frontend"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.protocol", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.limits.1033039851.max_connections", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.limits.1033039851.max_pending_requests", "1900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.limits.1033039851.max_concurrent_requests", "9399"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.passive_health_check.3595791510.interval", "19s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.passive_health_check.3595791510.max_failures", "8"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.passive_health_check.3595791510.enforcing_consecutive_5xx", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.passive_health_check.3595791510.max_ejection_percent", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.overrides.1.passive_health_check.3595791510.base_ejection_time", "30s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.mesh_gateway.3192341522.mode", "tcp"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.balance_outbound_connections", "exact_balance"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.limits.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.limits.3460439324.max_connections", "1000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.limits.3460439324.max_pending_requests", "9000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.limits.3460439324.max_concurrent_requests", "2900"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.passive_health_check.2909148994.interval", "6h38m20s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.passive_health_check.2909148994.max_failures", "29030"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.passive_health_check.2909148994.enforcing_consecutive_5xx", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.passive_health_check.2909148994.max_ejection_percent", "12"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "upstream_config.4033055082.defaults.52894523.passive_health_check.2909148994.base_ejection_time", "8h25m9s"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "transparent_proxy.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "transparent_proxy.3186228498.outbound_listener_port", "1001"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "transparent_proxy.3186228498.dialed_directly", "true"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "mutual_tls_mode", "strict"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "envoy_extensions.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "envoy_extensions.0.name", "builtin/aws/lambda"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "envoy_extensions.0.required", "false"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "envoy_extensions.0.arguments.ARN", "some-arn"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "envoy_extensions.0.consul_version", "1.16"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "envoy_extensions.0.envoy_version", "1.2"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "max_inbound_connections", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "local_connect_timeout_ms", "5000"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "local_request_timeout_ms", "15"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "mesh_gateway.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "mesh_gateway.3963046091.mode", "strict"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "external_sni", "10.0.0.1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.#", "1"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.checks", "false"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.0.listener_port", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.0.local_path_port", "0"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.0.path", "/local/dir"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.0.protocol", "http"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.1.listener_port", "20"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.1.local_path_port", "10"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.1.path", "/test"), + resource.TestCheckResourceAttr("consul_config_entry_service_defaults.bar", "expose.539725082.paths.1.protocol", "http"), + ), + }, + }, + }) +} + +// Destination and Upstream Config are exclusive. +const testConsulServiceDefaultsConfigEntryWithDestinationEE = ` +resource "consul_config_entry_service_defaults" "foo" { + name = "service-defaults-test-1" + namespace = "namespace1" + partition = "partition1" + meta = { + key = "value" + } + protocol = "tcp" + balance_inbound_connections = "exact_balance" + mode = "test" + transparent_proxy { + outbound_listener_port = 1001 + dialed_directly = true + } + mutual_tls_mode = "strict" # only supported when services are in transparent proxy mode + envoy_extensions { + name = "builtin/aws/lambda" + required = false + arguments = { + "ARN" = "some-arn" + } + consul_version = "1.16" + envoy_version = "1.2" + } + destination { + addresses = [ + "10.0.0.1", + "10.0.0.2" + ] + port = 1000 + } + max_inbound_connections = 0 + local_connect_timeout_ms = 5000 + local_request_timeout_ms = 15 + mesh_gateway { + mode = "mode" + } + external_sni = "10.0.0.1" + + expose { + checks = false + paths { + path = "/local/dir" + local_path_port = 0 + listener_port = 0 + protocol = "http" + } + paths { + path = "/test" + local_path_port = 10 + listener_port = 20 + protocol = "http" + } + } +} +` + +const testConsulServiceDefaultsConfigEntryWithUpstreamConfigEE = ` +resource "consul_config_entry_service_defaults" "bar" { + name = "service-defaults-test-2" + namespace = "namespace2" + partition = "partition2" + meta = { + key = "value" + } + protocol = "tcp" + balance_inbound_connections = "exact_balance" + mode = "test" + upstream_config { + overrides { + name = "backend" + protocol = "tcp" + connect_timeout_ms = 500 + mesh_gateway { + mode = "tcp" + } + balance_outbound_connections = "exact_balance" + limits { + max_connections = 1900 + max_pending_requests = 1900 + max_concurrent_requests = 9399 + } + passive_health_check { + interval = 19 + max_failures = 8 + enforcing_consecutive_5xx = 10 + max_ejection_percent = 10 + base_ejection_time = 30 + } + } + overrides { + name = "frontend" + protocol = "tcp" + connect_timeout_ms = 5000 + mesh_gateway { + mode = "tcp" + } + balance_outbound_connections = "exact_balance" + limits { + max_connections = 1900 + max_pending_requests = 1900 + max_concurrent_requests = 9399 + } + passive_health_check { + interval = 19 + max_failures = 8 + enforcing_consecutive_5xx = 10 + max_ejection_percent = 10 + base_ejection_time = 30 + } + } + defaults { + protocol = "http" + connect_timeout_ms = 5000 + mesh_gateway { + mode = "tcp" + } + balance_outbound_connections = "exact_balance" + limits { + max_connections = 1000 + max_pending_requests = 9000 + max_concurrent_requests = 2900 + } + passive_health_check { + interval = 23900 + max_failures = 29030 + enforcing_consecutive_5xx = 1 + max_ejection_percent = 12 + base_ejection_time = 30309 + } + } + } + transparent_proxy { + outbound_listener_port = 1001 + dialed_directly = true + } + mutual_tls_mode = "strict" # only supported when services are in transparent proxy mode + envoy_extensions { + name = "builtin/aws/lambda" + required = false + arguments = { + "ARN" = "some-arn" + } + consul_version = "1.16" + envoy_version = "1.2" + } + max_inbound_connections = 0 + local_connect_timeout_ms = 5000 + local_request_timeout_ms = 15 + mesh_gateway { + mode = "strict" + } + external_sni = "10.0.0.1" + + expose { + checks = false + paths { + path = "/local/dir" + local_path_port = 0 + listener_port = 0 + protocol = "http" + } + paths { + path = "/test" + local_path_port = 10 + listener_port = 20 + protocol = "http" + } + } +} +` diff --git a/consul/resource_provider.go b/consul/resource_provider.go index 1b4ca267..887a457b 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -239,6 +239,7 @@ func Provider() terraform.ResourceProvider { "consul_catalog_entry": resourceConsulCatalogEntry(), "consul_certificate_authority": resourceConsulCertificateAuthority(), "consul_config_entry_service_splitter": resourceFromConfigEntryImplementation(&serviceSplitter{}), + "consul_config_entry_service_defaults": resourceFromConfigEntryImplementation(&serviceDefaults{}), "consul_config_entry": resourceConsulConfigEntry(), "consul_intention": resourceConsulIntention(), "consul_key_prefix": resourceConsulKeyPrefix(), diff --git a/docs/resources/config_entry_service_defaults.md b/docs/resources/config_entry_service_defaults.md new file mode 100644 index 00000000..092c3f94 --- /dev/null +++ b/docs/resources/config_entry_service_defaults.md @@ -0,0 +1,199 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "consul_config_entry_service_defaults Resource - terraform-provider-consul" +subcategory: "" +description: |- + The consul_config_entry_service_defaults resource configures a service defaults https://developer.hashicorp.com/consul/docs/connect/config-entries/service-defaults config entry that contains common configuration settings for service mesh services, such as upstreams and gateways. +--- + +# consul_config_entry_service_defaults (Resource) + +The `consul_config_entry_service_defaults` resource configures a [service defaults](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-defaults) config entry that contains common configuration settings for service mesh services, such as upstreams and gateways. + + + + +## Schema + +### Required + +- `expose` (Block Set, Min: 1) Specifies default configurations for exposing HTTP paths through Envoy. (see [below for nested schema](#nestedblock--expose)) +- `name` (String) Specifies the name of the service you are setting the defaults for. +- `protocol` (String) Specifies the default protocol for the service. + +### Optional + +- `balance_inbound_connections` (String) Specifies the strategy for allocating inbound connections to the service across Envoy proxy threads. +- `destination` (Block Set) Configures the destination for service traffic through terminating gateways. (see [below for nested schema](#nestedblock--destination)) +- `envoy_extensions` (Block List) List of extensions to modify Envoy proxy configuration. (see [below for nested schema](#nestedblock--envoy_extensions)) +- `external_sni` (String) Specifies the TLS server name indication (SNI) when federating with an external system. +- `local_connect_timeout_ms` (Number) Specifies the number of milliseconds allowed for establishing connections to the local application instance before timing out. +- `local_request_timeout_ms` (Number) Specifies the timeout for HTTP requests to the local application instance. +- `max_inbound_connections` (Number) Specifies the maximum number of concurrent inbound connections to each service instance. +- `mesh_gateway` (Block Set) Specifies the default mesh gateway mode field for the service. (see [below for nested schema](#nestedblock--mesh_gateway)) +- `meta` (Map of String) Specifies a set of custom key-value pairs to add to the Consul KV store. +- `mode` (String) Specifies a mode for how the service directs inbound and outbound traffic. +- `mutual_tls_mode` (String) Controls whether mutual TLS is required for incoming connections to this service. This setting is only supported for services with transparent proxy enabled. +- `namespace` (String) Specifies the Consul namespace that the configuration entry applies to. +- `partition` (String) Specifies the name of the name of the Consul admin partition that the configuration entry applies to. Refer to Admin Partitions for additional information. +- `transparent_proxy` (Block Set) Controls configurations specific to proxies in transparent mode. Refer to Transparent Proxy Mode for additional information. (see [below for nested schema](#nestedblock--transparent_proxy)) +- `upstream_config` (Block Set) Controls default upstream connection settings and custom overrides for individual upstream services. (see [below for nested schema](#nestedblock--upstream_config)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `expose` + +Optional: + +- `checks` (Boolean) +- `paths` (Block List) (see [below for nested schema](#nestedblock--expose--paths)) + + +### Nested Schema for `expose.paths` + +Optional: + +- `listener_port` (Number) +- `local_path_port` (Number) +- `path` (String) +- `protocol` (String) + + + + +### Nested Schema for `destination` + +Required: + +- `addresses` (List of String) +- `port` (Number) + + + +### Nested Schema for `envoy_extensions` + +Optional: + +- `arguments` (Map of String) +- `consul_version` (String) +- `envoy_version` (String) +- `name` (String) +- `required` (Boolean) + + + +### Nested Schema for `mesh_gateway` + +Required: + +- `mode` (String) + + + +### Nested Schema for `transparent_proxy` + +Required: + +- `dialed_directly` (Boolean) +- `outbound_listener_port` (Number) + + + +### Nested Schema for `upstream_config` + +Optional: + +- `defaults` (Block Set) Specifies configurations that set default upstream settings. For information about overriding the default configurations for in for individual upstreams, refer to UpstreamConfig.Overrides. (see [below for nested schema](#nestedblock--upstream_config--defaults)) +- `overrides` (Block List) Specifies options that override the default upstream configurations for individual upstreams. (see [below for nested schema](#nestedblock--upstream_config--overrides)) + + +### Nested Schema for `upstream_config.defaults` + +Optional: + +- `balance_outbound_connections` (String) Sets the strategy for allocating outbound connections from upstreams across Envoy proxy threads. +- `connect_timeout_ms` (Number) +- `limits` (Block Set) Map that specifies a set of limits to apply to when connecting upstream services. (see [below for nested schema](#nestedblock--upstream_config--defaults--limits)) +- `mesh_gateway` (Block Set) Specifies the default mesh gateway mode field for all upstreams. (see [below for nested schema](#nestedblock--upstream_config--defaults--mesh_gateway)) +- `passive_health_check` (Block Set) Map that specifies a set of rules that enable Consul to remove hosts from the upstream cluster that are unreachable or that return errors. (see [below for nested schema](#nestedblock--upstream_config--defaults--passive_health_check)) +- `protocol` (String) Specifies the default protocol for the service. + + +### Nested Schema for `upstream_config.defaults.limits` + +Optional: + +- `max_concurrent_requests` (Number) Specifies the maximum number of concurrent requests. +- `max_connections` (Number) Specifies the maximum number of connections a service instance can establish against the upstream. +- `max_pending_requests` (Number) Specifies the maximum number of requests that are queued while waiting for a connection to establish. + + + +### Nested Schema for `upstream_config.defaults.mesh_gateway` + +Optional: + +- `mode` (String) + + + +### Nested Schema for `upstream_config.defaults.passive_health_check` + +Optional: + +- `base_ejection_time` (String) Specifies the minimum amount of time that an ejected host must remain outside the cluster before rejoining. +- `enforcing_consecutive_5xx` (Number) Specifies a percentage that indicates how many times out of 100 that Consul ejects the host when it detects an outlier status. +- `interval` (String) Specifies the time between checks. +- `max_ejection_percent` (Number) Specifies the maximum percentage of an upstream cluster that Consul ejects when the proxy reports an outlier. +- `max_failures` (Number) Specifies the number of consecutive failures allowed per check interval. If exceeded, Consul removes the host from the load balancer. + + + + +### Nested Schema for `upstream_config.overrides` + +Optional: + +- `balance_outbound_connections` (String) Sets the strategy for allocating outbound connections from upstreams across Envoy proxy threads. +- `connect_timeout_ms` (Number) +- `envoy_listener_json` (String) +- `limits` (Block Set) Map that specifies a set of limits to apply to when connecting upstream services. (see [below for nested schema](#nestedblock--upstream_config--overrides--limits)) +- `mesh_gateway` (Block Set) Specifies the default mesh gateway mode field for all upstreams. (see [below for nested schema](#nestedblock--upstream_config--overrides--mesh_gateway)) +- `name` (String) Specifies the name of the service you are setting the defaults for. +- `namespace` (String) Specifies the namespace containing the upstream service that the configuration applies to. +- `partition` (String) Specifies the name of the name of the Consul admin partition that the configuration entry applies to. +- `passive_health_check` (Block Set) Map that specifies a set of rules that enable Consul to remove hosts from the upstream cluster that are unreachable or that return errors. (see [below for nested schema](#nestedblock--upstream_config--overrides--passive_health_check)) +- `peer` (String) Specifies the peer name of the upstream service that the configuration applies to. +- `protocol` (String) Specifies the default protocol for the service. + + +### Nested Schema for `upstream_config.overrides.limits` + +Optional: + +- `max_concurrent_requests` (Number) Specifies the maximum number of concurrent requests. +- `max_connections` (Number) Specifies the maximum number of connections a service instance can establish against the upstream. +- `max_pending_requests` (Number) Specifies the maximum number of requests that are queued while waiting for a connection to establish. + + + +### Nested Schema for `upstream_config.overrides.mesh_gateway` + +Optional: + +- `mode` (String) + + + +### Nested Schema for `upstream_config.overrides.passive_health_check` + +Optional: + +- `base_ejection_time` (String) Specifies the minimum amount of time that an ejected host must remain outside the cluster before rejoining. +- `enforcing_consecutive_5xx` (Number) Specifies a percentage that indicates how many times out of 100 that Consul ejects the host when it detects an outlier status. +- `interval` (String) Specifies the time between checks. +- `max_ejection_percent` (Number) Specifies the maximum percentage of an upstream cluster that Consul ejects when the proxy reports an outlier. +- `max_failures` (Number) Specifies the number of consecutive failures allowed per check interval. If exceeded, Consul removes the host from the load balancer.